Refactor Energy code saving space

Refactor Energy code saving space
This commit is contained in:
Theo Arends 2019-08-16 14:41:02 +02:00
parent cafec2eccd
commit 0e4d4a889a
9 changed files with 448 additions and 439 deletions

View File

@ -488,7 +488,6 @@ struct WEB {
uint8_t config_xor_on_set = CONFIG_FILE_XOR;
} Web;
// Helper function to avoid code duplication (saves 4k Flash)
static void WebGetArg(const char* arg, char* out, size_t max)
{

View File

@ -67,94 +67,98 @@ void (* const EnergyCommand[])(void) PROGMEM = {
#endif // USE_ENERGY_MARGIN_DETECTION
&CmndEnergyReset };
float energy_voltage = 0; // 123.1 V
float energy_current = 0; // 123.123 A
float energy_active_power = 0; // 123.1 W
float energy_apparent_power = NAN; // 123.1 VA
float energy_reactive_power = NAN; // 123.1 VAr
float energy_power_factor = NAN; // 0.12
float energy_frequency = NAN; // 123.1 Hz
float energy_start = 0; // 12345.12345 kWh total previous
struct ENERGY {
float voltage = 0; // 123.1 V
float current = 0; // 123.123 A
float active_power = 0; // 123.1 W
float apparent_power = NAN; // 123.1 VA
float reactive_power = NAN; // 123.1 VAr
float power_factor = NAN; // 0.12
float frequency = NAN; // 123.1 Hz
float start_energy = 0; // 12345.12345 kWh total previous
float energy_daily = 0; // 123.123 kWh
float energy_total = 0; // 12345.12345 kWh
unsigned long energy_kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to energy_kWhtoday (HLW and CSE only)
unsigned long energy_kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily
unsigned long energy_period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily
float daily = 0; // 123.123 kWh
float total = 0; // 12345.12345 kWh
uint8_t energy_command_code = 0;
uint8_t energy_data_valid = 0;
unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only)
unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
bool energy_voltage_available = true; // Enable if voltage is measured
bool energy_current_available = true; // Enable if current is measured
uint8_t fifth_second = 0;
uint8_t command_code = 0;
uint8_t data_valid = 0;
bool energy_type_dc = false;
bool energy_power_on = true;
bool voltage_available = true; // Enable if voltage is measured
bool current_available = true; // Enable if current is measured
bool type_dc = false;
bool power_on = true;
#ifdef USE_ENERGY_MARGIN_DETECTION
float energy_power_last[3] = { 0 };
uint8_t energy_power_delta = 0;
bool energy_min_power_flag = false;
bool energy_max_power_flag = false;
bool energy_min_voltage_flag = false;
bool energy_max_voltage_flag = false;
bool energy_min_current_flag = false;
bool energy_max_current_flag = false;
uint8_t energy_power_steady_cntr = 8; // Allow for power on stabilization
float power_history[3] = { 0 };
uint8_t power_steady_counter = 8; // Allow for power on stabilization
uint8_t power_delta = 0;
bool min_power_flag = false;
bool max_power_flag = false;
bool min_voltage_flag = false;
bool max_voltage_flag = false;
bool min_current_flag = false;
bool max_current_flag = false;
#ifdef USE_ENERGY_POWER_LIMIT
uint16_t energy_mplh_counter = 0;
uint16_t energy_mplw_counter = 0;
uint8_t energy_mplr_counter = 0;
uint8_t energy_max_energy_state = 0;
uint16_t mplh_counter = 0;
uint16_t mplw_counter = 0;
uint8_t mplr_counter = 0;
uint8_t max_energy_state = 0;
#endif // USE_ENERGY_POWER_LIMIT
#endif // USE_ENERGY_MARGIN_DETECTION
uint8_t energy_fifth_second = 0;
#endif // USE_ENERGY_MARGIN_DETECTION
} Energy;
Ticker ticker_energy;
/********************************************************************************************/
void EnergyUpdateToday(void)
{
if (energy_kWhtoday_delta > 1000) {
unsigned long delta = energy_kWhtoday_delta / 1000;
energy_kWhtoday_delta -= (delta * 1000);
energy_kWhtoday += delta;
if (Energy.kWhtoday_delta > 1000) {
unsigned long delta = Energy.kWhtoday_delta / 1000;
Energy.kWhtoday_delta -= (delta * 1000);
Energy.kWhtoday += delta;
}
RtcSettings.energy_kWhtoday = energy_kWhtoday;
energy_daily = (float)energy_kWhtoday / 100000;
energy_total = (float)(RtcSettings.energy_kWhtotal + energy_kWhtoday) / 100000;
RtcSettings.energy_kWhtoday = Energy.kWhtoday;
Energy.daily = (float)Energy.kWhtoday / 100000;
Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday) / 100000;
}
/*********************************************************************************************/
void Energy200ms(void)
{
energy_power_on = (power != 0) | Settings.flag.no_power_on_check;
Energy.power_on = (power != 0) | Settings.flag.no_power_on_check;
energy_fifth_second++;
if (5 == energy_fifth_second) {
energy_fifth_second = 0;
Energy.fifth_second++;
if (5 == Energy.fifth_second) {
Energy.fifth_second = 0;
XnrgCall(FUNC_ENERGY_EVERY_SECOND);
if (RtcTime.valid) {
if (LocalTime() == Midnight()) {
Settings.energy_kWhyesterday = energy_kWhtoday;
Settings.energy_kWhtotal += energy_kWhtoday;
Settings.energy_kWhyesterday = Energy.kWhtoday;
Settings.energy_kWhtotal += Energy.kWhtoday;
RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal;
energy_kWhtoday = 0;
energy_kWhtoday_delta = 0;
energy_period = energy_kWhtoday;
Energy.kWhtoday = 0;
Energy.kWhtoday_delta = 0;
Energy.period = Energy.kWhtoday;
EnergyUpdateToday();
#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT)
energy_max_energy_state = 3;
Energy.max_energy_state = 3;
#endif // USE_ENERGY_POWER_LIMIT
}
#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT)
if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == energy_max_energy_state)) {
energy_max_energy_state = 0;
if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) {
Energy.max_energy_state = 0;
}
#endif // USE_ENERGY_POWER_LIMIT
@ -167,8 +171,8 @@ void Energy200ms(void)
void EnergySaveState(void)
{
Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0;
Settings.energy_kWhtoday = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
Settings.energy_kWhtoday = Energy.kWhtoday;
RtcSettings.energy_kWhtoday = Energy.kWhtoday;
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
}
@ -197,55 +201,55 @@ void EnergyMarginCheck(void)
bool flag;
bool jsonflg;
if (energy_power_steady_cntr) {
energy_power_steady_cntr--;
if (Energy.power_steady_counter) {
Energy.power_steady_counter--;
return;
}
if (Settings.energy_power_delta) {
float delta = abs(energy_power_last[0] - energy_active_power);
float delta = abs(Energy.power_history[0] - Energy.active_power);
// Any delta compared to minimal delta
float min_power = (energy_power_last[0] > energy_active_power) ? energy_active_power : energy_power_last[0];
float min_power = (Energy.power_history[0] > Energy.active_power) ? Energy.active_power : Energy.power_history[0];
if (((delta / min_power) * 100) > Settings.energy_power_delta) {
energy_power_delta = 1;
energy_power_last[1] = energy_active_power; // We only want one report so reset history
energy_power_last[2] = energy_active_power;
Energy.power_delta = 1;
Energy.power_history[1] = Energy.active_power; // We only want one report so reset history
Energy.power_history[2] = Energy.active_power;
}
}
energy_power_last[0] = energy_power_last[1]; // Shift in history every second allowing power changes to settle for up to three seconds
energy_power_last[1] = energy_power_last[2];
energy_power_last[2] = energy_active_power;
Energy.power_history[0] = Energy.power_history[1]; // Shift in history every second allowing power changes to settle for up to three seconds
Energy.power_history[1] = Energy.power_history[2];
Energy.power_history[2] = Energy.active_power;
if (energy_power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) {
energy_power_u = (uint16_t)(energy_active_power);
energy_voltage_u = (uint16_t)(energy_voltage);
energy_current_u = (uint16_t)(energy_current * 1000);
if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) {
energy_power_u = (uint16_t)(Energy.active_power);
energy_voltage_u = (uint16_t)(Energy.voltage);
energy_current_u = (uint16_t)(Energy.current * 1000);
DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u);
Response_P(PSTR("{"));
jsonflg = false;
if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, energy_min_power_flag)) {
if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, energy_max_power_flag)) {
if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, energy_min_voltage_flag)) {
if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, energy_max_voltage_flag)) {
if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, energy_min_current_flag)) {
if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) {
ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, energy_max_current_flag)) {
if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) {
ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
@ -259,35 +263,35 @@ void EnergyMarginCheck(void)
#ifdef USE_ENERGY_POWER_LIMIT
// Max Power
if (Settings.energy_max_power_limit) {
if (energy_active_power > Settings.energy_max_power_limit) {
if (!energy_mplh_counter) {
energy_mplh_counter = Settings.energy_max_power_limit_hold;
if (Energy.active_power > Settings.energy_max_power_limit) {
if (!Energy.mplh_counter) {
Energy.mplh_counter = Settings.energy_max_power_limit_hold;
} else {
energy_mplh_counter--;
if (!energy_mplh_counter) {
Energy.mplh_counter--;
if (!Energy.mplh_counter) {
Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : "");
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
EnergyMqttShow();
ExecuteCommandPower(1, POWER_OFF, SRC_MAXPOWER);
if (!energy_mplr_counter) {
energy_mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1;
if (!Energy.mplr_counter) {
Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1;
}
energy_mplw_counter = Settings.energy_max_power_limit_window;
Energy.mplw_counter = Settings.energy_max_power_limit_window;
}
}
}
else if (power && (energy_power_u <= Settings.energy_max_power_limit)) {
energy_mplh_counter = 0;
energy_mplr_counter = 0;
energy_mplw_counter = 0;
Energy.mplh_counter = 0;
Energy.mplr_counter = 0;
Energy.mplw_counter = 0;
}
if (!power) {
if (energy_mplw_counter) {
energy_mplw_counter--;
if (Energy.mplw_counter) {
Energy.mplw_counter--;
} else {
if (energy_mplr_counter) {
energy_mplr_counter--;
if (energy_mplr_counter) {
if (Energy.mplr_counter) {
Energy.mplr_counter--;
if (Energy.mplr_counter) {
Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1));
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR));
ExecuteCommandPower(1, POWER_ON, SRC_MAXPOWER);
@ -303,16 +307,16 @@ void EnergyMarginCheck(void)
// Max Energy
if (Settings.energy_max_energy) {
energy_daily_u = (uint16_t)(energy_daily * 1000);
if (!energy_max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) {
energy_max_energy_state = 1;
energy_daily_u = (uint16_t)(Energy.daily * 1000);
if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) {
Energy.max_energy_state = 1;
Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1));
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR));
ExecuteCommandPower(1, POWER_ON, SRC_MAXENERGY);
}
else if ((1 == energy_max_energy_state) && (energy_daily_u >= Settings.energy_max_energy)) {
energy_max_energy_state = 2;
dtostrfd(energy_daily, 3, mqtt_data);
else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) {
Energy.max_energy_state = 2;
dtostrfd(Energy.daily, 3, mqtt_data);
Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : "");
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
EnergyMqttShow();
@ -321,7 +325,7 @@ void EnergyMarginCheck(void)
}
#endif // USE_ENERGY_POWER_LIMIT
if (energy_power_delta) { EnergyMqttShow(); }
if (Energy.power_delta) { EnergyMqttShow(); }
}
void EnergyMqttShow(void)
@ -334,7 +338,7 @@ void EnergyMqttShow(void)
tele_period = tele_period_save;
ResponseJsonEnd();
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
energy_power_delta = 0;
Energy.power_delta = 0;
}
#endif // USE_ENERGY_MARGIN_DETECTION
@ -345,16 +349,16 @@ void EnergyOverTempCheck()
SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP);
}
}
if (energy_data_valid <= ENERGY_WATCHDOG) {
energy_data_valid++;
if (energy_data_valid > ENERGY_WATCHDOG) {
if (Energy.data_valid <= ENERGY_WATCHDOG) {
Energy.data_valid++;
if (Energy.data_valid > ENERGY_WATCHDOG) {
// Reset energy registers
energy_voltage = 0;
energy_current = 0;
energy_active_power = 0;
if (!isnan(energy_frequency)) { energy_frequency = 0; }
if (!isnan(energy_power_factor)) { energy_power_factor = 0; }
energy_start = 0;
Energy.voltage = 0;
Energy.current = 0;
Energy.active_power = 0;
if (!isnan(Energy.frequency)) { Energy.frequency = 0; }
if (!isnan(Energy.power_factor)) { Energy.power_factor = 0; }
Energy.start_energy = 0;
}
}
}
@ -386,13 +390,13 @@ void CmndEnergyReset(void)
if (p != XdrvMailbox.data) {
switch (XdrvMailbox.index) {
case 1:
energy_kWhtoday = lnum *100;
energy_kWhtoday_delta = 0;
energy_period = energy_kWhtoday;
Settings.energy_kWhtoday = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
energy_daily = (float)energy_kWhtoday / 100000;
if (!RtcSettings.energy_kWhtotal && !energy_kWhtoday) { Settings.energy_kWhtotal_time = LocalTime(); }
Energy.kWhtoday = lnum *100;
Energy.kWhtoday_delta = 0;
Energy.period = Energy.kWhtoday;
Settings.energy_kWhtoday = Energy.kWhtoday;
RtcSettings.energy_kWhtoday = Energy.kWhtoday;
Energy.daily = (float)Energy.kWhtoday / 100000;
if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday) { Settings.energy_kWhtotal_time = LocalTime(); }
break;
case 2:
Settings.energy_kWhyesterday = lnum *100;
@ -400,15 +404,15 @@ void CmndEnergyReset(void)
case 3:
RtcSettings.energy_kWhtotal = lnum *100;
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
energy_total = (float)(RtcSettings.energy_kWhtotal + energy_kWhtoday) / 100000;
Settings.energy_kWhtotal_time = (!energy_kWhtoday) ? LocalTime() : Midnight();
Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday) / 100000;
Settings.energy_kWhtotal_time = (!Energy.kWhtoday) ? LocalTime() : Midnight();
break;
}
}
char energy_total_chr[33];
dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr);
dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr);
char energy_daily_chr[33];
dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr);
dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr);
char energy_yesterday_chr[33];
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
@ -419,7 +423,7 @@ void CmndEnergyReset(void)
void CmndPowerCal(void)
{
energy_command_code = CMND_POWERCAL;
Energy.command_code = CMND_POWERCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
Settings.energy_power_calibration = XdrvMailbox.payload;
@ -430,7 +434,7 @@ void CmndPowerCal(void)
void CmndVoltageCal(void)
{
energy_command_code = CMND_VOLTAGECAL;
Energy.command_code = CMND_VOLTAGECAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
Settings.energy_voltage_calibration = XdrvMailbox.payload;
@ -441,7 +445,7 @@ void CmndVoltageCal(void)
void CmndCurrentCal(void)
{
energy_command_code = CMND_CURRENTCAL;
Energy.command_code = CMND_CURRENTCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
Settings.energy_current_calibration = XdrvMailbox.payload;
@ -452,7 +456,7 @@ void CmndCurrentCal(void)
void CmndPowerSet(void)
{
energy_command_code = CMND_POWERSET;
Energy.command_code = CMND_POWERSET;
if (XnrgCall(FUNC_COMMAND)) { // Watt
EnergyCommandResponse(Settings.energy_power_calibration, UNIT_MILLISECOND);
}
@ -460,7 +464,7 @@ void CmndPowerSet(void)
void CmndVoltageSet(void)
{
energy_command_code = CMND_VOLTAGESET;
Energy.command_code = CMND_VOLTAGESET;
if (XnrgCall(FUNC_COMMAND)) { // Volt
EnergyCommandResponse(Settings.energy_voltage_calibration, UNIT_MILLISECOND);
}
@ -468,7 +472,7 @@ void CmndVoltageSet(void)
void CmndCurrentSet(void)
{
energy_command_code = CMND_CURRENTSET;
Energy.command_code = CMND_CURRENTSET;
if (XnrgCall(FUNC_COMMAND)) { // milliAmpere
EnergyCommandResponse(Settings.energy_current_calibration, UNIT_MILLISECOND);
}
@ -476,7 +480,7 @@ void CmndCurrentSet(void)
void CmndFrequencySet(void)
{
energy_command_code = CMND_FREQUENCYSET;
Energy.command_code = CMND_FREQUENCYSET;
if (XnrgCall(FUNC_COMMAND)) { // Hz
EnergyCommandResponse(Settings.energy_frequency_calibration, UNIT_MILLISECOND);
}
@ -592,7 +596,7 @@ void CmndMaxEnergy(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_energy = XdrvMailbox.payload;
energy_max_energy_state = 3;
Energy.max_energy_state = 3;
}
EnergyCommandResponse(Settings.energy_max_energy, UNIT_WATTHOUR);
}
@ -618,9 +622,9 @@ void EnergySnsInit(void)
XnrgCall(FUNC_INIT);
if (energy_flg) {
energy_kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_kWhtoday : 0;
energy_kWhtoday_delta = 0;
energy_period = energy_kWhtoday;
Energy.kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_kWhtoday : 0;
Energy.kWhtoday_delta = 0;
Energy.period = Energy.kWhtoday;
EnergyUpdateToday();
ticker_energy.attach_ms(200, Energy200ms);
}
@ -645,35 +649,35 @@ void EnergyShow(bool json)
bool show_energy_period = (0 == tele_period);
float power_factor = energy_power_factor;
float power_factor = Energy.power_factor;
char apparent_power_chr[33];
char reactive_power_chr[33];
char power_factor_chr[33];
char frequency_chr[33];
if (!energy_type_dc) {
if (energy_current_available && energy_voltage_available) {
float apparent_power = energy_apparent_power;
if (!Energy.type_dc) {
if (Energy.current_available && Energy.voltage_available) {
float apparent_power = Energy.apparent_power;
if (isnan(apparent_power)) {
apparent_power = energy_voltage * energy_current;
apparent_power = Energy.voltage * Energy.current;
}
if (apparent_power < energy_active_power) { // Should be impossible
energy_active_power = apparent_power;
if (apparent_power < Energy.active_power) { // Should be impossible
Energy.active_power = apparent_power;
}
if (isnan(power_factor)) {
power_factor = (energy_active_power && apparent_power) ? energy_active_power / apparent_power : 0;
power_factor = (Energy.active_power && apparent_power) ? Energy.active_power / apparent_power : 0;
if (power_factor > 1) power_factor = 1;
}
float reactive_power = energy_reactive_power;
float reactive_power = Energy.reactive_power;
if (isnan(reactive_power)) {
reactive_power = 0;
uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(energy_active_power * 100)) / 10;
if ((energy_current > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) {
uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power * 100)) / 10;
if ((Energy.current > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) {
// calculating reactive power only if current is greater than 0.005A and
// difference between active and apparent power is greater than 1.5W or 1%
reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(energy_active_power * energy_active_power * 100))) / 10;
reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(Energy.active_power * Energy.active_power * 100))) / 10;
}
}
@ -681,29 +685,29 @@ void EnergyShow(bool json)
dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr);
dtostrfd(power_factor, 2, power_factor_chr);
}
if (!isnan(energy_frequency)) {
dtostrfd(energy_frequency, Settings.flag2.frequency_resolution, frequency_chr);
if (!isnan(Energy.frequency)) {
dtostrfd(Energy.frequency, Settings.flag2.frequency_resolution, frequency_chr);
}
}
char voltage_chr[33];
dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, voltage_chr);
dtostrfd(Energy.voltage, Settings.flag2.voltage_resolution, voltage_chr);
char current_chr[33];
dtostrfd(energy_current, Settings.flag2.current_resolution, current_chr);
dtostrfd(Energy.current, Settings.flag2.current_resolution, current_chr);
char active_power_chr[33];
dtostrfd(energy_active_power, Settings.flag2.wattage_resolution, active_power_chr);
dtostrfd(Energy.active_power, Settings.flag2.wattage_resolution, active_power_chr);
char energy_daily_chr[33];
dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr);
dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr);
char energy_yesterday_chr[33];
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
char energy_total_chr[33];
dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr);
dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr);
float energy = 0;
char energy_period_chr[33];
if (show_energy_period) {
if (energy_period) energy = (float)(energy_kWhtoday - energy_period) / 100;
energy_period = energy_kWhtoday;
if (Energy.period) energy = (float)(Energy.kWhtoday - Energy.period) / 100;
Energy.period = Energy.kWhtoday;
dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr);
snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr);
}
@ -711,64 +715,64 @@ void EnergyShow(bool json)
if (json) {
ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"),
GetDateAndTime(DT_ENERGY).c_str(), energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr);
if (!energy_type_dc) {
if (energy_current_available && energy_voltage_available) {
if (!Energy.type_dc) {
if (Energy.current_available && Energy.voltage_available) {
ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"),
apparent_power_chr, reactive_power_chr, power_factor_chr);
}
if (!isnan(energy_frequency)) {
if (!isnan(Energy.frequency)) {
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), frequency_chr);
}
}
if (energy_voltage_available) {
if (Energy.voltage_available) {
ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), voltage_chr);
}
if (energy_current_available) {
if (Energy.current_available) {
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), current_chr);
}
ResponseJsonEnd();
#ifdef USE_DOMOTICZ
if (show_energy_period) { // Only send if telemetry
dtostrfd(energy_total * 1000, 1, energy_total_chr);
DomoticzSensorPowerEnergy((int)energy_active_power, energy_total_chr); // PowerUsage, EnergyToday
if (energy_voltage_available) {
dtostrfd(Energy.total * 1000, 1, energy_total_chr);
DomoticzSensorPowerEnergy((int)Energy.active_power, energy_total_chr); // PowerUsage, EnergyToday
if (Energy.voltage_available) {
DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage
}
if (energy_current_available) {
if (Energy.current_available) {
DomoticzSensor(DZ_CURRENT, current_chr); // Current
}
}
#endif // USE_DOMOTICZ
#ifdef USE_KNX
if (show_energy_period) {
if (energy_voltage_available) {
KnxSensor(KNX_ENERGY_VOLTAGE, energy_voltage);
if (Energy.voltage_available) {
KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage);
}
if (energy_current_available) {
KnxSensor(KNX_ENERGY_CURRENT, energy_current);
if (Energy.current_available) {
KnxSensor(KNX_ENERGY_CURRENT, Energy.current);
}
KnxSensor(KNX_ENERGY_POWER, energy_active_power);
if (!energy_type_dc) { KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor); }
KnxSensor(KNX_ENERGY_DAILY, energy_daily);
KnxSensor(KNX_ENERGY_TOTAL, energy_total);
KnxSensor(KNX_ENERGY_START, energy_start);
KnxSensor(KNX_ENERGY_POWER, Energy.active_power);
if (!Energy.type_dc) { KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor); }
KnxSensor(KNX_ENERGY_DAILY, Energy.daily);
KnxSensor(KNX_ENERGY_TOTAL, Energy.total);
KnxSensor(KNX_ENERGY_START, Energy.start_energy);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
if (energy_voltage_available) {
if (Energy.voltage_available) {
WSContentSend_PD(PSTR("{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"), voltage_chr);
}
if (energy_current_available) {
if (Energy.current_available) {
WSContentSend_PD(PSTR("{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"), current_chr);
}
WSContentSend_PD(PSTR("{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"), active_power_chr);
if (!energy_type_dc) {
if (energy_current_available && energy_voltage_available) {
if (!Energy.type_dc) {
if (Energy.current_available && Energy.voltage_available) {
WSContentSend_PD(HTTP_ENERGY_SNS1, apparent_power_chr, reactive_power_chr, power_factor_chr);
}
if (!isnan(energy_frequency)) {
if (!isnan(Energy.frequency)) {
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), frequency_chr);
}
}
@ -795,7 +799,7 @@ bool Xdrv03(uint8_t function)
break;
#ifdef USE_ENERGY_MARGIN_DETECTION
case FUNC_SET_POWER:
energy_power_steady_cntr = 2;
Energy.power_steady_counter = 2;
break;
#endif // USE_ENERGY_MARGIN_DETECTION
case FUNC_SERIAL:

View File

@ -41,33 +41,35 @@
#define HLW_SAMPLE_COUNT 10 // Max number of samples per cycle
//#define HLW_DEBUG
struct HLW {
#ifdef HLW_DEBUG
unsigned long hlw_debug[HLW_SAMPLE_COUNT];
unsigned long debug[HLW_SAMPLE_COUNT];
#endif
unsigned long cf_pulse_length = 0;
unsigned long cf_pulse_last_time = 0;
unsigned long cf_power_pulse_length = 0;
unsigned long hlw_cf_pulse_length = 0;
unsigned long hlw_cf_pulse_last_time = 0;
unsigned long hlw_cf_power_pulse_length = 0;
unsigned long cf1_pulse_length = 0;
unsigned long cf1_pulse_last_time = 0;
unsigned long cf1_summed_pulse_length = 0;
unsigned long cf1_pulse_counter = 0;
unsigned long cf1_voltage_pulse_length = 0;
unsigned long cf1_current_pulse_length = 0;
unsigned long hlw_cf1_pulse_length = 0;
unsigned long hlw_cf1_pulse_last_time = 0;
unsigned long hlw_cf1_summed_pulse_length = 0;
unsigned long hlw_cf1_pulse_counter = 0;
unsigned long hlw_cf1_voltage_pulse_length = 0;
unsigned long hlw_cf1_current_pulse_length = 0;
unsigned long energy_period_counter = 0;
unsigned long hlw_energy_period_counter = 0;
unsigned long power_ratio = 0;
unsigned long voltage_ratio = 0;
unsigned long current_ratio = 0;
unsigned long hlw_power_ratio = 0;
unsigned long hlw_voltage_ratio = 0;
unsigned long hlw_current_ratio = 0;
uint8_t hlw_select_ui_flag = 0;
uint8_t hlw_ui_flag = 1;
uint8_t hlw_model_type = 0;
uint8_t hlw_load_off = 1;
uint8_t hlw_cf1_timer = 0;
uint8_t hlw_power_retry = 0;
uint8_t model_type = 0;
uint8_t cf1_timer = 0;
uint8_t power_retry = 0;
bool select_ui_flag = false;
bool ui_flag = true;
bool load_off = true;
} Hlw;
// Fix core 2.5.x ISR not in IRAM Exception
#ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception
@ -79,34 +81,34 @@ void HlwCfInterrupt(void) // Service Power
{
unsigned long us = micros();
if (hlw_load_off) { // Restart plen measurement
hlw_cf_pulse_last_time = us;
hlw_load_off = 0;
if (Hlw.load_off) { // Restart plen measurement
Hlw.cf_pulse_last_time = us;
Hlw.load_off = false;
} else {
hlw_cf_pulse_length = us - hlw_cf_pulse_last_time;
hlw_cf_pulse_last_time = us;
hlw_energy_period_counter++;
Hlw.cf_pulse_length = us - Hlw.cf_pulse_last_time;
Hlw.cf_pulse_last_time = us;
Hlw.energy_period_counter++;
}
energy_data_valid = 0;
Energy.data_valid = 0;
}
void HlwCf1Interrupt(void) // Service Voltage and Current
{
unsigned long us = micros();
hlw_cf1_pulse_length = us - hlw_cf1_pulse_last_time;
hlw_cf1_pulse_last_time = us;
if ((hlw_cf1_timer > 2) && (hlw_cf1_timer < 8)) { // Allow for 300 mSec set-up time and measure for up to 1 second
hlw_cf1_summed_pulse_length += hlw_cf1_pulse_length;
Hlw.cf1_pulse_length = us - Hlw.cf1_pulse_last_time;
Hlw.cf1_pulse_last_time = us;
if ((Hlw.cf1_timer > 2) && (Hlw.cf1_timer < 8)) { // Allow for 300 mSec set-up time and measure for up to 1 second
Hlw.cf1_summed_pulse_length += Hlw.cf1_pulse_length;
#ifdef HLW_DEBUG
hlw_debug[hlw_cf1_pulse_counter] = hlw_cf1_pulse_length;
Hlw.debug[Hlw.cf1_pulse_counter] = Hlw.cf1_pulse_length;
#endif
hlw_cf1_pulse_counter++;
if (HLW_SAMPLE_COUNT == hlw_cf1_pulse_counter) {
hlw_cf1_timer = 8; // We need up to HLW_SAMPLE_COUNT samples within 1 second (low current could take up to 0.3 second)
Hlw.cf1_pulse_counter++;
if (HLW_SAMPLE_COUNT == Hlw.cf1_pulse_counter) {
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;
Energy.data_valid = 0;
}
/********************************************************************************************/
@ -118,97 +120,97 @@ void HlwEvery200ms(void)
unsigned long hlw_u = 0;
unsigned long hlw_i = 0;
if (micros() - hlw_cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) {
hlw_cf_pulse_length = 0; // No load for some time
hlw_load_off = 1;
if (micros() - Hlw.cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) {
Hlw.cf_pulse_length = 0; // No load for some time
Hlw.load_off = true;
}
hlw_cf_power_pulse_length = hlw_cf_pulse_length;
Hlw.cf_power_pulse_length = Hlw.cf_pulse_length;
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 = (float)hlw_w / 10;
hlw_power_retry = 1; // Workaround issue #5161
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 = (float)hlw_w / 10;
Hlw.power_retry = 1; // Workaround issue #5161
} else {
if (hlw_power_retry) {
hlw_power_retry--;
if (Hlw.power_retry) {
Hlw.power_retry--;
} else {
energy_active_power = 0;
Energy.active_power = 0;
}
}
if (pin[GPIO_NRG_CF1] < 99) {
hlw_cf1_timer++;
if (hlw_cf1_timer >= 8) {
hlw_cf1_timer = 0;
hlw_select_ui_flag = (hlw_select_ui_flag) ? 0 : 1;
Hlw.cf1_timer++;
if (Hlw.cf1_timer >= 8) {
Hlw.cf1_timer = 0;
Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true;
if (pin[GPIO_NRG_SEL] < 99) {
digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag);
digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag);
}
if (hlw_cf1_pulse_counter) {
cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter;
if (Hlw.cf1_pulse_counter) {
cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter;
}
#ifdef HLW_DEBUG
// Debugging for calculating mean and median
char stemp[100];
stemp[0] = '\0';
for (uint32_t i = 0; i < hlw_cf1_pulse_counter; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, hlw_debug[i]);
for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, Hlw.debug[i]);
}
for (uint32_t i = 0; i < hlw_cf1_pulse_counter; i++) {
for (uint32_t j = i + 1; j < hlw_cf1_pulse_counter; j++) {
if (hlw_debug[i] > hlw_debug[j]) { // Sort ascending
std::swap(hlw_debug[i], hlw_debug[j]);
for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) {
for (uint32_t j = i + 1; j < Hlw.cf1_pulse_counter; j++) {
if (Hlw.debug[i] > Hlw.debug[j]) { // Sort ascending
std::swap(Hlw.debug[i], Hlw.debug[j]);
}
}
}
unsigned long median = hlw_debug[(hlw_cf1_pulse_counter +1) / 2];
unsigned long median = Hlw.debug[(Hlw.cf1_pulse_counter +1) / 2];
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"),
hlw_cf_power_pulse_length, hlw_select_ui_flag, hlw_cf1_pulse_counter, stemp, hlw_cf1_summed_pulse_length, cf1_pulse_length, median);
Hlw.cf_power_pulse_length , Hlw.select_ui_flag, Hlw.cf1_pulse_counter, stemp, Hlw.cf1_summed_pulse_length, cf1_pulse_length, median);
#endif
if (hlw_select_ui_flag == hlw_ui_flag) {
hlw_cf1_voltage_pulse_length = cf1_pulse_length;
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
hlw_u = (hlw_voltage_ratio * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; // V *10
energy_voltage = (float)hlw_u / 10;
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 = (float)hlw_u / 10;
} else {
energy_voltage = 0;
Energy.voltage = 0;
}
} else {
hlw_cf1_current_pulse_length = cf1_pulse_length;
Hlw.cf1_current_pulse_length = cf1_pulse_length;
if (hlw_cf1_current_pulse_length && energy_active_power) { // No current if no power being consumed
hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; // mA
energy_current = (float)hlw_i / 1000;
if (Hlw.cf1_current_pulse_length && Energy.active_power) { // No current if no power being consumed
hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; // mA
Energy.current = (float)hlw_i / 1000;
} else {
energy_current = 0;
Energy.current = 0;
}
}
hlw_cf1_summed_pulse_length = 0;
hlw_cf1_pulse_counter = 0;
Hlw.cf1_summed_pulse_length = 0;
Hlw.cf1_pulse_counter = 0;
}
}
}
void HlwEverySecond(void)
{
if (energy_data_valid > ENERGY_WATCHDOG) {
hlw_cf1_voltage_pulse_length = 0;
hlw_cf1_current_pulse_length = 0;
hlw_cf_power_pulse_length = 0;
if (Energy.data_valid > ENERGY_WATCHDOG) {
Hlw.cf1_voltage_pulse_length = 0;
Hlw.cf1_current_pulse_length = 0;
Hlw.cf_power_pulse_length = 0;
} else {
unsigned long hlw_len;
if (hlw_energy_period_counter) {
hlw_len = 10000 / hlw_energy_period_counter;
hlw_energy_period_counter = 0;
if (Hlw.energy_period_counter) {
hlw_len = 10000 / Hlw.energy_period_counter;
Hlw.energy_period_counter = 0;
if (hlw_len) {
energy_kWhtoday_delta += ((hlw_power_ratio * Settings.energy_power_calibration) / hlw_len) / 36;
Energy.kWhtoday_delta += ((Hlw.power_ratio * Settings.energy_power_calibration) / hlw_len) / 36;
EnergyUpdateToday();
}
}
@ -223,19 +225,19 @@ void HlwSnsInit(void)
Settings.energy_current_calibration = HLW_IREF_PULSE;
}
if (hlw_model_type) {
hlw_power_ratio = HJL_PREF;
hlw_voltage_ratio = HJL_UREF;
hlw_current_ratio = HJL_IREF;
if (Hlw.model_type) {
Hlw.power_ratio = HJL_PREF;
Hlw.voltage_ratio = HJL_UREF;
Hlw.current_ratio = HJL_IREF;
} else {
hlw_power_ratio = HLW_PREF;
hlw_voltage_ratio = HLW_UREF;
hlw_current_ratio = HLW_IREF;
Hlw.power_ratio = HLW_PREF;
Hlw.voltage_ratio = HLW_UREF;
Hlw.current_ratio = HLW_IREF;
}
if (pin[GPIO_NRG_SEL] < 99) {
pinMode(pin[GPIO_NRG_SEL], OUTPUT);
digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag);
digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag);
}
if (pin[GPIO_NRG_CF1] < 99) {
pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP);
@ -248,29 +250,29 @@ void HlwSnsInit(void)
void HlwDrvInit(void)
{
if (!energy_flg) {
hlw_model_type = 0; // HLW8012
Hlw.model_type = 0; // HLW8012
if (pin[GPIO_HJL_CF] < 99) {
pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF];
pin[GPIO_HJL_CF] = 99;
hlw_model_type = 1; // HJL-01/BL0937
Hlw.model_type = 1; // HJL-01/BL0937
}
if (pin[GPIO_HLW_CF] < 99) { // HLW8012 or HJL-01 based device Power monitor
hlw_ui_flag = 1; // Voltage on high
Hlw.ui_flag = true; // Voltage on high
if (pin[GPIO_NRG_SEL_INV] < 99) {
pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV];
pin[GPIO_NRG_SEL_INV] = 99;
hlw_ui_flag = 0; // Voltage on low
Hlw.ui_flag = false; // Voltage on low
}
if (pin[GPIO_NRG_CF1] < 99) { // Voltage and/or Current monitor
if (99 == pin[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_flg = XNRG_01;
@ -282,22 +284,22 @@ 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) {
if (XdrvMailbox.data_len && hlw_cf_power_pulse_length) {
Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * hlw_cf_power_pulse_length) / hlw_power_ratio;
else if (CMND_POWERSET == Energy.command_code) {
if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) {
Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio;
}
}
else if (CMND_VOLTAGESET == energy_command_code) {
if (XdrvMailbox.data_len && hlw_cf1_voltage_pulse_length) {
Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * hlw_cf1_voltage_pulse_length) / hlw_voltage_ratio;
else if (CMND_VOLTAGESET == Energy.command_code) {
if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) {
Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio;
}
}
else if (CMND_CURRENTSET == energy_command_code) {
if (XdrvMailbox.data_len && hlw_cf1_current_pulse_length) {
Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * hlw_cf1_current_pulse_length) / hlw_current_ratio;
else if (CMND_CURRENTSET == Energy.command_code) {
if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) {
Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio;
}
}
else serviced = false; // Unknown command

View File

@ -37,15 +37,17 @@
#define CSE_PREF 1000
#define CSE_UREF 100
uint8_t cse_receive_flag = 0;
struct CSE {
long voltage_cycle = 0;
long current_cycle = 0;
long power_cycle = 0;
long power_cycle_first = 0;
long cf_pulses = 0;
long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED;
long voltage_cycle = 0;
long current_cycle = 0;
long power_cycle = 0;
long power_cycle_first = 0;
long cf_pulses = 0;
long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED;
uint8_t cse_power_invalid = 0;
uint8_t power_invalid = 0;
bool received = false;
} Cse;
void CseReceived(void)
{
@ -84,54 +86,54 @@ void CseReceived(void)
}
uint8_t adjustement = serial_in_buffer[20];
voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7];
current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13];
power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19];
cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22];
Cse.voltage_cycle = serial_in_buffer[5] << 16 | serial_in_buffer[6] << 8 | serial_in_buffer[7];
Cse.current_cycle = serial_in_buffer[11] << 16 | serial_in_buffer[12] << 8 | serial_in_buffer[13];
Cse.power_cycle = serial_in_buffer[17] << 16 | serial_in_buffer[18] << 8 | serial_in_buffer[19];
Cse.cf_pulses = serial_in_buffer[21] << 8 | serial_in_buffer[22];
if (energy_power_on) { // Powered on
if (Energy.power_on) { // Powered on
if (adjustement & 0x40) { // Voltage valid
energy_voltage = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)voltage_cycle;
Energy.voltage = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle;
}
if (adjustement & 0x10) { // Power valid
cse_power_invalid = 0;
Cse.power_invalid = 0;
if ((header & 0xF2) == 0xF2) { // Power cycle exceeds range
energy_active_power = 0;
Energy.active_power = 0;
} else {
if (0 == power_cycle_first) { power_cycle_first = power_cycle; } // Skip first incomplete power_cycle
if (power_cycle_first != power_cycle) {
power_cycle_first = -1;
energy_active_power = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)power_cycle;
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 = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle;
} else {
energy_active_power = 0;
Energy.active_power = 0;
}
}
} else {
if (cse_power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { // Allow measurements down to about 1W
cse_power_invalid++;
if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { // Allow measurements down to about 1W
Cse.power_invalid++;
} else {
power_cycle_first = 0;
energy_active_power = 0; // Powered on but no load
Cse.power_cycle_first = 0;
Energy.active_power = 0; // Powered on but no load
}
}
if (adjustement & 0x20) { // Current valid
if (0 == energy_active_power) {
energy_current = 0;
if (0 == Energy.active_power) {
Energy.current = 0;
} else {
energy_current = (float)Settings.energy_current_calibration / (float)current_cycle;
Energy.current = (float)Settings.energy_current_calibration / (float)Cse.current_cycle;
}
}
} else { // Powered off
power_cycle_first = 0;
energy_voltage = 0;
energy_active_power = 0;
energy_current = 0;
Cse.power_cycle_first = 0;
Energy.voltage = 0;
Energy.active_power = 0;
Energy.current = 0;
}
}
bool CseSerialInput(void)
{
if (cse_receive_flag) {
if (Cse.received) {
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
if (24 == serial_in_byte_counter) {
@ -140,9 +142,9 @@ bool CseSerialInput(void)
uint8_t checksum = 0;
for (uint32_t i = 2; i < 23; i++) { checksum += serial_in_buffer[i]; }
if (checksum == serial_in_buffer[23]) {
energy_data_valid = 0;
Energy.data_valid = 0;
CseReceived();
cse_receive_flag = 0;
Cse.received = false;
return 1;
} else {
AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE));
@ -151,14 +153,14 @@ bool CseSerialInput(void)
serial_in_byte_counter--;
} while ((serial_in_byte_counter > 2) && (0x5A != serial_in_buffer[1]));
if (0x5A != serial_in_buffer[1]) {
cse_receive_flag = 0;
Cse.received = false;
serial_in_byte_counter = 0;
}
}
}
} else {
if ((0x5A == serial_in_byte) && (1 == serial_in_byte_counter)) { // 0x5A - Packet header 2
cse_receive_flag = 1;
Cse.received = true;
} else {
serial_in_byte_counter = 0;
}
@ -172,31 +174,31 @@ bool CseSerialInput(void)
void CseEverySecond(void)
{
if (energy_data_valid > ENERGY_WATCHDOG) {
voltage_cycle = 0;
current_cycle = 0;
power_cycle = 0;
if (Energy.data_valid > ENERGY_WATCHDOG) {
Cse.voltage_cycle = 0;
Cse.current_cycle = 0;
Cse.power_cycle = 0;
} else {
long cf_frequency = 0;
if (CSE_PULSES_NOT_INITIALIZED == cf_pulses_last_time) {
cf_pulses_last_time = cf_pulses; // Init after restart
if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) {
Cse.cf_pulses_last_time = Cse.cf_pulses; // Init after restart
} else {
if (cf_pulses < cf_pulses_last_time) { // Rolled over after 65535 pulses
cf_frequency = (65536 - cf_pulses_last_time) + cf_pulses;
if (Cse.cf_pulses < Cse.cf_pulses_last_time) { // Rolled over after 65535 pulses
cf_frequency = (65536 - Cse.cf_pulses_last_time) + Cse.cf_pulses;
} else {
cf_frequency = cf_pulses - cf_pulses_last_time;
cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time;
}
if (cf_frequency && energy_active_power) {
if (cf_frequency && Energy.active_power) {
unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36;
// prevent invalid load delta steps even checksum is valid (issue #5789):
if (delta <= (3680*100/36) * 10 ) { // max load for S31/Pow R2: 3.68kW
cf_pulses_last_time = cf_pulses;
energy_kWhtoday_delta += delta;
Cse.cf_pulses_last_time = Cse.cf_pulses;
Energy.kWhtoday_delta += delta;
}
else {
AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow"));
cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED;
Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED;
}
EnergyUpdateToday();
}
@ -213,7 +215,7 @@ void CseDrvInit(void)
if (0 == Settings.param[P_CSE7766_INVALID_POWER]) {
Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255
}
cse_power_invalid = Settings.param[P_CSE7766_INVALID_POWER];
Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER];
energy_flg = XNRG_02;
}
}
@ -223,19 +225,19 @@ bool CseCommand(void)
{
bool serviced = true;
if (CMND_POWERSET == energy_command_code) {
if (XdrvMailbox.data_len && power_cycle) {
Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * power_cycle) / CSE_PREF;
if (CMND_POWERSET == Energy.command_code) {
if (XdrvMailbox.data_len && Cse.power_cycle) {
Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF;
}
}
else if (CMND_VOLTAGESET == energy_command_code) {
if (XdrvMailbox.data_len && voltage_cycle) {
Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * voltage_cycle) / CSE_UREF;
else if (CMND_VOLTAGESET == Energy.command_code) {
if (XdrvMailbox.data_len && Cse.voltage_cycle) {
Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF;
}
}
else if (CMND_CURRENTSET == energy_command_code) {
if (XdrvMailbox.data_len && current_cycle) {
Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * current_cycle) / 1000;
else if (CMND_CURRENTSET == Energy.command_code) {
if (XdrvMailbox.data_len && Cse.current_cycle) {
Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000;
}
}
else serviced = false; // Unknown command

View File

@ -169,22 +169,22 @@ void PzemEvery200ms(void)
if (data_ready) {
float value = 0;
if (PzemRecieve(pzem_responses[pzem_read_state], &value)) {
energy_data_valid = 0;
Energy.data_valid = 0;
switch (pzem_read_state) {
case 1: // Voltage as 230.2V
energy_voltage = value;
Energy.voltage = value;
break;
case 2: // Current as 17.32A
energy_current = value;
Energy.current = value;
break;
case 3: // Power as 20W
energy_active_power = value;
Energy.active_power = value;
break;
case 4: // Total energy as 99999Wh
if (!energy_start || (value < energy_start)) energy_start = value; // Init after restart and hanlde roll-over if any
if (value != energy_start) {
energy_kWhtoday += (unsigned long)((value - energy_start) * 100);
energy_start = value;
if (!Energy.start_energy || (value < Energy.start_energy)) Energy.start_energy = value; // Init after restart and hanlde roll-over if any
if (value != Energy.start_energy) {
Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * 100);
Energy.start_energy = value;
}
EnergyUpdateToday();
break;

View File

@ -454,22 +454,22 @@ 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_frequency = (float)mcp_line_frequency / 1000;
energy_voltage = (float)mcp_voltage_rms / 10;
energy_active_power = (float)mcp_active_power / 100;
if (0 == energy_active_power) {
energy_current = 0;
if (Energy.power_on) { // Powered on
Energy.frequency = (float)mcp_line_frequency / 1000;
Energy.voltage = (float)mcp_voltage_rms / 10;
Energy.active_power = (float)mcp_active_power / 100;
if (0 == Energy.active_power) {
Energy.current = 0;
} else {
energy_current = (float)mcp_current_rms / 10000;
Energy.current = (float)mcp_current_rms / 10000;
}
} else { // Powered off
energy_frequency = 0;
energy_voltage = 0;
energy_active_power = 0;
energy_current = 0;
Energy.frequency = 0;
Energy.voltage = 0;
Energy.active_power = 0;
Energy.current = 0;
}
energy_data_valid = 0;
Energy.data_valid = 0;
}
/********************************************************************************************/
@ -527,7 +527,7 @@ void McpSerialInput(void)
void McpEverySecond(void)
{
if (energy_data_valid > ENERGY_WATCHDOG) {
if (Energy.data_valid > ENERGY_WATCHDOG) {
mcp_voltage_rms = 0;
mcp_current_rms = 0;
mcp_active_power = 0;
@ -535,7 +535,7 @@ void McpEverySecond(void)
}
if (mcp_active_power) {
energy_kWhtoday_delta += ((mcp_active_power * 10) / 36);
Energy.kWhtoday_delta += ((mcp_active_power * 10) / 36);
EnergyUpdateToday();
}
@ -602,7 +602,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
@ -612,7 +612,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
@ -622,7 +622,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
@ -632,7 +632,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

@ -70,22 +70,22 @@ void PzemAcEverySecond(void)
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemAc response error %d"), error);
} else {
// if ((PzemCalculateCRC(buffer, 23)) == ((buffer[24] << 8) | buffer[23])) {
energy_data_valid = 0;
Energy.data_valid = 0;
// 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
// 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 = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V
energy_current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A
energy_active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W
energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz
energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
Energy.voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V
Energy.current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A
Energy.active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W
Energy.frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz
Energy.power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh
if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and handle roll-over if any
if (energy != energy_start) {
energy_kWhtoday += (unsigned long)((energy - energy_start) * 100);
energy_start = energy;
if (!Energy.start_energy || (energy < Energy.start_energy)) { Energy.start_energy = energy; } // Init after restart and handle roll-over if any
if (energy != Energy.start_energy) {
Energy.kWhtoday += (unsigned long)((energy - Energy.start_energy) * 100);
Energy.start_energy = energy;
}
EnergyUpdateToday();
// }

View File

@ -51,20 +51,20 @@ void PzemDcEverySecond(void)
if (error) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemDc response error %d"), error);
} else {
energy_data_valid = 0;
Energy.data_valid = 0;
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// 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 = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V
energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A
energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W
Energy.voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V
Energy.current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A
Energy.active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W
float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh
if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and handle roll-over if any
if (energy != energy_start) {
energy_kWhtoday += (unsigned long)((energy - energy_start) * 100);
energy_start = energy;
if (!Energy.start_energy || (energy < Energy.start_energy)) { Energy.start_energy = energy; } // Init after restart and handle roll-over if any
if (energy != Energy.start_energy) {
Energy.kWhtoday += (unsigned long)((energy - Energy.start_energy) * 100);
Energy.start_energy = energy;
}
EnergyUpdateToday();
}
@ -85,7 +85,7 @@ void PzemDcSnsInit(void)
uint8_t result = PzemDcModbus->Begin(9600, 2); // Uses two stop bits!!
if (result) {
if (2 == result) { ClaimSerial(); }
energy_type_dc = true;
Energy.type_dc = true;
} else {
energy_flg = ENERGY_NONE;
}

View File

@ -36,14 +36,16 @@
#define ADE7953_ADDR 0x38
uint32_t ade7953_active_power = 0;
uint32_t ade7953_active_power1 = 0;
uint32_t ade7953_active_power2 = 0;
uint32_t ade7953_current_rms = 0;
uint32_t ade7953_current_rms1 = 0;
uint32_t ade7953_current_rms2 = 0;
uint32_t ade7953_voltage_rms = 0;
uint8_t ade7953_init = 0;
struct Ade7953 {
uint32_t active_power = 0;
uint32_t active_power1 = 0;
uint32_t active_power2 = 0;
uint32_t current_rms = 0;
uint32_t current_rms1 = 0;
uint32_t current_rms2 = 0;
uint32_t voltage_rms = 0;
uint8_t init_step = 0;
} Ade7953;
int Ade7953RegSize(uint16_t reg)
{
@ -109,57 +111,57 @@ void Ade7953GetData(void)
{
int32_t active_power;
ade7953_voltage_rms = Ade7953Read(0x31C); // Both relays
ade7953_current_rms1 = Ade7953Read(0x31B); // Relay 1
if (ade7953_current_rms1 < 2000) { // No load threshold (20mA)
ade7953_current_rms1 = 0;
ade7953_active_power1 = 0;
Ade7953.voltage_rms = Ade7953Read(0x31C); // Both relays
Ade7953.current_rms1 = Ade7953Read(0x31B); // Relay 1
if (Ade7953.current_rms1 < 2000) { // No load threshold (20mA)
Ade7953.current_rms1 = 0;
Ade7953.active_power1 = 0;
} else {
active_power = (int32_t)Ade7953Read(0x313) * -1; // Relay 1
ade7953_active_power1 = (active_power > 0) ? active_power : 0;
Ade7953.active_power1 = (active_power > 0) ? active_power : 0;
}
ade7953_current_rms2 = Ade7953Read(0x31A); // Relay 2
if (ade7953_current_rms2 < 2000) { // No load threshold (20mA)
ade7953_current_rms2 = 0;
ade7953_active_power2 = 0;
Ade7953.current_rms2 = Ade7953Read(0x31A); // Relay 2
if (Ade7953.current_rms2 < 2000) { // No load threshold (20mA)
Ade7953.current_rms2 = 0;
Ade7953.active_power2 = 0;
} else {
active_power = (int32_t)Ade7953Read(0x312); // Relay 2
ade7953_active_power2 = (active_power > 0) ? active_power : 0;
Ade7953.active_power2 = (active_power > 0) ? active_power : 0;
}
// First phase only supports accumulated Current and Power
ade7953_current_rms = ade7953_current_rms1 + ade7953_current_rms2;
ade7953_active_power = ade7953_active_power1 + ade7953_active_power2;
Ade7953.current_rms = Ade7953.current_rms1 + Ade7953.current_rms2;
Ade7953.active_power = Ade7953.active_power1 + Ade7953.active_power2;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, I %d + %d = %d, P %d + %d = %d"),
ade7953_voltage_rms, ade7953_current_rms1, ade7953_current_rms2, ade7953_current_rms, ade7953_active_power1, ade7953_active_power2, ade7953_active_power);
Ade7953.voltage_rms, Ade7953.current_rms1, Ade7953.current_rms2, Ade7953.current_rms, Ade7953.active_power1, Ade7953.active_power2, Ade7953.active_power);
if (energy_power_on) { // Powered on
energy_voltage = (float)ade7953_voltage_rms / Settings.energy_voltage_calibration;
energy_active_power = (float)ade7953_active_power / (Settings.energy_power_calibration / 10);
if (0 == energy_active_power) {
energy_current = 0;
if (Energy.power_on) { // Powered on
Energy.voltage = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration;
Energy.active_power = (float)Ade7953.active_power / (Settings.energy_power_calibration / 10);
if (0 == Energy.active_power) {
Energy.current = 0;
} else {
energy_current = (float)ade7953_current_rms / (Settings.energy_current_calibration * 10);
Energy.current = (float)Ade7953.current_rms / (Settings.energy_current_calibration * 10);
}
} else { // Powered off
energy_voltage = 0;
energy_active_power = 0;
energy_current = 0;
Energy.voltage = 0;
Energy.active_power = 0;
Energy.current = 0;
}
if (ade7953_active_power) {
energy_kWhtoday_delta += ((ade7953_active_power * (100000 / (Settings.energy_power_calibration / 10))) / 3600);
if (Ade7953.active_power) {
Energy.kWhtoday_delta += ((Ade7953.active_power * (100000 / (Settings.energy_power_calibration / 10))) / 3600);
EnergyUpdateToday();
}
}
void Ade7953EnergyEverySecond()
{
if (ade7953_init) {
if (1 == ade7953_init) {
if (Ade7953.init_step) {
if (1 == Ade7953.init_step) {
Ade7953Init();
}
ade7953_init--;
Ade7953.init_step--;
} else {
Ade7953GetData();
}
@ -177,7 +179,7 @@ void Ade7953DrvInit(void)
Settings.energy_current_calibration = ADE7953_IREF;
}
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADE7953", ADE7953_ADDR);
ade7953_init = 2;
Ade7953.init_step = 2;
energy_flg = XNRG_07;
}
}
@ -190,36 +192,36 @@ bool Ade7953Command(void)
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) {
if (XdrvMailbox.data_len && ade7953_active_power) {
else if (CMND_POWERSET == Energy.command_code) {
if (XdrvMailbox.data_len && Ade7953.active_power) {
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
Settings.energy_power_calibration = (ade7953_active_power * 1000) / value; // 0.00 W
Settings.energy_power_calibration = (Ade7953.active_power * 1000) / value; // 0.00 W
}
}
}
else if (CMND_VOLTAGESET == energy_command_code) {
if (XdrvMailbox.data_len && ade7953_voltage_rms) {
else if (CMND_VOLTAGESET == Energy.command_code) {
if (XdrvMailbox.data_len && Ade7953.voltage_rms) {
if ((value > 10000) && (value < 26000)) { // Between 100V and 260V
Settings.energy_voltage_calibration = (ade7953_voltage_rms * 100) / value; // 0.00 V
Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; // 0.00 V
}
}
}
else if (CMND_CURRENTSET == energy_command_code) {
if (XdrvMailbox.data_len && ade7953_current_rms) {
else if (CMND_CURRENTSET == Energy.command_code) {
if (XdrvMailbox.data_len && Ade7953.current_rms) {
if ((value > 2000) && (value < 1000000)) { // Between 20mA and 10A
Settings.energy_current_calibration = ((ade7953_current_rms * 100) / value) * 100; // 0.00 mA
Settings.energy_current_calibration = ((Ade7953.current_rms * 100) / value) * 100; // 0.00 mA
}
}
}