mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' of https://github.com/arendst/Sonoff-Tasmota into issue_6191
This commit is contained in:
commit
1de7abe9f4
|
@ -49,7 +49,7 @@ memory is dynamically allocated as a result of the D section.
|
|||
copying a string to a number or reverse is supported
|
||||
|
||||
>**\>B**
|
||||
executed on BOOT time
|
||||
executed on BOOT time and script save
|
||||
|
||||
>**\>T**
|
||||
executed on teleperiod time (**SENSOR** and **STATE**), get tele vars only in this section
|
||||
|
@ -183,6 +183,7 @@ and on the same line conditions may be bracketed e.g. if ((a==b) and ((c==d) or
|
|||
**spin(x m)** set gpio pin x (0-16) to value m (0,1) only the last bit is used, so even values set the pin to zero and uneven values set the pin to 1
|
||||
**spinm(x m)** set pin mode gpio pin x (0-16) to mode m (input=0,output=1,input with pullup=2)
|
||||
**ws2812(array)** copies an array (defined with m:name) to the WS2812 LED chain the array should be defined as long as the number of pixels. the color is coded as 24 bit RGB
|
||||
**hsvrgb(h s v)** converts hue (0-360), saturation (0-100) and value (0-100) to RGB color
|
||||
|
||||
>**#name** names a subroutine, subroutines are called with **=#name**
|
||||
**#name(param)** names a subroutines with a parameter is called with **=#name(param)**
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
/*********************************************************************************************\
|
||||
* 6.6.0.5 20190816
|
||||
* Add command WebSensor<sensor number> 0/1 to control display of sensor data in web GUI (#6085)
|
||||
* Change some table locations from RAM to Flash
|
||||
*
|
||||
* 6.6.0.4 20190806
|
||||
* Add support for CHIRP soil moisture sensor by Christian Baars
|
||||
* Add debug compile features using defines DEBUG_TASMOTA_CORE, DEBUG_TASMOTA_DRIVER and DEBUG_TASMOTA_SENSOR.
|
||||
|
|
|
@ -324,6 +324,7 @@
|
|||
#define D_CMND_WEBREFRESH "WebRefresh"
|
||||
#define D_CMND_WEBSEND "WebSend"
|
||||
#define D_CMND_WEBCOLOR "WebColor"
|
||||
#define D_CMND_WEBSENSOR "WebSensor"
|
||||
#define D_CMND_EMULATION "Emulation"
|
||||
|
||||
// Commands xdrv_03_energy.ino
|
||||
|
|
|
@ -344,7 +344,7 @@ struct SYSCFG {
|
|||
uint32_t adc_param2; // 798
|
||||
int adc_param3; // 79C
|
||||
uint32_t monitors; // 7A0
|
||||
uint32_t sensors[3]; // 7A4
|
||||
uint32_t sensors[3]; // 7A4 Normal WebSensor, Debug SetSensor
|
||||
uint32_t displays; // 7B0
|
||||
uint32_t energy_kWhtotal_time; // 7B4
|
||||
unsigned long weight_item; // 7B8 Weight of one item in gram * 10
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* Performance ROM (PROGMEM) vs RAM (RODATA)
|
||||
\*********************************************************************************************/
|
||||
|
||||
//#define XFUNC_PTR_IN_ROM // Enable for keeping tables in ROM (PROGMEM) which seem to have access issues on some flash types
|
||||
#define XFUNC_PTR_IN_ROM // Enable for keeping tables in ROM (PROGMEM) which seem to have access issues on some flash types
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Default sensor states
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
#ifndef _SONOFF_VERSION_H_
|
||||
#define _SONOFF_VERSION_H_
|
||||
|
||||
const uint32_t VERSION = 0x06060004;
|
||||
const uint32_t VERSION = 0x06060005;
|
||||
|
||||
#endif // _SONOFF_VERSION_H_
|
||||
|
|
|
@ -331,12 +331,13 @@ void CmndStatus(void)
|
|||
}
|
||||
|
||||
if ((0 == payload) || (4 == payload)) {
|
||||
char sensors[LOGSZ];
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\""
|
||||
D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\""
|
||||
D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"),
|
||||
D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"],\"Sensors\":%s}}"),
|
||||
ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024,
|
||||
ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(),
|
||||
LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5);
|
||||
LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, XsnsSensorsAvailable(sensors));
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4"));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -2461,13 +2460,13 @@ const char kWebCommands[] PROGMEM = "|" // No prefix
|
|||
#ifdef USE_EMULATION
|
||||
D_CMND_EMULATION "|"
|
||||
#endif
|
||||
D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR ;
|
||||
D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR;
|
||||
|
||||
void (* const WebCommand[])(void) PROGMEM = {
|
||||
#ifdef USE_EMULATION
|
||||
&CmndEmulation,
|
||||
#endif
|
||||
&CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor };
|
||||
&CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor };
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
|
@ -2564,6 +2563,16 @@ void CmndWebColor(void)
|
|||
ResponseAppend_P(PSTR("]}"));
|
||||
}
|
||||
|
||||
void CmndWebSensor(void)
|
||||
{
|
||||
if (XdrvMailbox.index < MAX_XSNS_DRIVERS) {
|
||||
if (XdrvMailbox.payload >= 0) {
|
||||
bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1);
|
||||
}
|
||||
ResponseCmndIdxChar(GetStateText(bitRead(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32)));
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -174,7 +174,11 @@ const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255
|
|||
// from 11 bits (lower values) to 8 bits (upper values).
|
||||
// We're using the fact that lower values are small and can fit within 8 bits
|
||||
// To save flash space, the array is only 8 bits uint
|
||||
#ifdef XFUNC_PTR_IN_ROM
|
||||
const uint8_t _ledTable[] PROGMEM = {
|
||||
#else
|
||||
const uint8_t _ledTable[] = {
|
||||
#endif
|
||||
// 11 bits resolution
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, // 11 bits, 0..2047
|
||||
2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, // 11 bits, 0..2047
|
||||
|
@ -997,7 +1001,11 @@ uint16_t ledGamma(uint8_t v, uint16_t bits_out = 8) {
|
|||
// bits_resolution: the resolution of _ledTable[v], between 8 and 11
|
||||
uint32_t bits_resolution = 11 - (v / 64); // 8..11
|
||||
int32_t bits_correction = bits_out - bits_resolution; // -3..3
|
||||
#ifdef XFUNC_PTR_IN_ROM
|
||||
uint32_t uncorrected_value = pgm_read_byte(_ledTable + v); // 0..255
|
||||
#else
|
||||
uint32_t uncorrected_value = _ledTable[v]; // 0..255
|
||||
#endif
|
||||
if (0 == bits_correction) {
|
||||
// we already match the required resolution, no change
|
||||
result = uncorrected_value;
|
||||
|
|
|
@ -109,7 +109,6 @@ struct M_FILT {
|
|||
float rbuff[1];
|
||||
};
|
||||
|
||||
|
||||
typedef union {
|
||||
uint8_t data;
|
||||
struct {
|
||||
|
@ -200,8 +199,6 @@ void RulesTeleperiod(void) {
|
|||
if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">T",2, mqtt_data);
|
||||
}
|
||||
|
||||
//#define USE_24C256
|
||||
|
||||
// EEPROM MACROS
|
||||
#ifdef USE_24C256
|
||||
#ifndef USE_SCRIPT_FATFS
|
||||
|
@ -710,6 +707,91 @@ float DoMedian5(uint8_t index, float in) {
|
|||
return median_array(mf->buffer,MEDIAN_SIZE);
|
||||
}
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
#ifdef USE_WS2812
|
||||
uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value) {
|
||||
float r = 0, g = 0, b = 0;
|
||||
struct HSV {
|
||||
float H;
|
||||
float S;
|
||||
float V;
|
||||
} hsv;
|
||||
|
||||
hsv.H=hue;
|
||||
hsv.S=(float)saturation/100.0;
|
||||
hsv.V=(float)value/100.0;
|
||||
|
||||
if (hsv.S == 0) {
|
||||
r = hsv.V;
|
||||
g = hsv.V;
|
||||
b = hsv.V;
|
||||
} else {
|
||||
int i;
|
||||
float f, p, q, t;
|
||||
|
||||
if (hsv.H == 360)
|
||||
hsv.H = 0;
|
||||
else
|
||||
hsv.H = hsv.H / 60;
|
||||
|
||||
i = (int)trunc(hsv.H);
|
||||
f = hsv.H - i;
|
||||
|
||||
p = hsv.V * (1.0 - hsv.S);
|
||||
q = hsv.V * (1.0 - (hsv.S * f));
|
||||
t = hsv.V * (1.0 - (hsv.S * (1.0 - f)));
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
r = hsv.V;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
r = q;
|
||||
g = hsv.V;
|
||||
b = p;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
r = p;
|
||||
g = hsv.V;
|
||||
b = t;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
r = p;
|
||||
g = q;
|
||||
b = hsv.V;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = hsv.V;
|
||||
break;
|
||||
|
||||
default:
|
||||
r = hsv.V;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t ir,ig,ib;
|
||||
ir=r*255;
|
||||
ig=g*255;
|
||||
ib=b*255;
|
||||
|
||||
uint32_t rgb=(ir<<16)|(ig<<8)|ib;
|
||||
return rgb;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// vtype => ff=nothing found, fe=constant number,fd = constant string else bit 7 => 80 = string, 0 = number
|
||||
// no flash strings here for performance reasons!!!
|
||||
|
@ -1212,6 +1294,30 @@ chknext:
|
|||
}
|
||||
goto strexit;
|
||||
}
|
||||
#ifdef USE_LIGHT
|
||||
#ifdef USE_WS2812
|
||||
if (!strncmp(vname,"hsvrgb(",7)) {
|
||||
lp=GetNumericResult(lp+7,OPER_EQU,&fvar,0);
|
||||
if (fvar<0 || fvar>360) fvar=0;
|
||||
SCRIPT_SKIP_SPACES
|
||||
// arg2
|
||||
float fvar2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||
if (fvar2<0 || fvar2>100) fvar2=0;
|
||||
SCRIPT_SKIP_SPACES
|
||||
// arg3
|
||||
float fvar3;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar3,0);
|
||||
if (fvar3<0 || fvar3>100) fvar3=0;
|
||||
|
||||
fvar=HSVToRGB(fvar,fvar2,fvar3);
|
||||
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
case 'i':
|
||||
if (!strncmp(vname,"int(",4)) {
|
||||
|
@ -2046,6 +2152,9 @@ exit:
|
|||
#define IF_NEST 8
|
||||
// execute section of scripter
|
||||
int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||
|
||||
if (tasm_cmd_activ && tlen>0) return 0;
|
||||
|
||||
uint8_t vtype=0,sindex,xflg,floop=0,globvindex;
|
||||
int8_t globaindex;
|
||||
struct T_INDEX ind;
|
||||
|
@ -2060,9 +2169,6 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
|||
check=1;
|
||||
}
|
||||
|
||||
if (tasm_cmd_activ) return 0;
|
||||
|
||||
|
||||
float *dfvar,*cv_count,cv_max,cv_inc;
|
||||
char *cv_ptr;
|
||||
float fvar=0,fvar1,sysvar,swvar;
|
||||
|
@ -3224,10 +3330,11 @@ bool ScriptMqttData(void)
|
|||
}
|
||||
}
|
||||
value.trim();
|
||||
|
||||
//Create an new event. Cannot directly call RulesProcessEvent().
|
||||
//snprintf_P(event_data, sizeof(event_data), PSTR("%s=%s"), event_item.Event.c_str(), value.c_str());
|
||||
char sbuffer[128];
|
||||
snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%s\n"), event_item.Event.c_str(), value.c_str());
|
||||
snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str());
|
||||
//toLog(sbuffer);
|
||||
execute_script(sbuffer);
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM =
|
|||
const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM =
|
||||
",\"uniq_id\":\"%s\","
|
||||
"\"device\":{\"identifiers\":[\"%06X\"],"
|
||||
"\"connections\":[[\"mac\",\"%s\"]],"
|
||||
"\"name\":\"%s\","
|
||||
"\"model\":\"%s\","
|
||||
"\"sw_version\":\"%s%s\","
|
||||
|
@ -136,7 +137,8 @@ const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM =
|
|||
|
||||
const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM =
|
||||
",\"uniq_id\":\"%s\","
|
||||
"\"device\":{\"identifiers\":[\"%06X\"]}";
|
||||
"\"device\":{\"identifiers\":[\"%06X\"],"
|
||||
"\"connections\":[[\"mac\",\"%s\"]]}";
|
||||
|
||||
const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM =
|
||||
",\"~\":\"%s\"";
|
||||
|
@ -237,7 +239,7 @@ void HAssAnnounceRelayLight(void)
|
|||
Shorten(&availability_topic, prefix);
|
||||
|
||||
Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic);
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId());
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str());
|
||||
TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
|
||||
|
||||
if (is_light) {
|
||||
|
@ -317,7 +319,7 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint
|
|||
Shorten(&state_topic, prefix);
|
||||
Shorten(&availability_topic, prefix);
|
||||
Response_P(HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic);
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId());
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str());
|
||||
if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
|
||||
if (toggle) TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_TOGGLE);
|
||||
else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, Settings.state_text[0]);
|
||||
|
@ -416,7 +418,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype)
|
|||
Shorten(&availability_topic, prefix);
|
||||
|
||||
Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic);
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId());
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str());
|
||||
TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
|
||||
if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) {
|
||||
TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname);
|
||||
|
@ -516,7 +518,7 @@ void HAssAnnounceStatusSensor(void)
|
|||
|
||||
Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic);
|
||||
TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic);
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(),
|
||||
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(),
|
||||
Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
|
||||
TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
|
||||
TryResponseAppend_P(PSTR("}"));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
// }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -422,6 +422,428 @@ bool (* const xsns_func_ptr[])(uint8_t) = { // Sensor Function Pointers for sim
|
|||
|
||||
const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Xsns available list
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef XFUNC_PTR_IN_ROM
|
||||
const uint8_t kXsnsList[] PROGMEM = {
|
||||
#else
|
||||
const uint8_t kXsnsList[] = {
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_01
|
||||
XSNS_01,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_02
|
||||
XSNS_02,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_03
|
||||
XSNS_03,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_04
|
||||
XSNS_04,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_05
|
||||
XSNS_05,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_06
|
||||
XSNS_06,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_07
|
||||
XSNS_07,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_08
|
||||
XSNS_08,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_09
|
||||
XSNS_09,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_10
|
||||
XSNS_10,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_11
|
||||
XSNS_11,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_12
|
||||
XSNS_12,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_13
|
||||
XSNS_13,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_14
|
||||
XSNS_14,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_15
|
||||
XSNS_15,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_16
|
||||
XSNS_16,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_17
|
||||
XSNS_17,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_18
|
||||
XSNS_18,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_19
|
||||
XSNS_19,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_20
|
||||
XSNS_20,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_21
|
||||
XSNS_21,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_22
|
||||
XSNS_22,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_23
|
||||
XSNS_23,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_24
|
||||
XSNS_24,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_25
|
||||
XSNS_25,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_26
|
||||
XSNS_26,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_27
|
||||
XSNS_27,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_28
|
||||
XSNS_28,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_29
|
||||
XSNS_29,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_30
|
||||
XSNS_30,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_31
|
||||
XSNS_31,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_32
|
||||
XSNS_32,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_33
|
||||
XSNS_33,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_34
|
||||
XSNS_34,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_35
|
||||
XSNS_35,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_36
|
||||
XSNS_36,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_37
|
||||
XSNS_37,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_38
|
||||
XSNS_38,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_39
|
||||
XSNS_39,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_40
|
||||
XSNS_40,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_41
|
||||
XSNS_41,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_42
|
||||
XSNS_42,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_43
|
||||
XSNS_43,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_44
|
||||
XSNS_44,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_45
|
||||
XSNS_45,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_46
|
||||
XSNS_46,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_47
|
||||
XSNS_47,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_48
|
||||
XSNS_48,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_49
|
||||
XSNS_49,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_50
|
||||
XSNS_50,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_51
|
||||
XSNS_51,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_52
|
||||
XSNS_52,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_53
|
||||
XSNS_53,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_54
|
||||
XSNS_54,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_55
|
||||
XSNS_55,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_56
|
||||
XSNS_56,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_57
|
||||
XSNS_57,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_58
|
||||
XSNS_58,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_59
|
||||
XSNS_59,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_60
|
||||
XSNS_60,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_61
|
||||
XSNS_61,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_62
|
||||
XSNS_62,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_63
|
||||
XSNS_63,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_64
|
||||
XSNS_64,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_65
|
||||
XSNS_65,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_66
|
||||
XSNS_66,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_67
|
||||
XSNS_67,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_68
|
||||
XSNS_68,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_69
|
||||
XSNS_69,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_70
|
||||
XSNS_70,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_71
|
||||
XSNS_71,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_72
|
||||
XSNS_72,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_73
|
||||
XSNS_73,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_74
|
||||
XSNS_74,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_75
|
||||
XSNS_75,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_76
|
||||
XSNS_76,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_77
|
||||
XSNS_77,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_78
|
||||
XSNS_78,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_79
|
||||
XSNS_79,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_80
|
||||
XSNS_80,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_81
|
||||
XSNS_81,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_82
|
||||
XSNS_82,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_83
|
||||
XSNS_83,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_84
|
||||
XSNS_84,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_85
|
||||
XSNS_85,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_86
|
||||
XSNS_86,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_87
|
||||
XSNS_87,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_88
|
||||
XSNS_88,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_89
|
||||
XSNS_89,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_90
|
||||
XSNS_90,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_91
|
||||
XSNS_91,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_92
|
||||
XSNS_92,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_93
|
||||
XSNS_93,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_94
|
||||
XSNS_94,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_95
|
||||
XSNS_95
|
||||
#endif
|
||||
};
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
bool XsnsEnabled(uint32_t sns_index)
|
||||
{
|
||||
if (sns_index < sizeof(kXsnsList)) {
|
||||
#ifdef XFUNC_PTR_IN_ROM
|
||||
uint32_t index = pgm_read_byte(kXsnsList + sns_index);
|
||||
#else
|
||||
uint32_t index = kXsnsList[sns_index];
|
||||
#endif
|
||||
return bitRead(Settings.sensors[index / 32], index % 32);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char* XsnsSensorsAvailable(char* sensors)
|
||||
{
|
||||
// Return string like [2,3,4,5,8,9,10,14,15,17,18,34]
|
||||
sensors[0] = '\0';
|
||||
for (uint32_t i = 0; i < sizeof(kXsnsList); i++) {
|
||||
#ifdef XFUNC_PTR_IN_ROM
|
||||
uint32_t sensorid = pgm_read_byte(kXsnsList + i);
|
||||
#else
|
||||
uint32_t sensorid = kXsnsList[i];
|
||||
#endif
|
||||
snprintf_P(sensors, LOGSZ, PSTR("%s%s%d"), sensors, (!i) ? "[" : ",", sensorid);
|
||||
}
|
||||
snprintf_P(sensors, LOGSZ, PSTR("%s]"), sensors); // Max length is about 3 x 96 < LOGSZ
|
||||
return sensors;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Function call to all xsns
|
||||
\*********************************************************************************************/
|
||||
|
@ -453,6 +875,8 @@ bool XsnsCall(uint8_t Function)
|
|||
if (XsnsEnabled(x)) {
|
||||
#endif
|
||||
|
||||
if ((FUNC_WEB_SENSOR == Function) && !XsnsEnabled(x)) { continue; } // Skip web info for disabled sensors
|
||||
|
||||
#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND
|
||||
uint32_t profile_start_millis = millis();
|
||||
#endif // PROFILE_XSNS_SENSOR_EVERY_SECOND
|
||||
|
|
|
@ -24,256 +24,6 @@
|
|||
* Needs to be the last alphabetical file due to DEFINE compile order
|
||||
\*********************************************************************************************/
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Xsns available list
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef XFUNC_PTR_IN_ROM
|
||||
const uint8_t kXsnsList[] PROGMEM = {
|
||||
#else
|
||||
const uint8_t kXsnsList[] = {
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_01
|
||||
XSNS_01,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_02
|
||||
XSNS_02,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_03
|
||||
XSNS_03,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_04
|
||||
XSNS_04,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_05
|
||||
XSNS_05,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_06
|
||||
XSNS_06,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_07
|
||||
XSNS_07,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_08
|
||||
XSNS_08,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_09
|
||||
XSNS_09,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_10
|
||||
XSNS_10,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_11
|
||||
XSNS_11,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_12
|
||||
XSNS_12,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_13
|
||||
XSNS_13,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_14
|
||||
XSNS_14,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_15
|
||||
XSNS_15,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_16
|
||||
XSNS_16,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_17
|
||||
XSNS_17,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_18
|
||||
XSNS_18,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_19
|
||||
XSNS_19,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_20
|
||||
XSNS_20,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_21
|
||||
XSNS_21,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_22
|
||||
XSNS_22,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_23
|
||||
XSNS_23,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_24
|
||||
XSNS_24,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_25
|
||||
XSNS_25,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_26
|
||||
XSNS_26,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_27
|
||||
XSNS_27,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_28
|
||||
XSNS_28,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_29
|
||||
XSNS_29,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_30
|
||||
XSNS_30,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_31
|
||||
XSNS_31,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_32
|
||||
XSNS_32,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_33
|
||||
XSNS_33,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_34
|
||||
XSNS_34,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_35
|
||||
XSNS_35,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_36
|
||||
XSNS_36,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_37
|
||||
XSNS_37,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_38
|
||||
XSNS_38,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_39
|
||||
XSNS_39,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_40
|
||||
XSNS_40,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_41
|
||||
XSNS_41,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_42
|
||||
XSNS_42,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_43
|
||||
XSNS_43,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_44
|
||||
XSNS_44,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_45
|
||||
XSNS_45,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_46
|
||||
XSNS_46,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_47
|
||||
XSNS_47,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_48
|
||||
XSNS_48,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_49
|
||||
XSNS_49,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_50
|
||||
XSNS_50,
|
||||
#endif
|
||||
|
||||
// Optional user defined sensors in range 91 - 99
|
||||
|
||||
#ifdef XSNS_91
|
||||
XSNS_91,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_92
|
||||
XSNS_92,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_93
|
||||
XSNS_93,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_94
|
||||
XSNS_94,
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_95
|
||||
XSNS_95
|
||||
#endif
|
||||
};
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Xsns sensor control
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool XsnsEnabled(uint8_t sns_index)
|
||||
{
|
||||
if (sns_index < sizeof(kXsnsList)) {
|
||||
#ifdef XFUNC_PTR_IN_ROM
|
||||
uint8_t index = pgm_read_byte(kXsnsList + sns_index);
|
||||
#else
|
||||
uint8_t index = kXsnsList[sns_index];
|
||||
#endif
|
||||
return bitRead(Settings.sensors[index / 32], index % 32);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool XsnsPresent(uint8_t sns_index)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
|
|
Loading…
Reference in New Issue