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}
| Head1 | | Head2 | | Head3 | | {e}
// {s} | | Head1 | | Head2 | | Head3 | | Head4 | | {e}
WSContentSend_P(PSTR(" {t}{s} | | ")); // First column is empty ({t} = , {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 | | "), (no_label)?"":"L", (no_label)?"":itoa(i +1, value_chr, 10));
+ WSContentSend_P(PSTR("%s%s | | "), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10));
}
WSContentSend_P(PSTR("{e}")); // Last column is units ({e} = |
)
#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} | Head1 | | Head2 | | Head3 | | {e}
// {s} | | Head1 | | Head2 | | Head3 | | Head4 | | {e}
WSContentSend_P(PSTR(" |
{t}{s} | ")); // First column is empty ({t} = , {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 | | "), (no_label)?"":"L", (no_label)?"":itoa(i +1, value_chr, 10));
+ WSContentSend_P(PSTR("%s%s | | "), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10));
}
WSContentSend_P(PSTR("{e}")); // Last column is units ({e} = |
)
#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;
}