Prep new energy driver

This commit is contained in:
Theo Arends 2023-01-27 15:53:40 +01:00
parent 9f538e9986
commit f6827590f3
5 changed files with 122 additions and 141 deletions

View File

@ -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

View File

@ -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}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><td>{e}
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><th>Head4</th><th></th><td>{e}
WSContentSend_P(PSTR("</table><hr/>{t}{s}</th><th></th>")); // First column is empty ({t} = <table style='width:100%'>, {s} = <tr><th>)
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("<th style='text-align:center'>%s%s<th></th>"), (no_label)?"":"L", (no_label)?"":itoa(i +1, value_chr, 10));
WSContentSend_P(PSTR("<th style='text-align:center'>%s%s<th></th>"), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10));
}
WSContentSend_P(PSTR("<td>{e}")); // Last column is units ({e} = </td></tr>)
#endif // USE_ENERGY_COLUMN_GUI

View File

@ -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}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><td>{e}
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><th>Head4</th><th></th><td>{e}
WSContentSend_P(PSTR("</table><hr/>{t}{s}</th><th></th>")); // First column is empty ({t} = <table style='width:100%'>, {s} = <tr><th>)
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("<th style='text-align:center'>%s%s<th></th>"), (no_label)?"":"L", (no_label)?"":itoa(i +1, value_chr, 10));
WSContentSend_P(PSTR("<th style='text-align:center'>%s%s<th></th>"), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10));
}
WSContentSend_P(PSTR("<td>{e}")); // Last column is units ({e} = </td></tr>)
#endif // USE_ENERGY_COLUMN_GUI

View File

@ -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;

View File

@ -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;
}