Advertisement
hanpa

Code for washing machine monitoring using SCT-013-030

Aug 1st, 2017
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.94 KB | None | 0 0
  1. #include <Arduino.h>
  2. #include <ESP8266WiFi.h>
  3. #include <ESP8266mDNS.h>
  4. #include "Adafruit_MQTT.h"
  5. #include "Adafruit_MQTT_Client.h"
  6. #include <ArduinoOTA.h>
  7. #include "/Users/hanpa/Dropbox/Hem/Arduino/common/credentials.h"
  8.  
  9. const char* version   = "WashingMachineMonitor 1.0";
  10. const char* date_name = "2017-08-01 Hans Palm";
  11.  
  12. // Hans Palm 2017
  13. // http://www.hobbyelektronik.nu/
  14. //
  15. // This code monitors the washing machine using a SCT-013-030 current transformer
  16. // on one of the electrical phases. SCT-013-030 returns AC of 1V for 30A so a small
  17. // circuit is needed to transform this to a voltage suitable for the analogue A0 input
  18. // on a Wemos D1 mini that has a rage from 0 - 3.3V.
  19. // A circuit and description of the projekt is available here:
  20. //   http://www.hobbyelektronik.nu/forum/viewtopic.php?f=13&t=42
  21. //
  22. // Max and min values of the current is logged during 1 second, the difference
  23. // of max - min is the maximum current span (max current amplitude) during that period.
  24. // This value is then used by a state machine to determine the status of
  25. // the washing machine. The logic will need to be adapted to a certain washing machine.
  26. // Use mqtt values for current span for checking your current levels during a washing cycle
  27. // and adapt the logic accordingly.
  28. //
  29. // The current state of washing machine is sent using mqtt each second and also using a separate
  30. // mqtt message on the event of that the washing machine is finished
  31.  
  32. /************************* WiFi Access Point *********************************/
  33.  
  34. #define WLAN_SSID       ssid
  35. #define WLAN_PASS       password
  36.  
  37. /***************************** MQTT settings *********************************/
  38. #define SERVER      mqtt_server
  39. #define SERVERPORT  mqtt_port              // use 8883 for SSL
  40. #define USERNAME    ""                     // Not used, from Adafruit.io Setup
  41. #define KEY         ""                     // Not used, from Adafruit.io Setup
  42.  
  43. /************************* OTA *********************************/
  44. #define OTA_HOST_NAME   "WashingMachineM"        // No _ in host names!
  45. const char* host = OTA_HOST_NAME;
  46.  
  47. // The follwing parameters are only required for fixed IP, otherwise uncomment, also uncomment WiFi.config(ip, gateway, subnet)
  48. //IPAddress ip(192, 168, 0, TBD);
  49. IPAddress gateway(192, 168, 0, 1);
  50. IPAddress subnet(255, 255, 255, 0);
  51.  
  52. /******************** Types and values for monitoring ************************/
  53.  
  54. enum washingMachineStates {
  55.   Off,
  56.   Inactive,
  57.   Running
  58. };
  59. washingMachineStates washingMachineState = Off;
  60.  
  61. // A measured current span above this value indicates a running machine
  62. #define TO_RUNNING_THRESHOLD 30
  63.  
  64. // Require some seconds above threshold before considered running to filter out power transients
  65. #define TIME_ABOVE_TO_RUNNING_THRESHOLD_BEFORE_RUNNING 3
  66.  
  67. // A measured current span below this value indicates an inactive machine, can be temporarily, e.g. filling up water
  68. #define TO_INACTIVE_THRESHOLD 20
  69.  
  70. // Time in seconds of Inactive before considered Not_Running
  71. #define TIME_IN_INACTIVE_BEFORE_NOT_RUNNING 180
  72.  
  73. // For keeping track of how long the current span has been above TO_RUNNING_THRESHOLD when in Off, to filter out transients
  74. int secondsInOffAboveToRunningThreshold = 0;
  75.  
  76. // For keeping track of how long the state has been Inactive. Stored value of millis() when Inactive was assigned.
  77. unsigned int startTimeInInactive = 0;
  78.  
  79. // Create an ESP8266 WiFiClient class to connect to the MQTT server.
  80. WiFiClient client;
  81. // or... use WiFiFlientSecure for SSL
  82. //WiFiClientSecure client;
  83.  
  84. // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
  85. Adafruit_MQTT_Client mqtt(&client, SERVER, SERVERPORT, USERNAME, KEY);
  86.  
  87. /****************************** Feeds ***************************************/
  88.  
  89. // Setup feeds for publishing.
  90. Adafruit_MQTT_Publish mqttWashingMachineCurrentSpan1s = Adafruit_MQTT_Publish(&mqtt, USERNAME "WashingMachineCurrentSpan1s");
  91. Adafruit_MQTT_Publish mqttWashingMachineState = Adafruit_MQTT_Publish(&mqtt, USERNAME "WashingMachineState");
  92. Adafruit_MQTT_Publish mqttWashingMachineFinishedEvent = Adafruit_MQTT_Publish(&mqtt, USERNAME "WashingMachineFinishedEvent");
  93.  
  94. void MQTT_connect();
  95.  
  96. void OTA_setup() {
  97.   ArduinoOTA.setHostname(host);
  98.  
  99.   ArduinoOTA.onStart([]() {
  100.     String type;
  101. //    if (ArduinoOTA.getCommand() == U_FLASH)
  102.       type = "sketch";
  103. //    else // U_SPIFFS
  104. //      type = "filesystem";
  105.  
  106.     // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
  107.     Serial.println("Start updating " + type);
  108.   });
  109.   ArduinoOTA.onEnd([]() {
  110.     Serial.println("\nEnd");
  111.   });
  112.   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
  113.     Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  114.   });
  115.   ArduinoOTA.onError([](ota_error_t error) {
  116.     Serial.printf("Error[%u]: ", error);
  117.     if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
  118.     else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
  119.     else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
  120.     else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
  121.     else if (error == OTA_END_ERROR) Serial.println("End Failed");
  122.   });
  123.   ArduinoOTA.begin();
  124. }
  125.  
  126. void setup() {
  127.   Serial.begin(115200);
  128.   delay(10);
  129.  
  130.   // Connect to WiFi access point.
  131.   Serial.println(); Serial.println();
  132.   Serial.print("Connecting to ");
  133.   Serial.println(WLAN_SSID);
  134.  
  135.   //WiFi.config(ip, gateway, subnet); // Only required for fixed IP
  136.   WiFi.begin(WLAN_SSID, WLAN_PASS);
  137.   while (WiFi.status() != WL_CONNECTED) {
  138.     delay(500);
  139.     Serial.print(".");
  140.   }
  141.   Serial.println();
  142.  
  143.   Serial.println("WiFi connected");
  144.   Serial.println("IP address: "); Serial.println(WiFi.localIP());
  145.  
  146.   OTA_setup();
  147. }
  148.  
  149. void loop() {
  150.   ArduinoOTA.handle();
  151.  
  152.   // Ensure the connection to the MQTT server is alive (this will make the first
  153.   // connection and automatically reconnect when disconnected).  See the MQTT_connect
  154.   // function definition further below.
  155.   MQTT_connect();
  156.  
  157.   // Process mqtt data
  158.   mqtt.processPackets(50);
  159.  
  160.   // ping the server to keep the mqtt connection alive
  161.   // NOT required if you are publishing once every KEEPALIVE seconds
  162.   /*
  163.   if(! mqtt.ping()) {
  164.    mqtt.disconnect();
  165.  }
  166.  */
  167.  
  168.  // Read current levels from analogue (A0) input during 1 second to determine min, max and current span (amplitude)
  169.  int max = 0;
  170.  int min = 1023;
  171.  unsigned int startTimeOfMeasuring = millis();
  172.  while (true) {
  173.    int v = analogRead(A0);
  174.    if (v > max) {
  175.      max = v;
  176.    }
  177.    if (v < min) {
  178.      min = v;
  179.    }
  180.    if ( (millis() - startTimeOfMeasuring) > 1000) {
  181.      break; // 1 second of reading A0 completed
  182.    }
  183.    // Free some time for network tasks and check request for OTA update
  184.    delay(10);
  185.    ArduinoOTA.handle();
  186.  }
  187.  
  188.  int currentSpan = max - min;
  189.  
  190.  // Publish current span value on MQTT
  191.  mqttWashingMachineCurrentSpan1s.publish(currentSpan);
  192.  
  193.  // Evaluate state
  194.  switch (washingMachineState) {
  195.    case Off:
  196.    if (currentSpan > TO_RUNNING_THRESHOLD) {
  197.      // Filter out power transients, require vurrent span above threshold for some seconds before considered running
  198.      if (secondsInOffAboveToRunningThreshold >= TIME_ABOVE_TO_RUNNING_THRESHOLD_BEFORE_RUNNING ) {
  199.        washingMachineState = Running;
  200.        secondsInOffAboveToRunningThreshold = 0;
  201.      } else {
  202.        secondsInOffAboveToRunningThreshold++;
  203.      }
  204.    } else {
  205.      secondsInOffAboveToRunningThreshold = 0;
  206.    }
  207.    break;
  208.    case Running:
  209.    if (currentSpan < TO_INACTIVE_THRESHOLD) {
  210.      startTimeInInactive = millis();
  211.      washingMachineState = Inactive;
  212.    }
  213.    break;
  214.    case Inactive:
  215.    if ( (millis() - startTimeInInactive) > TIME_IN_INACTIVE_BEFORE_NOT_RUNNING*1000) {
  216.      // The washing machine has completed a washing cycle
  217.      washingMachineState = Off;
  218.      // Publish the event of completion on MQTT
  219.      mqttWashingMachineFinishedEvent.publish(1);
  220.    } else if (currentSpan > TO_RUNNING_THRESHOLD) {
  221.      washingMachineState = Running;
  222.    }
  223.    break;
  224.  }
  225.  
  226.  // Publish current state on MQTT
  227.  switch (washingMachineState) {
  228.    case Off:
  229.    mqttWashingMachineState.publish("Off");
  230.    break;
  231.    case Running:
  232.    mqttWashingMachineState.publish("Running");
  233.    break;
  234.    case Inactive:
  235.    mqttWashingMachineState.publish("Inactive");
  236.    break;
  237.  }
  238. } // end of loop()
  239.  
  240. // Function to connect and reconnect as necessary to the MQTT server.
  241. // Should be called in the loop function and it will take care if connecting.
  242. void MQTT_connect() {
  243.   int8_t ret;
  244.  
  245.   // Stop if already connected.
  246.   if (mqtt.connected()) {
  247.     return;
  248.   }
  249.  
  250.   Serial.print("Connecting to MQTT... ");
  251.  
  252.   while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
  253.     Serial.println(mqtt.connectErrorString(ret));
  254.     Serial.println("Retrying MQTT connection in 5 seconds...");
  255.     mqtt.disconnect();
  256.     delay(5000);  // wait 5 seconds
  257.   }
  258.   Serial.println("MQTT Connected!");
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement