mirror of https://github.com/arendst/Tasmota.git
Add Energy command ``PowerSet 60,230`` to calibrate both Current and Power with known resistive load of 60W at 230V using calibrated Voltage
This commit is contained in:
parent
c5b92d3ab1
commit
ab2d6c1169
|
@ -6,10 +6,13 @@ All notable changes to this project will be documented in this file.
|
||||||
## [14.2.0.1]
|
## [14.2.0.1]
|
||||||
### Added
|
### Added
|
||||||
- Energy Log level 4 message when (Calculated) Apparent Power is less than Active Power indicating wrong calibration (#20653)
|
- Energy Log level 4 message when (Calculated) Apparent Power is less than Active Power indicating wrong calibration (#20653)
|
||||||
|
- Energy command ``PowerSet 60,230`` to calibrate both Current and Power with known resistive load of 60W at 230V using calibrated Voltage
|
||||||
|
- Energy command ``CurrentSet 60,230`` to calibrate both Power and Current with known resistive load of 60W at 230V using calibrated Voltage
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Energy force Apparent Power equals Active Power when (Calculated) Apparent Power is less than Active Power (#20653)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Shutter timing registers overflow (#21966)
|
- Shutter timing registers overflow (#21966)
|
||||||
|
@ -18,8 +21,6 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- ESP8266 Analog input support using energy driver as only one channel is available
|
- ESP8266 Analog input support using energy driver as only one channel is available
|
||||||
- Energy force Active Power equals Apparent Power when (Calculated) Apparent Power is less than Active Power (#20653)
|
|
||||||
- Energy force Power Factor to be always 1 or lower (#20653)
|
|
||||||
|
|
||||||
## [Released]
|
## [Released]
|
||||||
|
|
||||||
|
|
|
@ -121,11 +121,14 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
||||||
|
|
||||||
## Changelog v14.2.0.1
|
## Changelog v14.2.0.1
|
||||||
### Added
|
### Added
|
||||||
|
- Energy command ``PowerSet 60,230`` to calibrate both Current and Power with known resistive load of 60W at 230V using calibrated Voltage
|
||||||
|
- Energy command ``CurrentSet 60,230`` to calibrate both Power and Current with known resistive load of 60W at 230V using calibrated Voltage
|
||||||
- Energy Log level 4 message when (Calculated) Apparent Power is less than Active Power indicating wrong calibration [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
- Energy Log level 4 message when (Calculated) Apparent Power is less than Active Power indicating wrong calibration [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Energy force Apparent Power equals Active Power when (Calculated) Apparent Power is less than Active Power [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Energy calculation [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
- Energy calculation [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
||||||
|
@ -133,6 +136,4 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
||||||
- PZEM continue energy monitoring when one phase fails [#21968](https://github.com/arendst/Tasmota/issues/21968)
|
- PZEM continue energy monitoring when one phase fails [#21968](https://github.com/arendst/Tasmota/issues/21968)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Energy force Active Power equals Apparent Power when (Calculated) Apparent Power is less than Active Power [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
|
||||||
- Energy force Power Factor to be always 1 or lower [#20653](https://github.com/arendst/Tasmota/issues/20653)
|
|
||||||
- ESP8266 Analog input support using energy driver as only one channel is available
|
- ESP8266 Analog input support using energy driver as only one channel is available
|
||||||
|
|
|
@ -974,14 +974,56 @@ void EnergyCommandSetCalResponse(uint32_t cal_type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnergyCommandSetCal(uint32_t cal_type) {
|
||||||
|
if (XdrvMailbox.data_len) {
|
||||||
|
// PowerSet 61.2
|
||||||
|
// CurrentSet 263
|
||||||
|
if (ArgC() > 1) {
|
||||||
|
// Calibrate current and power using calibrated voltage and known resistive load voltage and power
|
||||||
|
// PowerSet 60.0,230
|
||||||
|
// CurrentSet 60.0,230
|
||||||
|
char argument[32];
|
||||||
|
float Pgoal = CharToFloat(ArgV(argument, 1)); // 60.0 W
|
||||||
|
float Ugoal = CharToFloat(ArgV(argument, 2)); // 230 V
|
||||||
|
float Igoal = Pgoal / Ugoal; // 0.26087 A
|
||||||
|
float R = Ugoal / Igoal; // 881,666 Ohm
|
||||||
|
|
||||||
|
uint32_t channel = XdrvMailbox.index;
|
||||||
|
if (channel > Energy->phase_count) { channel = 1; }
|
||||||
|
channel--;
|
||||||
|
float Umeas = Energy->voltage[channel]; // 232.0
|
||||||
|
// Calculate current and power based on measured voltage
|
||||||
|
float Ical = Umeas / R; // 0.26306 A
|
||||||
|
float Pcal = Umeas * Ical; // 61.03 W
|
||||||
|
Ical *= 1000; // A to mA
|
||||||
|
|
||||||
|
uint32_t cal_type1 = ENERGY_CURRENT_CALIBRATION;
|
||||||
|
float cal1 = Ical;
|
||||||
|
float cal2 = Pcal;
|
||||||
|
if (ENERGY_CURRENT_CALIBRATION == cal_type) {
|
||||||
|
cal_type1 = ENERGY_POWER_CALIBRATION;
|
||||||
|
cal1 = Pcal;
|
||||||
|
cal2 = Ical;
|
||||||
|
}
|
||||||
|
XdrvMailbox.data = argument;
|
||||||
|
ext_snprintf_P(argument, sizeof(argument), PSTR("%5_f"), &cal1);
|
||||||
|
XdrvMailbox.data_len = strlen(argument);
|
||||||
|
EnergyCommandSetCalResponse(cal_type1);
|
||||||
|
ext_snprintf_P(argument, sizeof(argument), PSTR("%5_f"), &cal2);
|
||||||
|
XdrvMailbox.data_len = strlen(argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EnergyCommandSetCalResponse(cal_type);
|
||||||
|
}
|
||||||
|
|
||||||
void CmndPowerSet(void) {
|
void CmndPowerSet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_POWER_CALIBRATION);
|
EnergyCommandSetCal(ENERGY_POWER_CALIBRATION);
|
||||||
}
|
}
|
||||||
void CmndVoltageSet(void) {
|
void CmndVoltageSet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_VOLTAGE_CALIBRATION);
|
EnergyCommandSetCalResponse(ENERGY_VOLTAGE_CALIBRATION);
|
||||||
}
|
}
|
||||||
void CmndCurrentSet(void) {
|
void CmndCurrentSet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_CURRENT_CALIBRATION);
|
EnergyCommandSetCal(ENERGY_CURRENT_CALIBRATION);
|
||||||
}
|
}
|
||||||
void CmndFrequencySet(void) {
|
void CmndFrequencySet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_FREQUENCY_CALIBRATION);
|
EnergyCommandSetCalResponse(ENERGY_FREQUENCY_CALIBRATION);
|
||||||
|
@ -1184,6 +1226,10 @@ void EnergyShow(bool json) {
|
||||||
if (!Energy->type_dc) {
|
if (!Energy->type_dc) {
|
||||||
if (Energy->current_available && Energy->voltage_available) {
|
if (Energy->current_available && Energy->voltage_available) {
|
||||||
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
||||||
|
if (0 == Energy->current[i]) {
|
||||||
|
Energy->active_power[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
apparent_power[i] = Energy->apparent_power[i];
|
apparent_power[i] = Energy->apparent_power[i];
|
||||||
if (isnan(apparent_power[i])) {
|
if (isnan(apparent_power[i])) {
|
||||||
apparent_power[i] = Energy->voltage[i] * Energy->current[i];
|
apparent_power[i] = Energy->voltage[i] * Energy->current[i];
|
||||||
|
@ -1209,11 +1255,15 @@ void EnergyShow(bool json) {
|
||||||
}
|
}
|
||||||
if (apparent_power[i] < Energy->active_power[i]) { // Should be impossible
|
if (apparent_power[i] < Energy->active_power[i]) { // Should be impossible
|
||||||
if (apparent_power[i]) {
|
if (apparent_power[i]) {
|
||||||
if ((power_factor[i] > 1.005) && (power_factor[i] < 2.0f)) { // Skip below 0.5% and don't expect 50% differences
|
if ((power_factor[i] >= 1.02f) && (power_factor[i] < 2.0f)) { // Skip below 2% and don't expect 50% differences
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("NRG: Calibrate as Active %3_fW > Apparent %3_fVA (PF = %4_f)"),
|
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("NRG: Calibrate as Active %3_fW > Apparent %3_fVA (PF = %4_f)"),
|
||||||
&Energy->active_power[i], &apparent_power[i], &power_factor[i]);
|
&Energy->active_power[i], &apparent_power[i], &power_factor[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
apparent_power[i] = Energy->active_power[i]; // Force apparent equal to active as mis-calibrated
|
||||||
|
if (power_factor[i] > 1) { // Should not happen (Active > Apparent)
|
||||||
|
power_factor[i] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reactive_power[i] = Energy->reactive_power[i];
|
reactive_power[i] = Energy->reactive_power[i];
|
||||||
|
|
|
@ -1285,14 +1285,56 @@ void EnergyCommandSetCalResponse(uint32_t cal_type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnergyCommandSetCal(uint32_t cal_type) {
|
||||||
|
if (XdrvMailbox.data_len && (XdrvMailbox.index > 0)) {
|
||||||
|
// PowerSet 61.2
|
||||||
|
// CurrentSet 263
|
||||||
|
if (ArgC() > 1) {
|
||||||
|
// Calibrate current and power using calibrated voltage and known resistive load voltage and power
|
||||||
|
// PowerSet 60.0,230
|
||||||
|
// CurrentSet 60.0,230
|
||||||
|
char argument[32];
|
||||||
|
float Pgoal = CharToFloat(ArgV(argument, 1)); // 60.0 W
|
||||||
|
float Ugoal = CharToFloat(ArgV(argument, 2)); // 230 V
|
||||||
|
float Igoal = Pgoal / Ugoal; // 0.26087 A
|
||||||
|
float R = Ugoal / Igoal; // 881,666 Ohm
|
||||||
|
|
||||||
|
uint32_t channel = XdrvMailbox.index;
|
||||||
|
if (channel > Energy->phase_count) { channel = 1; }
|
||||||
|
channel--;
|
||||||
|
float Umeas = Energy->voltage[channel]; // 232.0
|
||||||
|
// Calculate current and power based on measured voltage
|
||||||
|
float Ical = Umeas / R; // 0.26306 A
|
||||||
|
float Pcal = Umeas * Ical; // 61.03 W
|
||||||
|
Ical *= 1000; // A to mA
|
||||||
|
|
||||||
|
uint32_t cal_type1 = ENERGY_CURRENT_CALIBRATION;
|
||||||
|
float cal1 = Ical;
|
||||||
|
float cal2 = Pcal;
|
||||||
|
if (ENERGY_CURRENT_CALIBRATION == cal_type) {
|
||||||
|
cal_type1 = ENERGY_POWER_CALIBRATION;
|
||||||
|
cal1 = Pcal;
|
||||||
|
cal2 = Ical;
|
||||||
|
}
|
||||||
|
XdrvMailbox.data = argument;
|
||||||
|
ext_snprintf_P(argument, sizeof(argument), PSTR("%5_f"), &cal1);
|
||||||
|
XdrvMailbox.data_len = strlen(argument);
|
||||||
|
EnergyCommandSetCalResponse(cal_type1);
|
||||||
|
ext_snprintf_P(argument, sizeof(argument), PSTR("%5_f"), &cal2);
|
||||||
|
XdrvMailbox.data_len = strlen(argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EnergyCommandSetCalResponse(cal_type);
|
||||||
|
}
|
||||||
|
|
||||||
void CmndPowerSet(void) {
|
void CmndPowerSet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_POWER_CALIBRATION);
|
EnergyCommandSetCal(ENERGY_POWER_CALIBRATION);
|
||||||
}
|
}
|
||||||
void CmndVoltageSet(void) {
|
void CmndVoltageSet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_VOLTAGE_CALIBRATION);
|
EnergyCommandSetCalResponse(ENERGY_VOLTAGE_CALIBRATION);
|
||||||
}
|
}
|
||||||
void CmndCurrentSet(void) {
|
void CmndCurrentSet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_CURRENT_CALIBRATION);
|
EnergyCommandSetCal(ENERGY_CURRENT_CALIBRATION);
|
||||||
}
|
}
|
||||||
void CmndFrequencySet(void) {
|
void CmndFrequencySet(void) {
|
||||||
EnergyCommandSetCalResponse(ENERGY_FREQUENCY_CALIBRATION);
|
EnergyCommandSetCalResponse(ENERGY_FREQUENCY_CALIBRATION);
|
||||||
|
@ -1526,6 +1568,10 @@ void EnergyShow(bool json) {
|
||||||
if (!Energy->type_dc) {
|
if (!Energy->type_dc) {
|
||||||
if (Energy->current_available && Energy->voltage_available) {
|
if (Energy->current_available && Energy->voltage_available) {
|
||||||
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
||||||
|
if (0 == Energy->current[i]) {
|
||||||
|
Energy->active_power[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
apparent_power[i] = Energy->apparent_power[i];
|
apparent_power[i] = Energy->apparent_power[i];
|
||||||
if (isnan(apparent_power[i])) {
|
if (isnan(apparent_power[i])) {
|
||||||
apparent_power[i] = Energy->voltage[i] * Energy->current[i];
|
apparent_power[i] = Energy->voltage[i] * Energy->current[i];
|
||||||
|
@ -1551,11 +1597,15 @@ void EnergyShow(bool json) {
|
||||||
}
|
}
|
||||||
if (apparent_power[i] < Energy->active_power[i]) { // Should be impossible
|
if (apparent_power[i] < Energy->active_power[i]) { // Should be impossible
|
||||||
if (apparent_power[i]) {
|
if (apparent_power[i]) {
|
||||||
if ((power_factor[i] > 1.005) && (power_factor[i] < 2.0f)) { // Skip below 0.5% and don't expect 50% differences
|
if ((power_factor[i] >= 1.02f) && (power_factor[i] < 2.0f)) { // Skip below 2% and don't expect 50% differences
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("NRG: Calibrate as Active %3_fW > Apparent %3_fVA (PF = %4_f)"),
|
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("NRG: Calibrate as Active %3_fW > Apparent %3_fVA (PF = %4_f)"),
|
||||||
&Energy->active_power[i], &apparent_power[i], &power_factor[i]);
|
&Energy->active_power[i], &apparent_power[i], &power_factor[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
apparent_power[i] = Energy->active_power[i]; // Force apparent equal to active as mis-calibrated
|
||||||
|
if (power_factor[i] > 1) { // Should not happen (Active > Apparent)
|
||||||
|
power_factor[i] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reactive_power[i] = Energy->reactive_power[i];
|
reactive_power[i] = Energy->reactive_power[i];
|
||||||
|
|
Loading…
Reference in New Issue