From 0c582d6a1223ad95606ac37848e0a5aff36f56ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Sat, 30 Jul 2016 00:22:55 +0200 Subject: [PATCH] Small fixes to DHT, energy monitor and main code --- code/data/index.html | 18 +++ code/lib/EmonLiteESP/EmonLiteESP.cpp | 28 +++- code/lib/EmonLiteESP/EmonLiteESP.h | 10 +- code/src/Config.h | 2 +- code/src/main.cpp | 224 ++++++++++++++++----------- 5 files changed, 189 insertions(+), 93 deletions(-) diff --git a/code/data/index.html b/code/data/index.html index 456e2504..1c40ae68 100644 --- a/code/data/index.html +++ b/code/data/index.html @@ -86,6 +86,8 @@ }).done(function(data) { $("#mqtt").val(data.mqtt ? "CONNECTED" : "NOT CONNECTED"); $("#power").val((data.power | 0) + "W"); + $("#temperature").val((data.temperature | 0) + "ÂșC"); + $("#humidity").val((data.humidity | 0) + "%"); if (data.relay) { $("#relay").addClass('btn-primary').html("ON"); $("#status").val(1); @@ -203,6 +205,22 @@ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
diff --git a/code/lib/EmonLiteESP/EmonLiteESP.cpp b/code/lib/EmonLiteESP/EmonLiteESP.cpp index 9e4b6ea8..47f6a16c 100644 --- a/code/lib/EmonLiteESP/EmonLiteESP.cpp +++ b/code/lib/EmonLiteESP/EmonLiteESP.cpp @@ -14,11 +14,19 @@ void EnergyMonitor::initCurrent(current_c callback, double ref, double ratio) { _referenceVoltage = ref; _currentRatio = ratio; _currentMidPoint = (ADC_COUNTS>>1); - calculatePrecision(); + warmup(); }; +void EnergyMonitor::warmup() { + int sample; + for (unsigned int n = 0; n < WARMUP_COUNTS; n++) { + sample = _currentCallback(); + _currentMidPoint = (_currentMidPoint + (sample - _currentMidPoint) / ADC_COUNTS); + } +} + void EnergyMonitor::calculatePrecision() { _currentFactor = _currentRatio * _referenceVoltage / ADC_COUNTS; _precision = 0; @@ -55,13 +63,15 @@ double EnergyMonitor::getCurrent(unsigned int samples) { double filtered; double sum; + //Serial.print("_currentMidPoint: "); Serial.println(_currentMidPoint); + for (unsigned int n = 0; n < samples; n++) { // Read analog value sample = _currentCallback(); // Digital low pass filter extracts the VDC offset - _currentMidPoint = (_currentMidPoint + (sample - _currentMidPoint) / 10.0); + _currentMidPoint = (_currentMidPoint + (sample - _currentMidPoint) / ADC_COUNTS); filtered = sample - _currentMidPoint; // Root-mean-square method @@ -69,8 +79,20 @@ double EnergyMonitor::getCurrent(unsigned int samples) { } - double rms = int(sqrt(sum / samples) - 0.5); + double rms = sqrt(sum / samples) - COUNT_OFFSET; + if (rms < 0) rms = 0; double current = _currentFactor * rms; + + /* + Serial.print("_currentMidPoint: "); Serial.println(_currentMidPoint); + Serial.print("sample : "); Serial.println(sample); + Serial.print("sum : "); Serial.println(sum); + Serial.print("samples : "); Serial.println(samples); + Serial.print("rms1 : "); Serial.println(sqrt(sum / samples)); + Serial.print("rms2 : "); Serial.println(rms); + Serial.print("current : "); Serial.println(current); + */ + current = round(current * _multiplier) / _multiplier; return current; diff --git a/code/lib/EmonLiteESP/EmonLiteESP.h b/code/lib/EmonLiteESP/EmonLiteESP.h index 9f58b0e7..e0f10ece 100644 --- a/code/lib/EmonLiteESP/EmonLiteESP.h +++ b/code/lib/EmonLiteESP/EmonLiteESP.h @@ -8,8 +8,11 @@ #ifndef EmonLiteESP_h #define EmonLiteESP_h -#define ADC_BITS 10 -#define ADC_COUNTS (1<. #define DEBUG +//#define ESPURNA +//#define SONOFF +#define SLAMPHER +//#define S20 + #define ENABLE_RF 0 #define ENABLE_OTA 1 #define ENABLE_OTA_AUTO 0 #define ENABLE_MQTT 1 #define ENABLE_WEBSERVER 1 -#define ENABLE_ENERGYMONITOR 1 -#define ENABLE_DHT 1 +#define ENABLE_ENERGYMONITOR 0 +#define ENABLE_DHT 0 #define APP_NAME "Espurna" -#define APP_VERSION "0.9.3" +#define APP_VERSION "0.9.4" #define APP_AUTHOR "xose.perez@gmail.com" #define APP_WEBSITE "http://tinkerman.cat" -#define MANUFACTURER "ITEAD" -#define MODEL "SONOFF" -//#define MODEL "S20" +#ifdef ESPURNA + #define MANUFACTURER "TINKERMAN" + #define MODEL "ESPURNA" +#endif + +#ifdef SONOFF + #define MANUFACTURER "ITEAD" + #define MODEL "SONOFF" +#endif + +#ifdef SLAMPHER + #define MANUFACTURER "ITEAD" + #define MODEL "SLAMPHER" +#endif + +#ifdef S20 + #define MANUFACTURER "ITEAD" + #define MODEL "S20" +#endif + #define BUTTON_PIN 0 #define RELAY_PIN 12 #define LED_PIN 13 @@ -90,7 +112,7 @@ along with this program. If not, see . #define CURRENT_PIN A0 #define REFERENCE_VOLTAGE 1.0 #define CURRENT_PRECISION 1 -#define SAMPLES_X_MEASUREMENT 1500 +#define SAMPLES_X_MEASUREMENT 1000 #define MEASUREMENT_INTERVAL 10000 #define MEASUREMENTS_X_MESSAGE 6 @@ -107,6 +129,7 @@ DebounceEvent button1 = false; #endif #if ENABLE_MQTT + void mqttSend(char * topic, char * message); WiFiClient client; PubSubClient mqtt(client); char mqttStatusTopic[40]; @@ -129,6 +152,8 @@ DebounceEvent button1 = false; #if ENABLE_DHT DHT dht(DHT_PIN, DHT_TYPE, DHT_TIMING); + double temperature; + double humidity; #endif #if ENABLE_ENERGYMONITOR @@ -203,39 +228,41 @@ void showStatus() { // ----------------------------------------------------------------------------- void switchRelayOn() { + if (!digitalRead(RELAY_PIN)) { + #ifdef DEBUG Serial.println(F("[RELAY] ON")); #endif + digitalWrite(RELAY_PIN, HIGH); + EEPROM.write(0, 1); + EEPROM.commit(); + #if ENABLE_MQTT - if (!isMQTTMessage && mqtt.connected()) { - mqtt.publish(mqttStatusTopic, "1", MQTT_RETAIN); - } + if (!isMQTTMessage) mqttSend(mqttStatusTopic, (char *) "1"); #endif - digitalWrite(RELAY_PIN, HIGH); - if (EEPROM.read(0) == 0) { - EEPROM.write(0, 1); - EEPROM.commit(); - } + } + } void switchRelayOff() { + if (digitalRead(RELAY_PIN)) { + #ifdef DEBUG Serial.println(F("[RELAY] OFF")); #endif + digitalWrite(RELAY_PIN, LOW); + EEPROM.write(0, 0); + EEPROM.commit(); + #if ENABLE_MQTT - if (!isMQTTMessage && mqtt.connected()) { - mqtt.publish(mqttStatusTopic, "0", MQTT_RETAIN); - } + if (!isMQTTMessage) mqttSend(mqttStatusTopic, (char *) "0"); #endif - digitalWrite(RELAY_PIN, LOW); - if (EEPROM.read(0) == 1) { - EEPROM.write(0, 0); - EEPROM.commit(); - } + } + } void toggleRelay() { @@ -263,13 +290,13 @@ void toggleRelay() { RemoteReceiver::disable(); #endif #ifdef DEBUG - Serial.println(F("[OTA] - Start")); + Serial.println(F("[OTA] Start")); #endif }); ArduinoOTA.onEnd([]() { #ifdef DEBUG - Serial.println(F("[OTA] - End")); + Serial.println(F("[OTA] End")); #endif #if ENABLE_RF RemoteReceiver::enable(); @@ -278,18 +305,18 @@ void toggleRelay() { ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { #ifdef DEBUG - Serial.printf("[OTA] - Progress: %u%%\r", (progress / (total / 100))); + Serial.printf("[OTA] Progress: %u%%\r", (progress / (total / 100))); #endif }); ArduinoOTA.onError([](ota_error_t error) { #ifdef DEBUG - Serial.printf("[OTA] - Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) Serial.println(F("[OTA] - Auth Failed")); - else if (error == OTA_BEGIN_ERROR) Serial.println(F("[OTA] - Begin Failed")); - else if (error == OTA_CONNECT_ERROR) Serial.println(F("[OTA] - Connect Failed")); - else if (error == OTA_RECEIVE_ERROR) Serial.println(F("[OTA] - Receive Failed")); - else if (error == OTA_END_ERROR) Serial.println(F("[OTA] - End Failed")); + Serial.printf("[OTA] Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) Serial.println(F("[OTA] Auth Failed")); + else if (error == OTA_BEGIN_ERROR) Serial.println(F("[OTA] Begin Failed")); + else if (error == OTA_CONNECT_ERROR) Serial.println(F("[OTA] Connect Failed")); + else if (error == OTA_RECEIVE_ERROR) Serial.println(F("[OTA] Receive Failed")); + else if (error == OTA_END_ERROR) Serial.println(F("[OTA] End Failed")); #endif }); @@ -303,26 +330,26 @@ void toggleRelay() { if (code == AUTO_OTA_FILESYSTEM_UPDATED) { #ifdef DEBUG - Serial.print(F("[AUTOOTA] - File System Updated")); + Serial.print(F("[AUTOOTA] File System Updated")); #endif config.save(); } #ifdef DEBUG if (code == AUTO_OTA_START) { - Serial.println(F("[AUTOOTA] - Start")); + Serial.println(F("[AUTOOTA] Start")); } if (code == AUTO_OTA_UPTODATE) { - Serial.println(F("[AUTOOTA] - Already in the last version")); + Serial.println(F("[AUTOOTA] Already in the last version")); } if (code == AUTO_OTA_PARSE_ERROR) { - Serial.println(F("[AUTOOTA] - Error parsing server response")); + Serial.println(F("[AUTOOTA] Error parsing server response")); } if (code == AUTO_OTA_UPDATING) { - Serial.println(F("[AUTOOTA] - Updating")); + Serial.println(F("[AUTOOTA] Updating")); Serial.print( F(" New version: ")); Serial.println(AutoOTA.getNewVersion()); Serial.print( F(" Firmware: ")); @@ -332,25 +359,25 @@ void toggleRelay() { } if (code == AUTO_OTA_FILESYSTEM_UPDATE_ERROR) { - Serial.print(F("[AUTOOTA] - File System Update Error: ")); + Serial.print(F("[AUTOOTA] File System Update Error: ")); Serial.println(AutoOTA.getErrorString()); } if (code == AUTO_OTA_FIRMWARE_UPDATE_ERROR) { - Serial.print(F("[AUTOOTA] - Firmware Update Error: ")); + Serial.print(F("[AUTOOTA] Firmware Update Error: ")); Serial.println(AutoOTA.getErrorString()); } if (code == AUTO_OTA_FIRMWARE_UPDATED) { - Serial.print(F("[AUTOOTA] - Firmware Updated")); + Serial.print(F("[AUTOOTA] Firmware Updated")); } if (code == AUTO_OTA_RESET) { - Serial.println(F("[AUTOOTA] - Resetting board")); + Serial.println(F("[AUTOOTA] Resetting board")); } if (code == AUTO_OTA_END) { - Serial.println(F("[AUTOOTA] - End")); + Serial.println(F("[AUTOOTA] End")); } #endif @@ -392,7 +419,7 @@ void wifiSetupAP() { status = WIFI_STATUS_AP; delay(100); #ifdef DEBUG - Serial.print(F("[WIFI] Mode: AP, SSID: ")); + Serial.print(F("[WIFI] ACCESS POINT Mode, SSID: ")); Serial.print(config.hostname); Serial.print(F(", Password: \"")); Serial.print(ADMIN_PASS); @@ -457,7 +484,7 @@ void wifiSetupSTA() { WiFi.setAutoConnect(true); status = WIFI_STATUS_CONNECTED; #ifdef DEBUG - Serial.print(F("[WIFI] Mode: STA, SSID: ")); + Serial.print(F("[WIFI] STATION Mode, SSID: ")); Serial.print(WiFi.SSID()); Serial.print(F(", IP address: ")); Serial.println(WiFi.localIP()); @@ -554,6 +581,7 @@ void wifiLoop() { } void rfSetup() { + pinMode(RF_PIN, INPUT_PULLUP); rfBuildCodes(); RemoteReceiver::init(RF_PIN, 3, rfCallback); RemoteReceiver::enable(); @@ -692,6 +720,10 @@ void wifiLoop() { #if ENABLE_ENERGYMONITOR root["power"] = current * config.pwMainsVoltage.toFloat(); #endif + #if ENABLE_DHT + root["temperature"] = temperature; + root["humidity"] = humidity; + #endif String output; root.printTo(output); @@ -719,6 +751,7 @@ void wifiLoop() { if (server.hasArg("pass1")) config.pass[1] = server.arg("pass1"); if (server.hasArg("ssid2")) config.ssid[2] = server.arg("ssid2"); if (server.hasArg("pass2")) config.pass[2] = server.arg("pass2"); + #if ENABLE_MQTT if (server.hasArg("mqttServer")) config.mqttServer = server.arg("mqttServer"); if (server.hasArg("mqttPort")) config.mqttPort = server.arg("mqttPort"); @@ -831,12 +864,27 @@ void wifiLoop() { } + void mqttSend(char * topic, char * message) { + + if (!mqtt.connected()) return; + + #ifdef DEBUG + Serial.print(F("[MQTT] Sending ")); + Serial.print(topic); + Serial.print(F(" ")); + Serial.println(message); + #endif + + mqtt.publish(topic, message, MQTT_RETAIN); + + } + void mqttCallback(char* topic, byte* payload, unsigned int length) { #ifdef DEBUG - Serial.print(F("[MQTT] Message ")); + Serial.print(F("[MQTT] Received ")); Serial.print(topic); - Serial.print(F(" => ")); + Serial.print(F(" ")); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } @@ -898,10 +946,10 @@ void wifiLoop() { buildTopics(); // Say hello and report our IP - mqtt.publish(mqttIPTopic, (const char *) WiFi.localIP().toString().c_str(), MQTT_RETAIN); + mqttSend(mqttIPTopic, (char *) WiFi.localIP().toString().c_str()); // Publish current relay status - mqtt.publish(mqttStatusTopic, digitalRead(RELAY_PIN) ? "1" : "0", MQTT_RETAIN); + mqttSend(mqttStatusTopic, (char *) (digitalRead(RELAY_PIN) ? "1" : "0")); // Subscribe to topic #ifdef DEBUG @@ -957,36 +1005,36 @@ void wifiLoop() { static unsigned long last_check = 0; if (!mqtt.connected()) return; - if ((millis() - last_check) < DHT_UPDATE_INTERVAL) return; + if ((last_check > 0) && ((millis() - last_check) < DHT_UPDATE_INTERVAL)) return; last_check = millis(); char buffer[10]; - float t = dht.readTemperature(); - if (isnan(t)) { + temperature = dht.readTemperature(); + if (isnan(temperature)) { #ifdef DEBUG - Serial.println(F("[DHT] - Error reading temperature")); + Serial.println(F("[DHT] Error reading temperature")); #endif } else { - dtostrf(t, 4, 1, buffer); - mqtt.publish(mqttTemperatureTopic, buffer, MQTT_RETAIN); + dtostrf(temperature, 4, 1, buffer); + mqttSend(mqttTemperatureTopic, buffer); #ifdef DEBUG - Serial.print(F("[DHT] - Temperature: ")); - Serial.println(t); + Serial.print(F("[DHT] Temperature: ")); + Serial.println(temperature); #endif } - float h = dht.readHumidity(); - if (isnan(h)) { + humidity = dht.readHumidity(); + if (isnan(humidity)) { #ifdef DEBUG - Serial.println(F("[DHT] - Error reading humidity")); + Serial.println(F("[DHT] Error reading humidity")); #endif } else { - dtostrf(h, 4, 1, buffer); - mqtt.publish(mqttHumidityTopic, buffer, MQTT_RETAIN); + dtostrf(humidity, 4, 1, buffer); + mqttSend(mqttHumidityTopic, buffer); #ifdef DEBUG - Serial.print(F("[DHT] - Humidity: ")); - Serial.println(h); + Serial.print(F("[DHT] Humidity: ")); + Serial.println(humidity); #endif } @@ -1000,6 +1048,7 @@ void wifiLoop() { // ----------------------------------------------------------------------------- #if ENABLE_ENERGYMONITOR +#if ENABLE_MQTT unsigned int getCurrent() { return analogRead(CURRENT_PIN); @@ -1014,31 +1063,41 @@ void wifiLoop() { static unsigned long next_measurement = millis(); static byte measurements = 0; + static double max = 0; + static double min = 0; static double sum = 0; + if (!mqtt.connected()) return; + if (millis() > next_measurement) { - current = monitor.getCurrent(SAMPLES_X_MEASUREMENT); + // Safety check: do not read current if relay is OFF + if (!digitalRead(RELAY_PIN)) { + current = 0; + } else { + current = monitor.getCurrent(SAMPLES_X_MEASUREMENT); + } + + if (measurements == 0) { + max = min = current; + } else { + if (current > max) max = current; + if (current < min) min = current; + } sum += current; ++measurements; - /* #ifdef DEBUG - Serial.print(F("Power reading: ")); - Serial.println(current * config.pwMainsVoltage.toFloat()); + Serial.print(F("[ENERGY] Power now: ")); + Serial.print(int(current * config.pwMainsVoltage.toFloat())); + Serial.println(F("W")); #endif - */ if (measurements == MEASUREMENTS_X_MESSAGE) { char buffer[8]; - sprintf(buffer, "%d", int(sum * config.pwMainsVoltage.toFloat() / measurements)); - #ifdef DEBUG - Serial.print(F("[ENERGY] Power: ")); - Serial.println(buffer); - #endif - #if ENABLE_MQTT - mqtt.publish(mqttPowerTopic, buffer, MQTT_RETAIN); - #endif + double power = (sum - max - min) * config.pwMainsVoltage.toFloat() / (measurements - 2); + sprintf(buffer, "%d", int(power)); + mqttSend(mqttPowerTopic, buffer); sum = 0; measurements = 0; } @@ -1050,6 +1109,7 @@ void wifiLoop() { } #endif +#endif // ----------------------------------------------------------------------------- // Hardware (buttons, LEDs,...) @@ -1059,7 +1119,6 @@ void hardwareSetup() { Serial.begin(115200); pinMode(RELAY_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT); - pinMode(RF_PIN, INPUT_PULLUP); button1 = DebounceEvent(BUTTON_PIN); SPIFFS.begin(); EEPROM.begin(4096); @@ -1104,13 +1163,6 @@ void welcome() { Serial.println(fs_info.usedBytes); } - /* - int value = EEPROM.read(10); - Serial.println(value++); - EEPROM.write(10, value); - EEPROM.commit(); - */ - Serial.println(); } @@ -1119,10 +1171,8 @@ void setup() { hardwareSetup(); delay(1000); welcome(); + config.hostname = getIdentifier(); config.load(); - if (config.hostname.length() == 0) { - config.hostname = getIdentifier(); - } // We are handling first connection in the loop //wifiSetup(false);