From d2aeb8439abc664ba75d629372f9efe755d78451 Mon Sep 17 00:00:00 2001 From: arendst Date: Sun, 4 Feb 2018 18:09:09 +0100 Subject: [PATCH] v5.11.1i - Energy Monitoring Fixes 5.11.1i * Fix some Energy Monitoring related issues * Add command SetOption21 1 to allow Energy Monitoring when power is off on Sonoff Pow and Sonoff S31 (#1420) --- README.md | 1 + sonoff/_releasenotes.ino | 2 + sonoff/settings.h | 2 +- sonoff/sonoff.ino | 3 +- sonoff/support.ino | 9 +++ sonoff/xdrv_03_energy.ino | 114 +++++++++++++++-------------------- sonoff/xdrv_04_snfbridge.ino | 8 +-- 7 files changed, 64 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index fd0997c22..15a13ba22 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ The following devices are supported: - [iTead Sonoff 4CH Pro](https://www.itead.cc/smart-home/sonoff-4ch-pro.html) - [iTead S20 Smart Socket](https://www.itead.cc/smart-socket.html) - [Sonoff S22 Smart Socket](https://github.com/arendst/Sonoff-Tasmota/issues/627) +- [iTead Sonoff S31 Smart Socket with Energy Monitoring](https://www.itead.cc/sonoff-s31.html) - [iTead Slampher](https://www.itead.cc/slampher.html) - [iTead Sonoff Touch](https://www.itead.cc/sonoff-touch.html) - [iTead Sonoff T1](https://www.itead.cc/sonoff-t1.html) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 956f6f714..ffc7219f9 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -2,6 +2,8 @@ * Update TasmotaSerial library to 1.1.0 * Rename commands HlwPCal, HlwUCal and HlwICal to PowerCal, VoltageCal and CurrentCal to be used for both Pow and S31 calibration * Rename commands HlwPSet, HlwUSet and HlwISet to PowerSet, VoltageSet and CurrentSet to be used for both Pow and S31 calibration + * Fix some Energy Monitoring related issues + * Add command SetOption21 1 to allow Energy Monitoring when power is off on Sonoff Pow and Sonoff S31 (#1420) * Add support for Sonoff S31 Smart Socket with Power Consumption Detection (#1626) * Fix IRReceive Data value (#1663) * Fix compiler warnings (#1774) diff --git a/sonoff/settings.h b/sonoff/settings.h index 36610eaf6..cfcd49df1 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -46,7 +46,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t light_signal : 1; // bit 18 (v5.10.0c) uint32_t hass_discovery : 1; // bit 19 (v5.11.1a) uint32_t not_power_linked : 1; // bit 20 (v5.11.1f) - uint32_t spare21 : 1; + uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i) uint32_t spare22 : 1; uint32_t spare23 : 1; uint32_t spare24 : 1; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 4b8ca8b6d..a3a211bc6 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -997,7 +997,7 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len) // type = NULL; // } } - else if ((CMND_SETOPTION == command_code) && ((index <= 20) || ((index > 31) && (index <= P_MAX_PARAM8 + 31)))) { + else if ((CMND_SETOPTION == command_code) && ((index <= 21) || ((index > 31) && (index <= P_MAX_PARAM8 + 31)))) { if (index <= 31) { ptype = 0; // SetOption0 .. 31 } else { @@ -1026,6 +1026,7 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len) case 17: // decimal_text case 18: // light_signal case 20: // not_power_linked + case 21: // no_power_on_check bitWrite(Settings.flag.data, index, payload); } if (12 == index) { // stop_flash_rotate diff --git a/sonoff/support.ino b/sonoff/support.ino index 5b97c6479..2ece5455a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1428,6 +1428,15 @@ void AddLog_P(byte loglevel, const char *formatP, const char *formatP2) AddLog(loglevel); } +void AddLogSerial(byte loglevel) +{ + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL D_RECEIVED)); + for (byte i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, serial_in_buffer[i]); + } + AddLog(loglevel); +} + /*********************************************************************************************\ * \*********************************************************************************************/ diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 66c5cdcf2..a098d91c4 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -51,6 +51,8 @@ float energy_start = 0; // 12345.12345 kWh total from yesterday unsigned long energy_kWhtoday; // 1212312345 Wh * 10^-5 (deca micro Watt hours) - 5763924 = 0.05763924 kWh = 0.058 kWh = energy_daily unsigned long energy_period = 0; // 1212312345 Wh * 10^-5 (deca micro Watt hours) - 5763924 = 0.05763924 kWh = 0.058 kWh = energy_daily +bool energy_power_on = true; + byte energy_min_power_flag = 0; byte energy_max_power_flag = 0; byte energy_min_voltage_flag = 0; @@ -67,10 +69,18 @@ uint16_t energy_mplh_counter = 0; uint16_t energy_mplw_counter = 0; #endif // FEATURE_POWER_LIMIT -byte energy_startup = 1; byte energy_fifth_second = 0; Ticker ticker_energy; +/********************************************************************************************/ + +void EnergyUpdateToday() +{ + RtcSettings.energy_kWhtoday = energy_kWhtoday; + energy_daily = (float)energy_kWhtoday / 100000000; + energy_total = (float)(RtcSettings.energy_kWhtotal + (energy_kWhtoday / 1000)) / 100000; +} + /*********************************************************************************************\ * HLW8012 - Energy (Sonoff Pow) * @@ -136,18 +146,13 @@ void HlwCf1Interrupt() // Service Voltage and Current void HlwEverySecond() { unsigned long hlw_len; - unsigned long hlw_temp; if (hlw_energy_period_counter) { hlw_len = 10000 / hlw_energy_period_counter; hlw_energy_period_counter = 0; if (hlw_len) { - hlw_temp = ((HLW_PREF * Settings.energy_power_calibration) / hlw_len) / 36; - energy_kWhtoday += hlw_temp; - RtcSettings.energy_kWhtoday = energy_kWhtoday; - - energy_total = (float)(RtcSettings.energy_kWhtotal + (energy_kWhtoday / 1000)) / 100000; - energy_daily = (float)energy_kWhtoday / 100000000; + energy_kWhtoday += ((HLW_PREF * Settings.energy_power_calibration) / hlw_len) / 36; + EnergyUpdateToday(); } } } @@ -163,7 +168,7 @@ void HlwEvery200ms() hlw_load_off = 1; } - if (hlw_cf_pulse_length && (power &1) && !hlw_load_off) { + if (hlw_cf_pulse_length && energy_power_on && !hlw_load_off) { hlw_w = (HLW_PREF * Settings.energy_power_calibration) / hlw_cf_pulse_length; energy_power = (float)hlw_w / 10; } else { @@ -185,7 +190,7 @@ void HlwEvery200ms() hlw_cf1_voltage_pulse_length = hlw_cf1_pulse_length; hlw_cf1_voltage_max_pulse_counter = hlw_cf1_pulse_counter; - if (hlw_cf1_voltage_pulse_length && (power &1)) { // If powered on always provide voltage + if (hlw_cf1_voltage_pulse_length && energy_power_on) { // If powered on always provide voltage hlw_u = (HLW_UREF * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; energy_voltage = (float)hlw_u / 10; } else { @@ -227,7 +232,7 @@ void HlwInit() hlw_cf1_current_max_pulse_counter = 0; hlw_load_off = 1; - hlw_energy_period_counter = 1; + hlw_energy_period_counter = 0; hlw_select_ui_flag = 0; // Voltage; @@ -247,41 +252,28 @@ void HlwInit() * Based on datasheet from http://www.chipsea.com/UploadFiles/2017/08/11144342F01B5662.pdf \*********************************************************************************************/ -#define CSE_NOT_CALIBRATED 0xAA +#define CSE_NOT_CALIBRATED 0xAA -#define CSE_PREF 1000 -#define CSE_UREF 100 +#define CSE_PULSES_NOT_INITIALIZED 0x90000 + +#define CSE_PREF 1000 +#define CSE_UREF 100 uint8_t cse_receive_flag = 0; -bool cse_load_off = 0; long voltage_cycle = 0; long current_cycle = 0; long power_cycle = 0; long cf_pulses = 0; -long cf_pulses_last_time = 0; - -void CseDumpSerial() -{ - char svalue[90]; - - svalue[0] = '\0'; - for (byte i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%02X "), svalue, serial_in_buffer[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("CSE: " D_RECEIVED " %s"), svalue); - AddLog(LOG_LEVEL_DEBUG); -} +long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; void CseReceived() { - if (LOG_LEVEL_DEBUG_MORE == Settings.weblog_level) CseDumpSerial(); + AddLogSerial(LOG_LEVEL_DEBUG_MORE); uint8_t header = serial_in_buffer[0]; - if ((header & 0xFC) == 0xFC) { AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); -// CseDumpSerial(); return; } @@ -290,7 +282,6 @@ void CseReceived() for (byte i = 2; i < 23; i++) checksum += serial_in_buffer[i]; if (checksum != serial_in_buffer[23]) { AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); -// CseDumpSerial(); return; } @@ -326,7 +317,7 @@ void CseReceived() if (adjustement & 0x80) { // CF overflow cf_pulses = cf_pulses | 0x10000; } - if (power &1) { // Powered on + if (energy_power_on) { // Powered on if (adjustement & 0x40) { // Voltage valid energy_voltage = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)voltage_cycle; } @@ -376,21 +367,19 @@ bool CseSerialInput() void CseEverySecond() { - if (cf_pulses < cf_pulses_last_time) cf_pulses_last_time = 0; - unsigned long cf_frequency = cf_pulses - cf_pulses_last_time; - if (cf_frequency) { + if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) { cf_pulses_last_time = cf_pulses; - unsigned long energy_temp = (cf_frequency * Settings.energy_power_calibration) / 36; - energy_kWhtoday += energy_temp; - RtcSettings.energy_kWhtoday = energy_kWhtoday; - - energy_total = (float)(RtcSettings.energy_kWhtotal + (energy_kWhtoday / 1000)) / 100000; - energy_daily = (float)energy_kWhtoday / 100000000; + } else { + if (cf_pulses < cf_pulses_last_time) cf_pulses_last_time = 0; // Looses at most one second of data + unsigned long cf_frequency = cf_pulses - cf_pulses_last_time; + if (cf_frequency && energy_power) { + cf_pulses_last_time = cf_pulses; + energy_kWhtoday += (cf_frequency * Settings.energy_power_calibration) / 36; + EnergyUpdateToday(); + } } } -/********************************************************************************************/ - #ifdef USE_PZEM004T /*********************************************************************************************\ * PZEM004T - Energy @@ -536,14 +525,13 @@ void PzemEvery200ms() break; case 4: energy_total = value / 1000; // 99999Wh - if (!energy_startup) { - if (energy_total < energy_start) { - energy_start = energy_total; - Settings.energy_power_calibration = energy_start * 1000; - } - energy_kWhtoday = (energy_total - energy_start) * 100000000; - energy_daily = (float)energy_kWhtoday / 100000000; + if (energy_total < energy_start) { + energy_start = energy_total; + Settings.energy_power_calibration = energy_start * 1000; } + energy_kWhtoday = (energy_total - energy_start) * 100000000; + RtcSettings.energy_kWhtoday = energy_kWhtoday; + energy_daily = (float)energy_kWhtoday / 100000000; break; } pzem_read_state++; @@ -604,16 +592,11 @@ void Energy200ms() if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == energy_max_energy_state)) { energy_max_energy_state = 0; } - if (energy_startup && (RtcTime.day_of_year == Settings.energy_kWhdoy)) { - energy_kWhtoday = Settings.energy_kWhtoday; - energy_period = energy_kWhtoday; - RtcSettings.energy_kWhtoday = energy_kWhtoday; - energy_start = (float)Settings.energy_power_calibration / 1000; // Used by PZEM004T to store total yesterday - energy_startup = 0; - } } } + energy_power_on = (power &1) | Settings.flag.no_power_on_check; + if (ENERGY_HLW8012 == energy_flg) { HlwEvery200ms(); #ifdef USE_PZEM004T @@ -637,6 +620,7 @@ void EnergySaveState() { Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; Settings.energy_kWhtoday = energy_kWhtoday; + RtcSettings.energy_kWhtoday = energy_kWhtoday; Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; } @@ -676,7 +660,7 @@ void EnergyMarginCheck() return; } - if (power && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { + if (energy_power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { energy_power_u = (uint16_t)(energy_power); energy_voltage_u = (uint16_t)(energy_voltage); energy_current_u = (uint16_t)(energy_current * 1000); @@ -856,8 +840,9 @@ boolean EnergyCommand() case 1: energy_kWhtoday = lnum *100000; energy_period = energy_kWhtoday; - RtcSettings.energy_kWhtoday = energy_kWhtoday; Settings.energy_kWhtoday = energy_kWhtoday; + RtcSettings.energy_kWhtoday = energy_kWhtoday; + energy_daily = (float)energy_kWhtoday / 100000000; break; case 2: Settings.energy_kWhyesterday = lnum *100000; @@ -1036,16 +1021,13 @@ void EnergyInit() { if (ENERGY_HLW8012 == energy_flg) { HlwInit(); -#ifdef USE_PZEM004T - } else if (ENERGY_PZEM004T == energy_flg) { -// PzemInit(); -#endif // USE_PZEM004T } if (energy_flg) { - energy_kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : 0; + energy_kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_kWhtoday : 0; energy_period = energy_kWhtoday; - energy_startup = 1; + EnergyUpdateToday(); + energy_start = (float)Settings.energy_power_calibration / 1000; // Used by PZEM004T to store total yesterday ticker_energy.attach_ms(200, Energy200ms); } } diff --git a/sonoff/xdrv_04_snfbridge.ino b/sonoff/xdrv_04_snfbridge.ino index 22c9717d2..4e1166e09 100644 --- a/sonoff/xdrv_04_snfbridge.ino +++ b/sonoff/xdrv_04_snfbridge.ino @@ -50,15 +50,9 @@ void SonoffBridgeReceived() uint16_t low_time = 0; uint16_t high_time = 0; uint32_t received_id = 0; - char svalue[90]; char rfkey[8]; - svalue[0] = '\0'; - for (byte i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%02X "), svalue, serial_in_buffer[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_BRIDGE D_RECEIVED " %s"), svalue); - AddLog(LOG_LEVEL_DEBUG); + AddLogSerial(LOG_LEVEL_DEBUG); if (0xA2 == serial_in_buffer[0]) { // Learn timeout SonoffBridgeLearnFailed();