Prep ESP32 energy

This commit is contained in:
Theo Arends 2023-01-24 16:54:03 +01:00
parent e81d59f658
commit e891830545
33 changed files with 779 additions and 773 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2773,43 +2773,43 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value);
while (*lp==' ') lp++;
switch ((uint32_t)fvar) {
case 0:
fvar = Energy.total_sum;
fvar = Energy->total_sum;
break;
case 1:
fvar = Energy.voltage[0];
fvar = Energy->voltage[0];
break;
case 2:
fvar = Energy.voltage[1];
fvar = Energy->voltage[1];
break;
case 3:
fvar = Energy.voltage[2];
fvar = Energy->voltage[2];
break;
case 4:
fvar = Energy.current[0];
fvar = Energy->current[0];
break;
case 5:
fvar = Energy.current[1];
fvar = Energy->current[1];
break;
case 6:
fvar = Energy.current[2];
fvar = Energy->current[2];
break;
case 7:
fvar = Energy.active_power[0];
fvar = Energy->active_power[0];
break;
case 8:
fvar = Energy.active_power[1];
fvar = Energy->active_power[1];
break;
case 9:
fvar = Energy.active_power[2];
fvar = Energy->active_power[2];
break;
case 10:
fvar = Energy.start_energy[0];
fvar = Energy->start_energy[0];
break;
case 11:
fvar = Energy.daily_sum;
fvar = Energy->daily_sum;
break;
case 12:
fvar = Energy.yesterday_sum;
fvar = Energy->yesterday_sum;
break;
default:

View File

@ -649,58 +649,58 @@ void KNX_CB_Action(message_t const &msg, void *arg)
#if defined(USE_ENERGY_SENSOR)
else if (chan->type == KNX_ENERGY_VOLTAGE) // Reply KNX_ENERGY_VOLTAGE
{
knx.answer_4byte_float(msg.received_on, Energy.voltage[0]);
knx.answer_4byte_float(msg.received_on, Energy->voltage[0]);
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.voltage[0]);
knx.answer_4byte_float(msg.received_on, Energy.voltage[0]);
knx.answer_4byte_float(msg.received_on, Energy->voltage[0]);
knx.answer_4byte_float(msg.received_on, Energy->voltage[0]);
}
}
else if (chan->type == KNX_ENERGY_CURRENT) // Reply KNX_ENERGY_CURRENT
{
knx.answer_4byte_float(msg.received_on, Energy.current[0]);
knx.answer_4byte_float(msg.received_on, Energy->current[0]);
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.current[0]);
knx.answer_4byte_float(msg.received_on, Energy.current[0]);
knx.answer_4byte_float(msg.received_on, Energy->current[0]);
knx.answer_4byte_float(msg.received_on, Energy->current[0]);
}
}
else if (chan->type == KNX_ENERGY_POWER) // Reply KNX_ENERGY_POWER
{
knx.answer_4byte_float(msg.received_on, Energy.active_power[0]);
knx.answer_4byte_float(msg.received_on, Energy->active_power[0]);
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.active_power[0]);
knx.answer_4byte_float(msg.received_on, Energy.active_power[0]);
knx.answer_4byte_float(msg.received_on, Energy->active_power[0]);
knx.answer_4byte_float(msg.received_on, Energy->active_power[0]);
}
}
else if (chan->type == KNX_ENERGY_POWERFACTOR) // Reply KNX_ENERGY_POWERFACTOR
{
knx.answer_4byte_float(msg.received_on, Energy.power_factor[0]);
knx.answer_4byte_float(msg.received_on, Energy->power_factor[0]);
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.power_factor[0]);
knx.answer_4byte_float(msg.received_on, Energy.power_factor[0]);
knx.answer_4byte_float(msg.received_on, Energy->power_factor[0]);
knx.answer_4byte_float(msg.received_on, Energy->power_factor[0]);
}
}
else if (chan->type == KNX_ENERGY_YESTERDAY) // Reply KNX_ENERGY_YESTERDAY
{
knx.answer_4byte_float(msg.received_on, Energy.yesterday_sum);
knx.answer_4byte_float(msg.received_on, Energy->yesterday_sum);
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.yesterday_sum);
knx.answer_4byte_float(msg.received_on, Energy.yesterday_sum);
knx.answer_4byte_float(msg.received_on, Energy->yesterday_sum);
knx.answer_4byte_float(msg.received_on, Energy->yesterday_sum);
}
}
else if (chan->type == KNX_ENERGY_DAILY) // Reply KNX_ENERGY_DAILY
{
knx.answer_4byte_float(msg.received_on, Energy.daily_sum);
knx.answer_4byte_float(msg.received_on, Energy->daily_sum);
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.daily_sum);
knx.answer_4byte_float(msg.received_on, Energy.daily_sum);
knx.answer_4byte_float(msg.received_on, Energy->daily_sum);
knx.answer_4byte_float(msg.received_on, Energy->daily_sum);
}
}
else if (chan->type == KNX_ENERGY_TOTAL) // Reply KNX_ENERGY_TOTAL
{
knx.answer_4byte_float(msg.received_on, Energy.total_sum);
knx.answer_4byte_float(msg.received_on, Energy->total_sum);
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.total_sum);
knx.answer_4byte_float(msg.received_on, Energy.total_sum);
knx.answer_4byte_float(msg.received_on, Energy->total_sum);
knx.answer_4byte_float(msg.received_on, Energy->total_sum);
}
}
#endif

View File

@ -812,16 +812,16 @@ void TuyaProcessStatePacket(void) {
uint16_t tmpVol = Tuya.buffer[dpidStart + 4] << 8 | Tuya.buffer[dpidStart + 5];
uint16_t tmpCur = Tuya.buffer[dpidStart + 7] << 8 | Tuya.buffer[dpidStart + 8];
uint16_t tmpPow = Tuya.buffer[dpidStart + 10] << 8 | Tuya.buffer[dpidStart + 11];
Energy.voltage[0] = (float)tmpVol / 10;
Energy.current[0] = (float)tmpCur / 1000;
Energy.active_power[0] = (float)tmpPow;
Energy->voltage[0] = (float)tmpVol / 10;
Energy->current[0] = (float)tmpCur / 1000;
Energy->active_power[0] = (float)tmpPow;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], tmpVol);
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], tmpCur);
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], tmpPow);
if (RtcTime.valid) {
if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) {
Energy.kWhtoday[0] += Energy.active_power[0] * (float)(Rtc.utc_time - Tuya.lastPowerCheckTime) / 36.0;
if (Tuya.lastPowerCheckTime != 0 && Energy->active_power[0] > 0) {
Energy->kWhtoday[0] += Energy->active_power[0] * (float)(Rtc.utc_time - Tuya.lastPowerCheckTime) / 36.0;
EnergyUpdateToday();
}
Tuya.lastPowerCheckTime = Rtc.utc_time;
@ -950,24 +950,24 @@ void TuyaProcessStatePacket(void) {
}
#ifdef USE_ENERGY_SENSOR
else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) {
Energy.voltage[0] = (float)packetValue / 10;
Energy->voltage[0] = (float)packetValue / 10;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue);
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) {
Energy.current[0] = (float)packetValue / 1000;
Energy->current[0] = (float)packetValue / 1000;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue);
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) {
Energy.active_power[0] = (float)packetValue / 10;
Energy->active_power[0] = (float)packetValue / 10;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue);
if (RtcTime.valid) {
if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) {
Energy.kWhtoday[0] += Energy.active_power[0] * (float)(Rtc.utc_time - Tuya.lastPowerCheckTime) / 36.0;
if (Tuya.lastPowerCheckTime != 0 && Energy->active_power[0] > 0) {
Energy->kWhtoday[0] += Energy->active_power[0] * (float)(Rtc.utc_time - Tuya.lastPowerCheckTime) / 36.0;
EnergyUpdateToday();
}
Tuya.lastPowerCheckTime = Rtc.utc_time;
}
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER_TOTAL) {
Energy.import_active[0] = (float)packetValue / 100;
Energy->import_active[0] = (float)packetValue / 100;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Total_Power=%d"), Tuya.buffer[dpidStart], packetValue);
EnergyUpdateTotal();
}
@ -1602,10 +1602,10 @@ bool Xnrg32(uint32_t function)
if (FUNC_PRE_INIT == function) {
if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0 || TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) != 0) {
if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) {
Energy.current_available = false;
Energy->current_available = false;
}
if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) {
Energy.voltage_available = false;
Energy->voltage_available = false;
}
TasmotaGlobal.energy_driver = XNRG_32;
}

View File

@ -1604,15 +1604,15 @@ void TuyaProcessRxedDP(uint8_t dpid, uint8_t type, uint8_t *data, int dpDataLen)
/* uint16_t tmpVol = pTuya->buffer[dpidStart + 4] << 8 | pTuya->buffer[dpidStart + 5];
uint16_t tmpCur = pTuya->buffer[dpidStart + 7] << 8 | pTuya->buffer[dpidStart + 8];
uint16_t tmpPow = pTuya->buffer[dpidStart + 10] << 8 | pTuya->buffer[dpidStart + 11];*/
Energy.voltage[0] = (float)tmpVol / 10;
Energy.current[0] = (float)tmpCur / 1000;
Energy.active_power[0] = (float)tmpPow;
Energy->voltage[0] = (float)tmpVol / 10;
Energy->current[0] = (float)tmpCur / 1000;
Energy->active_power[0] = (float)tmpPow;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d Rx ID=%d Voltage=%d Current=%d Active_Power=%d"), fnId, dpid, tmpVol, tmpCur, tmpPow);
if (RtcTime.valid) {
if (pTuya->lastPowerCheckTime != 0 && Energy.active_power[0] > 0) {
Energy.kWhtoday[0] += Energy.active_power[0] * (float)(Rtc.utc_time - pTuya->lastPowerCheckTime) / 36.0;
if (pTuya->lastPowerCheckTime != 0 && Energy->active_power[0] > 0) {
Energy->kWhtoday[0] += Energy->active_power[0] * (float)(Rtc.utc_time - pTuya->lastPowerCheckTime) / 36.0;
EnergyUpdateToday();
}
pTuya->lastPowerCheckTime = Rtc.utc_time;
@ -1745,24 +1745,24 @@ void TuyaProcessRxedDP(uint8_t dpid, uint8_t type, uint8_t *data, int dpDataLen)
}
#ifdef USE_ENERGY_SENSOR
else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) {
Energy.voltage[0] = (float)packetValue / 10;
Energy->voltage[0] = (float)packetValue / 10;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d Rx ID=%d Voltage=%d"), fnId, dpid, packetValue);
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) {
Energy.current[0] = (float)packetValue / 1000;
Energy->current[0] = (float)packetValue / 1000;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d Rx ID=%d Current=%d"), fnId, dpid, packetValue);
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) {
Energy.active_power[0] = (float)packetValue / 10;
Energy->active_power[0] = (float)packetValue / 10;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d Rx ID=%d Active_Power=%d"), fnId, dpid, packetValue);
if (RtcTime.valid) {
if (pTuya->lastPowerCheckTime != 0 && Energy.active_power[0] > 0) {
Energy.kWhtoday[0] += Energy.active_power[0] * (float)(Rtc.utc_time - pTuya->lastPowerCheckTime) / 36.0;
if (pTuya->lastPowerCheckTime != 0 && Energy->active_power[0] > 0) {
Energy->kWhtoday[0] += Energy->active_power[0] * (float)(Rtc.utc_time - pTuya->lastPowerCheckTime) / 36.0;
EnergyUpdateToday();
}
pTuya->lastPowerCheckTime = Rtc.utc_time;
}
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER_TOTAL) {
Energy.import_active[0] = (float)packetValue / 100;
Energy->import_active[0] = (float)packetValue / 100;
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d Rx ID=%d Total_Power=%d"), fnId, dpid, packetValue);
EnergyUpdateTotal();
}
@ -2441,10 +2441,10 @@ bool Xnrg32(uint32_t function)
if (FUNC_PRE_INIT == function) {
if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0 || TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) != 0) {
if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) {
Energy.current_available = false;
Energy->current_available = false;
}
if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0 && TuyaGetDpId(TUYA_MCU_FUNC_POWER_COMBINED) == 0) {
Energy.voltage_available = false;
Energy->voltage_available = false;
}
TasmotaGlobal.energy_driver = XNRG_32;
}

View File

@ -527,19 +527,19 @@ bool ShdPacketProcess(void)
#ifdef USE_ENERGY_SENSOR
if (Shd.hw_version == 2)
{
Energy.current_available = true;
Energy.voltage_available = true;
Energy->current_available = true;
Energy->voltage_available = true;
}
Energy.active_power[0] = wattage;
Energy.voltage[0] = voltage;
Energy.current[0] = current;
if (Shd.last_power_check > 10 && Energy.active_power[0] > 0) {
Energy->active_power[0] = wattage;
Energy->voltage[0] = voltage;
Energy->current[0] = current;
if (Shd.last_power_check > 10 && Energy->active_power[0] > 0) {
uint32_t time_passed = abs(TimePassedSince(Shd.last_power_check)); // Time passed in milliseconds
uint32_t deca_microWh = (uint32_t)(Energy.active_power[0] * time_passed) / 36;
uint32_t deca_microWh = (uint32_t)(Energy->active_power[0] * time_passed) / 36;
#ifdef SHELLY_DIMMER_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "%4_f W is %u dmWh during %u ms"), &Energy.active_power[0], deca_microWh, time_passed);
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "%4_f W is %u dmWh during %u ms"), &Energy->active_power[0], deca_microWh, time_passed);
#endif // SHELLY_DIMMER_DEBUG
Energy.kWhtoday_delta[0] += deca_microWh;
Energy->kWhtoday_delta[0] += deca_microWh;
EnergyUpdateToday();
}
Shd.last_power_check = millis();
@ -833,10 +833,10 @@ bool Xnrg31(uint32_t function) {
if (Shd.present) {
if (FUNC_PRE_INIT == function) {
#ifndef SHELLY_VOLTAGE_MON
Energy.current_available = false;
Energy.voltage_available = false;
Energy->current_available = false;
Energy->voltage_available = false;
#endif // SHELLY_VOLTAGE_MON
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy->use_overtemp = true; // Use global temperature for overtemp detection
TasmotaGlobal.energy_driver = XNRG_31;
}
}

View File

@ -429,13 +429,13 @@ void TM1621Show(void) {
if (TM1621_POWR316D == Tm1621.device) {
if (0 == Tm1621.display_rotate) {
ext_snprintf_P(Tm1621.row[0], sizeof(Tm1621.row[0]), PSTR("%1_f"), &Energy.voltage[0]);
ext_snprintf_P(Tm1621.row[1], sizeof(Tm1621.row[1]), PSTR("%1_f"), &Energy.current[0]);
ext_snprintf_P(Tm1621.row[0], sizeof(Tm1621.row[0]), PSTR("%1_f"), &Energy->voltage[0]);
ext_snprintf_P(Tm1621.row[1], sizeof(Tm1621.row[1]), PSTR("%1_f"), &Energy->current[0]);
Tm1621.voltage = true;
Tm1621.display_rotate = 1;
} else {
ext_snprintf_P(Tm1621.row[0], sizeof(Tm1621.row[0]), PSTR("%1_f"), &Energy.total[0]);
ext_snprintf_P(Tm1621.row[1], sizeof(Tm1621.row[1]), PSTR("%1_f"), &Energy.active_power[0]);
ext_snprintf_P(Tm1621.row[0], sizeof(Tm1621.row[0]), PSTR("%1_f"), &Energy->total[0]);
ext_snprintf_P(Tm1621.row[1], sizeof(Tm1621.row[1]), PSTR("%1_f"), &Energy->active_power[0]);
Tm1621.kwh = true;
Tm1621.display_rotate = 0;
}

View File

@ -93,7 +93,7 @@ void HlwCfInterrupt(void) { // Service Power
Hlw.cf_pulse_counter++;
Hlw.energy_period_counter++;
}
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
}
void HlwCf1Interrupt(void) { // Service Voltage and Current
@ -111,7 +111,7 @@ void HlwCf1Interrupt(void) { // Service Voltage and Current
Hlw.cf1_timer = 8; // We need up to HLW_SAMPLE_COUNT samples within 1 second (low current could take up to 0.3 second)
}
}
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
}
/********************************************************************************************/
@ -133,15 +133,15 @@ void HlwEvery200ms(void) {
Hlw.cf_summed_pulse_length = 0;
Hlw.cf_pulse_counter = 0;
if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) {
if (Hlw.cf_power_pulse_length && Energy->power_on && !Hlw.load_off) {
hlw_w = (Hlw.power_ratio * Settings->energy_power_calibration) / Hlw.cf_power_pulse_length ; // W *10
Energy.active_power[0] = (float)hlw_w / 10;
Energy->active_power[0] = (float)hlw_w / 10;
Hlw.power_retry = 1; // Workaround issue #5161
} else {
if (Hlw.power_retry) {
Hlw.power_retry--;
} else {
Energy.active_power[0] = 0;
Energy->active_power[0] = 0;
}
}
@ -178,21 +178,21 @@ void HlwEvery200ms(void) {
if (Hlw.select_ui_flag == Hlw.ui_flag) {
Hlw.cf1_voltage_pulse_length = cf1_pulse_length;
if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { // If powered on always provide voltage
if (Hlw.cf1_voltage_pulse_length && Energy->power_on) { // If powered on always provide voltage
hlw_u = (Hlw.voltage_ratio * Settings->energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; // V *10
Energy.voltage[0] = (float)hlw_u / 10;
Energy->voltage[0] = (float)hlw_u / 10;
} else {
Energy.voltage[0] = 0;
Energy->voltage[0] = 0;
}
} else {
Hlw.cf1_current_pulse_length = cf1_pulse_length;
if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { // No current if no power being consumed
if (Hlw.cf1_current_pulse_length && Energy->active_power[0]) { // No current if no power being consumed
hlw_i = (Hlw.current_ratio * Settings->energy_current_calibration) / Hlw.cf1_current_pulse_length; // mA
Energy.current[0] = (float)hlw_i / 1000;
Energy->current[0] = (float)hlw_i / 1000;
} else {
Energy.current[0] = 0;
Energy->current[0] = 0;
}
}
@ -203,7 +203,7 @@ void HlwEvery200ms(void) {
}
void HlwEverySecond(void) {
if (Energy.data_valid[0] > ENERGY_WATCHDOG) {
if (Energy->data_valid[0] > ENERGY_WATCHDOG) {
Hlw.cf1_voltage_pulse_length = 0;
Hlw.cf1_current_pulse_length = 0;
Hlw.cf_power_pulse_length = 0;
@ -217,7 +217,7 @@ void HlwEverySecond(void) {
hlw_len = 10000 * 100 / Hlw.energy_period_counter; // Add *100 to fix rounding on loads at 3.6kW (#9160)
Hlw.energy_period_counter = 0;
if (hlw_len) {
Energy.kWhtoday_delta[0] += (((Hlw.power_ratio * Settings->energy_power_calibration) / 36) * 100) / hlw_len;
Energy->kWhtoday_delta[0] += (((Hlw.power_ratio * Settings->energy_power_calibration) / 36) * 100) / hlw_len;
EnergyUpdateToday();
}
}
@ -270,13 +270,13 @@ void HlwDrvInit(void) {
if (PinUsed(GPIO_NRG_CF1)) { // Voltage and/or Current monitor
if (!PinUsed(GPIO_NRG_SEL)) { // Voltage and/or Current selector
Energy.current_available = false; // Assume Voltage
Energy->current_available = false; // Assume Voltage
}
} else {
Energy.current_available = false;
Energy.voltage_available = false;
Energy->current_available = false;
Energy->voltage_available = false;
}
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy->use_overtemp = true; // Use global temperature for overtemp detection
TasmotaGlobal.energy_driver = XNRG_01;
}
@ -285,20 +285,20 @@ void HlwDrvInit(void) {
bool HlwCommand(void) {
bool serviced = true;
if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) {
if ((CMND_POWERCAL == Energy->command_code) || (CMND_VOLTAGECAL == Energy->command_code) || (CMND_CURRENTCAL == Energy->command_code)) {
// Service in xdrv_03_energy.ino
}
else if (CMND_POWERSET == Energy.command_code) {
else if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) {
XdrvMailbox.payload = ((uint32_t)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio;
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) {
XdrvMailbox.payload = ((uint32_t)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio;
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) {
XdrvMailbox.payload = ((uint32_t)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio;
}

View File

@ -105,21 +105,21 @@ void CseReceived(void) {
Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19];
Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_buffer[22];
if (Energy.power_on) { // Powered on
if (Energy->power_on) { // Powered on
if (adjustement & 0x40) { // Voltage valid
Energy.voltage[0] = (float)(Settings->energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle;
Energy->voltage[0] = (float)(Settings->energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle;
}
if (adjustement & 0x10) { // Power valid
Cse.power_invalid = 0;
if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range
Energy.active_power[0] = 0;
Energy->active_power[0] = 0;
} else {
if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } // Skip first incomplete Cse.power_cycle
if (Cse.power_cycle_first != Cse.power_cycle) {
Cse.power_cycle_first = -1;
Energy.active_power[0] = (float)(Settings->energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle;
Energy->active_power[0] = (float)(Settings->energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle;
} else {
Energy.active_power[0] = 0;
Energy->active_power[0] = 0;
}
}
} else {
@ -127,21 +127,21 @@ void CseReceived(void) {
Cse.power_invalid++;
} else {
Cse.power_cycle_first = 0;
Energy.active_power[0] = 0; // Powered on but no load
Energy->active_power[0] = 0; // Powered on but no load
}
}
if (adjustement & 0x20) { // Current valid
if (0 == Energy.active_power[0]) {
Energy.current[0] = 0;
if (0 == Energy->active_power[0]) {
Energy->current[0] = 0;
} else {
Energy.current[0] = (float)Settings->energy_current_calibration / (float)Cse.current_cycle;
Energy->current[0] = (float)Settings->energy_current_calibration / (float)Cse.current_cycle;
}
}
} else { // Powered off
Cse.power_cycle_first = 0;
Energy.voltage[0] = 0;
Energy.active_power[0] = 0;
Energy.current[0] = 0;
Energy->voltage[0] = 0;
Energy->active_power[0] = 0;
Energy->current[0] = 0;
}
}
@ -159,7 +159,7 @@ void CseSerialInput(void) {
uint8_t checksum = 0;
for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; }
if (checksum == Cse.rx_buffer[23]) {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
CseReceived();
Cse.received = false;
return;
@ -189,7 +189,7 @@ void CseSerialInput(void) {
/********************************************************************************************/
void CseEverySecond(void) {
if (Energy.data_valid[0] > ENERGY_WATCHDOG) {
if (Energy->data_valid[0] > ENERGY_WATCHDOG) {
Cse.voltage_cycle = 0;
Cse.current_cycle = 0;
Cse.power_cycle = 0;
@ -203,7 +203,7 @@ void CseEverySecond(void) {
} else {
cf_pulses = Cse.cf_pulses - Cse.cf_pulses_last_time;
}
if (cf_pulses && Energy.active_power[0]) {
if (cf_pulses && Energy->active_power[0]) {
uint32_t delta = (cf_pulses * Settings->energy_power_calibration) / 36;
// prevent invalid load delta steps even checksum is valid (issue #5789):
// prevent invalid load delta steps even checksum is valid but allow up to 4kW (issue #7155):
@ -211,7 +211,7 @@ void CseEverySecond(void) {
// prevent invalid load delta steps even checksum is valid but allow up to 5.5kW (issue #14156):
if (delta <= (5500 * 1000 / 36)) { // max load for Pow R3: 5.50kW
Cse.cf_pulses_last_time = Cse.cf_pulses;
Energy.kWhtoday_delta[0] += delta;
Energy->kWhtoday_delta[0] += delta;
}
else {
AddLog(LOG_LEVEL_DEBUG, PSTR("CSE: Overload"));
@ -236,7 +236,7 @@ void CseSnsInit(void) {
Settings->param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255
}
Cse.power_invalid = Settings->param[P_CSE7766_INVALID_POWER];
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy->use_overtemp = true; // Use global temperature for overtemp detection
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
}
@ -255,17 +255,17 @@ void CseDrvInit(void) {
bool CseCommand(void) {
bool serviced = true;
if (CMND_POWERSET == Energy.command_code) {
if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len && Cse.power_cycle) {
XdrvMailbox.payload = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF;
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len && Cse.voltage_cycle) {
XdrvMailbox.payload = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF;
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len && Cse.current_cycle) {
XdrvMailbox.payload = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000;
}

View File

@ -180,20 +180,20 @@ void PzemEvery250ms(void)
if (data_ready) {
float value = 0;
if (PzemRecieve(pzem_responses[Pzem.read_state], &value)) {
Energy.data_valid[Pzem.phase] = 0;
Energy->data_valid[Pzem.phase] = 0;
switch (Pzem.read_state) {
case 1: // Voltage as 230.2V
Energy.voltage[Pzem.phase] = value;
Energy->voltage[Pzem.phase] = value;
break;
case 2: // Current as 17.32A
Energy.current[Pzem.phase] = value;
Energy->current[Pzem.phase] = value;
break;
case 3: // Power as 20W
Energy.active_power[Pzem.phase] = value;
Energy->active_power[Pzem.phase] = value;
break;
case 4: // Total energy as 99999Wh
Energy.import_active[Pzem.phase] = value / 1000.0f; // 99.999kWh
if (Pzem.phase == Energy.phase_count -1) {
Energy->import_active[Pzem.phase] = value / 1000.0f; // 99.999kWh
if (Pzem.phase == Energy->phase_count -1) {
if (TasmotaGlobal.uptime > PZEM_STABILIZE) {
EnergyUpdateTotal();
}
@ -212,12 +212,12 @@ void PzemEvery250ms(void)
if (0 == Pzem.send_retry || data_ready) {
if (1 == Pzem.read_state) {
if (0 == Pzem.phase) {
Pzem.phase = Energy.phase_count -1;
Pzem.phase = Energy->phase_count -1;
} else {
Pzem.phase--;
}
// AddLog(LOG_LEVEL_DEBUG, PSTR("PZM: Probing address %d, Max phases %d"), Pzem.phase +1, Energy.phase_count);
// AddLog(LOG_LEVEL_DEBUG, PSTR("PZM: Probing address %d, Max phases %d"), Pzem.phase +1, Energy->phase_count);
}
if (Pzem.address) {
@ -229,8 +229,8 @@ void PzemEvery250ms(void)
}
else {
Pzem.send_retry--;
if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (TasmotaGlobal.uptime < PZEM_STABILIZE)) {
Energy.phase_count--; // Decrement phases if no response after retry within 30 seconds after restart
if ((Energy->phase_count > 1) && (0 == Pzem.send_retry) && (TasmotaGlobal.uptime < PZEM_STABILIZE)) {
Energy->phase_count--; // Decrement phases if no response after retry within 30 seconds after restart
if (TasmotaGlobal.discovery_counter) {
TasmotaGlobal.discovery_counter += (PZEM_RETRY / 4) + 1; // Don't send Discovery yet, delay by 5 * 250ms + 1s
}
@ -246,7 +246,7 @@ void PzemSnsInit(void)
if (PzemSerial->hardwareSerial()) {
ClaimSerial();
}
Energy.phase_count = ENERGY_MAX_PHASES; // Start off with three phases
Energy->phase_count = ENERGY_MAX_PHASES; // Start off with three phases
Pzem.phase = 0;
Pzem.read_state = 1;
} else {
@ -265,7 +265,7 @@ bool PzemCommand(void)
{
bool serviced = true;
if (CMND_MODULEADDRESS == Energy.command_code) {
if (CMND_MODULEADDRESS == Energy->command_code) {
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= ENERGY_MAX_PHASES)) {
Pzem.address = XdrvMailbox.payload; // Valid addresses are 1, 2 and 3
}

View File

@ -454,19 +454,19 @@ void McpParseData(void)
// mcp_power_factor = McpExtractInt(mcp_buffer, 20, 2);
mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2);
if (Energy.power_on) { // Powered on
Energy.data_valid[0] = 0;
Energy.frequency[0] = (float)mcp_line_frequency / 1000;
Energy.voltage[0] = (float)mcp_voltage_rms / 10;
Energy.active_power[0] = (float)mcp_active_power / 100;
if (0 == Energy.active_power[0]) {
Energy.current[0] = 0;
if (Energy->power_on) { // Powered on
Energy->data_valid[0] = 0;
Energy->frequency[0] = (float)mcp_line_frequency / 1000;
Energy->voltage[0] = (float)mcp_voltage_rms / 10;
Energy->active_power[0] = (float)mcp_active_power / 100;
if (0 == Energy->active_power[0]) {
Energy->current[0] = 0;
} else {
Energy.current[0] = (float)mcp_current_rms / 10000;
Energy->current[0] = (float)mcp_current_rms / 10000;
}
/*
} else { // Powered off
Energy.data_valid[0] = ENERGY_WATCHDOG;
Energy->data_valid[0] = ENERGY_WATCHDOG;
*/
}
}
@ -526,7 +526,7 @@ void McpSerialInput(void)
void McpEverySecond(void)
{
if (Energy.data_valid[0] > ENERGY_WATCHDOG) {
if (Energy->data_valid[0] > ENERGY_WATCHDOG) {
mcp_voltage_rms = 0;
mcp_current_rms = 0;
mcp_active_power = 0;
@ -534,7 +534,7 @@ void McpEverySecond(void)
}
if (mcp_active_power) {
Energy.kWhtoday_delta[0] += ((mcp_active_power * 10) / 36);
Energy->kWhtoday_delta[0] += ((mcp_active_power * 10) / 36);
EnergyUpdateToday();
}
@ -573,7 +573,7 @@ void McpSnsInit(void)
mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE));
}
DigitalWrite(GPIO_MCP39F5_RST, 0, 1); // MCP enable
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy->use_overtemp = true; // Use global temperature for overtemp detection
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
}
@ -598,7 +598,7 @@ bool McpCommand(void)
bool serviced = true;
unsigned long value = 0;
if (CMND_POWERSET == Energy.command_code) {
if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len && mcp_active_power) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100);
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
@ -608,7 +608,7 @@ bool McpCommand(void)
}
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len && mcp_voltage_rms) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10);
if ((value > 1000) && (value < 2600)) { // Between 100V and 260V
@ -618,7 +618,7 @@ bool McpCommand(void)
}
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len && mcp_current_rms) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10);
if ((value > 100) && (value < 80000)) { // Between 10mA and 8A
@ -628,7 +628,7 @@ bool McpCommand(void)
}
}
}
else if (CMND_FREQUENCYSET == Energy.command_code) {
else if (CMND_FREQUENCYSET == Energy->command_code) {
if (XdrvMailbox.data_len && mcp_line_frequency) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000);
if ((value > 45000) && (value < 65000)) { // Between 45Hz and 65Hz

View File

@ -65,20 +65,20 @@ void PzemAcEverySecond(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("PAC: PzemAc %d error %d"), PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, error);
} else {
Energy.data_valid[PzemAc.phase] = 0;
Energy->data_valid[PzemAc.phase] = 0;
if (10 == registers) {
// 0 1 2 3 4 5 6 7 8 9 = ModBus register
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 = Buffer index
// 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34
// Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc--
Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0f; // 6553.0 V
Energy.current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0f; // 4294967.000 A
Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0f; // 429496729.0 W
Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0f; // 50.0 Hz
Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0f; // 1.00
Energy.import_active[PzemAc.phase] = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]) / 1000.0f; // 4294967.295 kWh
if (PzemAc.phase == Energy.phase_count -1) {
Energy->voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0f; // 6553.0 V
Energy->current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0f; // 4294967.000 A
Energy->active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0f; // 429496729.0 W
Energy->frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0f; // 50.0 Hz
Energy->power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0f; // 1.00
Energy->import_active[PzemAc.phase] = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]) / 1000.0f; // 4294967.295 kWh
if (PzemAc.phase == Energy->phase_count -1) {
if (TasmotaGlobal.uptime > PZEM_AC_STABILIZE) {
EnergyUpdateTotal();
}
@ -89,7 +89,7 @@ void PzemAcEverySecond(void)
if (0 == PzemAc.send_retry || data_ready) {
if (0 == PzemAc.phase) {
PzemAc.phase = Energy.phase_count -1;
PzemAc.phase = Energy->phase_count -1;
} else {
PzemAc.phase--;
}
@ -103,8 +103,8 @@ void PzemAcEverySecond(void)
}
else {
PzemAc.send_retry--;
if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (TasmotaGlobal.uptime < PZEM_AC_STABILIZE)) {
Energy.phase_count--; // Decrement phases if no response after retry within 30 seconds after restart
if ((Energy->phase_count > 1) && (0 == PzemAc.send_retry) && (TasmotaGlobal.uptime < PZEM_AC_STABILIZE)) {
Energy->phase_count--; // Decrement phases if no response after retry within 30 seconds after restart
if (TasmotaGlobal.discovery_counter) {
TasmotaGlobal.discovery_counter += ENERGY_WATCHDOG + 1; // Don't send Discovery yet, delay by 4s + 1s
}
@ -118,7 +118,7 @@ void PzemAcSnsInit(void)
uint8_t result = PzemAcModbus->Begin(9600);
if (result) {
if (2 == result) { ClaimSerial(); }
Energy.phase_count = ENERGY_MAX_PHASES; // Start off with three phases
Energy->phase_count = ENERGY_MAX_PHASES; // Start off with three phases
PzemAc.phase = 0;
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
@ -136,7 +136,7 @@ bool PzemAcCommand(void)
{
bool serviced = true;
if (CMND_MODULEADDRESS == Energy.command_code) {
if (CMND_MODULEADDRESS == Energy->command_code) {
PzemAc.address = XdrvMailbox.payload; // Valid addresses are 1, 2 and 3
PzemAc.address_step = ADDR_SEND;
}

View File

@ -64,18 +64,18 @@ void PzemDcEverySecond(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("PDC: PzemDc %d error %d"), PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, error);
} else {
Energy.data_valid[PzemDc.channel] = 0;
Energy->data_valid[PzemDc.channel] = 0;
if (8 == registers) {
// 0 1 2 3 4 5 6 7 = ModBus register
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 = Buffer index
// 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29
// Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc--
Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0f; // 655.00 V
Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0f; // 655.00 A
Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0f; // 429496729.0 W
Energy.import_active[PzemDc.channel] = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]) / 1000.0f; // 4294967.295 kWh
if (PzemDc.channel == Energy.phase_count -1) {
Energy->voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0f; // 655.00 V
Energy->current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0f; // 655.00 A
Energy->active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0f; // 429496729.0 W
Energy->import_active[PzemDc.channel] = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]) / 1000.0f; // 4294967.295 kWh
if (PzemDc.channel == Energy->phase_count -1) {
if (TasmotaGlobal.uptime > PZEM_DC_STABILIZE) {
EnergyUpdateTotal();
}
@ -86,7 +86,7 @@ void PzemDcEverySecond(void)
if (0 == PzemDc.send_retry || data_ready) {
if (0 == PzemDc.channel) {
PzemDc.channel = Energy.phase_count -1;
PzemDc.channel = Energy->phase_count -1;
} else {
PzemDc.channel--;
}
@ -100,8 +100,8 @@ void PzemDcEverySecond(void)
}
else {
PzemDc.send_retry--;
if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (TasmotaGlobal.uptime < PZEM_DC_STABILIZE)) {
Energy.phase_count--; // Decrement channels if no response after retry within 30 seconds after restart
if ((Energy->phase_count > 1) && (0 == PzemDc.send_retry) && (TasmotaGlobal.uptime < PZEM_DC_STABILIZE)) {
Energy->phase_count--; // Decrement channels if no response after retry within 30 seconds after restart
if (TasmotaGlobal.discovery_counter) {
TasmotaGlobal.discovery_counter += ENERGY_WATCHDOG + 1; // Don't send Discovery yet, delay by 4s + 1s
}
@ -115,8 +115,8 @@ void PzemDcSnsInit(void)
uint8_t result = PzemDcModbus->Begin(9600, SERIAL_8N2);
if (result) {
if (2 == result) { ClaimSerial(); }
Energy.type_dc = true;
Energy.phase_count = ENERGY_MAX_PHASES; // Start off with three channels
Energy->type_dc = true;
Energy->phase_count = ENERGY_MAX_PHASES; // Start off with three channels
PzemDc.channel = 0;
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
@ -134,7 +134,7 @@ bool PzemDcCommand(void)
{
bool serviced = true;
if (CMND_MODULEADDRESS == Energy.command_code) {
if (CMND_MODULEADDRESS == Energy->command_code) {
PzemDc.address = XdrvMailbox.payload; // Valid addresses are 1, 2 and 3
PzemDc.address_step = ADDR_SEND;
}

View File

@ -460,7 +460,7 @@ void Ade7953GetData(void) {
#endif // USE_ESP32_SPI
#ifdef USE_ESP32_SPI
if (1 == Energy.phase_count) {
if (1 == Energy->phase_count) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: ACCMODE 0x%06X, VRMS %d, Period %d, IRMS %d, WATT %d, VA %d, VAR %d"),
acc_mode, reg[0][4], reg[0][5], reg[0][0], reg[0][1], reg[0][2], reg[0][3]);
} else
@ -475,7 +475,7 @@ void Ade7953GetData(void) {
uint32_t apparent_power[2] = { 0, 0 };
uint32_t reactive_power[2] = { 0, 0 };
for (uint32_t channel = 0; channel < Energy.phase_count; channel++) {
for (uint32_t channel = 0; channel < Energy->phase_count; channel++) {
Ade7953.voltage_rms[channel] = reg[channel][4];
Ade7953.current_rms[channel] = reg[channel][0];
if (Ade7953.current_rms[channel] < 2000) { // No load threshold (20mA)
@ -491,10 +491,10 @@ void Ade7953GetData(void) {
}
}
if (Energy.power_on) { // Powered on
if (Energy->power_on) { // Powered on
float divider;
for (uint32_t channel = 0; channel < Energy.phase_count; channel++) {
Energy.data_valid[channel] = 0;
for (uint32_t channel = 0; channel < Energy->phase_count; channel++) {
Energy->data_valid[channel] = 0;
float power_calibration = (float)EnergyGetCalibration(channel, ENERGY_POWER_CALIBRATION) / 10;
#ifdef ADE7953_ACCU_ENERGY
@ -503,29 +503,29 @@ void Ade7953GetData(void) {
float voltage_calibration = (float)EnergyGetCalibration(channel, ENERGY_VOLTAGE_CALIBRATION);
float current_calibration = (float)EnergyGetCalibration(channel, ENERGY_CURRENT_CALIBRATION) * 10;
Energy.frequency[channel] = 223750.0f / ((float)reg[channel][5] + 1);
Energy->frequency[channel] = 223750.0f / ((float)reg[channel][5] + 1);
divider = (Ade7953.calib_data[channel][ADE7953_CAL_VGAIN] != ADE7953_GAIN_DEFAULT) ? 10000 : voltage_calibration;
Energy.voltage[channel] = (float)Ade7953.voltage_rms[channel] / divider;
Energy->voltage[channel] = (float)Ade7953.voltage_rms[channel] / divider;
divider = (Ade7953.calib_data[channel][ADE7953_CAL_WGAIN + channel] != ADE7953_GAIN_DEFAULT) ? ADE7953_LSB_PER_WATTSECOND : power_calibration;
Energy.active_power[channel] = (float)Ade7953.active_power[channel] / divider;
Energy->active_power[channel] = (float)Ade7953.active_power[channel] / divider;
divider = (Ade7953.calib_data[channel][ADE7953_CAL_VARGAIN + channel] != ADE7953_GAIN_DEFAULT) ? ADE7953_LSB_PER_WATTSECOND : power_calibration;
Energy.reactive_power[channel] = (float)reactive_power[channel] / divider;
Energy->reactive_power[channel] = (float)reactive_power[channel] / divider;
if (ADE7953_SHELLY_EM == Ade7953.model) {
if (bitRead(acc_mode, 10 +channel)) { // APSIGN
Energy.active_power[channel] *= -1;
Energy->active_power[channel] *= -1;
}
if (bitRead(acc_mode, 12 +channel)) { // VARSIGN
Energy.reactive_power[channel] *= -1;
Energy->reactive_power[channel] *= -1;
}
}
divider = (Ade7953.calib_data[channel][ADE7953_CAL_VAGAIN + channel] != ADE7953_GAIN_DEFAULT) ? ADE7953_LSB_PER_WATTSECOND : power_calibration;
Energy.apparent_power[channel] = (float)apparent_power[channel] / divider;
if (0 == Energy.active_power[channel]) {
Energy.current[channel] = 0;
Energy->apparent_power[channel] = (float)apparent_power[channel] / divider;
if (0 == Energy->active_power[channel]) {
Energy->current[channel] = 0;
} else {
divider = (Ade7953.calib_data[channel][ADE7953_CAL_IGAIN + channel] != ADE7953_GAIN_DEFAULT) ? 100000 : current_calibration;
Energy.current[channel] = (float)Ade7953.current_rms[channel] / divider;
Energy.kWhtoday_delta[channel] += Energy.active_power[channel] * 1000 / 36;
Energy->current[channel] = (float)Ade7953.current_rms[channel] / divider;
Energy->kWhtoday_delta[channel] += Energy->active_power[channel] * 1000 / 36;
}
}
EnergyUpdateToday();
@ -719,22 +719,22 @@ void Ade7953DrvInit(void) {
Ade7953.init_step = 3;
// Energy.phase_count = 1;
// Energy.voltage_common = false;
// Energy.frequency_common = false;
// Energy.use_overtemp = false;
// Energy->phase_count = 1;
// Energy->voltage_common = false;
// Energy->frequency_common = false;
// Energy->use_overtemp = false;
if (ADE7953_SHELLY_PRO_1PM == Ade7953.model) {
} else {
Energy.phase_count = 2; // Handle two channels as two phases
Energy->phase_count = 2; // Handle two channels as two phases
if (ADE7953_SHELLY_PRO_2PM == Ade7953.model) {
} else {
Energy.voltage_common = true; // Use common voltage
Energy.frequency_common = true; // Use common frequency
Energy->voltage_common = true; // Use common voltage
Energy->frequency_common = true; // Use common frequency
}
}
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy->use_overtemp = true; // Use global temperature for overtemp detection
if (ADE7953_SHELLY_EM == Ade7953.model) {
Energy.local_energy_active_export = true;
Energy->local_energy_active_export = true;
}
TasmotaGlobal.energy_driver = XNRG_07;
}
@ -746,19 +746,19 @@ bool Ade7953Command(void) {
uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0;
uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); // 1.23 = 123
if (CMND_POWERCAL == Energy.command_code) {
if (CMND_POWERCAL == Energy->command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; }
// Service in xdrv_03_energy.ino
}
else if (CMND_VOLTAGECAL == Energy.command_code) {
else if (CMND_VOLTAGECAL == Energy->command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; }
// Service in xdrv_03_energy.ino
}
else if (CMND_CURRENTCAL == Energy.command_code) {
else if (CMND_CURRENTCAL == Energy->command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; }
// Service in xdrv_03_energy.ino
}
else if (CMND_POWERSET == Energy.command_code) {
else if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len && Ade7953.active_power[channel]) {
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
#ifdef ADE7953_ACCU_ENERGY
@ -771,14 +771,14 @@ bool Ade7953Command(void) {
}
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len && Ade7953.voltage_rms[channel]) {
if ((value > 10000) && (value < 26000)) { // Between 100V and 260V
XdrvMailbox.payload = (Ade7953.voltage_rms[channel] * 100) / value; // 0.00 V
}
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) {
if ((value > 2000) && (value < 1000000)) { // Between 20mA and 10A
XdrvMailbox.payload = ((Ade7953.current_rms[channel] * 100) / value) * 100; // 0.00 mA

View File

@ -85,7 +85,7 @@ void SDM120Every250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
// 0 1 2 3 4 5 6 7 8
// SA FC BC Fh Fl Sh Sl Cl Ch
@ -98,31 +98,31 @@ void SDM120Every250ms(void)
switch(Sdm120.read_state) {
case 0:
Energy.voltage[0] = value; // 230.2 V
Energy->voltage[0] = value; // 230.2 V
break;
case 1:
Energy.current[0] = value; // 1.260 A
Energy->current[0] = value; // 1.260 A
break;
case 2:
Energy.active_power[0] = value; // -196.3 W
Energy->active_power[0] = value; // -196.3 W
break;
case 3:
Energy.apparent_power[0] = value; // 223.4 VA
Energy->apparent_power[0] = value; // 223.4 VA
break;
case 4:
Energy.reactive_power[0] = value; // 92.2
Energy->reactive_power[0] = value; // 92.2
break;
case 5:
Energy.power_factor[0] = value; // -0.91
Energy->power_factor[0] = value; // -0.91
break;
case 6:
Energy.frequency[0] = value; // 50.0 Hz
Energy->frequency[0] = value; // 50.0 Hz
break;
case 7:
@ -134,7 +134,7 @@ void SDM120Every250ms(void)
break;
case 9:
Energy.export_active[0] = value; // 6.216 kWh
Energy->export_active[0] = value; // 6.216 kWh
break;
case 10:
@ -161,7 +161,7 @@ void SDM120Every250ms(void)
Sdm120.start_address_count = sdm120_table; // No extended registers available
}
}
Energy.import_active[0] = Sdm120.total_active; // 484.708 kWh
Energy->import_active[0] = Sdm120.total_active; // 484.708 kWh
EnergyUpdateTotal(); // 484.708 kWh
}
}

View File

@ -52,7 +52,7 @@ void Dds2382EverySecond(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "DDS2382 response error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
// 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 = ModBus register
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 = Buffer index
@ -64,18 +64,18 @@ void Dds2382EverySecond(void)
// {"TotalStartTime":"2020-01-08T09:43:05","Total":0.060,"Yesterday":0.001,"Today":0.001,"ExportActive":12.670,"Period":0,"Power":1016,"ApparentPower":1020,"ReactivePower":112,"Factor":0.99,"Frequency":50,"Voltage":242,"Current":4.210}}
// {"TotalStartTime":"2020-01-08T00:00:00","Total":0.061,"Yesterday":0.001,"Today":0.001,"ExportActive":12.670,"Period":0.020,"Power":1199.000,"ApparentPower":1204.231,"ReactivePower":108.000,"Factor":1.00,"Frequency":49.98,"Voltage":242.3,"Current":4.970}}
Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0f;
Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0f;
Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]);
Energy.reactive_power[0] = (float)(int16_t)((buffer[33] << 8) + buffer[34]);
Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0f; // 1.00
Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0f; // 50.0 Hz
Energy->voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0f;
Energy->current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0f;
Energy->active_power[0] = (float)((buffer[31] << 8) + buffer[32]);
Energy->reactive_power[0] = (float)(int16_t)((buffer[33] << 8) + buffer[34]);
Energy->power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0f; // 1.00
Energy->frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0f; // 50.0 Hz
uint8_t offset = 11;
if (Settings->flag3.dds2382_model) { // SetOption71 - Select different Modbus registers for Active Energy (#6531)
offset = 19;
}
Energy.export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0f; // 429496.729 kW
Energy.import_active[0] = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0f; // 429496.729 kW
Energy->export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0f; // 429496.729 kW
Energy->import_active[0] = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0f; // 429496.729 kW
EnergyUpdateTotal(); // 484.708 kWh
}
} // end data ready

View File

@ -88,9 +88,9 @@ void SDM630Every250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy.data_valid[1] = 0;
Energy.data_valid[2] = 0;
Energy->data_valid[0] = 0;
Energy->data_valid[1] = 0;
Energy->data_valid[2] = 0;
// 0 1 2 3 4 5 6 7 8
// SA FC BC Fh Fl Sh Sl Cl Ch
@ -103,95 +103,95 @@ void SDM630Every250ms(void)
switch(Sdm630.read_state) {
case 0:
Energy.voltage[0] = value;
Energy->voltage[0] = value;
break;
case 1:
Energy.voltage[1] = value;
Energy->voltage[1] = value;
break;
case 2:
Energy.voltage[2] = value;
Energy->voltage[2] = value;
break;
case 3:
Energy.current[0] = value;
Energy->current[0] = value;
break;
case 4:
Energy.current[1] = value;
Energy->current[1] = value;
break;
case 5:
Energy.current[2] = value;
Energy->current[2] = value;
break;
case 6:
Energy.active_power[0] = value;
Energy->active_power[0] = value;
break;
case 7:
Energy.active_power[1] = value;
Energy->active_power[1] = value;
break;
case 8:
Energy.active_power[2] = value;
Energy->active_power[2] = value;
break;
case 9:
Energy.reactive_power[0] = value;
Energy->reactive_power[0] = value;
break;
case 10:
Energy.reactive_power[1] = value;
Energy->reactive_power[1] = value;
break;
case 11:
Energy.reactive_power[2] = value;
Energy->reactive_power[2] = value;
break;
case 12:
Energy.power_factor[0] = value;
Energy->power_factor[0] = value;
break;
case 13:
Energy.power_factor[1] = value;
Energy->power_factor[1] = value;
break;
case 14:
Energy.power_factor[2] = value;
Energy->power_factor[2] = value;
break;
case 15:
Energy.frequency[0] = value;
Energy->frequency[0] = value;
break;
case 16:
Energy.export_active[0] = value;
Energy->export_active[0] = value;
break;
case 17:
Energy.export_active[1] = value;
Energy->export_active[1] = value;
break;
case 18:
Energy.export_active[2] = value;
Energy->export_active[2] = value;
break;
case 19:
Energy.import_active[0] = value;
Energy->import_active[0] = value;
break;
case 20:
Energy.import_active[1] = value;
Energy->import_active[1] = value;
break;
case 21:
Energy.import_active[2] = value;
Energy->import_active[2] = value;
break;
case 22:
// Energy.import_active[0] = value;
// Energy->import_active[0] = value;
EnergyUpdateTotal();
break;
}
@ -217,8 +217,8 @@ void Sdm630SnsInit(void)
uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED);
if (result) {
if (2 == result) { ClaimSerial(); }
Energy.phase_count = 3;
Energy.frequency_common = true; // Use common frequency
Energy->phase_count = 3;
Energy->frequency_common = true; // Use common frequency
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
}

View File

@ -68,7 +68,7 @@ void DDSU666Every250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("SDM: Ddsu666 error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
// 0 1 2 3 4 5 6 7 8
// SA FC BC Fh Fl Sh Sl Cl Ch
@ -81,35 +81,35 @@ void DDSU666Every250ms(void)
switch(Ddsu666.read_state) {
case 0:
Energy.voltage[0] = value; // 230.2 V
Energy->voltage[0] = value; // 230.2 V
break;
case 1:
Energy.current[0] = value; // 1.260 A
Energy->current[0] = value; // 1.260 A
break;
case 2:
Energy.active_power[0] = value * 1000; // -196.3 W
Energy->active_power[0] = value * 1000; // -196.3 W
break;
case 3:
Energy.reactive_power[0] = value * 1000; // 92.2
Energy->reactive_power[0] = value * 1000; // 92.2
break;
case 4:
Energy.power_factor[0] = value; // 0.91
Energy->power_factor[0] = value; // 0.91
break;
case 5:
Energy.frequency[0] = value; // 50.0 Hz
Energy->frequency[0] = value; // 50.0 Hz
break;
case 6:
Energy.import_active[0] = value; // 478.492 kWh
Energy->import_active[0] = value; // 478.492 kWh
break;
case 7:
Energy.export_active[0] = value; // 6.216 kWh
Energy->export_active[0] = value; // 6.216 kWh
break;
}

View File

@ -284,19 +284,19 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds
}
if (DataRead[6] == 0x11 && DataRead[7] == 0x82) { // received "Response for query (live data)"
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
solaxX1.temperature = (DataRead[9] << 8) | DataRead[10]; // Temperature
solaxX1.energy_today = ((DataRead[11] << 8) | DataRead[12]) * 0.1f; // Energy Today
solaxX1.dc1_voltage = ((DataRead[13] << 8) | DataRead[14]) * 0.1f; // PV1 Voltage
solaxX1.dc2_voltage = ((DataRead[15] << 8) | DataRead[16]) * 0.1f; // PV2 Voltage
solaxX1.dc1_current = ((DataRead[17] << 8) | DataRead[18]) * 0.1f; // PV1 Current
solaxX1.dc2_current = ((DataRead[19] << 8) | DataRead[20]) * 0.1f; // PV2 Current
Energy.current[0] = ((DataRead[21] << 8) | DataRead[22]) * 0.1f; // AC Current
Energy.voltage[0] = ((DataRead[23] << 8) | DataRead[24]) * 0.1f; // AC Voltage
Energy.frequency[0] = ((DataRead[25] << 8) | DataRead[26]) * 0.01f; // AC Frequency
Energy.active_power[0] = ((DataRead[27] << 8) | DataRead[28]); // AC Power
Energy->current[0] = ((DataRead[21] << 8) | DataRead[22]) * 0.1f; // AC Current
Energy->voltage[0] = ((DataRead[23] << 8) | DataRead[24]) * 0.1f; // AC Voltage
Energy->frequency[0] = ((DataRead[25] << 8) | DataRead[26]) * 0.01f; // AC Frequency
Energy->active_power[0] = ((DataRead[27] << 8) | DataRead[28]); // AC Power
//temporal = (float)((DataRead[29] << 8) | DataRead[30]) * 0.1f; // Not Used
Energy.import_active[0] = ((DataRead[31] << 24) | (DataRead[32] << 16) | (DataRead[33] << 8) | DataRead[34]) * 0.1f; // Energy Total
Energy->import_active[0] = ((DataRead[31] << 24) | (DataRead[32] << 16) | (DataRead[33] << 8) | DataRead[34]) * 0.1f; // Energy Total
solaxX1.runtime_total = (DataRead[35] << 24) | (DataRead[36] << 16) | (DataRead[37] << 8) | DataRead[38]; // Work Time Total
solaxX1.runMode = (DataRead[39] << 8) | DataRead[40]; // Work mode
//temporal = (float)((DataRead[41] << 8) | DataRead[42]); // Grid voltage fault value 0.1V
@ -444,9 +444,9 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds
if (!solaxX1_global.SendRetry_count) { // Inverter went "off"
solaxX1_global.SendRetry_count = 20;
DEBUG_SENSOR_LOG(PSTR("SX1: Inverter went \"off\""));
Energy.data_valid[0] = ENERGY_WATCHDOG;
Energy->data_valid[0] = ENERGY_WATCHDOG;
solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0;
solaxX1.dc2_power = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0;
solaxX1.dc2_power = Energy->current[0] = Energy->voltage[0] = Energy->frequency[0] = Energy->active_power[0] = 0;
solaxX1.runMode = -1; // off(line)
solaxX1_global.AddressAssigned = false;
} // end Inverter went "off"

View File

@ -125,7 +125,7 @@ void FifLEEvery250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
// CA=Client Address, FC=Function Code, BC=Byte Count, B3..B0=Data byte, Ch Cl = crc16 checksum
// U32 registers:
@ -153,36 +153,36 @@ void FifLEEvery250ms(void)
switch(Le01mr.read_state) {
case 0:
Energy.frequency[0] = value_buff * 0.01f; // 5000 => 50.00
Energy->frequency[0] = value_buff * 0.01f; // 5000 => 50.00
break;
case 1:
Energy.voltage[0] = value_buff * 0.01f; // 23298 => 232.98 V
Energy->voltage[0] = value_buff * 0.01f; // 23298 => 232.98 V
break;
case 2:
Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; // 1000 => 1.000 //note: I never saw this negative...
Energy->power_factor[0] = ((int16_t)value_buff) * 0.001f; // 1000 => 1.000 //note: I never saw this negative...
break;
case 3:
Energy.current[0] = value_buff * 0.001f; // 114 => 0.114 A
Energy->current[0] = value_buff * 0.001f; // 114 => 0.114 A
break;
case 4:
Energy.active_power[0] = value_buff * 1.0f; // P [W]
Energy->active_power[0] = value_buff * 1.0f; // P [W]
break;
case 5:
Energy.reactive_power[0] = value_buff * 1.0f; // Q [var]
Energy->reactive_power[0] = value_buff * 1.0f; // Q [var]
break;
case 6:
Energy.apparent_power[0] = value_buff * 1.0f; // S [VA]
Energy->apparent_power[0] = value_buff * 1.0f; // S [VA]
break;
case 7:
Energy.import_active[0] = value_buff * 0.01f; // [kWh]
Le01mr.total_active = Energy.import_active[0]; // Useless
Energy->import_active[0] = value_buff * 0.01f; // [kWh]
Le01mr.total_active = Energy->import_active[0]; // Useless
break;
case 8:

View File

@ -131,7 +131,7 @@ bool Bl09XXDecode3940(void) {
Bl09XX.power[0] = Bl09XX.rx_buffer[18] << 16 | Bl09XX.rx_buffer[17] << 8 | Bl09XX.rx_buffer[16]; // WATT_A signed
if (bitRead(Bl09XX.power[0], 23)) { Bl09XX.power[0] |= 0xFF000000; } // Extend sign bit
if (Energy.phase_count > 1) {
if (Energy->phase_count > 1) {
Bl09XX.current[1] = Bl09XX.rx_buffer[9] << 16 | Bl09XX.rx_buffer[8] << 8 | Bl09XX.rx_buffer[7]; // IB_RMS unsigned
Bl09XX.power[1] = Bl09XX.rx_buffer[21] << 16 | Bl09XX.rx_buffer[20] << 8 | Bl09XX.rx_buffer[19]; // WATT_B signed
if (bitRead(Bl09XX.power[1], 23)) { Bl09XX.power[1] |= 0xFF000000; } // Extend sign bit
@ -187,29 +187,29 @@ bool Bl09XXDecode42(void) {
}
void Bl09XXUpdateEnergy() {
if (Energy.power_on) { // Powered on
Energy.voltage[0] = (float)Bl09XX.voltage / Settings->energy_voltage_calibration;
if (Energy->power_on) { // Powered on
Energy->voltage[0] = (float)Bl09XX.voltage / Settings->energy_voltage_calibration;
#ifdef DEBUG_BL09XX
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %2_f, T %2_f"), &Energy.voltage[0], &Bl09XX.temperature);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %2_f, T %2_f"), &Energy->voltage[0], &Bl09XX.temperature);
#endif
for (uint32_t chan = 0; chan < Energy.phase_count; chan++) {
for (uint32_t chan = 0; chan < Energy->phase_count; chan++) {
uint32_t power_calibration = EnergyGetCalibration(chan, ENERGY_POWER_CALIBRATION);
uint32_t current_calibration = EnergyGetCalibration(chan, ENERGY_CURRENT_CALIBRATION);
if (Bl09XX.power[chan] > power_calibration) { // We need at least 1W
Energy.active_power[chan] = (float)Bl09XX.power[chan] / power_calibration;
Energy.current[chan] = (float)Bl09XX.current[chan] / current_calibration;
Energy->active_power[chan] = (float)Bl09XX.power[chan] / power_calibration;
Energy->current[chan] = (float)Bl09XX.current[chan] / current_calibration;
} else {
Energy.active_power[chan] = 0;
Energy.current[chan] = 0;
Energy->active_power[chan] = 0;
Energy->current[chan] = 0;
}
#ifdef DEBUG_BL09XX
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: Chan[%d] I %2_f, P %2_f"), chan, &Energy.current[chan], &Energy.active_power[chan]);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: Chan[%d] I %2_f, P %2_f"), chan, &Energy->current[chan], &Energy->active_power[chan]);
#endif
}
} else { // Powered off
Energy.voltage[0] = 0;
Energy.active_power[0] = Energy.active_power[1] = 0;
Energy.current[0] = Energy.current[1] = 0;
Energy->voltage[0] = 0;
Energy->active_power[0] = Energy->active_power[1] = 0;
Energy->current[0] = Energy->current[1] = 0;
}
}
@ -229,7 +229,7 @@ void Bl09XXSerialInput(void) {
for (uint32_t i = 0; i < Bl09XX.buffer_size -1; i++) { checksum += Bl09XX.rx_buffer[i]; }
checksum ^= 0xFF;
if (checksum == Bl09XX.rx_buffer[Bl09XX.buffer_size -1]) {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
bool ok;
if (BL0942_MODEL == Bl09XX.model) {
ok = Bl09XXDecode42();
@ -261,14 +261,14 @@ void Bl09XXSerialInput(void) {
/********************************************************************************************/
void Bl09XXEverySecond(void) {
if (Energy.data_valid[0] > ENERGY_WATCHDOG) {
if (Energy->data_valid[0] > ENERGY_WATCHDOG) {
Bl09XX.voltage = 0;
memset(Bl09XX.current, 0, sizeof(Bl09XX.current));
memset(Bl09XX.power, 0, sizeof(Bl09XX.power));
} else {
// Calculate energy by using active power
for (uint32_t channel = 0; channel < Energy.phase_count; channel++) {
Energy.kWhtoday_delta[channel] += Energy.active_power[channel] * 1000 / 36;
for (uint32_t channel = 0; channel < Energy->phase_count; channel++) {
Energy->kWhtoday_delta[channel] += Energy->active_power[channel] * 1000 / 36;
}
EnergyUpdateToday();
}
@ -303,7 +303,7 @@ void Bl09XXInit(void) {
#ifdef DEBUG_BL09XX
AddLog(LOG_LEVEL_DEBUG, PSTR("BL9: Send Init string"));
#endif
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy->use_overtemp = true; // Use global temperature for overtemp detection
for (uint32_t i = 0; i < 5; i++) {
uint8_t crc, byte;
crc = byte = BL09XX_WRITE_COMMAND | Bl09XX.address;
@ -316,7 +316,7 @@ void Bl09XXInit(void) {
delay(1);
}
} else {
Energy.use_overtemp = false; // Use global temperature for overtemp detection
Energy->use_overtemp = false; // Use global temperature for overtemp detection
}
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
@ -343,10 +343,10 @@ void Bl09XXPreInit(void) {
Bl09XX.buffer_size = bl09xx_buffer_size[Bl09XX.model];
Bl09XX.rx_buffer = (uint8_t*)(malloc(Bl09XX.buffer_size));
if (Bl09XX.rx_buffer != nullptr) {
Energy.voltage_common = true; // Use common voltage
Energy.frequency_common = true; // Use common frequency
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy.phase_count = bl09xx_phase_count[Bl09XX.model]; // Handle two channels as two phases
Energy->voltage_common = true; // Use common voltage
Energy->frequency_common = true; // Use common frequency
Energy->use_overtemp = true; // Use global temperature for overtemp detection
Energy->phase_count = bl09xx_phase_count[Bl09XX.model]; // Handle two channels as two phases
TasmotaGlobal.energy_driver = XNRG_14;
AddLog(LOG_LEVEL_DEBUG,PSTR("BL9: Enabling BL09%02d"), bl09xx_type[Bl09XX.model]);
}
@ -357,20 +357,20 @@ void Bl09XXPreInit(void) {
bool Bl09XXCommand(void) {
bool serviced = true;
uint32_t channel = (2 == XdrvMailbox.index) && (Energy.phase_count > 1) ? 1 : 0;
uint32_t channel = (2 == XdrvMailbox.index) && (Energy->phase_count > 1) ? 1 : 0;
uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); // 1.23 = 123
if (CMND_POWERSET == Energy.command_code) {
if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len && Bl09XX.power[channel]) {
XdrvMailbox.payload = (Bl09XX.power[channel] * 100) / value;
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len && Bl09XX.voltage) {
XdrvMailbox.payload = (Bl09XX.voltage * 100) / value;
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len && Bl09XX.current[channel]) {
XdrvMailbox.payload = (Bl09XX.current[channel] * 100) / value;
}

View File

@ -285,16 +285,16 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
// Voltage V (not present on all Smart Meter)
if ( ilabel == LABEL_TENSION || ilabel == LABEL_URMS1 || ilabel == LABEL_URMS2 || ilabel == LABEL_URMS3)
{
Energy.voltage_available = true;
Energy->voltage_available = true;
float volt = (float) atoi(me->value);
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Voltage %s=%s, now %d"), me->name, me->value, (int) volt);
if ( ilabel == LABEL_URMS2) {
Energy.voltage[1] = volt;
Energy->voltage[1] = volt;
} else if ( ilabel == LABEL_URMS3) {
Energy.voltage[2] = volt;
Energy->voltage[2] = volt;
} else {
Energy.voltage[0] = volt;
Energy->voltage[0] = volt;
}
}
@ -304,25 +304,25 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
|| ilabel == LABEL_IINST2 || ilabel == LABEL_IRMS2
|| ilabel == LABEL_IINST3 || ilabel == LABEL_IRMS3 )
{
Energy.current_available = true;
Energy->current_available = true;
float current = (float) atoi(me->value);
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Current %s=%s, now %d"), me->name, me->value, (int) current);
if (ilabel == LABEL_IINST2 || ilabel == LABEL_IRMS2) {
Energy.current[1] = current;
Energy->current[1] = current;
} else if (ilabel == LABEL_IINST3 || ilabel == LABEL_IRMS3) {
Energy.phase_count = 3;
Energy.current[2] = current;
Energy->phase_count = 3;
Energy->current[2] = current;
} else {
Energy.current[0] = current;
Energy->current[0] = current;
}
}
// Power P
else if (ilabel == LABEL_PAPP || ilabel == LABEL_SINSTS)
{
Energy.active_power[0] = (float) atoi(me->value);;
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, (int) Energy.active_power[0]);
Energy->active_power[0] = (float) atoi(me->value);;
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Power %s, now %d"), me->value, (int) Energy->active_power[0]);
}
// Ok now not so real time values Does this value is new or changed?
@ -394,11 +394,11 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
AddLog (LOG_LEVEL_INFO, PSTR ("TIC: Total counter updated to %ld Wh"), total_wh);
if (total_wh>0) {
Energy.total[0] = (float) total_wh / 1000.0f;
Energy.import_active[0] = Energy.total[0];
//Energy.import_active[0] = (float)total/1000.0f;
Energy->total[0] = (float) total_wh / 1000.0f;
Energy->import_active[0] = Energy->total[0];
//Energy->import_active[0] = (float)total/1000.0f;
//EnergyUpdateTotal();
AddLog (LOG_LEVEL_DEBUG_MORE, PSTR ("TIC: import_active[0]=%.3fKWh"), Energy.import_active[0] );
AddLog (LOG_LEVEL_DEBUG_MORE, PSTR ("TIC: import_active[0]=%.3fKWh"), Energy->import_active[0] );
}
}
@ -406,8 +406,8 @@ void DataCallback(struct _ValueList * me, uint8_t flags)
else if ( ilabel == LABEL_EAST)
{
total_wh = atol(me->value);
Energy.total[0] = (float) total_wh / 1000.0f;
Energy.import_active[0] = Energy.total[0];
Energy->total[0] = (float) total_wh / 1000.0f;
Energy->import_active[0] = Energy->total[0];
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%ldWh"), total_wh);
}
@ -591,7 +591,7 @@ Comments: -
void NewFrameCallback(struct _ValueList * me)
{
// Reset Energy Watchdog
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
// Deprecated see setOption108
// send teleinfo MQTT raw data only if setup like that
@ -631,8 +631,8 @@ void TInfoDrvInit(void) {
if (PinUsed(GPIO_TELEINFO_RX)) {
tic_rx_pin = Pin(GPIO_TELEINFO_RX);
TasmotaGlobal.energy_driver = XNRG_15;
Energy.voltage_available = false;
Energy.phase_count = 1;
Energy->voltage_available = false;
Energy->phase_count = 1;
// init hardware energy counters
total_wh = 0;
Settings->flag3.hardware_energy_total = true;
@ -763,7 +763,7 @@ bool TInfoCmd(void) {
//uint8_t name_len = strlen(D_NAME_TELEINFO);
// At least "EnergyConfig"
if (CMND_ENERGYCONFIG == Energy.command_code) {
if (CMND_ENERGYCONFIG == Energy->command_code) {
AddLog(LOG_LEVEL_DEBUG, PSTR("TIC: len %d, data '%s'"), XdrvMailbox.data_len, XdrvMailbox.data ? XdrvMailbox.data : "null" );
@ -1106,7 +1106,7 @@ void TInfoShow(bool json)
{
// Add new value (not part of TIC JSON Object)
if (isousc) {
ResponseAppend_P(PSTR(",\"Load\":%d"),(int) ((Energy.current[0]*100.0f) / isousc));
ResponseAppend_P(PSTR(",\"Load\":%d"),(int) ((Energy->current[0]*100.0f) / isousc));
}
// add teleinfo TIC object
@ -1126,8 +1126,8 @@ void TInfoShow(bool json)
uint8_t red, green, blue;
char phase_color[8];
for (int i=0; i<Energy.phase_count ; i++ ) {
percent = (int) ((Energy.current[i]*100.0f) / isousc) ;
for (int i=0; i<Energy->phase_count ; i++ ) {
percent = (int) ((Energy->current[i]*100.0f) / isousc) ;
if (percent > 100) {
percent = 100;
}
@ -1150,7 +1150,7 @@ void TInfoShow(bool json)
}
if (tinfo_mode==TINFO_MODE_HISTORIQUE ) {
if (Energy.phase_count==3) {
if (Energy->phase_count==3) {
int imax[3];
for (int i=LABEL_IMAX1; i<=LABEL_IMAX3; i++) {
if (getValueFromLabelIndex(i, value) ) {
@ -1177,7 +1177,7 @@ void TInfoShow(bool json)
}
}
if (contrat && isousc) {
int percent = (int) ((Energy.current[0]*100.0f) / isousc) ;
int percent = (int) ((Energy->current[0]*100.0f) / isousc) ;
GetTextIndexed(name, sizeof(name), contrat, kContratName);
WSContentSend_P(HTTP_ENERGY_CONTRAT_TELEINFO, name, isousc);
//WSContentSend_P(HTTP_ENERGY_LOAD_TELEINFO, percent);

View File

@ -83,7 +83,7 @@ void IEM3000Every250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("SDM: Iem3000 error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
// 0 1 2 3 4 5 6 7 8
// SA FC BC Fh Fl Sh Sl Cl Ch
@ -108,55 +108,55 @@ void IEM3000Every250ms(void)
switch(Iem3000.read_state) {
case 0:
Energy.current[0] = value;
Energy->current[0] = value;
break;
case 1:
Energy.current[1] = value;
Energy->current[1] = value;
break;
case 2:
Energy.current[2] = value;
Energy->current[2] = value;
break;
case 3:
Energy.voltage[0] = value;
Energy->voltage[0] = value;
break;
case 4:
Energy.voltage[1] = value;
Energy->voltage[1] = value;
break;
case 5:
Energy.voltage[2] = value;
Energy->voltage[2] = value;
break;
case 6:
Energy.active_power[0] = value*1000;
Energy->active_power[0] = value*1000;
break;
case 7:
Energy.active_power[1] = value*1000;
Energy->active_power[1] = value*1000;
break;
case 8:
Energy.active_power[2] = value*1000;
Energy->active_power[2] = value*1000;
break;
case 9:
Energy.frequency[0] = value;
Energy->frequency[0] = value;
break;
case 10:
Energy.import_active[0] = value64/1000.0;
Energy->import_active[0] = value64/1000.0;
break;
case 11:
Energy.import_active[1] = value64/1000.0;
Energy->import_active[1] = value64/1000.0;
break;
case 12:
Energy.import_active[2] = value64/1000.0;
Energy->import_active[2] = value64/1000.0;
break;
case 13:
@ -185,8 +185,8 @@ void Iem3000SnsInit(void)
uint8_t result = Iem3000Modbus->Begin(IEM3000_SPEED);
if (result) {
if (2 == result) { ClaimSerial(); }
Energy.phase_count = 3;
Energy.frequency_common = true; // Use common frequency
Energy->phase_count = 3;
Energy->frequency_common = true; // Use common frequency
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
}

View File

@ -84,9 +84,9 @@ void WE517Every250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("ORNO: WE517 error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy.data_valid[1] = 0;
Energy.data_valid[2] = 0;
Energy->data_valid[0] = 0;
Energy->data_valid[1] = 0;
Energy->data_valid[2] = 0;
// 0 1 2 3 4 5 6 7 8
// SA FC BC Fh Fl Sh Sl Cl Ch
@ -99,71 +99,71 @@ void WE517Every250ms(void)
switch(We517.read_state) {
case 0:
Energy.voltage[0] = value;
Energy->voltage[0] = value;
break;
case 1:
Energy.voltage[1] = value;
Energy->voltage[1] = value;
break;
case 2:
Energy.voltage[2] = value;
Energy->voltage[2] = value;
break;
case 3:
Energy.current[0] = value;
Energy->current[0] = value;
break;
case 4:
Energy.current[1] = value;
Energy->current[1] = value;
break;
case 5:
Energy.current[2] = value;
Energy->current[2] = value;
break;
case 6:
Energy.active_power[0] = value * 1000;
Energy->active_power[0] = value * 1000;
break;
case 7:
Energy.active_power[1] = value * 1000;
Energy->active_power[1] = value * 1000;
break;
case 8:
Energy.active_power[2] = value * 1000;
Energy->active_power[2] = value * 1000;
break;
case 9:
Energy.reactive_power[0] = value;
Energy->reactive_power[0] = value;
break;
case 10:
Energy.reactive_power[1] = value;
Energy->reactive_power[1] = value;
break;
case 11:
Energy.reactive_power[2] = value;
Energy->reactive_power[2] = value;
break;
case 12:
Energy.power_factor[0] = value;
Energy->power_factor[0] = value;
break;
case 13:
Energy.power_factor[1] = value;
Energy->power_factor[1] = value;
break;
case 14:
Energy.power_factor[2] = value;
Energy->power_factor[2] = value;
break;
case 15:
Energy.frequency[0] = value;
Energy->frequency[0] = value;
break;
case 16:
Energy.import_active[0] = value;
Energy->import_active[0] = value;
EnergyUpdateTotal();
break;
}
@ -192,8 +192,8 @@ void We517SnsInit(void) {
Serial.begin(WE517_SPEED, SERIAL_8E1);
ClaimSerial();
}
Energy.phase_count = 3;
Energy.frequency_common = true; // Use common frequency
Energy->phase_count = 3;
Energy->frequency_common = true; // Use common frequency
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
}

View File

@ -76,7 +76,7 @@ void Sdm72Every250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("SDM: SDM72 error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
float value;
((uint8_t*)&value)[3] = buffer[3]; // Get float values
@ -86,7 +86,7 @@ void Sdm72Every250ms(void)
switch(Sdm72.read_state) {
case 0:
Energy.active_power[0] = value; // W
Energy->active_power[0] = value; // W
break;
case 1:
@ -103,18 +103,18 @@ void Sdm72Every250ms(void)
break;
case 4:
Energy.import_active[0] = value; // kWh
Energy->import_active[0] = value; // kWh
break;
case 5:
Energy.export_active[0] = value; // kWh
Energy->export_active[0] = value; // kWh
break;
#endif // SDM72_IMPEXP
}
++Sdm72.read_state %= nitems(sdm72_register);
if (0 == Sdm72.read_state && !isnan(Sdm72.total_active)) {
Energy.import_active[0] = Sdm72.total_active;
Energy->import_active[0] = Sdm72.total_active;
EnergyUpdateTotal();
}
}
@ -144,8 +144,8 @@ void Sdm72SnsInit(void)
void Sdm72DrvInit(void)
{
if (PinUsed(GPIO_SDM72_RX) && PinUsed(GPIO_SDM72_TX)) {
Energy.voltage_available = false;
Energy.current_available = false;
Energy->voltage_available = false;
Energy->current_available = false;
TasmotaGlobal.energy_driver = XNRG_18;
}
}

View File

@ -458,28 +458,28 @@ void Cse7761GetData(void) {
CSE7761Data.current_rms[0], CSE7761Data.current_rms[1],
CSE7761Data.active_power[0], CSE7761Data.active_power[1]);
if (Energy.power_on) { // Powered on
if (Energy->power_on) { // Powered on
// Voltage = RmsU * RmsUC * 10 / 0x400000
// Energy.voltage[0] = (float)(((uint64_t)CSE7761Data.voltage_rms * CSE7761Data.coefficient[RmsUC] * 10) >> 22) / 1000; // V
Energy.voltage[0] = ((float)CSE7761Data.voltage_rms / Settings->energy_voltage_calibration); // V
// Energy->voltage[0] = (float)(((uint64_t)CSE7761Data.voltage_rms * CSE7761Data.coefficient[RmsUC] * 10) >> 22) / 1000; // V
Energy->voltage[0] = ((float)CSE7761Data.voltage_rms / Settings->energy_voltage_calibration); // V
#ifdef CSE7761_FREQUENCY
Energy.frequency[0] = (CSE7761Data.frequency) ? ((float)Settings->energy_frequency_calibration / 8 / CSE7761Data.frequency) : 0; // Hz
Energy->frequency[0] = (CSE7761Data.frequency) ? ((float)Settings->energy_frequency_calibration / 8 / CSE7761Data.frequency) : 0; // Hz
#endif
for (uint32_t channel = 0; channel < 2; channel++) {
Energy.data_valid[channel] = 0;
Energy->data_valid[channel] = 0;
uint32_t power_calibration = EnergyGetCalibration(channel, ENERGY_POWER_CALIBRATION);
// Active power = PowerPA * PowerPAC * 1000 / 0x80000000
// Energy.active_power[channel] = (float)(((uint64_t)CSE7761Data.active_power[channel] * CSE7761Data.coefficient[PowerPAC + channel] * 1000) >> 31) / 1000; // W
Energy.active_power[channel] = (float)CSE7761Data.active_power[channel] / power_calibration; // W
if (0 == Energy.active_power[channel]) {
Energy.current[channel] = 0;
// Energy->active_power[channel] = (float)(((uint64_t)CSE7761Data.active_power[channel] * CSE7761Data.coefficient[PowerPAC + channel] * 1000) >> 31) / 1000; // W
Energy->active_power[channel] = (float)CSE7761Data.active_power[channel] / power_calibration; // W
if (0 == Energy->active_power[channel]) {
Energy->current[channel] = 0;
} else {
uint32_t current_calibration = EnergyGetCalibration(channel, ENERGY_CURRENT_CALIBRATION);
// Current = RmsIA * RmsIAC / 0x800000
// Energy.current[channel] = (float)(((uint64_t)CSE7761Data.current_rms[channel] * CSE7761Data.coefficient[RmsIAC + channel]) >> 23) / 1000; // A
Energy.current[channel] = (float)CSE7761Data.current_rms[channel] / current_calibration; // A
CSE7761Data.energy[channel] += Energy.active_power[channel];
// Energy->current[channel] = (float)(((uint64_t)CSE7761Data.current_rms[channel] * CSE7761Data.coefficient[RmsIAC + channel]) >> 23) / 1000; // A
Energy->current[channel] = (float)CSE7761Data.current_rms[channel] / current_calibration; // A
CSE7761Data.energy[channel] += Energy->active_power[channel];
CSE7761Data.energy_update[channel]++;
}
}
@ -563,7 +563,7 @@ void Cse7761EverySecond(void) {
if (2 == CSE7761Data.ready) {
for (uint32_t channel = 0; channel < 2; channel++) {
if (CSE7761Data.energy_update[channel]) {
Energy.kWhtoday_delta[channel] += ((CSE7761Data.energy[channel] * 1000) / CSE7761Data.energy_update[channel]) / 36;
Energy->kWhtoday_delta[channel] += ((CSE7761Data.energy[channel] * 1000) / CSE7761Data.energy_update[channel]) / 36;
CSE7761Data.energy[channel] = 0;
CSE7761Data.energy_update[channel] = 0;
}
@ -597,12 +597,12 @@ void Cse7761DrvInit(void) {
if (PinUsed(GPIO_CSE7761_RX) && PinUsed(GPIO_CSE7761_TX)) {
CSE7761Data.ready = 0;
CSE7761Data.init = 4; // Init setup steps
Energy.phase_count = 2; // Handle two channels as two phases
Energy.voltage_common = true; // Use common voltage
Energy->phase_count = 2; // Handle two channels as two phases
Energy->voltage_common = true; // Use common voltage
#ifdef CSE7761_FREQUENCY
Energy.frequency_common = true; // Use common frequency
Energy->frequency_common = true; // Use common frequency
#endif
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy->use_overtemp = true; // Use global temperature for overtemp detection
TasmotaGlobal.energy_driver = XNRG_19;
}
}
@ -613,33 +613,33 @@ bool Cse7761Command(void) {
uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0;
uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); // 1.23 = 123
if (CMND_POWERCAL == Energy.command_code) {
if (CMND_POWERCAL == Energy->command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = Cse7761Ref(PowerPAC); }
// Service in xdrv_03_energy.ino
}
else if (CMND_POWERSET == Energy.command_code) {
else if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len && CSE7761Data.active_power[channel]) {
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
XdrvMailbox.payload = ((CSE7761Data.active_power[channel]) / value) * 100;
}
}
}
else if (CMND_VOLTAGECAL == Energy.command_code) {
else if (CMND_VOLTAGECAL == Energy->command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = Cse7761Ref(RmsUC); }
// Service in xdrv_03_energy.ino
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len && CSE7761Data.voltage_rms) {
if ((value > 10000) && (value < 26000)) { // Between 100V and 260V
XdrvMailbox.payload = (CSE7761Data.voltage_rms * 100) / value;
}
}
}
else if (CMND_CURRENTCAL == Energy.command_code) {
else if (CMND_CURRENTCAL == Energy->command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = Cse7761Ref(RmsIAC); }
// Service in xdrv_03_energy.ino
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len && CSE7761Data.current_rms[channel]) {
if ((value > 1000) && (value < 1000000)) { // Between 10mA and 10A
XdrvMailbox.payload = ((CSE7761Data.current_rms[channel] * 100) / value) * 1000;
@ -647,11 +647,11 @@ bool Cse7761Command(void) {
}
}
#ifdef CSE7761_FREQUENCY
else if (CMND_FREQUENCYCAL == Energy.command_code) {
else if (CMND_FREQUENCYCAL == Energy->command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = CSE7761_FREF; }
// Service in xdrv_03_energy.ino
}
else if (CMND_FREQUENCYSET == Energy.command_code) {
else if (CMND_FREQUENCYSET == Energy->command_code) {
if (XdrvMailbox.data_len && CSE7761Data.frequency) {
if ((value > 4500) && (value < 6500)) { // Between 45.00Hz and 65.00Hz
XdrvMailbox.payload = (CSE7761Data.frequency * 8 * value) / 100;

View File

@ -58,7 +58,7 @@ const uint16_t sdm230_start_addresses[] {
0x0046, // SDM230_FREQUENCY [Hz]
0X0048, // SDM230_IMPORT_ACTIVE [kWh]
0X004A, // SDM230_EXPORT_ACTIVE [kWh]
// 0X0156, // SDM230_TOTAL_ENERGY_ACTIVE [kWh] // = SDM230_IMPORT_ACTIVE = Energy.total
// 0X0156, // SDM230_TOTAL_ENERGY_ACTIVE [kWh] // = SDM230_IMPORT_ACTIVE = Energy->total
// read more registers offered by SDM230 (may cause timing issues)
#ifdef SDM230_MORE_REGS
@ -106,7 +106,7 @@ void SDM230Every250ms(void)
if (error) {
AddLog(LOG_LEVEL_DEBUG, PSTR("SDM: SDM230 error %d"), error);
} else {
Energy.data_valid[0] = 0;
Energy->data_valid[0] = 0;
// 0 1 2 3 4 5 6 7 8
// SA FC BC Fh Fl Sh Sl Cl Ch
@ -119,39 +119,39 @@ void SDM230Every250ms(void)
switch(Sdm230.read_state) {
case 0:
Energy.voltage[0] = value; // 230.2 V
Energy->voltage[0] = value; // 230.2 V
break;
case 1:
Energy.current[0] = value; // 1.260 A
Energy->current[0] = value; // 1.260 A
break;
case 2:
Energy.active_power[0] = value; // -196.3 W
Energy->active_power[0] = value; // -196.3 W
break;
case 3:
Energy.apparent_power[0] = value; // 223.4 VA
Energy->apparent_power[0] = value; // 223.4 VA
break;
case 4:
Energy.reactive_power[0] = value; // 92.2
Energy->reactive_power[0] = value; // 92.2
break;
case 5:
Energy.power_factor[0] = value; // -0.91
Energy->power_factor[0] = value; // -0.91
break;
case 6:
Energy.frequency[0] = value; // 50.0 Hz
Energy->frequency[0] = value; // 50.0 Hz
break;
case 7:
Energy.import_active[0] = value; // 6.216 kWh => used in EnergyUpdateTotal()
Energy->import_active[0] = value; // 6.216 kWh => used in EnergyUpdateTotal()
break;
case 8:
Energy.export_active[0] = value; // 478.492 kWh
Energy->export_active[0] = value; // 478.492 kWh
break;
#ifdef SDM230_MORE_REGS
@ -192,8 +192,8 @@ void Sdm230SnsInit(void)
uint8_t result = Sdm230Modbus->Begin(SDM230_SPEED);
if (result) {
if (2 == result) { ClaimSerial(); }
Energy.phase_count = 1;
Energy.frequency_common = true; // Use common frequency
Energy->phase_count = 1;
Energy->frequency_common = true; // Use common frequency
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
}

View File

@ -162,16 +162,16 @@ RX: 35 0C TX: 00 00 00 F3 (WATT_HR)
switch(rx_buffer[1]) {
case BL6523_REG_AMPS :
Energy.current[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_current_calibration; // 1.260 A
Energy->current[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_current_calibration; // 1.260 A
break;
case BL6523_REG_VOLTS :
Energy.voltage[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_voltage_calibration; // 230.2 V
Energy->voltage[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_voltage_calibration; // 230.2 V
break;
case BL6523_REG_FREQ :
Energy.frequency[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_frequency_calibration; // 50.0 Hz
Energy->frequency[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_frequency_calibration; // 50.0 Hz
break;
case BL6523_REG_WATTS :
Energy.active_power[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_power_calibration; // -196.3 W
Energy->active_power[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_power_calibration; // -196.3 W
break;
case BL6523_REG_POWF :
/* Power factor =(sign bit)*((PF[22]×2^1PF[21]×2^2。。。)
@ -185,15 +185,15 @@ switch(rx_buffer[1]) {
powf_word = powf_word & (0x7fffff >> (1+i));
}
powf = (powf_buf >> 23) ? (0.0f - (powf)) : powf; // Negate if sign bit(24) is set
Energy.power_factor[SINGLE_PHASE] = powf;
Energy->power_factor[SINGLE_PHASE] = powf;
break;
case BL6523_REG_WATTHR :
Energy.import_active[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / ( Settings->energy_power_calibration - BL6523_PWHRREF_D ); // 6.216 kWh => used in EnergyUpdateTotal()
Energy->import_active[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / ( Settings->energy_power_calibration - BL6523_PWHRREF_D ); // 6.216 kWh => used in EnergyUpdateTotal()
break;
default :
break;
}
Energy.data_valid[SINGLE_PHASE] = 0;
Energy->data_valid[SINGLE_PHASE] = 0;
EnergyUpdateTotal();
if (!Bl6523.discovery_triggered)
{
@ -239,7 +239,7 @@ void Bl6523Init(void)
ClaimSerial();
}
Bl6523.type = 1;
Energy.phase_count = 1;
Energy->phase_count = 1;
AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Init Success" ));
}
else
@ -256,46 +256,46 @@ bool Bl6523Command(void) {
int32_t value = (int32_t)(CharToFloat(XdrvMailbox.data) * 1000); // 1.234 = 1234, -1.234 = -1234
uint32_t abs_value = abs(value) / 10; // 1.23 = 123, -1.23 = 123
if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) {
if ((CMND_POWERCAL == Energy->command_code) || (CMND_VOLTAGECAL == Energy->command_code) || (CMND_CURRENTCAL == Energy->command_code)) {
// Service in xdrv_03_energy.ino
}
else if (CMND_POWERSET == Energy.command_code) {
else if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value > 100) && (abs_value < 200000)) { // Between 1.00 and 2000.00 W
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value > 10000) && (abs_value < 26000)) { // Between 100.00 and 260.00 V
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value > 1000) && (abs_value < 1000000)) { // Between 10.00 mA and 10.00000 A
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_FREQUENCYSET == Energy.command_code) {
else if (CMND_FREQUENCYSET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value > 4500) && (abs_value < 6500)) { // Between 45.00 and 65.00 Hz
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_ENERGYCONFIG == Energy.command_code) {
else if (CMND_ENERGYCONFIG == Energy->command_code) {
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Config index %d, payload %d, value %d, data '%s'"),
XdrvMailbox.index, XdrvMailbox.payload, value, XdrvMailbox.data ? XdrvMailbox.data : "null" );
// EnergyConfig1 to 3 = Set Energy.current[channel] in A like 0.417 for 417mA
// EnergyConfig1 to 3 = Set Energy->current[channel] in A like 0.417 for 417mA
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index < 4)) {
//Bl6523.current[XdrvMailbox.index -1] = value;
}
// EnergyConfig4 to 6 = Set Energy.active_power[channel] in W like 100 for 100W
// EnergyConfig4 to 6 = Set Energy->active_power[channel] in W like 100 for 100W
if ((XdrvMailbox.index > 3) && (XdrvMailbox.index < 7)) {
//Bl6523.power[XdrvMailbox.index -4] = value;
}

View File

@ -501,16 +501,16 @@ void Ade7880Cycle(void) {
}
Ade7880.neutral_current = (float)Ade7880ReadVerify(ADE7880_NIRMS) / 100000; // 0x43C6
for (uint32_t phase = 0; phase < 3; phase++) {
Energy.data_valid[phase] = 0;
Energy.voltage[phase] = (float)Ade7880ReadVerify(ADE7880_AVRMS + (phase * 2)) / 10000; // 0x43C1 - 0x0024CC94 = 241.1668 V
Energy.current[phase] = (float)Ade7880ReadVerify(ADE7880_AIRMS + (phase * 2)) / 100000; // 0x43C0 - 0x00002D6D = 0.11629 A
Energy.active_power[phase] = (float)Ade7880ReadVerify(ADE7880_AWATT + phase) / 100; // 0xE513 - 0xFFFFF524 = -27.79 W
Energy.apparent_power[phase] = (float)Ade7880ReadVerify(ADE7880_AVA + phase) / 100; // 0xE519 - 0xFFFFF50D
Energy.frequency[phase] = 256000.0f / Ade7880ReadVerify(ADE7880_APERIOD + phase); // 0xE905 - Page 34 and based on ADE7880_FREQ_INIT
Energy->data_valid[phase] = 0;
Energy->voltage[phase] = (float)Ade7880ReadVerify(ADE7880_AVRMS + (phase * 2)) / 10000; // 0x43C1 - 0x0024CC94 = 241.1668 V
Energy->current[phase] = (float)Ade7880ReadVerify(ADE7880_AIRMS + (phase * 2)) / 100000; // 0x43C0 - 0x00002D6D = 0.11629 A
Energy->active_power[phase] = (float)Ade7880ReadVerify(ADE7880_AWATT + phase) / 100; // 0xE513 - 0xFFFFF524 = -27.79 W
Energy->apparent_power[phase] = (float)Ade7880ReadVerify(ADE7880_AVA + phase) / 100; // 0xE519 - 0xFFFFF50D
Energy->frequency[phase] = 256000.0f / Ade7880ReadVerify(ADE7880_APERIOD + phase); // 0xE905 - Page 34 and based on ADE7880_FREQ_INIT
// Suppose constant load during period of 100/120 periods as set by ADE7880_LINECYC disregards load change inbetween.
// ADE7880_AWATT = 6713 = 67,13 W
// 67,13 * 1000 / 36 = 1864 deca micro Wh (0.01864Wh)
// Energy.kWhtoday_delta[phase] += Energy.active_power[phase] * 1000 / 36;
// Energy->kWhtoday_delta[phase] += Energy->active_power[phase] * 1000 / 36;
// By measuring load 1024000 times/second load change in 100/120 periods can be accounted for.
// ADE7880_AWATT = 6713 = 67,13 W
@ -525,7 +525,7 @@ void Ade7880Cycle(void) {
// 273 * 402653184 / 16384 = 6709248 = 67092,48W / 3600 = 1863 deca micro Wh
// 273 * 24576 = 6709248 / 3600 = 1863 deca micro Wh
int32_t active_energy = Ade7880ReadVerify(ADE7880_AWATTHR + phase); // 0xE400 - 0xFFFFFF8F = -0.112
Energy.kWhtoday_delta[phase] += active_energy * 24576 / 3600; // Using int32_t allows loads up to 87kW (0x7FFFFFFF / 24576)
Energy->kWhtoday_delta[phase] += active_energy * 24576 / 3600; // Using int32_t allows loads up to 87kW (0x7FFFFFFF / 24576)
}
EnergyUpdateToday();
@ -662,10 +662,10 @@ void Ade7880DrvInit(void) {
Ade7880Defaults();
if (Ade7880SetCalibrate()) {
Energy.phase_count = 3; // Three phases
Energy->phase_count = 3; // Three phases
// Settings->flag5.energy_phase = 1; // SetOption129 - (Energy) Show phase information
// Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy.local_energy_active_export = true;
// Energy->use_overtemp = true; // Use global temperature for overtemp detection
Energy->local_energy_active_export = true;
TasmotaGlobal.energy_driver = XNRG_23;
}
}
@ -675,7 +675,7 @@ void Ade7880DrvInit(void) {
bool Ade7880Command(void) {
bool serviced = false;
if (CMND_ENERGYCONFIG == Energy.command_code) {
if (CMND_ENERGYCONFIG == Energy->command_code) {
// Non-pesistent settings
// EnergyConfig {"rms":{"current_a":3166385,"current_b":3125691,"current_c":3131983,"current_s":1756557,"voltage_a":-767262,"voltage_b":-763439,"voltage_c":-749854},"angles":{"angle0":180,"angle1":176,"angle2":176},"powers":{"totactive": {"a":-1345820,"b":-1347328,"c":-1351979}},"freq":0}
// EnergyConfig {"rms":{"voltage_c":-549854}}

View File

@ -216,7 +216,7 @@ void EnergyModbusLoop(void) {
* Cl = CRC lsb
* Ch = CRC msb
*/
Energy.data_valid[NrgMbsParam.phase] = 0;
Energy->data_valid[NrgMbsParam.phase] = 0;
float value;
switch (NrgMbsReg[NrgMbsParam.state].datatype) {
@ -293,31 +293,31 @@ void EnergyModbusLoop(void) {
switch (NrgMbsParam.state) {
case NRG_MBS_VOLTAGE:
Energy.voltage[NrgMbsParam.phase] = value; // 230.2 V
Energy->voltage[NrgMbsParam.phase] = value; // 230.2 V
break;
case NRG_MBS_CURRENT:
Energy.current[NrgMbsParam.phase] = value; // 1.260 A
Energy->current[NrgMbsParam.phase] = value; // 1.260 A
break;
case NRG_MBS_ACTIVE_POWER:
Energy.active_power[NrgMbsParam.phase] = value; // -196.3 W
Energy->active_power[NrgMbsParam.phase] = value; // -196.3 W
break;
case NRG_MBS_APPARENT_POWER:
Energy.apparent_power[NrgMbsParam.phase] = value; // 223.4 VA
Energy->apparent_power[NrgMbsParam.phase] = value; // 223.4 VA
break;
case NRG_MBS_REACTIVE_POWER:
Energy.reactive_power[NrgMbsParam.phase] = value; // 92.2
Energy->reactive_power[NrgMbsParam.phase] = value; // 92.2
break;
case NRG_MBS_POWER_FACTOR:
Energy.power_factor[NrgMbsParam.phase] = value; // -0.91
Energy->power_factor[NrgMbsParam.phase] = value; // -0.91
break;
case NRG_MBS_FREQUENCY:
Energy.frequency[NrgMbsParam.phase] = value; // 50.0 Hz
Energy->frequency[NrgMbsParam.phase] = value; // 50.0 Hz
break;
case NRG_MBS_TOTAL_ENERGY:
Energy.import_active[NrgMbsParam.phase] = value; // 6.216 kWh => used in EnergyUpdateTotal()
Energy->import_active[NrgMbsParam.phase] = value; // 6.216 kWh => used in EnergyUpdateTotal()
break;
case NRG_MBS_EXPORT_ACTIVE_ENERGY:
Energy.export_active[NrgMbsParam.phase] = value; // 478.492 kWh
Energy->export_active[NrgMbsParam.phase] = value; // 478.492 kWh
break;
default:
if (NrgMbsUser) {
@ -334,7 +334,7 @@ void EnergyModbusLoop(void) {
uint32_t phase = 0;
do {
NrgMbsParam.phase++;
if (NrgMbsParam.phase >= Energy.phase_count) {
if (NrgMbsParam.phase >= Energy->phase_count) {
NrgMbsParam.phase = 0;
NrgMbsParam.state++;
if (NrgMbsParam.state >= NrgMbsParam.total_regs) {
@ -434,8 +434,8 @@ bool EnergyModbusReadUserRegisters(JsonParserObject user_add_value, uint32_t add
if (!phase) {
return false; // No register entered so skip
}
if (phase > Energy.phase_count) {
Energy.phase_count = phase;
if (phase > Energy->phase_count) {
Energy->phase_count = phase;
NrgMbsParam.devices = 1; // Only one device allowed with multiple phases
}
@ -514,7 +514,7 @@ bool EnergyModbusReadRegisters(void) {
if (!root) { return false; } // Invalid JSON
// Init defaults
Energy.phase_count = 1;
Energy->phase_count = 1;
NrgMbsParam.serial_bps = ENERGY_MODBUS_SPEED;
NrgMbsParam.serial_config = ENERGY_MODBUS_CONFIG;
NrgMbsParam.ticker_poll = ENERGY_MODBUS_TICKER_POLL;
@ -603,8 +603,8 @@ bool EnergyModbusReadRegisters(void) {
// Get default energy registers
char register_name[32];
Energy.voltage_available = false; // Disable voltage is measured
Energy.current_available = false; // Disable current is measured
Energy->voltage_available = false; // Disable voltage is measured
Energy->current_available = false; // Disable current is measured
for (uint32_t names = 0; names < NRG_MBS_MAX_REGS; names++) {
val = root[GetTextIndexed(register_name, sizeof(register_name), names, kEnergyModbusValues)];
if (val) {
@ -631,24 +631,24 @@ bool EnergyModbusReadRegisters(void) {
NrgMbsReg[names].address[0] = val.getUInt();
phase++;
}
if (phase > Energy.phase_count) {
Energy.phase_count = phase;
if (phase > Energy->phase_count) {
Energy->phase_count = phase;
NrgMbsParam.devices = 1; // Only one device allowed with multiple phases
}
switch(names) {
case NRG_MBS_VOLTAGE:
Energy.voltage_available = true; // Enable if voltage is measured
Energy->voltage_available = true; // Enable if voltage is measured
if (1 == phase) {
Energy.voltage_common = true; // Use common voltage
Energy->voltage_common = true; // Use common voltage
}
break;
case NRG_MBS_CURRENT:
Energy.current_available = true; // Enable if current is measured
Energy->current_available = true; // Enable if current is measured
break;
case NRG_MBS_FREQUENCY:
if (1 == phase) {
Energy.frequency_common = true; // Use common frequency
Energy->frequency_common = true; // Use common frequency
}
break;
case NRG_MBS_TOTAL_ENERGY:
@ -707,9 +707,9 @@ bool EnergyModbusReadRegisters(void) {
}
if (NrgMbsParam.devices > 1) {
// Multiple devices have no common values
Energy.phase_count = NrgMbsParam.devices;
Energy.voltage_common = false; // Use no common voltage
Energy.frequency_common = false; // Use no common frequency
Energy->phase_count = NrgMbsParam.devices;
Energy->voltage_common = false; // Use no common voltage
Energy->frequency_common = false; // Use no common frequency
Settings->flag5.energy_phase = 1; // SetOption129 - (Energy) Show phase information
}

View File

@ -53,25 +53,25 @@ struct {
} NrgDummy;
void NrgDummyEverySecond(void) {
if (Energy.power_on) { // Powered on
for (uint32_t channel = 0; channel < Energy.phase_count; channel++) {
if (Energy->power_on) { // Powered on
for (uint32_t channel = 0; channel < Energy->phase_count; channel++) {
float power_calibration = (float)EnergyGetCalibration(channel, ENERGY_POWER_CALIBRATION) / 100;
float voltage_calibration = (float)EnergyGetCalibration(channel, ENERGY_VOLTAGE_CALIBRATION) / 100;
float current_calibration = (float)EnergyGetCalibration(channel, ENERGY_CURRENT_CALIBRATION) / 100000;
float frequency_calibration = (float)EnergyGetCalibration(channel, ENERGY_FREQUENCY_CALIBRATION) / 100;
Energy.voltage[channel] = voltage_calibration; // V
Energy.frequency[channel] = frequency_calibration; // Hz
Energy->voltage[channel] = voltage_calibration; // V
Energy->frequency[channel] = frequency_calibration; // Hz
if (bitRead(TasmotaGlobal.power, channel)) { // Emulate power read only if device is powered on
Energy.active_power[channel] = (NrgDummy.power[channel]) ? ((float)NrgDummy.power[channel] / 1000) : power_calibration; // W
if (0 == Energy.active_power[channel]) {
Energy.current[channel] = 0;
Energy->active_power[channel] = (NrgDummy.power[channel]) ? ((float)NrgDummy.power[channel] / 1000) : power_calibration; // W
if (0 == Energy->active_power[channel]) {
Energy->current[channel] = 0;
} else {
Energy.current[channel] = (NrgDummy.current[channel]) ? ((float)NrgDummy.current[channel] / 1000) : current_calibration; // A
Energy.kWhtoday_delta[channel] += Energy.active_power[channel] * 1000 / 36;
Energy->current[channel] = (NrgDummy.current[channel]) ? ((float)NrgDummy.current[channel] / 1000) : current_calibration; // A
Energy->kWhtoday_delta[channel] += Energy->active_power[channel] * 1000 / 36;
}
Energy.data_valid[channel] = 0;
Energy->data_valid[channel] = 0;
}
}
EnergyUpdateToday();
@ -84,46 +84,46 @@ bool NrgDummyCommand(void) {
int32_t value = (int32_t)(CharToFloat(XdrvMailbox.data) * 1000); // 1.234 = 1234, -1.234 = -1234
uint32_t abs_value = abs(value) / 10; // 1.23 = 123, -1.23 = 123
if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) {
if ((CMND_POWERCAL == Energy->command_code) || (CMND_VOLTAGECAL == Energy->command_code) || (CMND_CURRENTCAL == Energy->command_code)) {
// Service in xdrv_03_energy.ino
}
else if (CMND_POWERSET == Energy.command_code) {
else if (CMND_POWERSET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value >= 100) && (abs_value <= 16000000)) { // Between 1.00 and 160000.00 W
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
else if (CMND_VOLTAGESET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value >= 10000) && (abs_value <= 40000)) { // Between 100.00 and 400.00 V
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
else if (CMND_CURRENTSET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value >= 1000) && (abs_value <= 40000000)) { // Between 10.00 mA and 400.00000 A
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_FREQUENCYSET == Energy.command_code) {
else if (CMND_FREQUENCYSET == Energy->command_code) {
if (XdrvMailbox.data_len) {
if ((abs_value >= 4500) && (abs_value <= 6500)) { // Between 45.00 and 65.00 Hz
XdrvMailbox.payload = abs_value;
}
}
}
else if (CMND_ENERGYCONFIG == Energy.command_code) {
else if (CMND_ENERGYCONFIG == Energy->command_code) {
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Config index %d, payload %d, value %d, data '%s'"),
XdrvMailbox.index, XdrvMailbox.payload, value, XdrvMailbox.data ? XdrvMailbox.data : "null" );
// EnergyConfig1 to 3 = Set Energy.current[channel] in A like 0.417 for 417mA
// EnergyConfig1 to 3 = Set Energy->current[channel] in A like 0.417 for 417mA
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index < 4)) {
NrgDummy.current[XdrvMailbox.index -1] = value;
}
// EnergyConfig4 to 6 = Set Energy.active_power[channel] in W like 100 for 100W
// EnergyConfig4 to 6 = Set Energy->active_power[channel] in W like 100 for 100W
if ((XdrvMailbox.index > 3) && (XdrvMailbox.index < 7)) {
NrgDummy.power[XdrvMailbox.index -4] = value;
}
@ -145,11 +145,11 @@ void NrgDummyDrvInit(void) {
Settings->energy_power_calibration2 = NRG_DUMMY_PREF;
}
Energy.phase_count = (TasmotaGlobal.devices_present < ENERGY_MAX_PHASES) ? TasmotaGlobal.devices_present : ENERGY_MAX_PHASES;
Energy.voltage_common = NRG_DUMMY_U_COMMON; // Phase voltage = false, Common voltage = true
Energy.frequency_common = NRG_DUMMY_F_COMMON; // Phase frequency = false, Common frequency = true
Energy.type_dc = NRG_DUMMY_DC; // AC = false, DC = true;
Energy.use_overtemp = NRG_DUMMY_OVERTEMP; // Use global temperature for overtemp detection
Energy->phase_count = (TasmotaGlobal.devices_present < ENERGY_MAX_PHASES) ? TasmotaGlobal.devices_present : ENERGY_MAX_PHASES;
Energy->voltage_common = NRG_DUMMY_U_COMMON; // Phase voltage = false, Common voltage = true
Energy->frequency_common = NRG_DUMMY_F_COMMON; // Phase frequency = false, Common frequency = true
Energy->type_dc = NRG_DUMMY_DC; // AC = false, DC = true;
Energy->use_overtemp = NRG_DUMMY_OVERTEMP; // Use global temperature for overtemp detection
TasmotaGlobal.energy_driver = XNRG_30;
}

View File

@ -1899,11 +1899,11 @@ void MI32createPolyline(char *polyline, uint8_t *history){
#ifdef USE_MI_ESP32_ENERGY
void MI32sendEnergyWidget(){
if (Energy.current_available && Energy.voltage_available) {
WSContentSend_P(HTTP_MI32_POWER_WIDGET,MIBLEsensors.size()+1, Energy.voltage,Energy.current[1]);
if (Energy->current_available && Energy->voltage_available) {
WSContentSend_P(HTTP_MI32_POWER_WIDGET,MIBLEsensors.size()+1, Energy->voltage,Energy->current[1]);
char _polyline[176];
MI32createPolyline(_polyline,MI32.energy_history);
WSContentSend_P(PSTR("<p>" D_POWERUSAGE ": %.1f " D_UNIT_WATT ""),Energy.active_power);
WSContentSend_P(PSTR("<p>" D_POWERUSAGE ": %.1f " D_UNIT_WATT ""),Energy->active_power);
WSContentSend_P(HTTP_MI32_GRAPH,_polyline,185,124,124,_polyline,1);
WSContentSend_P(PSTR("</p></div>"));
}
@ -2243,7 +2243,7 @@ void MI32Show(bool json)
#ifdef USE_MI_EXT_GUI
Mi32invalidateOldHistory();
#ifdef USE_MI_ESP32_ENERGY
MI32addHistory(MI32.energy_history,Energy.active_power[0],100); //TODO: which value??
MI32addHistory(MI32.energy_history,Energy->active_power[0],100); //TODO: which value??
#endif //USE_MI_ESP32_ENERGY
#endif //USE_MI_EXT_GUI
vTaskResume(MI32.ScanTask);

View File

@ -260,19 +260,19 @@ void HandleMetrics(void) {
#ifdef USE_ENERGY_SENSOR
WritePromMetricDec(PSTR("energy_voltage_volts"),
kPromMetricGauge,
Energy.voltage[0], Settings->flag2.voltage_resolution, nullptr);
Energy->voltage[0], Settings->flag2.voltage_resolution, nullptr);
WritePromMetricDec(PSTR("energy_current_amperes"),
kPromMetricGauge,
Energy.current[0], Settings->flag2.current_resolution, nullptr);
Energy->current[0], Settings->flag2.current_resolution, nullptr);
WritePromMetricDec(PSTR("energy_power_active_watts"),
kPromMetricGauge,
Energy.active_power[0], Settings->flag2.wattage_resolution, nullptr);
Energy->active_power[0], Settings->flag2.wattage_resolution, nullptr);
WritePromMetricDec(PSTR("energy_power_kilowatts_daily"),
kPromMetricCounter,
Energy.daily_sum, Settings->flag2.energy_resolution, nullptr);
Energy->daily_sum, Settings->flag2.energy_resolution, nullptr);
WritePromMetricDec(PSTR("energy_power_kilowatts_total"),
kPromMetricCounter,
Energy.total_sum, Settings->flag2.energy_resolution, nullptr);
Energy->total_sum, Settings->flag2.energy_resolution, nullptr);
#endif
for (uint32_t device = 0; device < TasmotaGlobal.devices_present; device++) {