mirror of https://github.com/arendst/Tasmota.git
Prep new energy driver
This commit is contained in:
parent
9f538e9986
commit
f6827590f3
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue