diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 67bf25cd5..b0772932b 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -615,23 +615,23 @@ void setup(void) { snprintf_P(TasmotaGlobal.mqtt_topic, sizeof(TasmotaGlobal.mqtt_topic), ResolveToken(TasmotaGlobal.mqtt_topic).c_str()); RtcInit(); - GpioInit(); - ButtonInit(); - SwitchInit(); + GpioInit(); // FUNC_I2C_INIT -> FUNC_MODULE_INIT -> FUNC_LED_LINK + ButtonInit(); // FUNC_ADD_BUTTON + SwitchInit(); // FUNC_ADD_SWITCH #ifdef ROTARY_V1 RotaryInit(); #endif // ROTARY_V1 #ifdef USE_BERRY if (!TasmotaGlobal.no_autoexec) { - BerryInit(); + BerryInit(); // Load preinit.be } #endif // USE_BERRY - XdrvXsnsCall(FUNC_PRE_INIT); + XdrvXsnsCall(FUNC_PRE_INIT); // FUNC_PRE_INIT TasmotaGlobal.init_state = INIT_GPIOS; - SetPowerOnState(); + SetPowerOnState(); // FUNC_SET_POWER -> FUNC_SET_DEVICE_POWER WifiConnect(); AddLog(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s - %s " D_VERSION " %s%s-" ARDUINO_CORE_RELEASE "(%s)"), @@ -644,7 +644,7 @@ void setup(void) { ArduinoOTAInit(); #endif // USE_ARDUINO_OTA - XdrvXsnsCall(FUNC_INIT); + XdrvXsnsCall(FUNC_INIT); // FUNC_INIT #ifdef USE_SCRIPT if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">BS",3,0); #endif diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino index 2f8f9ecc8..f0533454f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino @@ -224,8 +224,7 @@ char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t /********************************************************************************************/ -bool EnergyTariff1Active() // Off-Peak hours -{ +bool EnergyTariff1Active() { // Off-Peak hours uint8_t dst = 0; if (IsDst() && (Settings->tariff[0][1] != Settings->tariff[1][1])) { dst = 1; @@ -355,8 +354,7 @@ void EnergyUpdateTotal(void) { /*********************************************************************************************/ -void Energy200ms(void) -{ +void Energy200ms(void) { Energy->power_on = (TasmotaGlobal.power != 0) | Settings->flag.no_power_on_check; // SetOption21 - Show voltage even if powered off Energy->fifth_second++; @@ -416,8 +414,7 @@ void Energy200ms(void) XnrgCall(FUNC_EVERY_200_MSECOND); } -void EnergySaveState(void) -{ +void EnergySaveState(void) { Settings->energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; for (uint32_t i = 0; i < 3; i++) { @@ -430,8 +427,7 @@ void EnergySaveState(void) } #ifdef USE_ENERGY_MARGIN_DETECTION -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) -{ +bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) { bool change; if (!margin) return false; @@ -606,8 +602,7 @@ void EnergyMarginCheck(void) { #endif // USE_ENERGY_POWER_LIMIT } -void EnergyMqttShow(void) -{ +void EnergyMqttShow(void) { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} int tele_period_save = TasmotaGlobal.tele_period; TasmotaGlobal.tele_period = 2; @@ -620,8 +615,7 @@ void EnergyMqttShow(void) } #endif // USE_ENERGY_MARGIN_DETECTION -void EnergyEverySecond(void) -{ +void EnergyEverySecond(void) { // Overtemp check if (Energy->use_overtemp && TasmotaGlobal.global_update) { if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings->param[P_OVER_TEMP])) { // SetOption42 Device overtemp, turn off relays @@ -731,6 +725,7 @@ void CmndEnergyYesterday(void) { } void CmndEnergyToday(void) { + // EnergyToday 22 = 0.022 kWh uint32_t values[2] = { 0 }; uint32_t params = ParseParameters(2, values); @@ -1396,9 +1391,10 @@ void EnergyShow(bool json) { // {s}Head1Head2Head3{e} // {s}Head1Head2Head3Head4{e} WSContentSend_P(PSTR("
{t}{s}")); // First column is empty ({t} = , {s} = "), (no_label)?"":"L", (no_label)?"":itoa(i +1, value_chr, 10)); + WSContentSend_P(PSTR(""), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10)); } WSContentSend_P(PSTR(") #endif // USE_ENERGY_COLUMN_GUI diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino index 0deb4d203..f4b940dae 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_esp32_energy.ino @@ -71,15 +71,15 @@ void (* const EnergyCommand[])(void) PROGMEM = { /********************************************************************************************/ typedef struct { - float usage_total_kWh[2]; - float return_total_kWh[2]; + float usage_total_kWh[4]; + float return_total_kWh[4]; float last_return_total_kWh; float last_usage_total_kWh; } tEnergyUsage; typedef struct { - uint32_t crc32; // To detect file changes - uint16_t version; // To detect driver function changes + uint32_t crc32; // To detect file changes + uint16_t version; // To detect driver function changes uint16_t energy_kWhdoy; uint32_t energy_kWhtotal_time; uint32_t spare1; @@ -93,15 +93,15 @@ typedef struct { uint32_t current_calibration[ENERGY_MAX_PHASES_FUTURE]; uint32_t frequency_calibration[ENERGY_MAX_PHASES_FUTURE]; - uint16_t tariff[2][2]; + float energy_today_kWh[ENERGY_MAX_PHASES_FUTURE]; // Energy today in kWh - float allows up to 262143.99 kWh + float energy_yesterday_kWh[ENERGY_MAX_PHASES_FUTURE]; // Energy yesterday in kWh - float allows up to 262143.99 kWh + float energy_total_kWh[ENERGY_MAX_PHASES_FUTURE]; // Total energy in kWh - float allows up to 262143.99 kWh + float energy_export_kWh[ENERGY_MAX_PHASES_FUTURE]; // Export energy in kWh - float allows up to 262143.99 kWh + + uint16_t power_delta[ENERGY_MAX_PHASES_FUTURE]; // PowerDelta + + uint16_t tariff[4][2]; tEnergyUsage energy_usage; - - float energy_today_kWh[ENERGY_MAX_PHASES_FUTURE]; // Energy today in kWh - float allows up to 262143.99 kWh - float energy_yesterday_kWh[ENERGY_MAX_PHASES_FUTURE]; // Energy yesterday in kWh - float allows up to 262143.99 kWh - float energy_total_kWh[ENERGY_MAX_PHASES_FUTURE]; // Total energy in kWh - float allows up to 262143.99 kWh - float energy_export_kWh[ENERGY_MAX_PHASES_FUTURE]; // Export energy in kWh - float allows up to 262143.99 kWh - - uint16_t power_delta[ENERGY_MAX_PHASES_FUTURE]; // PowerDelta } tEnergySettings; typedef struct { @@ -398,8 +398,7 @@ char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t /********************************************************************************************/ -bool EnergyTariff1Active() // Off-Peak hours -{ +bool EnergyTariff1Active() { // Off-Peak hours uint8_t dst = 0; if (IsDst() && (Energy->Settings.tariff[0][1] != Energy->Settings.tariff[1][1])) { dst = 1; @@ -528,8 +527,7 @@ void EnergyUpdateTotal(void) { /*********************************************************************************************/ -void Energy200ms(void) -{ +void Energy200ms(void) { Energy->power_on = (TasmotaGlobal.power != 0) | Settings->flag.no_power_on_check; // SetOption21 - Show voltage even if powered off Energy->fifth_second++; @@ -586,8 +584,7 @@ void Energy200ms(void) XnrgCall(FUNC_EVERY_200_MSECOND); } -void EnergySaveState(void) -{ +void EnergySaveState(void) { Energy->Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; for (uint32_t i = 0; i < 3; i++) { @@ -599,8 +596,7 @@ void EnergySaveState(void) Energy->Settings.energy_usage = RtcEnergySettings.energy_usage; } -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) -{ +bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) { bool change; if (!margin) return false; @@ -773,8 +769,7 @@ void EnergyMarginCheck(void) { } } -void EnergyMqttShow(void) -{ +void EnergyMqttShow(void) { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} int tele_period_save = TasmotaGlobal.tele_period; TasmotaGlobal.tele_period = 2; @@ -786,8 +781,7 @@ void EnergyMqttShow(void) MqttPublishTeleSensor(); } -void EnergyEverySecond(void) -{ +void EnergyEverySecond(void) { // Overtemp check if (Energy->use_overtemp && TasmotaGlobal.global_update) { if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings->param[P_OVER_TEMP])) { // SetOption42 Device overtemp, turn off relays @@ -895,6 +889,7 @@ void CmndEnergyYesterday(void) { } void CmndEnergyToday(void) { + // EnergyToday 22 = 0.022 kWh uint32_t values[2] = { 0 }; uint32_t params = ParseParameters(2, values); @@ -1277,8 +1272,6 @@ void EnergyDrvInit(void) { EnergySettingsLoad(); EnergyRtcSettingsLoad(); - - // Energy->voltage_common = false; // Energy->frequency_common = false; // Energy->use_overtemp = false; @@ -1545,9 +1538,10 @@ void EnergyShow(bool json) { // {s}
) - bool no_label = Energy->voltage_common || (1 == Energy->phase_count); + bool label_o = Energy->voltage_common; + bool no_label = (1 == Energy->phase_count); for (uint32_t i = 0; i < Energy->phase_count; i++) { - WSContentSend_P(PSTR("%s%s%s%s{e}")); // Last column is units ({e} =
Head1Head2Head3{e} // {s}Head1Head2Head3Head4{e} WSContentSend_P(PSTR("

{t}{s}")); // First column is empty ({t} = , {s} = "), (no_label)?"":"L", (no_label)?"":itoa(i +1, value_chr, 10)); + WSContentSend_P(PSTR(""), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10)); } WSContentSend_P(PSTR(") #endif // USE_ENERGY_COLUMN_GUI diff --git a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino index daf423a55..c30b6be13 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v2.ino @@ -23,10 +23,10 @@ /*********************************************************************************************\ * Shelly Pro support * - * {"NAME":"Shelly Pro 1","GPIO":[0,1,0,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,0,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"} - * {"NAME":"Shelly Pro 1PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3459,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"} - * {"NAME":"Shelly Pro 2","GPIO":[0,1,0,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,0,0,0,32,4736,4737,160,161],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350;AdcParam2 2,10000,10000,3350"} - * {"NAME":"Shelly Pro 2PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,9569,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3460,0,0,32,4736,4737,160,161],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350;AdcParam2 2,10000,10000,3350"} + * {"NAME":"Shelly Pro 1","GPIO":[0,1,0,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,0,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"} + * {"NAME":"Shelly Pro 1PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3459,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"} + * {"NAME":"Shelly Pro 2","GPIO":[0,1,0,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,0,0,0,32,4736,4737,160,161],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350;AdcParam2 2,5600,4700,3350"} + * {"NAME":"Shelly Pro 2PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,9569,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3460,0,0,32,4736,4737,160,161],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350;AdcParam2 2,5600,4700,3350"} * * {"NAME":"Shelly Pro 4PM","GPIO":[769,1,1,1,9568,0,0,0,1,705,9569,737,768,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,6214,736,704,3461,0,4736,1,0,672],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"} * {"NAME":"Shelly Pro 4PM No display","GPIO":[1,1,1,1,9568,0,0,0,1,1,9569,1,768,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,6214,736,704,3461,0,4736,1,0,672],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"} @@ -44,7 +44,6 @@ struct SPro { uint32_t last_update; - uint32_t probe_pin; uint16_t input_state; int8_t switch_offset; int8_t button_offset; @@ -52,6 +51,7 @@ struct SPro { uint8_t pin_mcp23s17_int; uint8_t ledlink; uint8_t power; + bool init_done; uint8_t detected; } SPro; @@ -364,17 +364,15 @@ void ShellyProPreInit(void) { TasmotaGlobal.devices_present += SPro.detected; SPro.pin_register_cs = Pin(GPIO_SPI_CS); + digitalWrite(SPro.pin_register_cs, (4 == SPro.detected) ? 1 : 0); // Prep 74HC595 rclk pinMode(SPro.pin_register_cs, OUTPUT); // Does nothing if SPI is already initiated (by ADE7953) so no harm done SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1); if (4 == SPro.detected) { - digitalWrite(SPro.pin_register_cs, 1); // Prep MCP23S17 chip select SPro.pin_mcp23s17_int = SHELLY_PRO_4_PIN_MCP23S17_INT; // GPIO35 = MCP23S17 common interrupt pinMode(SPro.pin_mcp23s17_int, INPUT); ShellyPro4Init(); // Init MCP23S17 - } else { - digitalWrite(SPro.pin_register_cs, 0); // Prep 74HC595 rclk } } } @@ -388,11 +386,17 @@ void ShellyProInit(void) { delay(1); // (t-rstia) This pin must be brought low for a minimum of 100 uS digitalWrite(pin_lan_reset, 1); - AddLog(LOG_LEVEL_INFO, PSTR("HDW: Shelly Pro %d%s initialized"), SPro.detected, (PinUsed(GPIO_ADE7953_CS))?"PM":""); + AddLog(LOG_LEVEL_INFO, PSTR("HDW: Shelly Pro %d%s initialized"), + SPro.detected, (PinUsed(GPIO_ADE7953_CS))?"PM":""); + + SPro.init_done = true; } void ShellyProPower(void) { - if (4 == SPro.detected) { + if (SPro.detected != 4) { + SPro.power = XdrvMailbox.index &3; + ShellyProUpdate(); + } else { // AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Set Power 0x%08X"), XdrvMailbox.index); @@ -402,29 +406,19 @@ void ShellyProPower(void) { SP4Mcp23S17DigitalWrite(sp4_relay_pin[i], state); rpower >>= 1; // Select next power } - } else { - SPro.power = XdrvMailbox.index &3; - ShellyProUpdate(); } } void ShellyProUpdateLedLink(uint32_t ledlink) { - if (4 == SPro.detected) { - - - } else { - if (ledlink != SPro.ledlink) { - SPro.ledlink = ledlink; - ShellyProUpdate(); - } + if (ledlink != SPro.ledlink) { + SPro.ledlink = ledlink; + ShellyProUpdate(); } } void ShellyProLedLink(void) { - if (4 == SPro.detected) { - - - } else { + if (!SPro.init_done) { return; } // Block write before first power update + if (SPro.detected != 4) { /* bit 2 = blue, 3 = green, 4 = red Shelly Pro documentation @@ -450,10 +444,8 @@ void ShellyProLedLink(void) { } void ShellyProLedLinkWifiOff(void) { - if (4 == SPro.detected) { - - - } else { + if (!SPro.init_done) { return; } + if (SPro.detected != 4) { /* bit 2 = blue, 3 = green, 4 = red - Green light indicator will be on if in STA mode and connected to a Wi-Fi network. @@ -483,11 +475,8 @@ bool Xdrv88(uint32_t function) { case FUNC_EVERY_SECOND: ShellyProLedLinkWifiOff(); break; - case FUNC_SET_DEVICE_POWER: + case FUNC_SET_POWER: ShellyProPower(); - return true; - case FUNC_LED_LINK: - ShellyProLedLink(); break; case FUNC_INIT: ShellyProInit(); @@ -498,6 +487,9 @@ bool Xdrv88(uint32_t function) { case FUNC_ADD_SWITCH: result = ShellyProAddSwitch(); break; + case FUNC_LED_LINK: + ShellyProLedLink(); + break; } } return result; diff --git a/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino b/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino index 6293d0330..4f899c90e 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino @@ -82,6 +82,8 @@ #define ADE7953_PHCAL_DEFAULT 0 // = range -383 to 383 - Default phase calibration for Shunts #define ADE7953_PHCAL_DEFAULT_CT 200 // = range -383 to 383 - Default phase calibration for Current Transformers (Shelly EM) +#define ADE7953_MAX_CHANNEL 4 + enum Ade7953Models { ADE7953_SHELLY_25, ADE7953_SHELLY_EM, ADE7953_SHELLY_PLUS_2PM, ADE7953_SHELLY_PRO_1PM, ADE7953_SHELLY_PRO_2PM, ADE7953_SHELLY_PRO_4PM }; enum Ade7953_8BitRegisters { @@ -227,16 +229,16 @@ typedef struct { } tAde7953Channel; struct Ade7953 { - uint32_t voltage_rms[4] = { 0, 0 }; - uint32_t current_rms[4] = { 0, 0 }; - uint32_t active_power[4] = { 0, 0 }; - int32_t calib_data[4][ADE7953_CALIBREGS]; + uint32_t voltage_rms[ADE7953_MAX_CHANNEL] = { 0, 0 }; + uint32_t current_rms[ADE7953_MAX_CHANNEL] = { 0, 0 }; + uint32_t active_power[ADE7953_MAX_CHANNEL] = { 0, 0 }; + int32_t calib_data[ADE7953_MAX_CHANNEL][ADE7953_CALIBREGS]; uint8_t init_step = 0; uint8_t model = 0; // 0 = Shelly 2.5, 1 = Shelly EM, 2 = Shelly Plus 2PM, 3 = Shelly Pro 1PM, 4 = Shelly Pro 2PM, 5 = Shelly Pro 4PM uint8_t cs_index; #ifdef USE_ESP32_SPI SPISettings spi_settings; - int8_t pin_cs[2]; + int8_t pin_cs[ADE7953_MAX_CHANNEL / 2]; #endif // USE_ESP32_SPI } Ade7953; @@ -428,9 +430,11 @@ void Ade7953Init(void) { } } #ifdef USE_ESP32_SPI - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: Chip%d CalibRegs%c V %d, I %d, W %d, VA %d, VAr %d, Ph %d"), chip +1, 'A'+channel, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: Chip%d CalibRegs%c V %d, I %d, W %d, VA %d, VAr %d, Ph %d"), + chip +1, 'A'+channel, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]); #else - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: CalibRegs%c V %d, I %d, W %d, VA %d, VAr %d, Ph %d"), 'A'+channel, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: CalibRegs%c V %d, I %d, W %d, VA %d, VAr %d, Ph %d"), + 'A'+channel, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]); #endif // USE_ESP32_SPI } @@ -442,12 +446,12 @@ void Ade7953Init(void) { void Ade7953GetData(void) { uint32_t acc_mode = 0; - int32_t reg[4][ADE7953_REGISTERS]; + int32_t reg[ADE7953_MAX_CHANNEL][ADE7953_REGISTERS]; #ifdef USE_ESP32_SPI if (Ade7953.pin_cs[0] >= 0) { uint32_t channel = 0; - for (uint32_t chip = 0; chip < 2; chip++) { + for (uint32_t chip = 0; chip < ADE7953_MAX_CHANNEL / 2; chip++) { if (Ade7953.pin_cs[chip] < 0) { continue; } Ade7953.cs_index = chip; for (uint32_t i = 0; i < ADE7953_REGISTERS; i++) { @@ -482,8 +486,8 @@ void Ade7953GetData(void) { // If the device is initializing, we read the energy registers to reset them, but don't report the values as the first read may be inaccurate if (Ade7953.init_step) { return; } - uint32_t apparent_power[4] = { 0, 0 }; - uint32_t reactive_power[4] = { 0, 0 }; + uint32_t apparent_power[ADE7953_MAX_CHANNEL] = { 0, 0 }; + uint32_t reactive_power[ADE7953_MAX_CHANNEL] = { 0, 0 }; for (uint32_t channel = 0; channel < Energy->phase_count; channel++) { Ade7953.voltage_rms[channel] = reg[channel][4]; @@ -578,60 +582,54 @@ bool Ade7953SetDefaults(const char* json) { // All parameters are optional allowing for partial changes JsonParserToken val; - JsonParserObject rms = root[PSTR("rms")].getObject(); - if (rms) { - val = rms[PSTR("voltage")]; - if (val) { - Ade7953.calib_data[0][ADE7953_CAL_VGAIN] = val.getInt(); - Ade7953.calib_data[1][ADE7953_CAL_VGAIN] = Ade7953.calib_data[0][ADE7953_CAL_VGAIN]; + char field[20]; + for (uint32_t i = 0; i < ADE7953_MAX_CHANNEL; i++) { + JsonParserObject rms = root[PSTR("rms")].getObject(); + if (rms) { + val = rms[PSTR("voltage")]; + if (val) { + Ade7953.calib_data[i][ADE7953_CAL_VGAIN] = val.getInt(); + } + #ifdef USE_ESP32_SPI + snprintf_P(field, sizeof(field), PSTR("voltage_%c"), 'a'+i); + val = rms[field]; // "voltage_a" .. "voltage_d" + if (val) { Ade7953.calib_data[i][ADE7953_CAL_VGAIN] = val.getInt(); } + #endif // USE_ESP32_SPI + snprintf_P(field, sizeof(field), PSTR("current_%c"), 'a'+i); + val = rms[field]; // "current_a" .. "current_d" + if (val) { Ade7953.calib_data[i][ADE7953_CAL_IGAIN] = val.getInt(); } } -#ifdef USE_ESP32_SPI - val = rms[PSTR("voltage_a")]; - if (val) { Ade7953.calib_data[0][ADE7953_CAL_VGAIN] = val.getInt(); } - val = rms[PSTR("voltage_b")]; - if (val) { Ade7953.calib_data[1][ADE7953_CAL_VGAIN] = val.getInt(); } -#endif // USE_ESP32_SPI - val = rms[PSTR("current_a")]; - if (val) { Ade7953.calib_data[0][ADE7953_CAL_IGAIN] = val.getInt(); } - val = rms[PSTR("current_b")]; - if (val) { Ade7953.calib_data[1][ADE7953_CAL_IGAIN] = val.getInt(); } - } - JsonParserObject angles = root[PSTR("angles")].getObject(); - if (angles) { - val = angles[PSTR("angle0")]; - if (val) { Ade7953.calib_data[0][ADE7943_CAL_PHCAL] = val.getInt(); } - val = angles[PSTR("angle1")]; - if (val) { Ade7953.calib_data[1][ADE7943_CAL_PHCAL] = val.getInt(); } - } - JsonParserObject powers = root[PSTR("powers")].getObject(); - if (powers) { - JsonParserObject totactive = powers[PSTR("totactive")].getObject(); - if (totactive) { - val = totactive[PSTR("a")]; - if (val) { Ade7953.calib_data[0][ADE7953_CAL_WGAIN] = val.getInt(); } - val = totactive[PSTR("b")]; - if (val) { Ade7953.calib_data[1][ADE7953_CAL_WGAIN] = val.getInt(); } + JsonParserObject angles = root[PSTR("angles")].getObject(); + if (angles) { + snprintf_P(field, sizeof(field), PSTR("angle%c"), '0'+i); + val = angles[field]; // "angle0" .. "angle3" + if (val) { Ade7953.calib_data[i][ADE7943_CAL_PHCAL] = val.getInt(); } } - JsonParserObject apparent = powers[PSTR("apparent")].getObject(); - if (apparent) { - val = apparent[PSTR("a")]; - if (val) { Ade7953.calib_data[0][ADE7953_CAL_VAGAIN] = val.getInt(); } - val = apparent[PSTR("b")]; - if (val) { Ade7953.calib_data[1][ADE7953_CAL_VAGAIN] = val.getInt(); } - } - JsonParserObject reactive = powers[PSTR("reactive")].getObject(); - if (reactive) { - val = reactive[PSTR("a")]; - if (val) { Ade7953.calib_data[0][ADE7953_CAL_VARGAIN] = val.getInt(); } - val = reactive[PSTR("b")]; - if (val) { Ade7953.calib_data[1][ADE7953_CAL_VARGAIN] = val.getInt(); } + JsonParserObject powers = root[PSTR("powers")].getObject(); + if (powers) { + snprintf_P(field, sizeof(field), PSTR("%c"), 'a'+i); + JsonParserObject totactive = powers[PSTR("totactive")].getObject(); + if (totactive) { + val = totactive[field]; // "a" .. "d" + if (val) { Ade7953.calib_data[i][ADE7953_CAL_WGAIN] = val.getInt(); } + } + JsonParserObject apparent = powers[PSTR("apparent")].getObject(); + if (apparent) { + val = apparent[field]; // "a" .. "d" + if (val) { Ade7953.calib_data[i][ADE7953_CAL_VAGAIN] = val.getInt(); } + } + JsonParserObject reactive = powers[PSTR("reactive")].getObject(); + if (reactive) { + val = reactive[field]; // "a" .. "d" + if (val) { Ade7953.calib_data[i][ADE7953_CAL_VARGAIN] = val.getInt(); } + } } } return true; } void Ade7953Defaults(void) { - for (uint32_t channel = 0; channel < 4; channel++) { + for (uint32_t channel = 0; channel < ADE7953_MAX_CHANNEL; channel++) { for (uint32_t i = 0; i < ADE7953_CALIBREGS; i++) { if (ADE7943_CAL_PHCAL == i) { Ade7953.calib_data[channel][i] = (ADE7953_SHELLY_EM == Ade7953.model) ? ADE7953_PHCAL_DEFAULT_CT : ADE7953_PHCAL_DEFAULT; @@ -722,7 +720,7 @@ void Ade7953DrvInit(void) { } #endif // USE_ESP32_SPI if (EnergyGetCalibration(ENERGY_POWER_CALIBRATION) == HLW_PREF_PULSE) { - for (uint32_t i = 0; i < 4; i++) { + for (uint32_t i = 0; i < ADE7953_MAX_CHANNEL; i++) { EnergySetCalibration(ENERGY_POWER_CALIBRATION, ADE7953_PREF, i); EnergySetCalibration(ENERGY_VOLTAGE_CALIBRATION, ADE7953_UREF, i); EnergySetCalibration(ENERGY_CURRENT_CALIBRATION, ADE7953_IREF, i); @@ -760,7 +758,8 @@ void Ade7953DrvInit(void) { bool Ade7953Command(void) { bool serviced = true; - uint32_t channel = (XdrvMailbox.index > 4) ? 0 : XdrvMailbox.index -1; + if (XdrvMailbox.index > ADE7953_MAX_CHANNEL) { return false; }; + uint32_t channel = XdrvMailbox.index -1; if (ADE7953_SHELLY_PRO_4PM != Ade7953.model) { channel = (2 == XdrvMailbox.index) ? 1 : 0; }
) - bool no_label = Energy->voltage_common || (1 == Energy->phase_count); + bool label_o = Energy->voltage_common; + bool no_label = (1 == Energy->phase_count); for (uint32_t i = 0; i < Energy->phase_count; i++) { - WSContentSend_P(PSTR("%s%s%s%s{e}")); // Last column is units ({e} =