mirror of https://github.com/arendst/Tasmota.git
Add Energy 3 phase/channel support
* Change energy sensors for three phase/channel support * Add Shelly 2.5 energy dual channel support (#6160)
This commit is contained in:
parent
180128dc4a
commit
5eb85075e5
|
@ -6,6 +6,8 @@
|
|||
* Add command Gpios 255/All to show all available GPIO components (#6407)
|
||||
* Change JSON output format for commands Adc, Adcs, Modules, Gpio and Gpios from list to dictionary (#6407)
|
||||
* Add Zigbee support phase 3 - support for Xiaomi lumi.weather air quality sensor, Osram mini-switch
|
||||
* Change energy sensors for three phase/channel support
|
||||
* Add Shelly 2.5 energy dual channel support (#6160)
|
||||
*
|
||||
* 6.6.0.11 20190907
|
||||
* Change Settings crc calculation allowing short term backward compatibility
|
||||
|
|
|
@ -68,33 +68,37 @@ void (* const EnergyCommand[])(void) PROGMEM = {
|
|||
#endif // USE_ENERGY_MARGIN_DETECTION
|
||||
&CmndEnergyReset, &CmndTariff };
|
||||
|
||||
const char kEnergyPhases[] PROGMEM = "|%s / %s|%s / %s / %s||[%s,%s]|[%s,%s,%s]";
|
||||
|
||||
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 voltage[3] = { 0, 0, 0 }; // 123.1 V
|
||||
float current[3] = { 0, 0, 0 }; // 123.123 A
|
||||
float active_power[3] = { 0, 0, 0 }; // 123.1 W
|
||||
float apparent_power[3] = { NAN, NAN, NAN }; // 123.1 VA
|
||||
float reactive_power[3] = { NAN, NAN, NAN }; // 123.1 VAr
|
||||
float power_factor[3] = { NAN, NAN, NAN }; // 0.12
|
||||
float frequency[3] = { NAN, NAN, NAN }; // 123.1 Hz
|
||||
|
||||
float start_energy = 0; // 12345.12345 kWh total previous
|
||||
float start_energy = 0; // 12345.12345 kWh total previous
|
||||
float daily = 0; // 123.123 kWh
|
||||
float total = 0; // 12345.12345 kWh tariff 1 + 2
|
||||
float total1 = 0; // 12345.12345 kWh tariff 1 - off-peak
|
||||
float export_active = NAN; // 123.123 KWh
|
||||
|
||||
float daily = 0; // 123.123 kWh
|
||||
float total = 0; // 12345.12345 kWh tariff 1 + 2
|
||||
float total1 = 0; // 12345.12345 kWh tariff 1 - off-peak
|
||||
float export_active = NAN; // 123.123 KWh
|
||||
|
||||
unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only)
|
||||
unsigned long kWhtoday_offset = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
||||
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
|
||||
unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only)
|
||||
unsigned long kWhtoday_offset = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
||||
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
|
||||
|
||||
uint8_t fifth_second = 0;
|
||||
uint8_t command_code = 0;
|
||||
uint8_t data_valid = 0;
|
||||
|
||||
bool voltage_available = true; // Enable if voltage is measured
|
||||
bool current_available = true; // Enable if current is measured
|
||||
uint8_t phase_count = 1; // Number of phases active
|
||||
bool voltage_common = false; // Use single voltage
|
||||
|
||||
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;
|
||||
|
@ -275,23 +279,23 @@ void EnergyMarginCheck(void)
|
|||
}
|
||||
|
||||
if (Settings.energy_power_delta) {
|
||||
float delta = abs(Energy.power_history[0] - Energy.active_power);
|
||||
float delta = abs(Energy.power_history[0] - Energy.active_power[0]);
|
||||
// Any delta compared to minimal delta
|
||||
float min_power = (Energy.power_history[0] > Energy.active_power) ? Energy.active_power : Energy.power_history[0];
|
||||
float min_power = (Energy.power_history[0] > Energy.active_power[0]) ? Energy.active_power[0] : Energy.power_history[0];
|
||||
if (((delta / min_power) * 100) > Settings.energy_power_delta) {
|
||||
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_history[1] = Energy.active_power[0]; // We only want one report so reset history
|
||||
Energy.power_history[2] = Energy.active_power[0];
|
||||
}
|
||||
}
|
||||
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;
|
||||
Energy.power_history[2] = Energy.active_power[0];
|
||||
|
||||
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);
|
||||
energy_power_u = (uint16_t)(Energy.active_power[0]);
|
||||
energy_voltage_u = (uint16_t)(Energy.voltage[0]);
|
||||
energy_current_u = (uint16_t)(Energy.current[0] * 1000);
|
||||
|
||||
DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u);
|
||||
|
||||
|
@ -331,7 +335,7 @@ 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.active_power[0] > Settings.energy_max_power_limit) {
|
||||
if (!Energy.mplh_counter) {
|
||||
Energy.mplh_counter = Settings.energy_max_power_limit_hold;
|
||||
} else {
|
||||
|
@ -422,13 +426,15 @@ void EnergyOverTempCheck()
|
|||
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.apparent_power)) { Energy.apparent_power = 0; }
|
||||
if (!isnan(Energy.reactive_power)) { Energy.reactive_power = 0; }
|
||||
if (!isnan(Energy.frequency)) { Energy.frequency = 0; }
|
||||
if (!isnan(Energy.power_factor)) { Energy.power_factor = 0; }
|
||||
for (uint32_t i = 0; i < Energy.phase_count; i++) {
|
||||
Energy.voltage[i] = 0;
|
||||
Energy.current[i] = 0;
|
||||
Energy.active_power[i] = 0;
|
||||
if (!isnan(Energy.apparent_power[i])) { Energy.apparent_power[i] = 0; }
|
||||
if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; }
|
||||
if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; }
|
||||
if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; }
|
||||
}
|
||||
if (!isnan(Energy.export_active)) { Energy.export_active = 0; }
|
||||
Energy.start_energy = 0;
|
||||
|
||||
|
@ -778,55 +784,93 @@ const char HTTP_ENERGY_SNS3[] PROGMEM =
|
|||
"{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
char* EnergyFormat(char* result, char* input, bool json, bool single = false)
|
||||
{
|
||||
uint8_t index = (single) ? 1 : Energy.phase_count; // 1,2,3
|
||||
|
||||
char layout[16];
|
||||
GetTextIndexed(layout, sizeof(layout), (index -1) + (3 * json), kEnergyPhases);
|
||||
switch (index) {
|
||||
case 2:
|
||||
snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ); // Dirty
|
||||
break;
|
||||
case 3:
|
||||
snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ, input + FLOATSZ + FLOATSZ); // Even dirtier
|
||||
break;
|
||||
default:
|
||||
snprintf_P(result, FLOATSZ *3, input);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void EnergyShow(bool json)
|
||||
{
|
||||
float power_factor = Energy.power_factor;
|
||||
|
||||
char apparent_power_chr[FLOATSZ];
|
||||
char reactive_power_chr[FLOATSZ];
|
||||
char power_factor_chr[FLOATSZ];
|
||||
char frequency_chr[FLOATSZ];
|
||||
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;
|
||||
}
|
||||
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;
|
||||
if (power_factor > 1) power_factor = 1;
|
||||
}
|
||||
|
||||
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)))) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr);
|
||||
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);
|
||||
for (uint32_t i = 0; i < Energy.phase_count; i++) {
|
||||
if (Energy.voltage_common) {
|
||||
Energy.voltage[i] = Energy.voltage[0];
|
||||
}
|
||||
}
|
||||
|
||||
char voltage_chr[FLOATSZ];
|
||||
dtostrfd(Energy.voltage, Settings.flag2.voltage_resolution, voltage_chr);
|
||||
char current_chr[FLOATSZ];
|
||||
dtostrfd(Energy.current, Settings.flag2.current_resolution, current_chr);
|
||||
char active_power_chr[FLOATSZ];
|
||||
dtostrfd(Energy.active_power, Settings.flag2.wattage_resolution, active_power_chr);
|
||||
float power_factor_knx = Energy.power_factor[0];
|
||||
|
||||
char apparent_power_chr[Energy.phase_count][FLOATSZ];
|
||||
char reactive_power_chr[Energy.phase_count][FLOATSZ];
|
||||
char power_factor_chr[Energy.phase_count][FLOATSZ];
|
||||
char frequency_chr[Energy.phase_count][FLOATSZ];
|
||||
if (!Energy.type_dc) {
|
||||
if (Energy.current_available && Energy.voltage_available) {
|
||||
for (uint32_t i = 0; i < Energy.phase_count; i++) {
|
||||
float apparent_power = Energy.apparent_power[i];
|
||||
if (isnan(apparent_power)) {
|
||||
apparent_power = Energy.voltage[i] * Energy.current[i];
|
||||
}
|
||||
if (apparent_power < Energy.active_power[i]) { // Should be impossible
|
||||
Energy.active_power[i] = apparent_power;
|
||||
}
|
||||
|
||||
float power_factor = Energy.power_factor[i];
|
||||
if (isnan(power_factor)) {
|
||||
power_factor = (Energy.active_power[i] && apparent_power) ? Energy.active_power[i] / apparent_power : 0;
|
||||
if (power_factor > 1) {
|
||||
power_factor = 1;
|
||||
}
|
||||
}
|
||||
if (0 == i) { power_factor_knx = power_factor; }
|
||||
|
||||
float reactive_power = Energy.reactive_power[i];
|
||||
if (isnan(reactive_power)) {
|
||||
reactive_power = 0;
|
||||
uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power[i] * 100)) / 10;
|
||||
if ((Energy.current[i] > 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[i] * Energy.active_power[i] * 100))) / 10;
|
||||
}
|
||||
}
|
||||
|
||||
dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]);
|
||||
dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]);
|
||||
dtostrfd(power_factor, 2, power_factor_chr[i]);
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < Energy.phase_count; i++) {
|
||||
float frequency = Energy.frequency[i];
|
||||
if (isnan(Energy.frequency[i])) {
|
||||
frequency = 0;
|
||||
}
|
||||
dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
char voltage_chr[Energy.phase_count][FLOATSZ];
|
||||
char current_chr[Energy.phase_count][FLOATSZ];
|
||||
char active_power_chr[Energy.phase_count][FLOATSZ];
|
||||
for (uint32_t i = 0; i < Energy.phase_count; i++) {
|
||||
dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]);
|
||||
dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]);
|
||||
dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]);
|
||||
}
|
||||
|
||||
char energy_daily_chr[FLOATSZ];
|
||||
dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr);
|
||||
char energy_yesterday_chr[FLOATSZ];
|
||||
|
@ -836,6 +880,10 @@ void EnergyShow(bool json)
|
|||
char export_active_chr[FLOATSZ];
|
||||
dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr);
|
||||
|
||||
char value_chr[FLOATSZ *3];
|
||||
char value2_chr[FLOATSZ *3];
|
||||
char value3_chr[FLOATSZ *3];
|
||||
|
||||
if (json) {
|
||||
bool show_energy_period = (0 == tele_period);
|
||||
|
||||
|
@ -854,21 +902,27 @@ void EnergyShow(bool json)
|
|||
dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr);
|
||||
}
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"), active_power_chr);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"),
|
||||
EnergyFormat(value_chr, active_power_chr[0], json));
|
||||
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);
|
||||
EnergyFormat(value_chr, apparent_power_chr[0], json),
|
||||
EnergyFormat(value2_chr, reactive_power_chr[0], json),
|
||||
EnergyFormat(value3_chr, power_factor_chr[0], json));
|
||||
}
|
||||
if (!isnan(Energy.frequency)) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), frequency_chr);
|
||||
if (!isnan(Energy.frequency[0])) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"),
|
||||
EnergyFormat(value_chr, frequency_chr[0], json));
|
||||
}
|
||||
}
|
||||
if (Energy.voltage_available) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), voltage_chr);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"),
|
||||
EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common));
|
||||
}
|
||||
if (Energy.current_available) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), current_chr);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"),
|
||||
EnergyFormat(value_chr, current_chr[0], json));
|
||||
}
|
||||
XnrgCall(FUNC_JSON_APPEND);
|
||||
ResponseJsonEnd();
|
||||
|
@ -876,7 +930,7 @@ void EnergyShow(bool json)
|
|||
#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
|
||||
DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr); // PowerUsage, EnergyToday
|
||||
|
||||
dtostrfd((Energy.total - Energy.total1) * 1000, 1, energy_total_chr); // Tariff2
|
||||
char energy_total1_chr[FLOATSZ];
|
||||
|
@ -885,26 +939,28 @@ void EnergyShow(bool json)
|
|||
dtostrfd(RtcSettings.energy_usage.return1_kWhtotal, 1, return1_total_chr);
|
||||
char return2_total_chr[FLOATSZ];
|
||||
dtostrfd(RtcSettings.energy_usage.return2_kWhtotal, 1, return2_total_chr);
|
||||
DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, return1_total_chr, return2_total_chr, (int)Energy.active_power);
|
||||
DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, return1_total_chr, return2_total_chr, (int)Energy.active_power[0]);
|
||||
|
||||
if (Energy.voltage_available) {
|
||||
DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage
|
||||
DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); // Voltage
|
||||
}
|
||||
if (Energy.current_available) {
|
||||
DomoticzSensor(DZ_CURRENT, current_chr); // Current
|
||||
DomoticzSensor(DZ_CURRENT, current_chr[0]); // Current
|
||||
}
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
if (show_energy_period) {
|
||||
if (Energy.voltage_available) {
|
||||
KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage);
|
||||
KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage[0]);
|
||||
}
|
||||
if (Energy.current_available) {
|
||||
KnxSensor(KNX_ENERGY_CURRENT, Energy.current);
|
||||
KnxSensor(KNX_ENERGY_CURRENT, Energy.current[0]);
|
||||
}
|
||||
KnxSensor(KNX_ENERGY_POWER, Energy.active_power[0]);
|
||||
if (!Energy.type_dc) {
|
||||
KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor_knx);
|
||||
}
|
||||
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);
|
||||
|
@ -913,18 +969,24 @@ void EnergyShow(bool json)
|
|||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
if (Energy.voltage_available) {
|
||||
WSContentSend_PD(PSTR("{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"), voltage_chr);
|
||||
WSContentSend_PD(PSTR("{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"),
|
||||
EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common));
|
||||
}
|
||||
if (Energy.current_available) {
|
||||
WSContentSend_PD(PSTR("{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"), current_chr);
|
||||
WSContentSend_PD(PSTR("{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"),
|
||||
EnergyFormat(value_chr, current_chr[0], json));
|
||||
}
|
||||
WSContentSend_PD(PSTR("{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"), active_power_chr);
|
||||
WSContentSend_PD(PSTR("{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"),
|
||||
EnergyFormat(value_chr, active_power_chr[0], json));
|
||||
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);
|
||||
WSContentSend_PD(HTTP_ENERGY_SNS1, EnergyFormat(value_chr, apparent_power_chr[0], json),
|
||||
EnergyFormat(value2_chr, reactive_power_chr[0], json),
|
||||
EnergyFormat(value3_chr, power_factor_chr[0], json));
|
||||
}
|
||||
if (!isnan(Energy.frequency)) {
|
||||
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), frequency_chr);
|
||||
if (!isnan(Energy.frequency[0])) {
|
||||
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"),
|
||||
EnergyFormat(value_chr, frequency_chr[0], json));
|
||||
}
|
||||
}
|
||||
WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr);
|
||||
|
|
|
@ -386,17 +386,17 @@ void TuyaPacketProcess(void)
|
|||
|
||||
#ifdef USE_ENERGY_SENSOR
|
||||
else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) {
|
||||
Energy.voltage = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
||||
Energy.voltage[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
||||
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) {
|
||||
Energy.current = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000;
|
||||
Energy.current[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000;
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
||||
} else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) {
|
||||
Energy.active_power = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
||||
Energy.active_power[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
||||
|
||||
if (Tuya.lastPowerCheckTime != 0 && Energy.active_power > 0) {
|
||||
Energy.kWhtoday += (float)Energy.active_power * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36;
|
||||
if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) {
|
||||
Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36;
|
||||
EnergyUpdateToday();
|
||||
}
|
||||
Tuya.lastPowerCheckTime = Rtc.utc_time;
|
||||
|
|
|
@ -128,13 +128,13 @@ void HlwEvery200ms(void)
|
|||
|
||||
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;
|
||||
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;
|
||||
Energy.active_power[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,19 +175,19 @@ void HlwEvery200ms(void)
|
|||
|
||||
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;
|
||||
Energy.voltage[0] = (float)hlw_u / 10;
|
||||
} else {
|
||||
Energy.voltage = 0;
|
||||
Energy.voltage[0] = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
Hlw.cf1_current_pulse_length = cf1_pulse_length;
|
||||
|
||||
if (Hlw.cf1_current_pulse_length && Energy.active_power) { // 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 = (float)hlw_i / 1000;
|
||||
Energy.current[0] = (float)hlw_i / 1000;
|
||||
} else {
|
||||
Energy.current = 0;
|
||||
Energy.current[0] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,8 +52,9 @@ struct CSE {
|
|||
void CseReceived(void)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
||||
// 55 5A 02 F7 60 00 03 5A 00 40 10 04 8B 9F 51 A6 58 18 72 75 61 AC A1 30 - Power not valid (load below 5W)
|
||||
// 55 5A 02 F7 60 00 03 AB 00 40 10 02 60 5D 51 A6 58 03 E9 EF 71 0B 7A 36
|
||||
// F2 5A 02 F7 60 00 03 61 00 40 10 05 72 40 51 A6 58 63 10 1B E1 7F 4D 4E - F2 = Power cycle exceeds range - takes too long - No load
|
||||
// 55 5A 02 F7 60 00 03 5A 00 40 10 04 8B 9F 51 A6 58 18 72 75 61 AC A1 30 - 55 = Ok, 61 = Power not valid (load below 5W)
|
||||
// 55 5A 02 F7 60 00 03 AB 00 40 10 02 60 5D 51 A6 58 03 E9 EF 71 0B 7A 36 - 55 = Ok, 71 = Ok
|
||||
// Hd Id VCal---- Voltage- ICal---- Current- PCal---- Power--- Ad CF--- Ck
|
||||
|
||||
uint8_t header = serial_in_buffer[0];
|
||||
|
@ -93,19 +94,19 @@ void CseReceived(void)
|
|||
|
||||
if (Energy.power_on) { // Powered on
|
||||
if (adjustement & 0x40) { // Voltage valid
|
||||
Energy.voltage = (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;
|
||||
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 = (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;
|
||||
Energy.active_power[0] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -113,21 +114,21 @@ void CseReceived(void)
|
|||
Cse.power_invalid++;
|
||||
} else {
|
||||
Cse.power_cycle_first = 0;
|
||||
Energy.active_power = 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) {
|
||||
Energy.current = 0;
|
||||
if (0 == Energy.active_power[0]) {
|
||||
Energy.current[0] = 0;
|
||||
} else {
|
||||
Energy.current = (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;
|
||||
Energy.active_power = 0;
|
||||
Energy.current = 0;
|
||||
Energy.voltage[0] = 0;
|
||||
Energy.active_power[0] = 0;
|
||||
Energy.current[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +190,7 @@ void CseEverySecond(void)
|
|||
} else {
|
||||
cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time;
|
||||
}
|
||||
if (cf_frequency && Energy.active_power) {
|
||||
if (cf_frequency && Energy.active_power[0]) {
|
||||
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
|
||||
|
|
|
@ -172,13 +172,13 @@ void PzemEvery200ms(void)
|
|||
Energy.data_valid = 0;
|
||||
switch (pzem_read_state) {
|
||||
case 1: // Voltage as 230.2V
|
||||
Energy.voltage = value;
|
||||
Energy.voltage[0] = value;
|
||||
break;
|
||||
case 2: // Current as 17.32A
|
||||
Energy.current = value;
|
||||
Energy.current[0] = value;
|
||||
break;
|
||||
case 3: // Power as 20W
|
||||
Energy.active_power = value;
|
||||
Energy.active_power[0] = value;
|
||||
break;
|
||||
case 4: // Total energy as 99999Wh
|
||||
EnergyUpdateTotal(value, false);
|
||||
|
|
|
@ -455,19 +455,19 @@ void McpParseData(void)
|
|||
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;
|
||||
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 = (float)mcp_current_rms / 10000;
|
||||
Energy.current[0] = (float)mcp_current_rms / 10000;
|
||||
}
|
||||
} else { // Powered off
|
||||
Energy.frequency = 0;
|
||||
Energy.voltage = 0;
|
||||
Energy.active_power = 0;
|
||||
Energy.current = 0;
|
||||
Energy.frequency[0] = 0;
|
||||
Energy.voltage[0] = 0;
|
||||
Energy.active_power[0] = 0;
|
||||
Energy.current[0] = 0;
|
||||
}
|
||||
Energy.data_valid = 0;
|
||||
}
|
||||
|
|
|
@ -56,11 +56,11 @@ void PzemAcEverySecond(void)
|
|||
// 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[0] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V
|
||||
Energy.current[0] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A
|
||||
Energy.active_power[0] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W
|
||||
Energy.frequency[0] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz
|
||||
Energy.power_factor[0] = (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
|
||||
|
||||
EnergyUpdateTotal(energy, false);
|
||||
|
|
|
@ -56,9 +56,9 @@ void PzemDcEverySecond(void)
|
|||
// 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[0] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V
|
||||
Energy.current[0] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A
|
||||
Energy.active_power[0] = (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
|
||||
|
||||
EnergyUpdateTotal(energy, false);
|
||||
|
|
|
@ -36,14 +36,22 @@
|
|||
|
||||
#define ADE7953_ADDR 0x38
|
||||
|
||||
const uint8_t Ade7953Registers[] {
|
||||
0x1B, // RMS current channel B (Relay 1)
|
||||
0x13, // Active power channel B
|
||||
0x11, // Apparent power channel B
|
||||
0x15, // Reactive power channel B
|
||||
0x1A, // RMS current channel A (Relay 2)
|
||||
0x12, // Active power channel A
|
||||
0x10, // Apparent power channel A
|
||||
0x14, // Reactive power channel A
|
||||
0x1C // RMS voltage (Both relays)
|
||||
};
|
||||
|
||||
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;
|
||||
uint32_t current_rms[2] = { 0, 0 };
|
||||
uint32_t active_power[2] = { 0, 0 };
|
||||
uint8_t init_step = 0;
|
||||
} Ade7953;
|
||||
|
||||
|
@ -80,7 +88,7 @@ void Ade7953Write(uint16_t reg, uint32_t val)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t Ade7953Read(uint16_t reg)
|
||||
int32_t Ade7953Read(uint16_t reg)
|
||||
{
|
||||
uint32_t response = 0;
|
||||
|
||||
|
@ -109,48 +117,65 @@ void Ade7953Init(void)
|
|||
|
||||
void Ade7953GetData(void)
|
||||
{
|
||||
int32_t active_power;
|
||||
int32_t reg[2][4];
|
||||
for (uint32_t i = 0; i < sizeof(Ade7953Registers); i++) {
|
||||
int32_t value = Ade7953Read(0x300 + Ade7953Registers[i]);
|
||||
if (8 == i) {
|
||||
Ade7953.voltage_rms = value; // RMS voltage (Both relays)
|
||||
} else {
|
||||
reg[i >> 2][i &3] = value;
|
||||
}
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"),
|
||||
Ade7953.voltage_rms, reg[0][0], reg[0][1], reg[0][2], reg[0][3],
|
||||
reg[1][0], reg[1][1], reg[1][2], reg[1][3]);
|
||||
|
||||
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;
|
||||
uint32_t apparent_power[2] = { 0, 0 };
|
||||
uint32_t reactive_power[2] = { 0, 0 };
|
||||
|
||||
for (uint32_t channel = 0; channel < 2; channel++) {
|
||||
Ade7953.current_rms[channel] = reg[channel][0];
|
||||
if (Ade7953.current_rms[channel] < 2000) { // No load threshold (20mA)
|
||||
Ade7953.current_rms[channel] = 0;
|
||||
Ade7953.active_power[channel] = 0;
|
||||
} else {
|
||||
Ade7953.active_power[channel] = abs(reg[channel][1]);
|
||||
apparent_power[channel] = abs(reg[channel][2]);
|
||||
reactive_power[channel] = abs(reg[channel][3]);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
|
||||
uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1];
|
||||
uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1];
|
||||
|
||||
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_rms[0], Ade7953.current_rms[1], current_rms_sum, Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum);
|
||||
|
||||
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.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration;
|
||||
|
||||
for (uint32_t channel = 0; channel < 2; channel++) {
|
||||
Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10);
|
||||
Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10);
|
||||
Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10);
|
||||
if (0 == Energy.active_power[channel]) {
|
||||
Energy.current[channel] = 0;
|
||||
} else {
|
||||
Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10);
|
||||
}
|
||||
}
|
||||
} else { // Powered off
|
||||
Energy.voltage = 0;
|
||||
Energy.active_power = 0;
|
||||
Energy.current = 0;
|
||||
Energy.voltage[0] = 0;
|
||||
for (uint32_t channel = 0; channel < 2; channel++) {
|
||||
Energy.current[channel] = 0;
|
||||
Energy.active_power[channel] = 0;
|
||||
Energy.reactive_power[channel] = 0;
|
||||
Energy.apparent_power[channel] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (Ade7953.active_power) {
|
||||
Energy.kWhtoday_delta += ((Ade7953.active_power * (100000 / (Settings.energy_power_calibration / 10))) / 3600);
|
||||
if (active_power_sum) {
|
||||
Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600);
|
||||
EnergyUpdateToday();
|
||||
}
|
||||
}
|
||||
|
@ -179,6 +204,10 @@ void Ade7953DrvInit(void)
|
|||
}
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADE7953", ADE7953_ADDR);
|
||||
Ade7953.init_step = 2;
|
||||
|
||||
Energy.phase_count = 2; // Handle two channels as two phases
|
||||
Energy.voltage_common = true; // Use common voltage
|
||||
|
||||
energy_flg = XNRG_07;
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +217,7 @@ bool Ade7953Command(void)
|
|||
{
|
||||
bool serviced = true;
|
||||
|
||||
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) {
|
||||
|
@ -203,9 +233,9 @@ bool Ade7953Command(void)
|
|||
// Service in xdrv_03_energy.ino
|
||||
}
|
||||
else if (CMND_POWERSET == Energy.command_code) {
|
||||
if (XdrvMailbox.data_len && Ade7953.active_power) {
|
||||
if (XdrvMailbox.data_len && Ade7953.active_power[channel]) {
|
||||
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[channel] * 1000) / value; // 0.00 W
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -217,9 +247,9 @@ bool Ade7953Command(void)
|
|||
}
|
||||
}
|
||||
else if (CMND_CURRENTSET == Energy.command_code) {
|
||||
if (XdrvMailbox.data_len && Ade7953.current_rms) {
|
||||
if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) {
|
||||
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[channel] * 100) / value) * 100; // 0.00 mA
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,31 +98,31 @@ void SDM120Every250ms(void)
|
|||
|
||||
switch(Sdm120.read_state) {
|
||||
case 0:
|
||||
Energy.voltage = value; // 230.2 V
|
||||
Energy.voltage[0] = value; // 230.2 V
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Energy.current = value; // 1.260 A
|
||||
Energy.current[0] = value; // 1.260 A
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Energy.active_power = value; // -196.3 W
|
||||
Energy.active_power[0] = value; // -196.3 W
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Energy.apparent_power = value; // 223.4 VA
|
||||
Energy.apparent_power[0] = value; // 223.4 VA
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Energy.reactive_power = value; // 92.2
|
||||
Energy.reactive_power[0] = value; // 92.2
|
||||
break;
|
||||
|
||||
case 5:
|
||||
Energy.power_factor = value; // -0.91
|
||||
Energy.power_factor[0] = value; // -0.91
|
||||
break;
|
||||
|
||||
case 6:
|
||||
Energy.frequency = value; // 50.0 Hz
|
||||
Energy.frequency[0] = value; // 50.0 Hz
|
||||
break;
|
||||
|
||||
case 7:
|
||||
|
|
|
@ -57,12 +57,12 @@ void Dds2382EverySecond(void)
|
|||
// 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
|
||||
// SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc--
|
||||
|
||||
Energy.voltage = (float)((buffer[27] << 8) + buffer[28]) / 10.0;
|
||||
Energy.current = (float)((buffer[29] << 8) + buffer[30]) / 100.0;
|
||||
Energy.active_power = (float)((buffer[31] << 8) + buffer[32]);
|
||||
Energy.reactive_power = (float)((buffer[33] << 8) + buffer[34]);
|
||||
Energy.power_factor = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; // 1.00
|
||||
Energy.frequency = (float)((buffer[37] << 8) + buffer[38]) / 100.0; // 50.0 Hz
|
||||
Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0;
|
||||
Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0;
|
||||
Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]);
|
||||
Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]);
|
||||
Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; // 1.00
|
||||
Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; // 50.0 Hz
|
||||
Energy.export_active = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[13] << 8) + buffer[14]) / 100.0; // 429496729.0 W
|
||||
// float energy_total = (float)((buffer[3] << 24) + (buffer[4] << 16) + (buffer[5] << 8) + buffer[6]) / 100.0; // 429496729.0 W
|
||||
float import_active = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[17] << 8) + buffer[18]) / 100.0; // 429496729.0 W
|
||||
|
|
Loading…
Reference in New Issue