From 41b65fd6b73b3fbe51857e3522e28a3e61a5603c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 30 Oct 2022 11:15:17 +0100 Subject: [PATCH] Add support for two phase power calibration Add support for two phase power calibration using commands ``PowerSet2``, ``VoltageSet2`` and ``CurrentSet2`` --- CHANGELOG.md | 3 +- RELEASENOTES.md | 1 + tasmota/tasmota_support/settings.ino | 6 +- .../tasmota_xdrv_driver/xdrv_03_energy.ino | 61 ++++++++++++------- .../tasmota_xnrg_energy/xnrg_07_ade7953.ino | 6 +- .../tasmota_xnrg_energy/xnrg_14_bl09xx.ino | 4 +- .../tasmota_xnrg_energy/xnrg_19_cse7761.ino | 4 +- tasmota/tasmota_xnrg_energy/xnrg_30_dummy.ino | 16 +++-- 8 files changed, 64 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ace4e9ac..eeeab257e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,12 @@ All notable changes to this project will be documented in this file. ## [12.2.0.2] ### Added - Support for Digital Addressable Lighting Interface (DALI) by Andrei Kazmirtsuk (#16938) +- Support for two phase power calibration using commands ``PowerSet2``, ``VoltageSet2`` and ``CurrentSet2`` ### Breaking Changed ### Changed -- Prepare for two phase power calibration and move some persistent data (PowerLow) +- Move some persistent data (PowerLow) - ESP32 Framework (Core) from v2.0.5 to v2.0.5.2 ### Fixed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3c44ef42c..2c6521331 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -109,6 +109,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo ## Changelog v12.2.0.2 ### Added +- Support for two phase power calibration using commands ``PowerSet2``, ``VoltageSet2`` and ``CurrentSet2`` - Command NeoPool ``NPFiltration 2`` toggle [#16859](https://github.com/arendst/Tasmota/issues/16859) - Support for Shelly Pro 1/1PM and 2/2PM [#16773](https://github.com/arendst/Tasmota/issues/16773) - Support for up to four DS18x20 GPIOs by md5sum-as [#16833](https://github.com/arendst/Tasmota/issues/16833) diff --git a/tasmota/tasmota_support/settings.ino b/tasmota/tasmota_support/settings.ino index bf1f9ba63..ecfe30063 100644 --- a/tasmota/tasmota_support/settings.ino +++ b/tasmota/tasmota_support/settings.ino @@ -45,7 +45,7 @@ void RtcSettingsSave(void) { if (RTC_MEM_VALID != RtcSettings.valid) { memset(&RtcSettings, 0, sizeof(RtcSettings)); RtcSettings.valid = RTC_MEM_VALID; -// RtcSettings.ex_energy_kWhtoday = Settings->energy_power_calibration2; +// RtcSettings.ex_energy_kWhtoday = Settings->energy_power_calibration2; // = ex_energy_kWhtoday // RtcSettings.ex_energy_kWhtotal = Settings->ex_energy_kWhtotal; for (uint32_t i = 0; i < 3; i++) { RtcSettings.energy_kWhtoday_ph[i] = Settings->energy_kWhtoday_ph[i]; @@ -1535,8 +1535,8 @@ void SettingsDelta(void) { memset(&Settings->energy_kWhtoday_ph, 0, 36); memset(&RtcSettings.energy_kWhtoday_ph, 0, 24); Settings->energy_kWhtotal_ph[0] = Settings->ex_energy_kWhtotal; - Settings->energy_kWhtoday_ph[0] = Settings->energy_power_calibration2; - Settings->energy_kWhyesterday_ph[0] = Settings->energy_voltage_calibration2; + Settings->energy_kWhtoday_ph[0] = Settings->energy_power_calibration2; // = ex_energy_kWhtoday + Settings->energy_kWhyesterday_ph[0] = Settings->energy_voltage_calibration2; // = ex_energy_kWhyesterday RtcSettings.energy_kWhtoday_ph[0] = RtcSettings.ex_energy_kWhtoday; RtcSettings.energy_kWhtotal_ph[0] = RtcSettings.ex_energy_kWhtotal; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino index d0a308a16..57d34ab43 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_03_energy.ino @@ -41,6 +41,9 @@ #define D_CMND_TARIFF "Tariff" #define D_CMND_MODULEADDRESS "ModuleAddress" +enum EnergyCalibration { + ENERGY_POWER_CALIBRATION, ENERGY_VOLTAGE_CALIBRATION, ENERGY_CURRENT_CALIBRATION, ENERGY_FREQUENCY_CALIBRATION }; + enum EnergyCommands { CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, CMND_FREQUENCYCAL, CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS, CMND_ENERGYCONFIG }; @@ -830,34 +833,50 @@ void CmndTariff(void) { GetStateText(Settings->flag3.energy_weekend)); // CMND_TARIFF } +uint32_t EnergyGetCalibration(uint32_t chan, uint32_t cal_type) { + uint32_t channel = ((1 == chan) && (2 == Energy.phase_count)) ? 1 : 0; + if (channel) { + switch (cal_type) { + case ENERGY_POWER_CALIBRATION: return Settings->energy_power_calibration2; + case ENERGY_VOLTAGE_CALIBRATION: return Settings->energy_voltage_calibration2; + case ENERGY_CURRENT_CALIBRATION: return Settings->energy_current_calibration2; + } + } else { + switch (cal_type) { + case ENERGY_POWER_CALIBRATION: return Settings->energy_power_calibration; + case ENERGY_VOLTAGE_CALIBRATION: return Settings->energy_voltage_calibration; + case ENERGY_CURRENT_CALIBRATION: return Settings->energy_current_calibration; + } + } + return Settings->energy_frequency_calibration; +} + void EnergyCommandCalSetResponse(uint32_t cal_type) { if (XdrvMailbox.payload > 999) { uint32_t channel = ((2 == XdrvMailbox.index) && (2 == Energy.phase_count)) ? 1 : 0; if (channel) { switch (cal_type) { - case 0: Settings->energy_power_calibration2 = XdrvMailbox.payload; break; - case 1: Settings->energy_voltage_calibration2 = XdrvMailbox.payload; break; - case 2: Settings->energy_current_calibration2 = XdrvMailbox.payload; break; - case 3: Settings->energy_frequency_calibration = XdrvMailbox.payload; break; + case ENERGY_POWER_CALIBRATION: Settings->energy_power_calibration2 = XdrvMailbox.payload; break; + case ENERGY_VOLTAGE_CALIBRATION: Settings->energy_voltage_calibration2 = XdrvMailbox.payload; break; + case ENERGY_CURRENT_CALIBRATION: Settings->energy_current_calibration2 = XdrvMailbox.payload; break; + case ENERGY_FREQUENCY_CALIBRATION: Settings->energy_frequency_calibration = XdrvMailbox.payload; break; } } else { switch (cal_type) { - case 0: Settings->energy_power_calibration = XdrvMailbox.payload; break; - case 1: Settings->energy_voltage_calibration = XdrvMailbox.payload; break; - case 2: Settings->energy_current_calibration = XdrvMailbox.payload; break; - case 3: Settings->energy_frequency_calibration = XdrvMailbox.payload; break; + case ENERGY_POWER_CALIBRATION: Settings->energy_power_calibration = XdrvMailbox.payload; break; + case ENERGY_VOLTAGE_CALIBRATION: Settings->energy_voltage_calibration = XdrvMailbox.payload; break; + case ENERGY_CURRENT_CALIBRATION: Settings->energy_current_calibration = XdrvMailbox.payload; break; + case ENERGY_FREQUENCY_CALIBRATION: Settings->energy_frequency_calibration = XdrvMailbox.payload; break; } } } - if (3 == cal_type) { + if (ENERGY_FREQUENCY_CALIBRATION == cal_type) { ResponseAppend_P(PSTR("%d}"), Settings->energy_frequency_calibration); } else { - uint32_t cal_array[2][3]; - memcpy(&cal_array, &Settings->energy_power_calibration, 24); if (2 == Energy.phase_count) { - ResponseAppend_P(PSTR("[%d,%d]}"), cal_array[0][cal_type], cal_array[1][cal_type]); + ResponseAppend_P(PSTR("[%d,%d]}"), EnergyGetCalibration(0, cal_type), EnergyGetCalibration(1, cal_type)); } else { - ResponseAppend_P(PSTR("%d}"), cal_array[0][cal_type]); + ResponseAppend_P(PSTR("%d}"), EnergyGetCalibration(0, cal_type)); } } } @@ -875,56 +894,56 @@ void EnergyCommandSetCalResponse(uint32_t cal_type) { void CmndPowerCal(void) { Energy.command_code = CMND_POWERCAL; if (XnrgCall(FUNC_COMMAND)) { // microseconds - EnergyCommandCalResponse(0); + EnergyCommandCalResponse(ENERGY_POWER_CALIBRATION); } } void CmndVoltageCal(void) { Energy.command_code = CMND_VOLTAGECAL; if (XnrgCall(FUNC_COMMAND)) { // microseconds - EnergyCommandCalResponse(1); + EnergyCommandCalResponse(ENERGY_VOLTAGE_CALIBRATION); } } void CmndCurrentCal(void) { Energy.command_code = CMND_CURRENTCAL; if (XnrgCall(FUNC_COMMAND)) { // microseconds - EnergyCommandCalResponse(2); + EnergyCommandCalResponse(ENERGY_CURRENT_CALIBRATION); } } void CmndFrequencyCal(void) { Energy.command_code = CMND_FREQUENCYCAL; if (XnrgCall(FUNC_COMMAND)) { // microseconds - EnergyCommandCalResponse(3); + EnergyCommandCalResponse(ENERGY_FREQUENCY_CALIBRATION); } } void CmndPowerSet(void) { Energy.command_code = CMND_POWERSET; if (XnrgCall(FUNC_COMMAND)) { // Watt - EnergyCommandSetCalResponse(0); + EnergyCommandSetCalResponse(ENERGY_POWER_CALIBRATION); } } void CmndVoltageSet(void) { Energy.command_code = CMND_VOLTAGESET; if (XnrgCall(FUNC_COMMAND)) { // Volt - EnergyCommandSetCalResponse(1); + EnergyCommandSetCalResponse(ENERGY_VOLTAGE_CALIBRATION); } } void CmndCurrentSet(void) { Energy.command_code = CMND_CURRENTSET; if (XnrgCall(FUNC_COMMAND)) { // milliAmpere - EnergyCommandSetCalResponse(2); + EnergyCommandSetCalResponse(ENERGY_CURRENT_CALIBRATION); } } void CmndFrequencySet(void) { Energy.command_code = CMND_FREQUENCYSET; if (XnrgCall(FUNC_COMMAND)) { // Hz - EnergyCommandSetCalResponse(3); + EnergyCommandSetCalResponse(ENERGY_FREQUENCY_CALIBRATION); } } diff --git a/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino b/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino index 4cf12061b..0bb88e293 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_07_ade7953.ino @@ -463,9 +463,9 @@ void Ade7953GetData(void) { for (uint32_t channel = 0; channel < 2; channel++) { Energy.data_valid[channel] = 0; - float power_calibration = ((channel) ? Settings->energy_power_calibration2 : Settings->energy_power_calibration) / 10; - float voltage_calibration = (channel) ? Settings->energy_voltage_calibration2 : Settings->energy_voltage_calibration; - float current_calibration = ((channel) ? Settings->energy_current_calibration2 : Settings->energy_current_calibration) * 10; + float power_calibration = (float)EnergyGetCalibration(channel, ENERGY_POWER_CALIBRATION) / 10; + float voltage_calibration = (float)EnergyGetCalibration(channel, ENERGY_VOLTAGE_CALIBRATION); + float current_calibration = (float)EnergyGetCalibration(channel, ENERGY_CURRENT_CALIBRATION) * 10; Energy.frequency[channel] = 223750.0f / ((float)reg[channel][5] + 1); divider = (Ade7953.calib_data[channel][ADE7953_CAL_VGAIN] != ADE7953_GAIN_DEFAULT) ? 10000 : voltage_calibration; diff --git a/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino b/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino index dd44ac14f..740029725 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_14_bl09xx.ino @@ -193,8 +193,8 @@ void Bl09XXUpdateEnergy() { AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %2_f, T %2_f"), &Energy.voltage[0], &Bl09XX.temperature); #endif for (uint32_t chan = 0; chan < Energy.phase_count; chan++) { - uint32_t power_calibration = (chan) ? Settings->energy_power_calibration2 : Settings->energy_power_calibration; - uint32_t current_calibration = (chan) ? Settings->energy_current_calibration2 : Settings->energy_current_calibration; + uint32_t power_calibration = EnergyGetCalibration(chan, ENERGY_POWER_CALIBRATION); + uint32_t current_calibration = EnergyGetCalibration(chan, ENERGY_CURRENT_CALIBRATION); if (Bl09XX.power[chan] > power_calibration) { // We need at least 1W Energy.active_power[chan] = (float)Bl09XX.power[chan] / power_calibration; Energy.current[chan] = (float)Bl09XX.current[chan] / current_calibration; diff --git a/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino b/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino index 02c13e121..5a282bc50 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino @@ -468,14 +468,14 @@ void Cse7761GetData(void) { for (uint32_t channel = 0; channel < 2; channel++) { Energy.data_valid[channel] = 0; - uint32_t power_calibration = (channel) ? Settings->energy_power_calibration2 : Settings->energy_power_calibration; + uint32_t power_calibration = EnergyGetCalibration(channel, ENERGY_POWER_CALIBRATION); // Active power = PowerPA * PowerPAC * 1000 / 0x80000000 // Energy.active_power[channel] = (float)(((uint64_t)CSE7761Data.active_power[channel] * CSE7761Data.coefficient[PowerPAC + channel] * 1000) >> 31) / 1000; // W Energy.active_power[channel] = (float)CSE7761Data.active_power[channel] / power_calibration; // W if (0 == Energy.active_power[channel]) { Energy.current[channel] = 0; } else { - uint32_t current_calibration = (channel) ? Settings->energy_current_calibration2 : Settings->energy_current_calibration; + uint32_t current_calibration = EnergyGetCalibration(channel, ENERGY_CURRENT_CALIBRATION); // Current = RmsIA * RmsIAC / 0x800000 // Energy.current[channel] = (float)(((uint64_t)CSE7761Data.current_rms[channel] * CSE7761Data.coefficient[RmsIAC + channel]) >> 23) / 1000; // A Energy.current[channel] = (float)CSE7761Data.current_rms[channel] / current_calibration; // A diff --git a/tasmota/tasmota_xnrg_energy/xnrg_30_dummy.ino b/tasmota/tasmota_xnrg_energy/xnrg_30_dummy.ino index b77474a12..021003e3a 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_30_dummy.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_30_dummy.ino @@ -55,14 +55,20 @@ struct { void NrgDummyEverySecond(void) { if (Energy.power_on) { // Powered on for (uint32_t channel = 0; channel < Energy.phase_count; channel++) { - Energy.voltage[channel] = ((float)Settings->energy_voltage_calibration / 100); // V - Energy.frequency[channel] = ((float)Settings->energy_frequency_calibration / 100); // Hz - if (bitRead(TasmotaGlobal.power, channel)) { // Emulate power read only if device is powered on - Energy.active_power[channel] = (NrgDummy.power[channel]) ? ((float)NrgDummy.power[channel] / 1000) : ((float)Settings->energy_power_calibration / 100); // W + + float power_calibration = (float)EnergyGetCalibration(channel, ENERGY_POWER_CALIBRATION) / 100; + float voltage_calibration = (float)EnergyGetCalibration(channel, ENERGY_VOLTAGE_CALIBRATION) / 100; + float current_calibration = (float)EnergyGetCalibration(channel, ENERGY_CURRENT_CALIBRATION) / 100000; + float frequency_calibration = (float)EnergyGetCalibration(channel, ENERGY_FREQUENCY_CALIBRATION) / 100; + + Energy.voltage[channel] = power_calibration; // V + Energy.frequency[channel] = frequency_calibration; // Hz + if (bitRead(TasmotaGlobal.power, channel)) { // Emulate power read only if device is powered on + Energy.active_power[channel] = (NrgDummy.power[channel]) ? ((float)NrgDummy.power[channel] / 1000) : voltage_calibration; // W if (0 == Energy.active_power[channel]) { Energy.current[channel] = 0; } else { - Energy.current[channel] = (NrgDummy.current[channel]) ? ((float)NrgDummy.current[channel] / 1000) : ((float)Settings->energy_current_calibration / 100000); // A + Energy.current[channel] = (NrgDummy.current[channel]) ? ((float)NrgDummy.current[channel] / 1000) : current_calibration; // A Energy.kWhtoday_delta[channel] += Energy.active_power[channel] * 1000 / 36; } Energy.data_valid[channel] = 0;