mirror of
https://github.com/arendst/Tasmota.git
synced 2025-08-03 16:07:43 +00:00
Add driver USE_SDM120_2 with Domoticz P1 Smart Meter functionality as future replacement for USE_SDM120 - Pls test and report
Add driver USE_SDM120_2 with Domoticz P1 Smart Meter functionality as future replacement for USE_SDM120 - Pls test and report (#6282)
This commit is contained in:
parent
7edcb84eab
commit
f4b5e565ef
@ -5,6 +5,7 @@
|
|||||||
* Add compile time define USE_WS2812_HARDWARE to select hardware type WS2812, WS2812X, WS2813, SK6812, LC8812 or APA106 (DMA mode only)
|
* Add compile time define USE_WS2812_HARDWARE to select hardware type WS2812, WS2812X, WS2813, SK6812, LC8812 or APA106 (DMA mode only)
|
||||||
* Add 'sonoff-ir' pre-packaged IR-dedicated firmware and 'sonoff-ircustom' to customize firmware with IR Full protocol support
|
* Add 'sonoff-ir' pre-packaged IR-dedicated firmware and 'sonoff-ircustom' to customize firmware with IR Full protocol support
|
||||||
* Add Zigbee support phase 2 - cc2530 initialization and basic ZCL decoding
|
* Add Zigbee support phase 2 - cc2530 initialization and basic ZCL decoding
|
||||||
|
* Add driver USE_SDM120_2 with Domoticz P1 Smart Meter functionality as future replacement for USE_SDM120 - Pls test and report
|
||||||
*
|
*
|
||||||
* 6.6.0.8 20190827
|
* 6.6.0.8 20190827
|
||||||
* Add Tuya Energy monitoring by Shantur Rathore
|
* Add Tuya Energy monitoring by Shantur Rathore
|
||||||
|
@ -429,8 +429,9 @@
|
|||||||
#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code)
|
#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code)
|
||||||
#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code)
|
#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code)
|
||||||
#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code)
|
#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code)
|
||||||
|
//#define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy meter (+1k4 code)
|
||||||
|
|
||||||
//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code)
|
//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+2k4 code)
|
||||||
#define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud)
|
#define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud)
|
||||||
#define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code)
|
#define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code)
|
||||||
//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code)
|
//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code)
|
||||||
|
@ -113,6 +113,7 @@ const uint16_t SERIALLOG_TIMER = 600; // Seconds to disable SerialLog
|
|||||||
const uint8_t OTA_ATTEMPTS = 5; // Number of times to try fetching the new firmware
|
const uint8_t OTA_ATTEMPTS = 5; // Number of times to try fetching the new firmware
|
||||||
|
|
||||||
const uint16_t INPUT_BUFFER_SIZE = 520; // Max number of characters in (serial and http) command buffer
|
const uint16_t INPUT_BUFFER_SIZE = 520; // Max number of characters in (serial and http) command buffer
|
||||||
|
const uint16_t FLOATSZ = 33; // Max number of characters in float result from dtostrfd
|
||||||
const uint16_t CMDSZ = 24; // Max number of characters in command
|
const uint16_t CMDSZ = 24; // Max number of characters in command
|
||||||
const uint16_t TOPSZ = 100; // Max number of characters in topic string
|
const uint16_t TOPSZ = 100; // Max number of characters in topic string
|
||||||
const uint16_t LOGSZ = 520; // Max number of characters in log
|
const uint16_t LOGSZ = 520; // Max number of characters in log
|
||||||
@ -261,7 +262,7 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU
|
|||||||
FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER,
|
FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER,
|
||||||
FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA,
|
FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA,
|
||||||
FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR,
|
FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR,
|
||||||
FUNC_ENERGY_EVERY_SECOND,
|
FUNC_ENERGY_EVERY_SECOND, FUNC_ENERGY_RESET,
|
||||||
FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED,
|
FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED,
|
||||||
FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER, FUNC_SET_CHANNELS};
|
FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER, FUNC_SET_CHANNELS};
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ struct ENERGY {
|
|||||||
float reactive_power = NAN; // 123.1 VAr
|
float reactive_power = NAN; // 123.1 VAr
|
||||||
float power_factor = NAN; // 0.12
|
float power_factor = NAN; // 0.12
|
||||||
float frequency = NAN; // 123.1 Hz
|
float frequency = NAN; // 123.1 Hz
|
||||||
|
|
||||||
float start_energy = 0; // 12345.12345 kWh total previous
|
float start_energy = 0; // 12345.12345 kWh total previous
|
||||||
|
|
||||||
float daily = 0; // 123.123 kWh
|
float daily = 0; // 123.123 kWh
|
||||||
@ -114,7 +115,6 @@ struct ENERGY {
|
|||||||
uint8_t mplr_counter = 0;
|
uint8_t mplr_counter = 0;
|
||||||
uint8_t max_energy_state = 0;
|
uint8_t max_energy_state = 0;
|
||||||
#endif // USE_ENERGY_POWER_LIMIT
|
#endif // USE_ENERGY_POWER_LIMIT
|
||||||
|
|
||||||
#endif // USE_ENERGY_MARGIN_DETECTION
|
#endif // USE_ENERGY_MARGIN_DETECTION
|
||||||
} Energy;
|
} Energy;
|
||||||
|
|
||||||
@ -384,9 +384,14 @@ void EnergyOverTempCheck()
|
|||||||
Energy.voltage = 0;
|
Energy.voltage = 0;
|
||||||
Energy.current = 0;
|
Energy.current = 0;
|
||||||
Energy.active_power = 0;
|
Energy.active_power = 0;
|
||||||
|
if (!isnan(Energy.apparent_power)) { Energy.apparent_power = 0; }
|
||||||
|
if (!isnan(Energy.reactive_power)) { Energy.reactive_power = 0; }
|
||||||
if (!isnan(Energy.frequency)) { Energy.frequency = 0; }
|
if (!isnan(Energy.frequency)) { Energy.frequency = 0; }
|
||||||
if (!isnan(Energy.power_factor)) { Energy.power_factor = 0; }
|
if (!isnan(Energy.power_factor)) { Energy.power_factor = 0; }
|
||||||
Energy.start_energy = 0;
|
Energy.start_energy = 0;
|
||||||
|
|
||||||
|
XnrgCall(FUNC_ENERGY_RESET);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -450,11 +455,11 @@ void CmndEnergyReset(void)
|
|||||||
RtcSettings.energy_usage.usage1_kWhtotal = Settings.energy_kWhtotal;
|
RtcSettings.energy_usage.usage1_kWhtotal = Settings.energy_kWhtotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
char energy_total_chr[33];
|
char energy_total_chr[FLOATSZ];
|
||||||
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];
|
char energy_daily_chr[FLOATSZ];
|
||||||
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];
|
char energy_yesterday_chr[FLOATSZ];
|
||||||
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
|
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
|
||||||
|
|
||||||
Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"),
|
Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"),
|
||||||
@ -704,16 +709,15 @@ const char HTTP_ENERGY_SNS2[] PROGMEM =
|
|||||||
void EnergyShow(bool json)
|
void EnergyShow(bool json)
|
||||||
{
|
{
|
||||||
char speriod[20];
|
char speriod[20];
|
||||||
// char sfrequency[20];
|
|
||||||
|
|
||||||
bool show_energy_period = (0 == tele_period);
|
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 apparent_power_chr[FLOATSZ];
|
||||||
char reactive_power_chr[33];
|
char reactive_power_chr[FLOATSZ];
|
||||||
char power_factor_chr[33];
|
char power_factor_chr[FLOATSZ];
|
||||||
char frequency_chr[33];
|
char frequency_chr[FLOATSZ];
|
||||||
if (!Energy.type_dc) {
|
if (!Energy.type_dc) {
|
||||||
if (Energy.current_available && Energy.voltage_available) {
|
if (Energy.current_available && Energy.voltage_available) {
|
||||||
float apparent_power = Energy.apparent_power;
|
float apparent_power = Energy.apparent_power;
|
||||||
@ -749,21 +753,21 @@ void EnergyShow(bool json)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char voltage_chr[33];
|
char voltage_chr[FLOATSZ];
|
||||||
dtostrfd(Energy.voltage, Settings.flag2.voltage_resolution, voltage_chr);
|
dtostrfd(Energy.voltage, Settings.flag2.voltage_resolution, voltage_chr);
|
||||||
char current_chr[33];
|
char current_chr[FLOATSZ];
|
||||||
dtostrfd(Energy.current, Settings.flag2.current_resolution, current_chr);
|
dtostrfd(Energy.current, Settings.flag2.current_resolution, current_chr);
|
||||||
char active_power_chr[33];
|
char active_power_chr[FLOATSZ];
|
||||||
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];
|
char energy_daily_chr[FLOATSZ];
|
||||||
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];
|
char energy_yesterday_chr[FLOATSZ];
|
||||||
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
|
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
|
||||||
char energy_total_chr[33];
|
char energy_total_chr[FLOATSZ];
|
||||||
dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr);
|
dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr);
|
||||||
|
|
||||||
float energy = 0;
|
float energy = 0;
|
||||||
char energy_period_chr[33];
|
char energy_period_chr[FLOATSZ];
|
||||||
if (show_energy_period) {
|
if (show_energy_period) {
|
||||||
if (Energy.period) energy = (float)(Energy.kWhtoday - Energy.period) / 100;
|
if (Energy.period) energy = (float)(Energy.kWhtoday - Energy.period) / 100;
|
||||||
Energy.period = Energy.kWhtoday;
|
Energy.period = Energy.kWhtoday;
|
||||||
@ -789,6 +793,7 @@ void EnergyShow(bool json)
|
|||||||
if (Energy.current_available) {
|
if (Energy.current_available) {
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), current_chr);
|
ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), current_chr);
|
||||||
}
|
}
|
||||||
|
XnrgCall(FUNC_JSON_APPEND);
|
||||||
ResponseJsonEnd();
|
ResponseJsonEnd();
|
||||||
|
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
@ -797,7 +802,7 @@ void EnergyShow(bool json)
|
|||||||
DomoticzSensorPowerEnergy((int)Energy.active_power, energy_total_chr); // PowerUsage, EnergyToday
|
DomoticzSensorPowerEnergy((int)Energy.active_power, energy_total_chr); // PowerUsage, EnergyToday
|
||||||
|
|
||||||
dtostrfd((Energy.total - Energy.total1) * 1000, 1, energy_total_chr); // Tariff2
|
dtostrfd((Energy.total - Energy.total1) * 1000, 1, energy_total_chr); // Tariff2
|
||||||
char energy_total1_chr[33];
|
char energy_total1_chr[FLOATSZ];
|
||||||
dtostrfd(Energy.total1 * 1000, 1, energy_total1_chr); // Tariff1
|
dtostrfd(Energy.total1 * 1000, 1, energy_total1_chr); // Tariff1
|
||||||
char energy_non[2] = "0";
|
char energy_non[2] = "0";
|
||||||
DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, energy_non, energy_non, (int)Energy.active_power, 0);
|
DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, energy_non, energy_non, (int)Energy.active_power, 0);
|
||||||
@ -843,6 +848,7 @@ void EnergyShow(bool json)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr);
|
WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr);
|
||||||
|
XnrgCall(FUNC_WEB_SENSOR);
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
293
sonoff/xnrg_09_sdm120.ino
Normal file
293
sonoff/xnrg_09_sdm120.ino
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
xnrg_09_sdm120.ino - Eastron SDM120-Modbus energy meter support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2019 Gennaro Tortone and Theo Arends
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_ENERGY_SENSOR
|
||||||
|
#ifdef USE_SDM120_2
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Eastron SDM120 or SDM220 Modbus energy meter
|
||||||
|
*
|
||||||
|
* Based on: https://github.com/reaper7/SDM_Energy_Meter
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XNRG_09 9
|
||||||
|
|
||||||
|
// can be user defined in my_user_config.h
|
||||||
|
#ifndef SDM120_SPEED
|
||||||
|
#define SDM120_SPEED 2400 // default SDM120 Modbus address
|
||||||
|
#endif
|
||||||
|
// can be user defined in my_user_config.h
|
||||||
|
#ifndef SDM120_ADDR
|
||||||
|
#define SDM120_ADDR 1 // default SDM120 Modbus address
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <TasmotaModbus.h>
|
||||||
|
TasmotaModbus *Sdm120Modbus;
|
||||||
|
|
||||||
|
const uint16_t sdm120_start_addresses[] {
|
||||||
|
0x0000, // SDM120C_VOLTAGE [V]
|
||||||
|
0x0006, // SDM120C_CURRENT [A]
|
||||||
|
0x000C, // SDM120C_POWER [W]
|
||||||
|
0x0012, // SDM120C_APPARENT_POWER [VA]
|
||||||
|
0x0018, // SDM120C_REACTIVE_POWER [VAR]
|
||||||
|
0x001E, // SDM120C_POWER_FACTOR
|
||||||
|
0x0046, // SDM120C_FREQUENCY [Hz]
|
||||||
|
#ifdef USE_SDM220
|
||||||
|
0x0156, // SDM120C_TOTAL_ACTIVE_ENERGY [Wh]
|
||||||
|
0X0024, // SDM220_PHASE_ANGLE [Degre]
|
||||||
|
0X0048, // SDM220_IMPORT_ACTIVE [kWh]
|
||||||
|
0X004A, // SDM220_EXPORT_ACTIVE [kWh]
|
||||||
|
0X004C, // SDM220_IMPORT_REACTIVE [kVArh]
|
||||||
|
0X004E, // SDM220_EXPORT_REACTIVE [kVArh]
|
||||||
|
0X0158 // SDM220 TOTAL_REACTIVE [kVArh]
|
||||||
|
#else // USE_SDM220
|
||||||
|
0x0156 // SDM120C_TOTAL_ACTIVE_ENERGY [Wh]
|
||||||
|
#endif // USE_SDM220
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SDM120 {
|
||||||
|
uint8_t read_state = 0;
|
||||||
|
uint8_t send_retry = 0;
|
||||||
|
} Sdm120;
|
||||||
|
|
||||||
|
#ifdef USE_SDM220
|
||||||
|
struct SDM220 {
|
||||||
|
float phase_angle = 0;
|
||||||
|
float import_active = 0;
|
||||||
|
float export_active = 0;
|
||||||
|
float import_reactive = 0;
|
||||||
|
float export_reactive = 0;
|
||||||
|
float total_reactive = 0;
|
||||||
|
} Sdm220;
|
||||||
|
#endif // USE_SDM220
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void SDM120Every200ms(void)
|
||||||
|
{
|
||||||
|
bool data_ready = Sdm120Modbus->ReceiveReady();
|
||||||
|
|
||||||
|
if (data_ready) {
|
||||||
|
uint8_t buffer[9];
|
||||||
|
|
||||||
|
uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2);
|
||||||
|
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer));
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error);
|
||||||
|
} else {
|
||||||
|
Energy.data_valid = 0;
|
||||||
|
|
||||||
|
float value;
|
||||||
|
((uint8_t*)&value)[3] = buffer[3];
|
||||||
|
((uint8_t*)&value)[2] = buffer[4];
|
||||||
|
((uint8_t*)&value)[1] = buffer[5];
|
||||||
|
((uint8_t*)&value)[0] = buffer[6];
|
||||||
|
|
||||||
|
switch(Sdm120.read_state) {
|
||||||
|
case 0:
|
||||||
|
Energy.voltage = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
Energy.current = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
Energy.active_power = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
Energy.apparent_power = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
Energy.reactive_power = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
Energy.power_factor = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
Energy.frequency = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
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;
|
||||||
|
|
||||||
|
#ifdef USE_SDM220
|
||||||
|
case 8:
|
||||||
|
Sdm220.phase_angle = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
Sdm220.import_active = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
Sdm220.export_active = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
Sdm220.import_reactive = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
Sdm220.export_reactive = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
Sdm220.total_reactive = value;
|
||||||
|
break;
|
||||||
|
#endif // USE_SDM220
|
||||||
|
} // end switch
|
||||||
|
|
||||||
|
Sdm120.read_state++;
|
||||||
|
if (sizeof(sdm120_start_addresses)/2 == Sdm120.read_state) {
|
||||||
|
Sdm120.read_state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end data ready
|
||||||
|
|
||||||
|
if (0 == Sdm120.send_retry || data_ready) {
|
||||||
|
Sdm120.send_retry = 5;
|
||||||
|
Sdm120Modbus->Send(SDM120_ADDR, 0x04, sdm120_start_addresses[Sdm120.read_state], 2);
|
||||||
|
} else {
|
||||||
|
Sdm120.send_retry--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sdm120SnsInit(void)
|
||||||
|
{
|
||||||
|
Sdm120Modbus = new TasmotaModbus(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX]);
|
||||||
|
uint8_t result = Sdm120Modbus->Begin(SDM120_SPEED);
|
||||||
|
if (result) {
|
||||||
|
if (2 == result) { ClaimSerial(); }
|
||||||
|
} else {
|
||||||
|
energy_flg = ENERGY_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sdm120DrvInit(void)
|
||||||
|
{
|
||||||
|
if (!energy_flg) {
|
||||||
|
if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) {
|
||||||
|
energy_flg = XNRG_09;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_SDM220
|
||||||
|
|
||||||
|
void Sdm220Reset(void)
|
||||||
|
{
|
||||||
|
Sdm220.phase_angle = 0;
|
||||||
|
Sdm220.import_active = 0;
|
||||||
|
Sdm220.export_active = 0;
|
||||||
|
Sdm220.import_reactive = 0;
|
||||||
|
Sdm220.export_reactive = 0;
|
||||||
|
Sdm220.total_reactive = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
const char HTTP_ENERGY_SDM220[] PROGMEM =
|
||||||
|
"{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"
|
||||||
|
"{s}" D_IMPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
|
||||||
|
"{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
|
||||||
|
"{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}"
|
||||||
|
"{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}"
|
||||||
|
"{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}";
|
||||||
|
#endif // USE_WEBSERVER
|
||||||
|
|
||||||
|
void Sdm220Show(bool json)
|
||||||
|
{
|
||||||
|
char phase_angle_chr[FLOATSZ];
|
||||||
|
dtostrfd(Sdm220.phase_angle, 2, phase_angle_chr);
|
||||||
|
char import_active_chr[FLOATSZ];
|
||||||
|
dtostrfd(Sdm220.import_active, Settings.flag2.wattage_resolution, import_active_chr);
|
||||||
|
char export_active_chr[FLOATSZ];
|
||||||
|
dtostrfd(Sdm220.export_active, Settings.flag2.wattage_resolution, export_active_chr);
|
||||||
|
char import_reactive_chr[FLOATSZ];
|
||||||
|
dtostrfd(Sdm220.import_reactive, Settings.flag2.wattage_resolution, import_reactive_chr);
|
||||||
|
char export_reactive_chr[FLOATSZ];
|
||||||
|
dtostrfd(Sdm220.export_reactive, Settings.flag2.wattage_resolution, export_reactive_chr);
|
||||||
|
char total_reactive_chr[FLOATSZ];
|
||||||
|
dtostrfd(Sdm220.total_reactive, Settings.flag2.wattage_resolution, total_reactive_chr);
|
||||||
|
|
||||||
|
if (json) {
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"),
|
||||||
|
phase_angle_chr, import_active_chr, export_active_chr, import_reactive_chr, export_reactive_chr, total_reactive_chr);
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
} else {
|
||||||
|
WSContentSend_PD(HTTP_ENERGY_SDM220, phase_angle_chr, import_active_chr, export_active_chr, import_reactive_chr, export_reactive_chr, total_reactive_chr);
|
||||||
|
#endif // USE_WEBSERVER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_SDM220
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
int Xnrg09(uint8_t function)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (FUNC_PRE_INIT == function) {
|
||||||
|
Sdm120DrvInit();
|
||||||
|
}
|
||||||
|
else if (XNRG_09 == energy_flg) {
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_INIT:
|
||||||
|
Sdm120SnsInit();
|
||||||
|
break;
|
||||||
|
case FUNC_EVERY_200_MSECOND:
|
||||||
|
if (uptime > 4) { SDM120Every200ms(); }
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef USE_SDM220
|
||||||
|
case FUNC_ENERGY_RESET:
|
||||||
|
Sdm220Reset();
|
||||||
|
break;
|
||||||
|
case FUNC_JSON_APPEND:
|
||||||
|
Sdm220Show(1);
|
||||||
|
break;
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
case FUNC_WEB_SENSOR:
|
||||||
|
Sdm220Show(0);
|
||||||
|
break;
|
||||||
|
#endif // USE_WEBSERVER
|
||||||
|
#endif // USE_SDM220
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_SDM120_2
|
||||||
|
#endif // USE_ENERGY_SENSOR
|
Loading…
x
Reference in New Issue
Block a user