diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index e0dc83dc..06d0ba17 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -430,6 +430,7 @@ PROGMEM const char* const custom_reset_string[] = { #define MQTT_TOPIC_POWER_REACTIVE "reactive" #define MQTT_TOPIC_POWER_FACTOR "factor" #define MQTT_TOPIC_ENERGY "energy" +#define MQTT_TOPIC_ENERGY_TOTAL "energy_total" // Light module #define MQTT_TOPIC_CHANNEL "channel" @@ -523,6 +524,12 @@ PROGMEM const char* const custom_reset_string[] = { #define POWER_HAS_ACTIVE 0 #endif +#if (POWER_PROVIDER == POWER_PROVIDER_HLW8012) +#define POWER_HAS_ENERGY 1 +#else +#define POWER_HAS_ENERGY 0 +#endif + #define POWER_VOLTAGE 230 // Default voltage #define POWER_READ_INTERVAL 6000 // Default reading interval (6 seconds) #define POWER_REPORT_INTERVAL 60000 // Default report interval (1 minute) @@ -530,7 +537,8 @@ PROGMEM const char* const custom_reset_string[] = { #define POWER_CURRENT_DECIMALS 2 // Decimals for current values #define POWER_VOLTAGE_DECIMALS 0 // Decimals for voltage values #define POWER_POWER_DECIMALS 0 // Decimals for power values -#define POWER_ENERGY_FACTOR (POWER_REPORT_INTERVAL / 1000.0 / 3600.0) +#define POWER_ENERGY_DECIMALS 3 // Decimals for energy values +#define POWER_ENERGY_FACTOR (1. / 3600.0) // Ws => Wh #if POWER_PROVIDER == POWER_PROVIDER_EMON_ANALOG #define EMON_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A) diff --git a/code/espurna/power.ino b/code/espurna/power.ino index d166c0e7..8b70cb13 100644 --- a/code/espurna/power.ino +++ b/code/espurna/power.ino @@ -23,6 +23,7 @@ bool _power_newdata = false; double _power_current = 0; double _power_voltage = 0; double _power_apparent = 0; +double _power_energy = 0; MedianFilter _filter_current = MedianFilter(POWER_REPORT_BUFFER); #if POWER_HAS_ACTIVE @@ -34,6 +35,10 @@ MedianFilter _filter_current = MedianFilter(POWER_REPORT_BUFFER); MedianFilter _filter_apparent = MedianFilter(POWER_REPORT_BUFFER); #endif +#if POWER_HAS_ENERGY + double _power_last_energy = 0; +#endif + // ----------------------------------------------------------------------------- // PRIVATE METHODS // ----------------------------------------------------------------------------- @@ -101,6 +106,9 @@ void _powerRead() { double factor = (apparent > 0) ? active / apparent : 1; if (factor > 1) factor = 1; #endif + #if POWER_HAS_ENERGY + _power_energy = _powerEnergy(); //Due to its nature this value doesn't have to be filtered + #endif // Filters _filter_current.add(current); @@ -132,6 +140,7 @@ void _powerRead() { root["pwrCurrent"] = roundTo(current, POWER_CURRENT_DECIMALS); root["pwrVoltage"] = roundTo(voltage, POWER_VOLTAGE_DECIMALS); root["pwrApparent"] = roundTo(apparent, POWER_POWER_DECIMALS); + root["pwrEnergy"] = roundTo(_power_energy * POWER_ENERGY_FACTOR, POWER_ENERGY_DECIMALS); #if POWER_HAS_ACTIVE root["pwrActive"] = roundTo(active, POWER_POWER_DECIMALS); root["pwrReactive"] = roundTo(reactive, POWER_POWER_DECIMALS); @@ -174,18 +183,26 @@ void _powerReport() { _power_apparent = _power_current * _power_voltage; double power = _power_apparent; #endif - double energy_delta = power * POWER_ENERGY_FACTOR; + #if POWER_HAS_ENERGY + double energy_delta = _power_energy - _power_last_energy; + _power_last_energy = _power_energy; + #else + double energy_delta = power * (POWER_REPORT_INTERVAL / 1000.); + _power_energy += energy_delta; + #endif _power_ready = true; char buf_current[10]; char buf_energy[10]; + char buf_energy_total[10]; dtostrf(_power_current, 1-sizeof(buf_current), POWER_CURRENT_DECIMALS, buf_current); - dtostrf(energy_delta, 1-sizeof(buf_energy), POWER_CURRENT_DECIMALS, buf_energy); - + dtostrf(energy_delta * POWER_ENERGY_FACTOR, 1-sizeof(buf_energy), POWER_ENERGY_DECIMALS, buf_energy); + dtostrf(_power_energy * POWER_ENERGY_FACTOR, 1-sizeof(buf_energy_total), POWER_ENERGY_DECIMALS, buf_energy_total); { mqttSend(MQTT_TOPIC_CURRENT, buf_current); mqttSend(MQTT_TOPIC_POWER_APPARENT, String((int) _power_apparent).c_str()); mqttSend(MQTT_TOPIC_ENERGY, buf_energy); + mqttSend(MQTT_TOPIC_ENERGY_TOTAL, buf_energy_total); #if POWER_HAS_ACTIVE mqttSend(MQTT_TOPIC_POWER_ACTIVE, String((int) _power_active).c_str()); mqttSend(MQTT_TOPIC_POWER_REACTIVE, String((int) _power_reactive).c_str()); @@ -214,6 +231,7 @@ void _powerReport() { influxDBSend(MQTT_TOPIC_CURRENT, buf_current); influxDBSend(MQTT_TOPIC_POWER_APPARENT, String((int) _power_apparent).c_str()); influxDBSend(MQTT_TOPIC_ENERGY, buf_energy); + influxDBSend(MQTT_TOPIC_ENERGY_TOTAL, buf_energy_total); #if POWER_HAS_ACTIVE influxDBSend(MQTT_TOPIC_POWER_ACTIVE, String((int) _power_active).c_str()); influxDBSend(MQTT_TOPIC_POWER_REACTIVE, String((int) _power_reactive).c_str()); diff --git a/code/espurna/power_hlw8012.ino b/code/espurna/power_hlw8012.ino index 38914e12..73944b62 100644 --- a/code/espurna/power_hlw8012.ino +++ b/code/espurna/power_hlw8012.ino @@ -75,6 +75,10 @@ double _powerPowerFactor() { return _hlw8012.getPowerFactor(); } +double _powerEnergy() { + return _hlw8012.getEnergy(); +} + void _powerEnabledProvider() { if (_power_enabled) { attachInterrupt(HLW8012_CF1_PIN, _hlw_cf1_isr, CHANGE); @@ -128,13 +132,16 @@ void _powerSetupProvider() { _hlwRestoreCalibration(); - _power_wifi_onconnect = WiFi.onStationModeGotIP([](WiFiEventStationModeGotIP ipInfo) { - powerEnabled(true); - }); - _power_wifi_ondisconnect = WiFi.onStationModeDisconnected([](WiFiEventStationModeDisconnected ipInfo) { - powerEnabled(false); - }); - + #if HLW8012_USE_INTERRUPTS + powerEnabled(true); //Always keep measurement active to keep track of energy used + #else + _power_wifi_onconnect = WiFi.onStationModeGotIP([](WiFiEventStationModeGotIP ipInfo) { + powerEnabled(true); + }); + _power_wifi_ondisconnect = WiFi.onStationModeDisconnected([](WiFiEventStationModeDisconnected ipInfo) { + powerEnabled(false); + }); + #endif } void _powerLoopProvider(bool before) {