From d1a8efe60d209a07a684962c05025831829443f0 Mon Sep 17 00:00:00 2001 From: tomcatxx <69747753+tomcatxx@users.noreply.github.com> Date: Wed, 10 Feb 2021 11:24:01 +0100 Subject: [PATCH 01/24] Update SDM.h Added all supported Registers from here: https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h --- lib/SDM_Energy_Meter/SDM.h | 255 +++++++++++++++++++++---------------- 1 file changed, 145 insertions(+), 110 deletions(-) diff --git a/lib/SDM_Energy_Meter/SDM.h b/lib/SDM_Energy_Meter/SDM.h index f5a58a458..e77340ef1 100644 --- a/lib/SDM_Energy_Meter/SDM.h +++ b/lib/SDM_Energy_Meter/SDM.h @@ -39,121 +39,156 @@ #endif #ifndef MAX_MILLIS_TO_WAIT - #define MAX_MILLIS_TO_WAIT 500 //default max time to wait for response from SDM + #define MAX_MILLIS_TO_WAIT 200 //default max time to wait for response from SDM #endif //------------------------------------------------------------------------------ -#define FRAMESIZE 9 //size of out/in array -#define SDM_REPLY_BYTE_COUNT 0x04 //number of bytes with data -#define SDM_B_01 0x01 //BYTE 1 -> slave address (default value 1 read from node 1) -#define SDM_B_02 0x04 //BYTE 2 -> function code (default value 0x04 read from 3X input registers) - //BYTES 3 & 4 (BELOW) -//SDM 120 registers -#define SDM120C_VOLTAGE 0x0000 //V -#define SDM120C_CURRENT 0x0006 //A -#define SDM120C_POWER 0x000C //W -#define SDM120C_ACTIVE_APPARENT_POWER 0x0012 //VA -#define SDM120C_REACTIVE_APPARENT_POWER 0x0018 //VAR -#define SDM120C_POWER_FACTOR 0x001E // -#define SDM120C_FREQUENCY 0x0046 //Hz -#define SDM120C_IMPORT_ACTIVE_ENERGY 0x0048 //Wh -#define SDM120C_EXPORT_ACTIVE_ENERGY 0x004A //Wh -#define SDM120C_TOTAL_ACTIVE_ENERGY 0x0156 //Wh -//SDM 220 registers -#define SDM220T_VOLTAGE 0x0000 //V -#define SDM220T_CURRENT 0x0006 //A -#define SDM220T_POWER 0x000C //W -#define SDM220T_ACTIVE_APPARENT_POWER 0x0012 //VA -#define SDM220T_REACTIVE_APPARENT_POWER 0x0018 //VAR -#define SDM220T_POWER_FACTOR 0x001E // -#define SDM220T_PHASE_ANGLE 0x0024 //DEGREE -#define SDM220T_FREQUENCY 0x0046 //Hz -#define SDM220T_IMPORT_ACTIVE_ENERGY 0x0048 //Wh -#define SDM220T_EXPORT_ACTIVE_ENERGY 0x004A //Wh -#define SDM220T_IMPORT_REACTIVE_ENERGY 0x004C //VARh -#define SDM220T_EXPORT_REACTIVE_ENERGY 0x004E //VARh -#define SDM220T_TOTAL_ACTIVE_ENERGY 0x0156 //Wh -#define SDM220T_TOTAL_REACTIVE_ENERGY 0x0158 //VARh -//SDM 230 registers -#define SDM230_VOLTAGE 0x0000 //V -#define SDM230_CURRENT 0x0006 //A -#define SDM230_POWER 0x000C //W -#define SDM230_ACTIVE_APPARENT_POWER 0x0012 //VA -#define SDM230_REACTIVE_APPARENT_POWER 0x0018 //VAR -#define SDM230_POWER_FACTOR 0x001E // -#define SDM230_PHASE_ANGLE 0x0024 //DEGREE -#define SDM230_FREQUENCY 0x0046 //Hz -#define SDM230_IMPORT_ACTIVE_ENERGY 0x0048 //Wh -#define SDM230_EXPORT_ACTIVE_ENERGY 0x004A //Wh -#define SDM230_IMPORT_REACTIVE_ENERGY 0x004C //VARh -#define SDM230_EXPORT_REACTIVE_ENERGY 0x004E //VARh -#define SDM230_TOTAL_SYSTEM_POWER_DEMAND 0x0054 //W -#define SDM230_MAXIMUM_SYSTEM_POWER_DEMAND 0x0056 //W -#define SDM230_CURRENT_POSITIVE_POWER_DEMAND 0x0058 //W -#define SDM230_MAXIMUM_POSITIVE_POWER_DEMAND 0x005A //W -#define SDM230_CURRENT_REVERSE_POWER_DEMAND 0x005C //W -#define SDM230_MAXIMUM_REVERSE_POWER_DEMAND 0x005E //W -#define SDM230_CURRENT_DEMAND 0x0102 //Amps -#define SDM230_MAXIMUM_CURRENT_DEMAND 0x0108 //Amps -#define SDM230_TOTAL_ACTIVE_ENERGY 0x0156 //kwh -#define SDM230_TOTAL_REACTIVE_ENERGY 0x0158 //kvarh -#define SDM230_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY 0x0180 //Wh -#define SDM230_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY 0x0182 //VARh -//SDM 630 registers -#define SDM630_VOLTAGE1 0x0000 //V -#define SDM630_VOLTAGE2 0x0002 //V -#define SDM630_VOLTAGE3 0x0004 //V -#define SDM630_CURRENT1 0x0006 //A -#define SDM630_CURRENT2 0x0008 //A -#define SDM630_CURRENT3 0x000A //A -#define SDM630_CURRENTSUM 0x0030 //A -#define SDM630_POWER1 0x000C //W -#define SDM630_POWER2 0x000E //W -#define SDM630_POWER3 0x0010 //W -#define SDM630_POWERTOTAL 0x0034 //W -#define SDM630_VOLT_AMPS1 0x0012 //VA -#define SDM630_VOLT_AMPS2 0x0014 //VA -#define SDM630_VOLT_AMPS3 0x0016 //VA -#define SDM630_VOLT_AMPS_TOTAL 0x0038 //VA -#define SDM630_VOLT_AMPS_REACTIVE1 0x0018 //VAr -#define SDM630_VOLT_AMPS_REACTIVE2 0x001A //VAr -#define SDM630_VOLT_AMPS_REACTIVE3 0x001C //VAr -#define SDM630_VOLT_AMPS_REACTIVE_TOTAL 0x003C //VAr -#define SDM630_POWER_FACTOR1 0x001E -#define SDM630_POWER_FACTOR2 0x0020 -#define SDM630_POWER_FACTOR3 0x0022 -#define SDM630_POWER_FACTOR_TOTAL 0x003E -#define SDM630_PHASE_ANGLE1 0x0024 //Degrees -#define SDM630_PHASE_ANGLE2 0x0026 //Degrees -#define SDM630_PHASE_ANGLE3 0x0028 //Degrees -#define SDM630_PHASE_ANGLE_TOTAL 0x0042 //Degrees -#define SDM630_VOLTAGE_AVERAGE 0x002A //V -#define SDM630_CURRENT_AVERAGE 0x002E //A -#define SDM630_FREQUENCY 0x0046 //HZ -#define SDM630_IMPORT_ACTIVE_ENERGY 0x0048 //Wh -#define SDM630_EXPORT_ACTIVE_ENERGY 0x004A //Wh -#define SDM630_IMPORT_REACTIVE_ENERGY 0x004C //VARh -#define SDM630_EXPORT_REACTIVE_ENERGY 0x004E //VARh -#define SDM630_TOTAL_SYSTEM_POWER_DEMAND 0x0054 //W -#define SDM630_MAXIMUM_TOTAL_SYSTEM_POWER 0x0056 //W -#define SDM630_PHASE_1_LN_VOLTS_THD 0x00EA //% -#define SDM630_PHASE_2_LN_VOLTS_THD 0x00EC //% -#define SDM630_PHASE_3_LN_VOLTS_THD 0x00EE //% -#define SDM630_AVERAGE_VOLTS_THD 0x00F8 //% -#define SDM630_PHASE_1_CURRENT_THD 0x00F0 //% -#define SDM630_PHASE_2_CURRENT_THD 0x00F2 //% -#define SDM630_PHASE_3_CURRENT_THD 0x00F4 //% -#define SDM630_AVERAGE_CURRENT_THD 0x00FA //% +#define SDM_ERR_NO_ERROR 0 // no error +#define SDM_ERR_CRC_ERROR 1 // crc error +#define SDM_ERR_WRONG_BYTES 2 // bytes b0,b1 or b2 wrong +#define SDM_ERR_NOT_ENOUGHT_BYTES 3 // not enough bytes from sdm +#define SDM_ERR_TIMEOUT 4 // timeout -#define SDM_B_05 0x00 //BYTE 5 -#define SDM_B_06 0x02 //BYTE 6 -//------------------------------------------------------------------------------ -#define SDM_ERR_NO_ERROR 0 //no error -#define SDM_ERR_CRC_ERROR 1 //crc error -#define SDM_ERR_WRONG_BYTES 2 //bytes b0,b1 or b2 wrong -#define SDM_ERR_NOT_ENOUGHT_BYTES 3 //not enough bytes from sdm -#define SDM_ERR_TIMEOUT 4 //timeout //------------------------------------------------------------------------------ + +#define FRAMESIZE 9 // size of out/in array +#define SDM_REPLY_BYTE_COUNT 0x04 // number of bytes with data + +#define SDM_B_01 0x01 // BYTE 1 -> slave address (default value 1 read from node 1) +#define SDM_B_02 0x04 // BYTE 2 -> function code (default value 0x04 read from 3X input registers) +#define SDM_B_05 0x00 // BYTE 5 +#define SDM_B_06 0x02 // BYTE 6 + // BYTES 3 & 4 (BELOW) + +//----------------------------------------------------------------------------------------------------------------------------------------------------------- +// REGISTERS LIST FOR SDM DEVICES | +//----------------------------------------------------------------------------------------------------------------------------------------------------------- +// REGISTER NAME REGISTER ADDRESS UNIT | SDM630 | SDM230 | SDM220 | SDM120CT| SDM120 | SDM72D | +//----------------------------------------------------------------------------------------------------------------------------------------------------------- +#define SDM_PHASE_1_VOLTAGE 0x0000 // V | 1 | 1 | 1 | 1 | 1 | | +#define SDM_PHASE_2_VOLTAGE 0x0002 // V | 1 | | | | | | +#define SDM_PHASE_3_VOLTAGE 0x0004 // V | 1 | | | | | | +#define SDM_PHASE_1_CURRENT 0x0006 // A | 1 | 1 | 1 | 1 | 1 | | +#define SDM_PHASE_2_CURRENT 0x0008 // A | 1 | | | | | | +#define SDM_PHASE_3_CURRENT 0x000A // A | 1 | | | | | | +#define SDM_PHASE_1_POWER 0x000C // W | 1 | 1 | 1 | 1 | 1 | | +#define SDM_PHASE_2_POWER 0x000E // W | 1 | | | | | | +#define SDM_PHASE_3_POWER 0x0010 // W | 1 | | | | | | +#define SDM_PHASE_1_APPARENT_POWER 0x0012 // VA | 1 | 1 | 1 | 1 | 1 | | +#define SDM_PHASE_2_APPARENT_POWER 0x0014 // VA | 1 | | | | | | +#define SDM_PHASE_3_APPARENT_POWER 0x0016 // VA | 1 | | | | | | +#define SDM_PHASE_1_REACTIVE_POWER 0x0018 // VAr | 1 | 1 | 1 | 1 | 1 | | +#define SDM_PHASE_2_REACTIVE_POWER 0x001A // VAr | 1 | | | | | | +#define SDM_PHASE_3_REACTIVE_POWER 0x001C // VAr | 1 | | | | | | +#define SDM_PHASE_1_POWER_FACTOR 0x001E // | 1 | 1 | 1 | 1 | 1 | | +#define SDM_PHASE_2_POWER_FACTOR 0x0020 // | 1 | | | | | | +#define SDM_PHASE_3_POWER_FACTOR 0x0022 // | 1 | | | | | | +#define SDM_PHASE_1_ANGLE 0x0024 // Degrees | 1 | 1 | 1 | 1 | | | +#define SDM_PHASE_2_ANGLE 0x0026 // Degrees | 1 | | | | | | +#define SDM_PHASE_3_ANGLE 0x0028 // Degrees | 1 | | | | | | +#define SDM_AVERAGE_L_TO_N_VOLTS 0x002A // V | 1 | | | | | | +#define SDM_AVERAGE_LINE_CURRENT 0x002E // A | 1 | | | | | | +#define SDM_SUM_LINE_CURRENT 0x0030 // A | 1 | | | | | | +#define SDM_TOTAL_SYSTEM_POWER 0x0034 // W | 1 | | | | | 1 | +#define SDM_TOTAL_SYSTEM_APPARENT_POWER 0x0038 // VA | 1 | | | | | | +#define SDM_TOTAL_SYSTEM_REACTIVE_POWER 0x003C // VAr | 1 | | | | | | +#define SDM_TOTAL_SYSTEM_POWER_FACTOR 0x003E // | 1 | | | | | | +#define SDM_TOTAL_SYSTEM_PHASE_ANGLE 0x0042 // Degrees | 1 | | | | | | +#define SDM_FREQUENCY 0x0046 // Hz | 1 | 1 | 1 | 1 | 1 | | +#define SDM_IMPORT_ACTIVE_ENERGY 0x0048 // kWh/MWh | 1 | 1 | 1 | 1 | 1 | 1 | +#define SDM_EXPORT_ACTIVE_ENERGY 0x004A // kWh/MWh | 1 | 1 | 1 | 1 | 1 | 1 | +#define SDM_IMPORT_REACTIVE_ENERGY 0x004C // kVArh/MVArh | 1 | 1 | 1 | 1 | 1 | | +#define SDM_EXPORT_REACTIVE_ENERGY 0x004E // kVArh/MVArh | 1 | 1 | 1 | 1 | 1 | | +#define SDM_VAH_SINCE_LAST_RESET 0x0050 // kVAh/MVAh | 1 | | | | | | +#define SDM_AH_SINCE_LAST_RESET 0x0052 // Ah/kAh | 1 | | | | | | +#define SDM_TOTAL_SYSTEM_POWER_DEMAND 0x0054 // W | 1 | 1 | | | | | +#define SDM_MAXIMUM_TOTAL_SYSTEM_POWER_DEMAND 0x0056 // W | 1 | 1 | | | | | +#define SDM_CURRENT_SYSTEM_POSITIVE_POWER_DEMAND 0x0058 // W | | 1 | | | | | +#define SDM_MAXIMUM_SYSTEM_POSITIVE_POWER_DEMAND 0x005A // W | | 1 | | | | | +#define SDM_CURRENT_SYSTEM_REVERSE_POWER_DEMAND 0x005C // W | | 1 | | | | | +#define SDM_MAXIMUM_SYSTEM_REVERSE_POWER_DEMAND 0x005E // W | | 1 | | | | | +#define SDM_TOTAL_SYSTEM_VA_DEMAND 0x0064 // VA | 1 | | | | | | +#define SDM_MAXIMUM_TOTAL_SYSTEM_VA_DEMAND 0x0066 // VA | 1 | | | | | | +#define SDM_NEUTRAL_CURRENT_DEMAND 0x0068 // A | 1 | | | | | | +#define SDM_MAXIMUM_NEUTRAL_CURRENT 0x006A // A | 1 | | | | | | +#define SDM_LINE_1_TO_LINE_2_VOLTS 0x00C8 // V | 1 | | | | | | +#define SDM_LINE_2_TO_LINE_3_VOLTS 0x00CA // V | 1 | | | | | | +#define SDM_LINE_3_TO_LINE_1_VOLTS 0x00CC // V | 1 | | | | | | +#define SDM_AVERAGE_LINE_TO_LINE_VOLTS 0x00CE // V | 1 | | | | | | +#define SDM_NEUTRAL_CURRENT 0x00E0 // A | 1 | | | | | | +#define SDM_PHASE_1_LN_VOLTS_THD 0x00EA // % | 1 | | | | | | +#define SDM_PHASE_2_LN_VOLTS_THD 0x00EC // % | 1 | | | | | | +#define SDM_PHASE_3_LN_VOLTS_THD 0x00EE // % | 1 | | | | | | +#define SDM_PHASE_1_CURRENT_THD 0x00F0 // % | 1 | | | | | | +#define SDM_PHASE_2_CURRENT_THD 0x00F2 // % | 1 | | | | | | +#define SDM_PHASE_3_CURRENT_THD 0x00F4 // % | 1 | | | | | | +#define SDM_AVERAGE_LINE_TO_NEUTRAL_VOLTS_THD 0x00F8 // % | 1 | | | | | | +#define SDM_AVERAGE_LINE_CURRENT_THD 0x00FA // % | 1 | | | | | | +#define SDM_TOTAL_SYSTEM_POWER_FACTOR_INV 0x00FE // | 1 | | | | | | +#define SDM_PHASE_1_CURRENT_DEMAND 0x0102 // A | 1 | 1 | | | | | +#define SDM_PHASE_2_CURRENT_DEMAND 0x0104 // A | 1 | | | | | | +#define SDM_PHASE_3_CURRENT_DEMAND 0x0106 // A | 1 | | | | | | +#define SDM_MAXIMUM_PHASE_1_CURRENT_DEMAND 0x0108 // A | 1 | 1 | | | | | +#define SDM_MAXIMUM_PHASE_2_CURRENT_DEMAND 0x010A // A | 1 | | | | | | +#define SDM_MAXIMUM_PHASE_3_CURRENT_DEMAND 0x010C // A | 1 | | | | | | +#define SDM_LINE_1_TO_LINE_2_VOLTS_THD 0x014E // % | 1 | | | | | | +#define SDM_LINE_2_TO_LINE_3_VOLTS_THD 0x0150 // % | 1 | | | | | | +#define SDM_LINE_3_TO_LINE_1_VOLTS_THD 0x0152 // % | 1 | | | | | | +#define SDM_AVERAGE_LINE_TO_LINE_VOLTS_THD 0x0154 // % | 1 | | | | | | +#define SDM_TOTAL_ACTIVE_ENERGY 0x0156 // kWh | 1 | 1 | 1 | 1 | 1 | 1 | +#define SDM_TOTAL_REACTIVE_ENERGY 0x0158 // kVArh | 1 | 1 | 1 | 1 | 1 | | +#define SDM_L1_IMPORT_ACTIVE_ENERGY 0x015A // kWh | 1 | | | | | | +#define SDM_L2_IMPORT_ACTIVE_ENERGY 0x015C // kWh | 1 | | | | | | +#define SDM_L3_IMPORT_ACTIVE_ENERGY 0x015E // kWh | 1 | | | | | | +#define SDM_L1_EXPORT_ACTIVE_ENERGY 0x0160 // kWh | 1 | | | | | | +#define SDM_L2_EXPORT_ACTIVE_ENERGY 0x0162 // kWh | 1 | | | | | | +#define SDM_L3_EXPORT_ACTIVE_ENERGY 0x0164 // kWh | 1 | | | | | | +#define SDM_L1_TOTAL_ACTIVE_ENERGY 0x0166 // kWh | 1 | | | | | | +#define SDM_L2_TOTAL_ACTIVE_ENERGY 0x0168 // kWh | 1 | | | | | | +#define SDM_L3_TOTAL_ACTIVE_ENERGY 0x016a // kWh | 1 | | | | | | +#define SDM_L1_IMPORT_REACTIVE_ENERGY 0x016C // kVArh | 1 | | | | | | +#define SDM_L2_IMPORT_REACTIVE_ENERGY 0x016E // kVArh | 1 | | | | | | +#define SDM_L3_IMPORT_REACTIVE_ENERGY 0x0170 // kVArh | 1 | | | | | | +#define SDM_L1_EXPORT_REACTIVE_ENERGY 0x0172 // kVArh | 1 | | | | | | +#define SDM_L2_EXPORT_REACTIVE_ENERGY 0x0174 // kVArh | 1 | | | | | | +#define SDM_L3_EXPORT_REACTIVE_ENERGY 0x0176 // kVArh | 1 | | | | | | +#define SDM_L1_TOTAL_REACTIVE_ENERGY 0x0178 // kVArh | 1 | | | | | | +#define SDM_L2_TOTAL_REACTIVE_ENERGY 0x017A // kVArh | 1 | | | | | | +#define SDM_L3_TOTAL_REACTIVE_ENERGY 0x017C // kVArh | 1 | | | | | | +#define SDM_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY 0x0180 // kWh | | 1 | | | | 1 | +#define SDM_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY 0x0182 // kVArh | | 1 | | | | | +#define SDM_CURRENT_RESETTABLE_IMPORT_ENERGY 0x0184 // kWh | | | | | | 1 | +#define SDM_CURRENT_RESETTABLE_EXPORT_ENERGY 0x0186 // kWh | | | | | | 1 | +#define SDM_IMPORT_POWER 0x0500 // W | | | | | | 1 | +#define SDM_EXPORT_POWER 0x0502 // W | | | | | | 1 | +//----------------------------------------------------------------------------------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------------------------------- +// REGISTERS LIST FOR DDM DEVICE | +//--------------------------------------------------------------------------------------------------------- +// REGISTER NAME REGISTER ADDRESS UNIT | DDM18SD | +//--------------------------------------------------------------------------------------------------------- +#define DDM_PHASE_1_VOLTAGE 0x0000 // V | 1 | +#define DDM_PHASE_1_CURRENT 0x0008 // A | 1 | +#define DDM_PHASE_1_POWER 0x0012 // W | 1 | +#define DDM_PHASE_1_REACTIVE_POWER 0x001A // VAr | 1 | +#define DDM_PHASE_1_POWER_FACTOR 0x002A // | 1 | +#define DDM_FREQUENCY 0x0036 // Hz | 1 | +#define DDM_IMPORT_ACTIVE_ENERGY 0x0100 // kWh | 1 | +#define DDM_IMPORT_REACTIVE_ENERGY 0x0400 // kVArh | 1 | +//--------------------------------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------------------------------- +// REGISTERS LIST FOR DEVNAME DEVICE | +//--------------------------------------------------------------------------------------------------------- +// REGISTER NAME REGISTER ADDRESS UNIT | DEVNAME | +//--------------------------------------------------------------------------------------------------------- +//#define DEVNAME_VOLTAGE 0x0000 // V | 1 | +//#define DEVNAME_CURRENT 0x0002 // A | 1 | +//#define DEVNAME_POWER 0x0004 // W | 1 | +//--------------------------------------------------------------------------------------------------------- + +//----------------------------------------------------------------------------------------------------------------------------------------------------------- class SDM { public: #ifdef USE_HARDWARESERIAL From 5ac0e9b9a7f475c9224bb854c4d7bad0d22a03a6 Mon Sep 17 00:00:00 2001 From: tomcatxx <69747753+tomcatxx@users.noreply.github.com> Date: Wed, 10 Feb 2021 11:29:19 +0100 Subject: [PATCH 02/24] Update _P078_Eastron.ino Added all registers / devices from here https://github.com/reaper7/SDM_Energy_Meter Changed webinterface for propper selection. Tested with SDM630 on ESP8266. ESP32 is not working, even with origional plugin for at the moment. Reason is unknown see https://github.com/letscontrolit/ESPEasy/issues/2671 --- src/_P078_Eastron.ino | 656 +++++++++++++++++++++++++++++++++++------- 1 file changed, 552 insertions(+), 104 deletions(-) diff --git a/src/_P078_Eastron.ino b/src/_P078_Eastron.ino index 3a87667ca..f99b1d989 100644 --- a/src/_P078_Eastron.ino +++ b/src/_P078_Eastron.ino @@ -3,18 +3,17 @@ #ifdef USES_P078 //####################################################################################################### -//######################## Plugin 078: SDM120C/220T/230/630 Eastron Energy Meter ######################## +//############## Plugin 078: SDM120/SDM120CT/220/230/630/72D/DDM18SD Eastron Energy Meter ############### //####################################################################################################### /* Plugin written by: Sergio Faustino sjfaustino__AT__gmail.com - This plugin reads available values of an Eastron SDM120C Energy Meter. - It will also work with all the other superior model such as SDM220T, SDM230 AND SDM630 series. + This plugin reads available values of an Eastron SDM120C SDM120/SDM120CT/220/230/630/72D & also DDM18SD. */ #define PLUGIN_078 #define PLUGIN_ID_078 78 -#define PLUGIN_NAME_078 "Energy (AC) - Eastron SDM120C/220T/230/630 [TESTING]" +#define PLUGIN_NAME_078 "Energy (AC) - Eastron SDM120/SDM120CT/220/230/630/72D/DDM18SD [TESTING]" #define P078_DEV_ID PCONFIG(0) #define P078_DEV_ID_LABEL PCONFIG_LABEL(0) @@ -36,8 +35,14 @@ #define P078_QUERY3_DFLT 2 // Power (W) #define P078_QUERY4_DFLT 5 // Power Factor (cos-phi) -#define P078_NR_OUTPUT_VALUES 4 -#define P078_NR_OUTPUT_OPTIONS 10 + +#define P078_NR_OUTPUT_VALUES 4 +#define P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120 14 +#define P078_NR_OUTPUT_OPTIONS_SDM230 24 +#define P078_NR_OUTPUT_OPTIONS_SDM630 86 +#define P078_NR_OUTPUT_OPTIONS_SDM72D 9 +#define P078_NR_OUTPUT_OPTIONS_DDM18SD 7 + #define P078_QUERY1_CONFIG_POS 3 #include @@ -78,21 +83,7 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) break; } - case PLUGIN_GET_DEVICEVALUENAMES: - { - for (byte i = 0; i < VARS_PER_TASK; ++i) { - if ( i < P078_NR_OUTPUT_VALUES) { - byte choice = PCONFIG(i + P078_QUERY1_CONFIG_POS); - safe_strncpy( - ExtraTaskSettings.TaskDeviceValueNames[i], - p078_getQueryValueString(choice), - sizeof(ExtraTaskSettings.TaskDeviceValueNames[i])); - } else { - ZERO_FILL(ExtraTaskSettings.TaskDeviceValueNames[i]); - } - } - break; - } + case PLUGIN_GET_DEVICEGPIONAMES: { @@ -166,23 +157,63 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_LOAD: { { - String options_model[4] = { F("SDM120C"), F("SDM220T"), F("SDM230"), F("SDM630") }; - addFormSelector(F("Model Type"), P078_MODEL_LABEL, 4, options_model, NULL, P078_MODEL ); + String options_model[5] = { F("SDM220 & SDM120CT & SDM120"), F("SDM230"), F("SDM72D"), F("DDM18SD"), F("SDM630") }; + addFormSelector(F("Model Type"), P078_MODEL_LABEL, 5, options_model, NULL, P078_MODEL ); + addFormNote(F("Submit after changing the modell to update Output Configuration.")); } { // In a separate scope to free memory of String array as soon as possible sensorTypeHelper_webformLoad_header(); - String options[P078_NR_OUTPUT_OPTIONS]; - for (int i = 0; i < P078_NR_OUTPUT_OPTIONS; ++i) { - options[i] = p078_getQueryString(i); - } - for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { - const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; - sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P078_NR_OUTPUT_OPTIONS, options); - } - } + int model = P078_MODEL; + if (model == 0) { + String options[P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120]; + for (int i = 0; i < P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120; ++i) { + options[i] = p078_getQueryString(i,model); + } + for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120, options); + } + } else if (model == 1) { + String options[P078_NR_OUTPUT_OPTIONS_SDM230]; + for (int i = 0; i < P078_NR_OUTPUT_OPTIONS_SDM230; ++i) { + options[i] = p078_getQueryString(i,model); + } + for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P078_NR_OUTPUT_OPTIONS_SDM230, options); + } + } else if (model == 2) { + String options[P078_NR_OUTPUT_OPTIONS_SDM72D]; + for (int i = 0; i < P078_NR_OUTPUT_OPTIONS_SDM72D; ++i) { + options[i] = p078_getQueryString(i,model); + } + for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P078_NR_OUTPUT_OPTIONS_SDM72D, options); + } + } else if (model == 3) { + String options[P078_NR_OUTPUT_OPTIONS_DDM18SD]; + for (int i = 0; i < P078_NR_OUTPUT_OPTIONS_DDM18SD; ++i) { + options[i] = p078_getQueryString(i,model); + } + for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P078_NR_OUTPUT_OPTIONS_DDM18SD, options); + } + } else if (model == 4) { + String options[P078_NR_OUTPUT_OPTIONS_SDM630]; + for (int i = 0; i < P078_NR_OUTPUT_OPTIONS_SDM630; ++i) { + options[i] = p078_getQueryString(i,model); + } + for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P078_NR_OUTPUT_OPTIONS_SDM630, options); + } + } + } success = true; break; @@ -191,10 +222,11 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_SAVE: { // Save output selector parameters. + int model = P078_MODEL; for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; const byte choice = PCONFIG(pconfigIndex); - sensorTypeHelper_saveOutputSelector(event, pconfigIndex, i, p078_getQueryValueString(choice)); + sensorTypeHelper_saveOutputSelector(event, pconfigIndex, i, p078_getQueryValueString(choice,model)); } P078_DEV_ID = getFormItemInt(P078_DEV_ID_LABEL); @@ -232,6 +264,24 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) break; } + case PLUGIN_GET_DEVICEVALUENAMES: + { + int model = P078_MODEL; + for (byte i = 0; i < VARS_PER_TASK; ++i) { + if ( i < P078_NR_OUTPUT_VALUES) { + byte choice = PCONFIG(i + P078_QUERY1_CONFIG_POS); + safe_strncpy( + ExtraTaskSettings.TaskDeviceValueNames[i], + p078_getQueryValueString(choice,model), + sizeof(ExtraTaskSettings.TaskDeviceValueNames[i])); + } else { + ZERO_FILL(ExtraTaskSettings.TaskDeviceValueNames[i]); + } + } + break; + } + + case PLUGIN_EXIT: { Plugin_078_init = false; @@ -256,6 +306,7 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) UserVar[event->BaseVarIndex + 1] = p078_readVal(P078_QUERY2, dev_id, model); UserVar[event->BaseVarIndex + 2] = p078_readVal(P078_QUERY3, dev_id, model); UserVar[event->BaseVarIndex + 3] = p078_readVal(P078_QUERY4, dev_id, model); + success = true; break; } @@ -285,101 +336,498 @@ float p078_readVal(byte query, byte node, unsigned int model) { log += ','; log += model; log += ") "; - log += p078_getQueryString(query); + log += p078_getQueryString(query,model); log += ": "; log += _tempvar; addLog(LOG_LEVEL_INFO, log); } + delay(1); return _tempvar; } unsigned int p078_getRegister(byte query, byte model) { - if (model == 0) { // SDM120C + if (model == 0) { //SDM220 & SDM120CT & SDM120 switch (query) { - case 0: return SDM120C_VOLTAGE; - case 1: return SDM120C_CURRENT; - case 2: return SDM120C_POWER; - case 3: return SDM120C_ACTIVE_APPARENT_POWER; - case 4: return SDM120C_REACTIVE_APPARENT_POWER; - case 5: return SDM120C_POWER_FACTOR; - case 6: return SDM120C_FREQUENCY; - case 7: return SDM120C_IMPORT_ACTIVE_ENERGY; - case 8: return SDM120C_EXPORT_ACTIVE_ENERGY; - case 9: return SDM120C_TOTAL_ACTIVE_ENERGY; + case 0: return SDM_PHASE_1_VOLTAGE; + case 1: return SDM_PHASE_1_CURRENT; + case 2: return SDM_PHASE_1_POWER; + case 3: return SDM_PHASE_1_APPARENT_POWER; + case 4: return SDM_PHASE_1_REACTIVE_POWER; + case 5: return SDM_PHASE_1_POWER_FACTOR; + case 6: return SDM_PHASE_1_ANGLE; + case 7: return SDM_FREQUENCY; + case 8: return SDM_IMPORT_ACTIVE_ENERGY; + case 9: return SDM_EXPORT_ACTIVE_ENERGY; + case 10: return SDM_IMPORT_REACTIVE_ENERGY; + case 11: return SDM_EXPORT_REACTIVE_ENERGY; + case 12: return SDM_TOTAL_ACTIVE_ENERGY; + case 13: return SDM_TOTAL_REACTIVE_ENERGY; + } - } else if (model == 1) { // SDM220T + } else if (model == 1) { //SDM230 switch (query) { - case 0: return SDM220T_VOLTAGE; - case 1: return SDM220T_CURRENT; - case 2: return SDM220T_POWER; - case 3: return SDM220T_ACTIVE_APPARENT_POWER; - case 4: return SDM220T_REACTIVE_APPARENT_POWER; - case 5: return SDM220T_POWER_FACTOR; - case 6: return SDM220T_FREQUENCY; - case 7: return SDM220T_IMPORT_ACTIVE_ENERGY; - case 8: return SDM220T_EXPORT_ACTIVE_ENERGY; - case 9: return SDM220T_TOTAL_ACTIVE_ENERGY; + case 0: return SDM_PHASE_1_VOLTAGE; + case 1: return SDM_PHASE_1_CURRENT; + case 2: return SDM_PHASE_1_POWER; + case 3: return SDM_PHASE_1_APPARENT_POWER; + case 4: return SDM_PHASE_1_REACTIVE_POWER; + case 5: return SDM_PHASE_1_POWER_FACTOR; + case 6: return SDM_PHASE_1_ANGLE; + case 7: return SDM_FREQUENCY; + case 8: return SDM_IMPORT_ACTIVE_ENERGY; + case 9: return SDM_EXPORT_ACTIVE_ENERGY; + case 10: return SDM_IMPORT_REACTIVE_ENERGY; + case 11: return SDM_EXPORT_REACTIVE_ENERGY; + case 12: return SDM_TOTAL_SYSTEM_POWER_DEMAND; + case 13: return SDM_MAXIMUM_TOTAL_SYSTEM_POWER_DEMAND; + case 14: return SDM_CURRENT_SYSTEM_POSITIVE_POWER_DEMAND; + case 15: return SDM_MAXIMUM_SYSTEM_POSITIVE_POWER_DEMAND; + case 16: return SDM_CURRENT_SYSTEM_REVERSE_POWER_DEMAND; + case 17: return SDM_MAXIMUM_SYSTEM_REVERSE_POWER_DEMAND; + case 18: return SDM_PHASE_1_CURRENT_DEMAND; + case 19: return SDM_MAXIMUM_PHASE_1_CURRENT_DEMAND; + case 20: return SDM_TOTAL_ACTIVE_ENERGY; + case 21: return SDM_TOTAL_REACTIVE_ENERGY; + case 22: return SDM_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY; + case 23: return SDM_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY; } - } else if (model == 2) { // SDM230 + } else if (model == 2) { //SDM72D switch (query) { - case 0: return SDM230_VOLTAGE; - case 1: return SDM230_CURRENT; - case 2: return SDM230_POWER; - case 3: return SDM230_ACTIVE_APPARENT_POWER; - case 4: return SDM230_REACTIVE_APPARENT_POWER; - case 5: return SDM230_POWER_FACTOR; - case 6: return SDM230_FREQUENCY; - case 7: return SDM230_IMPORT_ACTIVE_ENERGY; - case 8: return SDM230_EXPORT_ACTIVE_ENERGY; - case 9: return SDM230_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY; + case 0: return SDM_TOTAL_SYSTEM_POWER; + case 1: return SDM_IMPORT_ACTIVE_ENERGY; + case 2: return SDM_EXPORT_ACTIVE_ENERGY; + case 3: return SDM_TOTAL_ACTIVE_ENERGY; + case 4: return SDM_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY; + case 5: return SDM_CURRENT_RESETTABLE_IMPORT_ENERGY; + case 6: return SDM_CURRENT_RESETTABLE_EXPORT_ENERGY; + case 7: return SDM_IMPORT_POWER; + case 8: return SDM_EXPORT_POWER; } - } else if (model == 3) { // SDM630 + } else if (model == 3) { //DDM18SD switch (query) { - case 0: return SDM630_VOLTAGE_AVERAGE; - case 1: return SDM630_CURRENTSUM; - case 2: return SDM630_POWERTOTAL; - case 3: return SDM630_VOLT_AMPS_TOTAL; - case 4: return SDM630_VOLT_AMPS_REACTIVE_TOTAL; - case 5: return SDM630_POWER_FACTOR_TOTAL; - case 6: return SDM630_FREQUENCY; - case 7: return SDM630_IMPORT_ACTIVE_ENERGY; - case 8: return SDM630_EXPORT_ACTIVE_ENERGY; - case 9: return SDM630_IMPORT_ACTIVE_ENERGY; // No equivalent for TOTAL_ACTIVE_ENERGY present in the SDM630 + case 0: return DDM_PHASE_1_VOLTAGE; + case 1: return DDM_PHASE_1_CURRENT; + case 2: return DDM_PHASE_1_POWER; + case 3: return DDM_PHASE_1_REACTIVE_POWER; + case 4: return DDM_PHASE_1_POWER_FACTOR; + case 5: return DDM_FREQUENCY; + case 6: return DDM_IMPORT_ACTIVE_ENERGY; + case 7: return DDM_IMPORT_REACTIVE_ENERGY; + } + } else if (model == 4) { //SDM630 + switch (query) { + case 0: return SDM_PHASE_1_VOLTAGE; + case 1: return SDM_PHASE_2_VOLTAGE; + case 2: return SDM_PHASE_3_VOLTAGE; + case 3: return SDM_PHASE_1_CURRENT; + case 4: return SDM_PHASE_2_CURRENT; + case 5: return SDM_PHASE_3_CURRENT; + case 6: return SDM_PHASE_1_POWER; + case 7: return SDM_PHASE_2_POWER; + case 8: return SDM_PHASE_3_POWER; + case 9: return SDM_PHASE_1_APPARENT_POWER; + case 10: return SDM_PHASE_2_APPARENT_POWER; + case 11: return SDM_PHASE_3_APPARENT_POWER; + case 12: return SDM_PHASE_1_REACTIVE_POWER; + case 13: return SDM_PHASE_2_REACTIVE_POWER; + case 14: return SDM_PHASE_3_REACTIVE_POWER; + case 15: return SDM_PHASE_1_POWER_FACTOR; + case 16: return SDM_PHASE_2_POWER_FACTOR; + case 17: return SDM_PHASE_3_POWER_FACTOR; + case 18: return SDM_PHASE_1_ANGLE; + case 19: return SDM_PHASE_2_ANGLE; + case 20: return SDM_PHASE_3_ANGLE; + case 21: return SDM_AVERAGE_L_TO_N_VOLTS; + case 22: return SDM_AVERAGE_LINE_CURRENT; + case 23: return SDM_SUM_LINE_CURRENT; + case 24: return SDM_TOTAL_SYSTEM_POWER; + case 25: return SDM_TOTAL_SYSTEM_APPARENT_POWER; + case 26: return SDM_TOTAL_SYSTEM_REACTIVE_POWER; + case 27: return SDM_TOTAL_SYSTEM_POWER_FACTOR; + case 28: return SDM_TOTAL_SYSTEM_PHASE_ANGLE; + case 29: return SDM_FREQUENCY; + case 30: return SDM_IMPORT_ACTIVE_ENERGY; + case 31: return SDM_EXPORT_ACTIVE_ENERGY; + case 32: return SDM_IMPORT_REACTIVE_ENERGY; + case 33: return SDM_EXPORT_REACTIVE_ENERGY; + case 34: return SDM_VAH_SINCE_LAST_RESET; + case 35: return SDM_AH_SINCE_LAST_RESET; + case 36: return SDM_TOTAL_SYSTEM_POWER_DEMAND; + case 37: return SDM_MAXIMUM_TOTAL_SYSTEM_POWER_DEMAND; + case 38: return SDM_TOTAL_SYSTEM_VA_DEMAND; + case 39: return SDM_MAXIMUM_TOTAL_SYSTEM_VA_DEMAND; + case 40: return SDM_NEUTRAL_CURRENT_DEMAND; + case 41: return SDM_MAXIMUM_NEUTRAL_CURRENT; + case 42: return SDM_LINE_1_TO_LINE_2_VOLTS; + case 43: return SDM_LINE_2_TO_LINE_3_VOLTS; + case 44: return SDM_LINE_3_TO_LINE_1_VOLTS; + case 45: return SDM_AVERAGE_LINE_TO_LINE_VOLTS; + case 46: return SDM_NEUTRAL_CURRENT; + case 47: return SDM_PHASE_1_LN_VOLTS_THD; + case 48: return SDM_PHASE_2_LN_VOLTS_THD; + case 49: return SDM_PHASE_3_LN_VOLTS_THD; + case 50: return SDM_PHASE_1_CURRENT_THD; + case 51: return SDM_PHASE_2_CURRENT_THD; + case 52: return SDM_PHASE_3_CURRENT_THD; + case 53: return SDM_AVERAGE_LINE_TO_NEUTRAL_VOLTS_THD; + case 54: return SDM_AVERAGE_LINE_CURRENT_THD; + case 55: return SDM_TOTAL_SYSTEM_POWER_FACTOR_INV; + case 56: return SDM_PHASE_1_CURRENT_DEMAND; + case 57: return SDM_PHASE_2_CURRENT_DEMAND; + case 58: return SDM_PHASE_3_CURRENT_DEMAND; + case 59: return SDM_MAXIMUM_PHASE_1_CURRENT_DEMAND; + case 60: return SDM_MAXIMUM_PHASE_2_CURRENT_DEMAND; + case 61: return SDM_MAXIMUM_PHASE_3_CURRENT_DEMAND; + case 62: return SDM_LINE_1_TO_LINE_2_VOLTS_THD; + case 63: return SDM_LINE_2_TO_LINE_3_VOLTS_THD; + case 64: return SDM_LINE_3_TO_LINE_1_VOLTS_THD; + case 65: return SDM_AVERAGE_LINE_TO_LINE_VOLTS_THD; + case 66: return SDM_TOTAL_ACTIVE_ENERGY; + case 67: return SDM_TOTAL_REACTIVE_ENERGY; + case 68: return SDM_L1_IMPORT_ACTIVE_ENERGY; + case 69: return SDM_L2_IMPORT_ACTIVE_ENERGY; + case 70: return SDM_L3_IMPORT_ACTIVE_ENERGY; + case 71: return SDM_L1_EXPORT_ACTIVE_ENERGY; + case 72: return SDM_L2_EXPORT_ACTIVE_ENERGY; + case 73: return SDM_L3_EXPORT_ACTIVE_ENERGY; + case 74: return SDM_L1_TOTAL_ACTIVE_ENERGY; + case 75: return SDM_L2_TOTAL_ACTIVE_ENERGY; + case 76: return SDM_L3_TOTAL_ACTIVE_ENERGY; + case 77: return SDM_L1_IMPORT_REACTIVE_ENERGY; + case 78: return SDM_L2_IMPORT_REACTIVE_ENERGY; + case 79: return SDM_L3_IMPORT_REACTIVE_ENERGY; + case 80: return SDM_L1_EXPORT_REACTIVE_ENERGY; + case 81: return SDM_L2_EXPORT_REACTIVE_ENERGY; + case 82: return SDM_L3_EXPORT_REACTIVE_ENERGY; + case 83: return SDM_L1_TOTAL_REACTIVE_ENERGY; + case 84: return SDM_L2_TOTAL_REACTIVE_ENERGY; + case 85: return SDM_L3_TOTAL_REACTIVE_ENERGY; } } return 0; } -String p078_getQueryString(byte query) { - switch(query) - { - case 0: return F("Voltage (V)"); - case 1: return F("Current (A)"); - case 2: return F("Power (W)"); - case 3: return F("Active Apparent Power (VA)"); - case 4: return F("Reactive Apparent Power (VAr)"); - case 5: return F("Power Factor (cos-phi)"); - case 6: return F("Frequency (Hz)"); - case 7: return F("Import Active Energy (Wh)"); - case 8: return F("Export Active Energy (Wh)"); - case 9: return F("Total Active Energy (Wh)"); +String p078_getQueryString(byte query, byte model) { + if (model == 0) { //SDM220 & SDM120CT & SDM120 + switch (query) { + case 0: return F("Voltage (V)"); + case 1: return F("Current (A)"); + case 2: return F("Power (W)"); + case 3: return F("ActiveApparentPower (VA)"); + case 4: return F("ReactiveApparentPower (VAr)"); + case 5: return F("PowerFactor (cos-phi)"); + case 6: return F("PhaseAngle(Degrees) (not SDM120)"); + case 7: return F("Frequency (Hz)"); + case 8: return F("ImportActiveEnergy (kWh/MWh)"); + case 9: return F("ExportActiveEnergy (kWh/MWh)"); + case 10: return F("ImportReactiveEnergy (kVArh/MVArh)"); + case 11: return F("ExportReactiveEnergy (kVArh/MVArh)"); + case 12: return F("TotalActiveEnergy (kWh)"); + case 13: return F("TotalReactiveEnergy (kVArh)"); + + } + } else if (model == 1) { //SDM230 + switch (query) { + case 0: return F("Voltage (V)"); + case 1: return F("Current (A)"); + case 2: return F("Power (W)"); + case 3: return F("Active Apparent Power (VA)"); + case 4: return F("Reactive Apparent Power (VAr)"); + case 5: return F("Power Factor (cos-phi)"); + case 6: return F("Phase Angle (Degrees)"); + case 7: return F("Frequency (Hz)"); + case 8: return F("Import Active Energy (kWh/MWh)"); + case 9: return F("Export Active Energy (kWh/MWh)"); + case 10: return F("Import Reactive Energy ( kVArh/MVArh)"); + case 11: return F("Export Reactive Energy ( kVArh/MVArh)"); + case 12: return F("Total system power demand (W)"); + case 13: return F("Total Reactive Energy (kVArh)"); + case 14: return F("Maximum total system power demand (W)"); + case 15: return F("Maximum system positive power demand (W)"); + case 16: return F("Currentsystem reverse power demand (W)"); + case 17: return F("Maximum system reverse power demand (W)"); + case 18: return F("Current demand (A)"); + case 19: return F("Maximum current demand (A)"); + case 20: return F("Total active energy (kWh)"); + case 21: return F("Total reactive energy (kVArh)"); + case 22: return F("Current resettable total active energy (kWh)"); + case 23: return F("Current resettable total reactive energy (kVArh)"); + } + } else if (model == 2) { //SDM72D + switch (query) { + case 0: return F("Total System Power (W)"); + case 1: return F("Import Active Energy since last reset (kWh/MWh)"); + case 2: return F("Export Active Energy since last reset (kWh/MWh)"); + case 3: return F("Total Active Energy (kwh)"); + case 4: return F("Resettable total Active Energy (kWh)"); + case 5: return F("Resettable import (kWh)"); + case 6: return F("Resettable export (kWh)"); + case 7: return F("Import power (W)"); + case 8: return F("Export power (W)"); + } + } else if (model == 3) { //DDM18SD + switch (query) { + case 0: return F("Voltage (V)"); + case 1: return F("Current (A)"); + case 2: return F("Power (W)"); + case 3: return F("Reactive Power (VAr)"); + case 4: return F("Power Factor (cos-phi)"); + case 5: return F("Frequency (Hz)"); + case 6: return F("Import Active Energy (kWh)"); + case 7: return F("Import Reactive Energy (kVArh)"); + } + } else if (model == 4) { //SDM630 + switch (query) { + case 0: return F("Voltage (V) Phase 1"); + case 1: return F("Voltage (V) Phase 2"); + case 2: return F("Voltage (V) Phase 3"); + case 3: return F("Current (A) Phase 1"); + case 4: return F("Current (A) Phase 2"); + case 5: return F("Current (A) Phase 3"); + case 6: return F("Power (W) Phase 1"); + case 7: return F("Power (W) Phase 2"); + case 8: return F("Power (W) Phase 3"); + case 9: return F("Active Apparent Power (VA) Phase 1"); + case 10: return F("Active Apparent Power (VA) Phase 2"); + case 11: return F("Active Apparent Power (VA) Phase 3"); + case 12: return F("Reactive Apparent Power (VAr) Phase 1"); + case 13: return F("Reactive Apparent Power (VAr) Phase 2"); + case 14: return F("Reactive Apparent Power (VAr) Phase 3"); + case 15: return F("Power Factor (cos-phi) Phase 1"); + case 16: return F("Power Factor (cos-phi) Phase 2"); + case 17: return F("Power Factor (cos-phi) Phase 3"); + case 18: return F("Phase Angle (Degrees) Phase 1"); + case 19: return F("Phase Angle (Degrees) Phase 2"); + case 20: return F("Phase Angle (Degrees) Phase 3"); + case 21: return F("Average line to neutral volts (V)"); + case 22: return F("Average line Current (A)"); + case 23: return F("Sum of line Currents (A)"); + case 24: return F("Total System Power (W)"); + case 25: return F("Total System Active Apparent Power (VA)"); + case 26: return F("Total System Reactive Apparent Power (VAr)"); + case 27: return F("Total System Power Factor (cos-phi)"); + case 28: return F("Total System Phase Angle (Degrees)"); + case 29: return F("Frequency of Supply Voltages (Hz)"); + case 30: return F("Import Active Energy since last reset (kWh/MWh)"); + case 31: return F("Export Active Energy since last reset (kWh/MWh)"); + case 32: return F("Import Reactive Energy since last reset (kVArh/MVArh)"); + case 33: return F("Export Reactive Energy since last reset (kVArh/MVArh)"); + case 34: return F("VAh since last Reset (kVAh/MVAh)"); + case 35: return F("Ah since last Reset (Ah/kAh)"); + case 36: return F("Total System Power Demand (W)"); + case 37: return F("Maximum Total System Power Demand (W)"); + case 38: return F("Total System VA demand (VA)"); + case 39: return F("Maximum Total System VA Demand (VA)"); + case 40: return F("Neutral Current Demand (A)"); + case 41: return F("Maximum Neutral Current Demand (A)"); + case 42: return F("Line 1 to Line 2 Volts (V)"); + case 43: return F("Line 2 to Line 3 Volts (V)"); + case 44: return F("Line 3 to Line 1 Volts (V)"); + case 45: return F("Average Line to Line Volts (V)"); + case 46: return F("Neutral Current (A)"); + case 47: return F("L/N Volts THD (%) Phase 1"); + case 48: return F("L/N Volts THD (%) Phase 2"); + case 49: return F("L/N Volts THD (%) Phase 3"); + case 50: return F("Current THD (%) Phase 1 "); + case 51: return F("Current THD (%) Phase 2"); + case 52: return F("Current THD (%) Phase 3"); + case 53: return F("Average Line to Neutral Volts THD (cos-phi)"); + case 54: return F("Average Line Current THD (%)"); + case 55: return F("Total System Power Factor (%)"); + case 56: return F("Current Demand (A) Phase 1 "); + case 57: return F("Current Demand (A) Phase 2"); + case 58: return F("Current Demand (A) Phase 3"); + case 59: return F("Maximum Current Demand (A) Phase 1 "); + case 60: return F("Maximum Current Demand (A) Phase 2"); + case 61: return F("Maximum Current Demand (A) Phase 3"); + case 62: return F("Line 1 to Line 2 Volts THD (%)"); + case 63: return F("Line 2 to Line 3 Volts THD (%)"); + case 64: return F("Line 3 to Line 1 Volts THD (%)"); + case 65: return F("Average Line to Line Volts THD (%)"); + case 66: return F("Total Active Energy (kwh)"); + case 67: return F("Total Reactive Energy (kVArh)"); + case 68: return F("Import Active Energy (kWh) L1"); + case 69: return F("Import Active Energy (kWh) L2"); + case 70: return F("Import Active Energy (kWh) L3"); + case 71: return F("Export Active Energy (kWh) L1"); + case 72: return F("Export Active Energy (kWh) L2"); + case 73: return F("Export Active Energy (kWh) L3"); + case 74: return F("Total Active Energy (kWh) L1"); + case 75: return F("Total Active Energy (kWh) L2"); + case 76: return F("Total Active Energy (kWh) L3"); + case 77: return F("Import Reactive Energy (kVArh) L1"); + case 78: return F("Import Reactive Energy (kVArh) L2"); + case 79: return F("Import Reactive Energy (kVArh) L3"); + case 80: return F("Export Reactive Energy (kVArh) L1"); + case 81: return F("Export Reactive Energy (kVArh) L2"); + case 82: return F("Export Reactive Energy (kVArh) L3"); + case 83: return F("Total Reactive Energy (kVArh) L1"); + case 84: return F("Total Reactive Energy (kVArh) L2"); + case 85: return F("Total Reactive Energy (kVArh) L3"); + + } } return ""; } -String p078_getQueryValueString(byte query) { - switch(query) - { - case 0: return F("V"); - case 1: return F("A"); - case 2: return F("W"); - case 3: return F("VA"); - case 4: return F("VAr"); - case 5: return F("cos_phi"); - case 6: return F("Hz"); - case 7: return F("Wh_imp"); - case 8: return F("Wh_exp"); - case 9: return F("Wh_tot"); +String p078_getQueryValueString(byte query, byte model) { + if (model == 0) { //SDM220 & SDM120CT & SDM120 + switch (query) { + case 0: return F("V"); + case 1: return F("A"); + case 2: return F("W"); + case 3: return F("VA"); + case 4: return F("VAr"); + case 5: return F("cos-phi"); + case 6: return F("Degrees"); + case 7: return F("Hz"); + case 8: return F("kWh/MWh"); + case 9: return F("kWh/MWh"); + case 10: return F("kVArh/MVArh"); + case 11: return F("kVArh/MVArh"); + case 12: return F("kWh"); + case 13: return F("kVArh"); + + } + } else if (model == 1) { //SDM230 + switch (query) { + case 0: return F("V"); + case 1: return F("A"); + case 2: return F("W"); + case 3: return F("VA"); + case 4: return F("VAr"); + case 5: return F("cos-phi"); + case 6: return F("Degrees"); + case 7: return F("Hz"); + case 8: return F("kWh/MWh"); + case 9: return F("kWh/MWh"); + case 10: return F("kVArh/MVArh"); + case 11: return F("kVArh/MVArh"); + case 12: return F("W"); + case 13: return F("W"); + case 14: return F("W"); + case 15: return F("W"); + case 16: return F("W"); + case 17: return F("W"); + case 18: return F("A"); + case 19: return F("A"); + case 20: return F("kWh"); + case 21: return F("kVArh"); + case 22: return F("kWh"); + case 23: return F("kVArh"); + } + } else if (model == 2) { //SDM72D + switch (query) { + case 0: return F("W"); + case 1: return F("kWh/MWh"); + case 2: return F("kWh/MWh"); + case 3: return F("kWh"); + case 4: return F("kWh"); + case 5: return F("kWh"); + case 6: return F("kWh"); + case 7: return F("W"); + case 8: return F("W"); + } + } else if (model == 3) { //DDM18SD + switch (query) { + case 0: return F("V"); + case 1: return F("A"); + case 2: return F("W"); + case 3: return F("Var"); + case 4: return F("cos-phi"); + case 5: return F("Hz"); + case 6: return F("kWh"); + case 7: return F("kVArh"); + } + } else if (model == 4) { //SDM630 + switch (query) { + case 0: return F("V"); + case 1: return F("V"); + case 2: return F("V"); + case 3: return F("A"); + case 4: return F("A"); + case 5: return F("A"); + case 6: return F("W"); + case 7: return F("W"); + case 8: return F("W"); + case 9: return F("VA"); + case 10: return F("VA"); + case 11: return F("VA"); + case 12: return F("VAr"); + case 13: return F("VAr"); + case 14: return F("VAr"); + case 15: return F("cos-phi"); + case 16: return F("cos-phi"); + case 17: return F("cos-phi"); + case 18: return F("Degrees"); + case 19: return F("Degrees"); + case 20: return F("Degrees"); + case 21: return F("V"); + case 22: return F("A"); + case 23: return F("A"); + case 24: return F("W"); + case 25: return F("VA"); + case 26: return F("VAr"); + case 27: return F("cos-phi"); + case 28: return F("Degrees"); + case 29: return F("Hz"); + case 30: return F("kWh/MWh"); + case 31: return F("kWh/MWh"); + case 32: return F("kVArh/MVArh"); + case 33: return F("kVArh/MVArh"); + case 34: return F("kVAh/MVAh"); + case 35: return F("Ah/kAh"); + case 36: return F("W"); + case 37: return F("W"); + case 38: return F("VA"); + case 39: return F("VA"); + case 40: return F("A"); + case 41: return F("A"); + case 42: return F("V"); + case 43: return F("V"); + case 44: return F("V"); + case 45: return F("V"); + case 46: return F("A"); + case 47: return F("%"); + case 48: return F("%"); + case 49: return F("%"); + case 50: return F("%"); + case 51: return F("%"); + case 52: return F("%"); + case 53: return F("%"); + case 54: return F("%"); + case 55: return F("cos-phi"); + case 56: return F("A"); + case 57: return F("A"); + case 58: return F("A"); + case 59: return F("A"); + case 60: return F("A"); + case 61: return F("A"); + case 62: return F("%"); + case 63: return F("%"); + case 64: return F("%"); + case 65: return F("%"); + case 66: return F("kWh"); + case 67: return F("kVArh"); + case 68: return F("kWh"); + case 69: return F("kWh"); + case 70: return F("kWh"); + case 71: return F("kWh"); + case 72: return F("kWh"); + case 73: return F("kWh"); + case 74: return F("kWh"); + case 75: return F("kWh"); + case 76: return F("kWh"); + case 77: return F("kVArh"); + case 78: return F("kVArh"); + case 79: return F("kVArh"); + case 80: return F("kVArh"); + case 81: return F("kVArh"); + case 82: return F("kVArh"); + case 83: return F("kVArh"); + case 84: return F("kVArh"); + case 85: return F("kVArh"); + } } return ""; } From 97118d360a4d1f3dfe07467da92120f7591e5c90 Mon Sep 17 00:00:00 2001 From: tomcatxx <69747753+tomcatxx@users.noreply.github.com> Date: Wed, 10 Feb 2021 11:35:57 +0100 Subject: [PATCH 03/24] Update SDM.h --- lib/SDM_Energy_Meter/SDM.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SDM_Energy_Meter/SDM.h b/lib/SDM_Energy_Meter/SDM.h index e77340ef1..0253e3c44 100644 --- a/lib/SDM_Energy_Meter/SDM.h +++ b/lib/SDM_Energy_Meter/SDM.h @@ -39,7 +39,7 @@ #endif #ifndef MAX_MILLIS_TO_WAIT - #define MAX_MILLIS_TO_WAIT 200 //default max time to wait for response from SDM + #define MAX_MILLIS_TO_WAIT 500 //default max time to wait for response from SDM. Try to get as low as possible with higest possible Baud Rate to decrease loop time. #endif //------------------------------------------------------------------------------ From 970d05eeb92ad2712a02033a62a637d99ebbf1cd Mon Sep 17 00:00:00 2001 From: TD-er Date: Fri, 28 May 2021 23:34:07 +0200 Subject: [PATCH 04/24] [Eastron] Fix merge issues --- src/_P078_Eastron.ino | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/_P078_Eastron.ino b/src/_P078_Eastron.ino index 506c28c8f..d8c978896 100644 --- a/src/_P078_Eastron.ino +++ b/src/_P078_Eastron.ino @@ -56,8 +56,8 @@ boolean Plugin_078_init = false; // Forward declaration helper functions -const __FlashStringHelper * p078_getQueryString(byte query); -const __FlashStringHelper * p078_getQueryValueString(byte query); +const __FlashStringHelper * p078_getQueryString(byte query, byte model); +const __FlashStringHelper * p078_getQueryValueString(byte query, byte model); unsigned int p078_getRegister(byte query, byte model); float p078_readVal(byte query, byte node, unsigned int model); @@ -187,8 +187,9 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) options[i] = p078_getQueryString(i, P078_MODEL); } for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { - const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; - sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, nrOptions, options); + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, nrOptions, options); + } } success = true; From 4a6987949844372c7d9e0398f978b0ee3593b43d Mon Sep 17 00:00:00 2001 From: TD-er Date: Fri, 28 May 2021 23:43:39 +0200 Subject: [PATCH 05/24] [Eastron] Uncrustify + remove 500 bytes of duplicate strings --- src/_P078_Eastron.ino | 786 +++++++++++++++++++++--------------------- 1 file changed, 400 insertions(+), 386 deletions(-) diff --git a/src/_P078_Eastron.ino b/src/_P078_Eastron.ino index d8c978896..65fbd7255 100644 --- a/src/_P078_Eastron.ino +++ b/src/_P078_Eastron.ino @@ -2,65 +2,70 @@ #ifdef USES_P078 -//####################################################################################################### -//############## Plugin 078: SDM120/SDM120CT/220/230/630/72D/DDM18SD Eastron Energy Meter ############### -//####################################################################################################### +// ####################################################################################################### +// ############## Plugin 078: SDM120/SDM120CT/220/230/630/72D/DDM18SD Eastron Energy Meter ############### +// ####################################################################################################### + /* - Plugin written by: Sergio Faustino sjfaustino__AT__gmail.com + Plugin written by: Sergio Faustino sjfaustino__AT__gmail.com - This plugin reads available values of an Eastron SDM120C SDM120/SDM120CT/220/230/630/72D & also DDM18SD. -*/ + This plugin reads available values of an Eastron SDM120C SDM120/SDM120CT/220/230/630/72D & also DDM18SD. + */ -#define PLUGIN_078 -#define PLUGIN_ID_078 78 -#define PLUGIN_NAME_078 "Energy (AC) - Eastron SDM120/SDM120CT/220/230/630/72D/DDM18SD [TESTING]" +# define PLUGIN_078 +# define PLUGIN_ID_078 78 +# define PLUGIN_NAME_078 "Energy (AC) - Eastron SDM120/SDM120CT/220/230/630/72D/DDM18SD [TESTING]" -#define P078_DEV_ID PCONFIG(0) -#define P078_DEV_ID_LABEL PCONFIG_LABEL(0) -#define P078_MODEL PCONFIG(1) -#define P078_MODEL_LABEL PCONFIG_LABEL(1) -#define P078_BAUDRATE PCONFIG(2) -#define P078_BAUDRATE_LABEL PCONFIG_LABEL(2) -#define P078_QUERY1 PCONFIG(3) -#define P078_QUERY2 PCONFIG(4) -#define P078_QUERY3 PCONFIG(5) -#define P078_QUERY4 PCONFIG(6) -#define P078_DEPIN CONFIG_PIN3 +# define P078_DEV_ID PCONFIG(0) +# define P078_DEV_ID_LABEL PCONFIG_LABEL(0) +# define P078_MODEL PCONFIG(1) +# define P078_MODEL_LABEL PCONFIG_LABEL(1) +# define P078_BAUDRATE PCONFIG(2) +# define P078_BAUDRATE_LABEL PCONFIG_LABEL(2) +# define P078_QUERY1 PCONFIG(3) +# define P078_QUERY2 PCONFIG(4) +# define P078_QUERY3 PCONFIG(5) +# define P078_QUERY4 PCONFIG(6) +# define P078_DEPIN CONFIG_PIN3 -#define P078_DEV_ID_DFLT 1 -#define P078_MODEL_DFLT 0 // SDM120C -#define P078_BAUDRATE_DFLT 1 // 9600 baud -#define P078_QUERY1_DFLT 0 // Voltage (V) -#define P078_QUERY2_DFLT 1 // Current (A) -#define P078_QUERY3_DFLT 2 // Power (W) -#define P078_QUERY4_DFLT 5 // Power Factor (cos-phi) +# define P078_DEV_ID_DFLT 1 +# define P078_MODEL_DFLT 0 // SDM120C +# define P078_BAUDRATE_DFLT 1 // 9600 baud +# define P078_QUERY1_DFLT 0 // Voltage (V) +# define P078_QUERY2_DFLT 1 // Current (A) +# define P078_QUERY3_DFLT 2 // Power (W) +# define P078_QUERY4_DFLT 5 // Power Factor (cos-phi) -#define P078_NR_OUTPUT_VALUES 4 -#define P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120 14 -#define P078_NR_OUTPUT_OPTIONS_SDM230 24 -#define P078_NR_OUTPUT_OPTIONS_SDM630 86 -#define P078_NR_OUTPUT_OPTIONS_SDM72D 9 -#define P078_NR_OUTPUT_OPTIONS_DDM18SD 7 +# define P078_NR_OUTPUT_VALUES 4 +# define P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120 14 +# define P078_NR_OUTPUT_OPTIONS_SDM230 24 +# define P078_NR_OUTPUT_OPTIONS_SDM630 86 +# define P078_NR_OUTPUT_OPTIONS_SDM72D 9 +# define P078_NR_OUTPUT_OPTIONS_DDM18SD 7 -#define P078_QUERY1_CONFIG_POS 3 +# define P078_QUERY1_CONFIG_POS 3 -#include -#include // Requires SDM library from Reaper7 - https://github.com/reaper7/SDM_Energy_Meter/ +# include +# include // Requires SDM library from Reaper7 - https://github.com/reaper7/SDM_Energy_Meter/ // These pointers may be used among multiple instances of the same plugin, // as long as the same serial settings are used. -ESPeasySerial* Plugin_078_SoftSerial = NULL; -SDM* Plugin_078_SDM = NULL; -boolean Plugin_078_init = false; +ESPeasySerial *Plugin_078_SoftSerial = NULL; +SDM *Plugin_078_SDM = NULL; +boolean Plugin_078_init = false; // Forward declaration helper functions -const __FlashStringHelper * p078_getQueryString(byte query, byte model); -const __FlashStringHelper * p078_getQueryValueString(byte query, byte model); -unsigned int p078_getRegister(byte query, byte model); -float p078_readVal(byte query, byte node, unsigned int model); - +const __FlashStringHelper* p078_getQueryString(byte query, + byte model); +const __FlashStringHelper* p078_getQueryValueString(byte query, + byte model); +unsigned int p078_getRegister(byte query, + byte model); +float p078_readVal(byte query, + byte node, + unsigned int model); boolean Plugin_078(byte function, struct EventStruct *event, String& string) @@ -69,92 +74,93 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) switch (function) { - case PLUGIN_DEVICE_ADD: - { - Device[++deviceCount].Number = PLUGIN_ID_078; - Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins - Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; - Device[deviceCount].Ports = 0; - Device[deviceCount].PullUpOption = false; - Device[deviceCount].InverseLogicOption = false; - Device[deviceCount].FormulaOption = true; - Device[deviceCount].ValueCount = P078_NR_OUTPUT_VALUES; - Device[deviceCount].SendDataOption = true; - Device[deviceCount].TimerOption = true; - Device[deviceCount].GlobalSyncOption = true; - break; - } + { + Device[++deviceCount].Number = PLUGIN_ID_078; + Device[deviceCount].Type = DEVICE_TYPE_SERIAL_PLUS1; // connected through 3 datapins + Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_QUAD; + Device[deviceCount].Ports = 0; + Device[deviceCount].PullUpOption = false; + Device[deviceCount].InverseLogicOption = false; + Device[deviceCount].FormulaOption = true; + Device[deviceCount].ValueCount = P078_NR_OUTPUT_VALUES; + Device[deviceCount].SendDataOption = true; + Device[deviceCount].TimerOption = true; + Device[deviceCount].GlobalSyncOption = true; + break; + } case PLUGIN_GET_DEVICENAME: - { - string = F(PLUGIN_NAME_078); - break; - } - + { + string = F(PLUGIN_NAME_078); + break; + } case PLUGIN_GET_DEVICEGPIONAMES: - { - serialHelper_getGpioNames(event); - event->String3 = formatGpioName_output_optional("DE"); - break; - } + { + serialHelper_getGpioNames(event); + event->String3 = formatGpioName_output_optional("DE"); + break; + } case PLUGIN_WEBFORM_SHOW_CONFIG: - { - string += serialHelper_getSerialTypeLabel(event); - success = true; - break; - } + { + string += serialHelper_getSerialTypeLabel(event); + success = true; + break; + } case PLUGIN_SET_DEFAULTS: - { - P078_DEV_ID = P078_DEV_ID_DFLT; - P078_MODEL = P078_MODEL_DFLT; - P078_BAUDRATE = P078_BAUDRATE_DFLT; - P078_QUERY1 = P078_QUERY1_DFLT; - P078_QUERY2 = P078_QUERY2_DFLT; - P078_QUERY3 = P078_QUERY3_DFLT; - P078_QUERY4 = P078_QUERY4_DFLT; + { + P078_DEV_ID = P078_DEV_ID_DFLT; + P078_MODEL = P078_MODEL_DFLT; + P078_BAUDRATE = P078_BAUDRATE_DFLT; + P078_QUERY1 = P078_QUERY1_DFLT; + P078_QUERY2 = P078_QUERY2_DFLT; + P078_QUERY3 = P078_QUERY3_DFLT; + P078_QUERY4 = P078_QUERY4_DFLT; - success = true; - break; - } + success = true; + break; + } case PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS: { - if (P078_DEV_ID == 0 || P078_DEV_ID > 247 || P078_BAUDRATE >= 6) { + if ((P078_DEV_ID == 0) || (P078_DEV_ID > 247) || (P078_BAUDRATE >= 6)) { // Load some defaults - P078_DEV_ID = P078_DEV_ID_DFLT; - P078_MODEL = P078_MODEL_DFLT; + P078_DEV_ID = P078_DEV_ID_DFLT; + P078_MODEL = P078_MODEL_DFLT; P078_BAUDRATE = P078_BAUDRATE_DFLT; - P078_QUERY1 = P078_QUERY1_DFLT; - P078_QUERY2 = P078_QUERY2_DFLT; - P078_QUERY3 = P078_QUERY3_DFLT; - P078_QUERY4 = P078_QUERY4_DFLT; + P078_QUERY1 = P078_QUERY1_DFLT; + P078_QUERY2 = P078_QUERY2_DFLT; + P078_QUERY3 = P078_QUERY3_DFLT; + P078_QUERY4 = P078_QUERY4_DFLT; } { String options_baudrate[6]; + for (int i = 0; i < 6; ++i) { options_baudrate[i] = String(p078_storageValueToBaudrate(i)); } - addFormSelector(F("Baud Rate"), P078_BAUDRATE_LABEL, 6, options_baudrate, NULL, P078_BAUDRATE ); + addFormSelector(F("Baud Rate"), P078_BAUDRATE_LABEL, 6, options_baudrate, NULL, P078_BAUDRATE); addUnit(F("baud")); } - if (P078_MODEL == 0 && P078_BAUDRATE > 3) + if ((P078_MODEL == 0) && (P078_BAUDRATE > 3)) { addFormNote(F(" SDM120 only allows up to 9600 baud with default 2400!")); + } - if (P078_MODEL == 3 && P078_BAUDRATE == 0) + if ((P078_MODEL == 3) && (P078_BAUDRATE == 0)) { addFormNote(F(" SDM630 only allows 2400 to 38400 baud with default 9600!")); + } addFormNumericBox(F("Modbus Address"), P078_DEV_ID_LABEL, P078_DEV_ID, 1, 247); if (Plugin_078_SDM != nullptr) { addRowLabel(F("Checksum (pass/fail)")); String chksumStats; - chksumStats = Plugin_078_SDM->getSuccCount(); + chksumStats = Plugin_078_SDM->getSuccCount(); chksumStats += '/'; chksumStats += Plugin_078_SDM->getErrCount(); addHtml(chksumStats); @@ -164,156 +170,170 @@ boolean Plugin_078(byte function, struct EventStruct *event, String& string) } case PLUGIN_WEBFORM_LOAD: + { { - { - const __FlashStringHelper * options_model[5] = { F("SDM220 & SDM120CT & SDM120"), F("SDM230"), F("SDM72D"), F("DDM18SD"), F("SDM630") }; - addFormSelector(F("Model Type"), P078_MODEL_LABEL, 5, options_model, NULL, P078_MODEL ); - addFormNote(F("Submit after changing the modell to update Output Configuration.")); - } - - { - // In a separate scope to free memory of String array as soon as possible - sensorTypeHelper_webformLoad_header(); - int nrOptions = 0; - switch (P078_MODEL) { - case 0: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120; break; - case 1: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM230; break; - case 2: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM72D; break; - case 3: nrOptions = P078_NR_OUTPUT_OPTIONS_DDM18SD; break; - case 4: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM630; break; - } - const __FlashStringHelper * options[nrOptions]; - for (int i = 0; i < nrOptions; ++i) { - options[i] = p078_getQueryString(i, P078_MODEL); - } - for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { - const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; - sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, nrOptions, options); - } - } - - success = true; - break; + const __FlashStringHelper *options_model[5] = + { F("SDM220 & SDM120CT & SDM120"), F("SDM230"), F("SDM72D"), F("DDM18SD"), F("SDM630") }; + addFormSelector(F("Model Type"), P078_MODEL_LABEL, 5, options_model, NULL, P078_MODEL); + addFormNote(F("Submit after changing the modell to update Output Configuration.")); } + { + // In a separate scope to free memory of String array as soon as possible + sensorTypeHelper_webformLoad_header(); + int nrOptions = 0; + + switch (P078_MODEL) { + case 0: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM220_SDM120CT_SDM120; break; + case 1: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM230; break; + case 2: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM72D; break; + case 3: nrOptions = P078_NR_OUTPUT_OPTIONS_DDM18SD; break; + case 4: nrOptions = P078_NR_OUTPUT_OPTIONS_SDM630; break; + } + const __FlashStringHelper *options[nrOptions]; + + for (int i = 0; i < nrOptions; ++i) { + options[i] = p078_getQueryString(i, P078_MODEL); + } + + for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, nrOptions, options); + } + } + + success = true; + break; + } + case PLUGIN_WEBFORM_SAVE: - { - // Save output selector parameters. - int model = P078_MODEL; - for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { - const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; - const byte choice = PCONFIG(pconfigIndex); - sensorTypeHelper_saveOutputSelector(event, pconfigIndex, i, p078_getQueryValueString(choice,model)); - } + { + // Save output selector parameters. + int model = P078_MODEL; - P078_DEV_ID = getFormItemInt(P078_DEV_ID_LABEL); - P078_MODEL = getFormItemInt(P078_MODEL_LABEL); - P078_BAUDRATE = getFormItemInt(P078_BAUDRATE_LABEL); - - Plugin_078_init = false; // Force device setup next time - success = true; - break; + for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + const byte choice = PCONFIG(pconfigIndex); + sensorTypeHelper_saveOutputSelector(event, pconfigIndex, i, p078_getQueryValueString(choice, model)); } + P078_DEV_ID = getFormItemInt(P078_DEV_ID_LABEL); + P078_MODEL = getFormItemInt(P078_MODEL_LABEL); + P078_BAUDRATE = getFormItemInt(P078_BAUDRATE_LABEL); + + Plugin_078_init = false; // Force device setup next time + success = true; + break; + } + case PLUGIN_INIT: - { - Plugin_078_init = true; - if (Plugin_078_SoftSerial != NULL) { - delete Plugin_078_SoftSerial; - Plugin_078_SoftSerial=NULL; - } - Plugin_078_SoftSerial = new (std::nothrow) ESPeasySerial(static_cast(CONFIG_PORT), CONFIG_PIN1, CONFIG_PIN2); - if (Plugin_078_SoftSerial == nullptr) { - break; - } - unsigned int baudrate = p078_storageValueToBaudrate(P078_BAUDRATE); - Plugin_078_SoftSerial->begin(baudrate); + { + Plugin_078_init = true; - if (Plugin_078_SDM != NULL) { - delete Plugin_078_SDM; - Plugin_078_SDM=NULL; - } - Plugin_078_SDM = new SDM(*Plugin_078_SoftSerial, baudrate, P078_DEPIN); - if (Plugin_078_SDM != nullptr) { - Plugin_078_SDM->begin(); - success = true; - } + if (Plugin_078_SoftSerial != NULL) { + delete Plugin_078_SoftSerial; + Plugin_078_SoftSerial = NULL; + } + Plugin_078_SoftSerial = new (std::nothrow) ESPeasySerial(static_cast(CONFIG_PORT), CONFIG_PIN1, CONFIG_PIN2); + + if (Plugin_078_SoftSerial == nullptr) { break; } + unsigned int baudrate = p078_storageValueToBaudrate(P078_BAUDRATE); + Plugin_078_SoftSerial->begin(baudrate); + + if (Plugin_078_SDM != NULL) { + delete Plugin_078_SDM; + Plugin_078_SDM = NULL; + } + Plugin_078_SDM = new SDM(*Plugin_078_SoftSerial, baudrate, P078_DEPIN); + + if (Plugin_078_SDM != nullptr) { + Plugin_078_SDM->begin(); + success = true; + } + break; + } case PLUGIN_GET_DEVICEVALUENAMES: - { - int model = P078_MODEL; - for (byte i = 0; i < VARS_PER_TASK; ++i) { - if ( i < P078_NR_OUTPUT_VALUES) { - byte choice = PCONFIG(i + P078_QUERY1_CONFIG_POS); - safe_strncpy( - ExtraTaskSettings.TaskDeviceValueNames[i], - p078_getQueryValueString(choice,model), - sizeof(ExtraTaskSettings.TaskDeviceValueNames[i])); - } else { - ZERO_FILL(ExtraTaskSettings.TaskDeviceValueNames[i]); - } + { + int model = P078_MODEL; + + for (byte i = 0; i < VARS_PER_TASK; ++i) { + if (i < P078_NR_OUTPUT_VALUES) { + byte choice = PCONFIG(i + P078_QUERY1_CONFIG_POS); + safe_strncpy( + ExtraTaskSettings.TaskDeviceValueNames[i], + p078_getQueryValueString(choice, model), + sizeof(ExtraTaskSettings.TaskDeviceValueNames[i])); + } else { + ZERO_FILL(ExtraTaskSettings.TaskDeviceValueNames[i]); } - break; } + break; + } case PLUGIN_EXIT: { Plugin_078_init = false; + if (Plugin_078_SoftSerial != NULL) { delete Plugin_078_SoftSerial; - Plugin_078_SoftSerial=NULL; + Plugin_078_SoftSerial = NULL; } + if (Plugin_078_SDM != NULL) { delete Plugin_078_SDM; - Plugin_078_SDM=NULL; + Plugin_078_SDM = NULL; } break; } case PLUGIN_READ: + { + if (Plugin_078_init) { - if (Plugin_078_init) - { - int model = P078_MODEL; - byte dev_id = P078_DEV_ID; - UserVar[event->BaseVarIndex] = p078_readVal(P078_QUERY1, dev_id, model); - UserVar[event->BaseVarIndex + 1] = p078_readVal(P078_QUERY2, dev_id, model); - UserVar[event->BaseVarIndex + 2] = p078_readVal(P078_QUERY3, dev_id, model); - UserVar[event->BaseVarIndex + 3] = p078_readVal(P078_QUERY4, dev_id, model); - - success = true; - break; - } + int model = P078_MODEL; + byte dev_id = P078_DEV_ID; + UserVar[event->BaseVarIndex] = p078_readVal(P078_QUERY1, dev_id, model); + UserVar[event->BaseVarIndex + 1] = p078_readVal(P078_QUERY2, dev_id, model); + UserVar[event->BaseVarIndex + 2] = p078_readVal(P078_QUERY3, dev_id, model); + UserVar[event->BaseVarIndex + 3] = p078_readVal(P078_QUERY4, dev_id, model); + + success = true; break; } + break; + } } return success; } float p078_readVal(byte query, byte node, unsigned int model) { - if (Plugin_078_SDM == NULL) return 0.0f; + if (Plugin_078_SDM == NULL) { return 0.0f; } + + byte retry_count = 3; + bool success = false; + float _tempvar = NAN; - byte retry_count = 3; - bool success = false; - float _tempvar = NAN; while (retry_count > 0 && !success) { Plugin_078_SDM->clearErrCode(); _tempvar = Plugin_078_SDM->readVal(p078_getRegister(query, model), node); --retry_count; + if (Plugin_078_SDM->getErrCode() == SDM_ERR_NO_ERROR) { success = true; } } + if (loglevelActiveFor(LOG_LEVEL_INFO)) { String log = F("EASTRON: ("); log += node; log += ','; log += model; log += ") "; - log += p078_getQueryString(query,model); + log += p078_getQueryString(query, model); log += ": "; log += _tempvar; addLog(LOG_LEVEL_INFO, log); @@ -323,7 +343,7 @@ float p078_readVal(byte query, byte node, unsigned int model) { } unsigned int p078_getRegister(byte query, byte model) { - if (model == 0) { //SDM220 & SDM120CT & SDM120 + if (model == 0) { // SDM220 & SDM120CT & SDM120 switch (query) { case 0: return SDM_PHASE_1_VOLTAGE; case 1: return SDM_PHASE_1_CURRENT; @@ -339,9 +359,8 @@ unsigned int p078_getRegister(byte query, byte model) { case 11: return SDM_EXPORT_REACTIVE_ENERGY; case 12: return SDM_TOTAL_ACTIVE_ENERGY; case 13: return SDM_TOTAL_REACTIVE_ENERGY; - } - } else if (model == 1) { //SDM230 + } else if (model == 1) { // SDM230 switch (query) { case 0: return SDM_PHASE_1_VOLTAGE; case 1: return SDM_PHASE_1_CURRENT; @@ -368,7 +387,7 @@ unsigned int p078_getRegister(byte query, byte model) { case 22: return SDM_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY; case 23: return SDM_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY; } - } else if (model == 2) { //SDM72D + } else if (model == 2) { // SDM72D switch (query) { case 0: return SDM_TOTAL_SYSTEM_POWER; case 1: return SDM_IMPORT_ACTIVE_ENERGY; @@ -380,7 +399,7 @@ unsigned int p078_getRegister(byte query, byte model) { case 7: return SDM_IMPORT_POWER; case 8: return SDM_EXPORT_POWER; } - } else if (model == 3) { //DDM18SD + } else if (model == 3) { // DDM18SD switch (query) { case 0: return DDM_PHASE_1_VOLTAGE; case 1: return DDM_PHASE_1_CURRENT; @@ -391,7 +410,7 @@ unsigned int p078_getRegister(byte query, byte model) { case 6: return DDM_IMPORT_ACTIVE_ENERGY; case 7: return DDM_IMPORT_REACTIVE_ENERGY; } - } else if (model == 4) { //SDM630 + } else if (model == 4) { // SDM630 switch (query) { case 0: return SDM_PHASE_1_VOLTAGE; case 1: return SDM_PHASE_2_VOLTAGE; @@ -484,8 +503,8 @@ unsigned int p078_getRegister(byte query, byte model) { return 0; } -const __FlashStringHelper * p078_getQueryString(byte query, byte model) { - if (model == 0) { //SDM220 & SDM120CT & SDM120 +const __FlashStringHelper* p078_getQueryString(byte query, byte model) { + if (model == 0) { // SDM220 & SDM120CT & SDM120 switch (query) { case 0: return F("Voltage (V)"); case 1: return F("Current (A)"); @@ -501,9 +520,8 @@ const __FlashStringHelper * p078_getQueryString(byte query, byte model) { case 11: return F("ExportReactiveEnergy (kVArh/MVArh)"); case 12: return F("TotalActiveEnergy (kWh)"); case 13: return F("TotalReactiveEnergy (kVArh)"); - } - } else if (model == 1) { //SDM230 + } else if (model == 1) { // SDM230 switch (query) { case 0: return F("Voltage (V)"); case 1: return F("Current (A)"); @@ -530,19 +548,19 @@ const __FlashStringHelper * p078_getQueryString(byte query, byte model) { case 22: return F("Current resettable total active energy (kWh)"); case 23: return F("Current resettable total reactive energy (kVArh)"); } - } else if (model == 2) { //SDM72D + } else if (model == 2) { // SDM72D switch (query) { - case 0: return F("Total System Power (W)"); - case 1: return F("Import Active Energy since last reset (kWh/MWh)"); - case 2: return F("Export Active Energy since last reset (kWh/MWh)"); - case 3: return F("Total Active Energy (kwh)"); - case 4: return F("Resettable total Active Energy (kWh)"); - case 5: return F("Resettable import (kWh)"); - case 6: return F("Resettable export (kWh)"); - case 7: return F("Import power (W)"); - case 8: return F("Export power (W)"); + case 0: return F("Total System Power (W)"); + case 1: return F("Import Active Energy since last reset (kWh/MWh)"); + case 2: return F("Export Active Energy since last reset (kWh/MWh)"); + case 3: return F("Total Active Energy (kwh)"); + case 4: return F("Resettable total Active Energy (kWh)"); + case 5: return F("Resettable import (kWh)"); + case 6: return F("Resettable export (kWh)"); + case 7: return F("Import power (W)"); + case 8: return F("Export power (W)"); } - } else if (model == 3) { //DDM18SD + } else if (model == 3) { // DDM18SD switch (query) { case 0: return F("Voltage (V)"); case 1: return F("Current (A)"); @@ -553,102 +571,101 @@ const __FlashStringHelper * p078_getQueryString(byte query, byte model) { case 6: return F("Import Active Energy (kWh)"); case 7: return F("Import Reactive Energy (kVArh)"); } - } else if (model == 4) { //SDM630 + } else if (model == 4) { // SDM630 switch (query) { - case 0: return F("Voltage (V) Phase 1"); - case 1: return F("Voltage (V) Phase 2"); - case 2: return F("Voltage (V) Phase 3"); - case 3: return F("Current (A) Phase 1"); - case 4: return F("Current (A) Phase 2"); - case 5: return F("Current (A) Phase 3"); - case 6: return F("Power (W) Phase 1"); - case 7: return F("Power (W) Phase 2"); - case 8: return F("Power (W) Phase 3"); - case 9: return F("Active Apparent Power (VA) Phase 1"); - case 10: return F("Active Apparent Power (VA) Phase 2"); - case 11: return F("Active Apparent Power (VA) Phase 3"); - case 12: return F("Reactive Apparent Power (VAr) Phase 1"); - case 13: return F("Reactive Apparent Power (VAr) Phase 2"); - case 14: return F("Reactive Apparent Power (VAr) Phase 3"); - case 15: return F("Power Factor (cos-phi) Phase 1"); - case 16: return F("Power Factor (cos-phi) Phase 2"); - case 17: return F("Power Factor (cos-phi) Phase 3"); - case 18: return F("Phase Angle (Degrees) Phase 1"); - case 19: return F("Phase Angle (Degrees) Phase 2"); - case 20: return F("Phase Angle (Degrees) Phase 3"); - case 21: return F("Average line to neutral volts (V)"); - case 22: return F("Average line Current (A)"); - case 23: return F("Sum of line Currents (A)"); - case 24: return F("Total System Power (W)"); - case 25: return F("Total System Active Apparent Power (VA)"); - case 26: return F("Total System Reactive Apparent Power (VAr)"); - case 27: return F("Total System Power Factor (cos-phi)"); - case 28: return F("Total System Phase Angle (Degrees)"); - case 29: return F("Frequency of Supply Voltages (Hz)"); - case 30: return F("Import Active Energy since last reset (kWh/MWh)"); - case 31: return F("Export Active Energy since last reset (kWh/MWh)"); - case 32: return F("Import Reactive Energy since last reset (kVArh/MVArh)"); - case 33: return F("Export Reactive Energy since last reset (kVArh/MVArh)"); - case 34: return F("VAh since last Reset (kVAh/MVAh)"); - case 35: return F("Ah since last Reset (Ah/kAh)"); - case 36: return F("Total System Power Demand (W)"); - case 37: return F("Maximum Total System Power Demand (W)"); - case 38: return F("Total System VA demand (VA)"); - case 39: return F("Maximum Total System VA Demand (VA)"); - case 40: return F("Neutral Current Demand (A)"); - case 41: return F("Maximum Neutral Current Demand (A)"); - case 42: return F("Line 1 to Line 2 Volts (V)"); - case 43: return F("Line 2 to Line 3 Volts (V)"); - case 44: return F("Line 3 to Line 1 Volts (V)"); - case 45: return F("Average Line to Line Volts (V)"); - case 46: return F("Neutral Current (A)"); - case 47: return F("L/N Volts THD (%) Phase 1"); - case 48: return F("L/N Volts THD (%) Phase 2"); - case 49: return F("L/N Volts THD (%) Phase 3"); - case 50: return F("Current THD (%) Phase 1 "); - case 51: return F("Current THD (%) Phase 2"); - case 52: return F("Current THD (%) Phase 3"); - case 53: return F("Average Line to Neutral Volts THD (cos-phi)"); - case 54: return F("Average Line Current THD (%)"); - case 55: return F("Total System Power Factor (%)"); - case 56: return F("Current Demand (A) Phase 1 "); - case 57: return F("Current Demand (A) Phase 2"); - case 58: return F("Current Demand (A) Phase 3"); - case 59: return F("Maximum Current Demand (A) Phase 1 "); - case 60: return F("Maximum Current Demand (A) Phase 2"); - case 61: return F("Maximum Current Demand (A) Phase 3"); - case 62: return F("Line 1 to Line 2 Volts THD (%)"); - case 63: return F("Line 2 to Line 3 Volts THD (%)"); - case 64: return F("Line 3 to Line 1 Volts THD (%)"); - case 65: return F("Average Line to Line Volts THD (%)"); - case 66: return F("Total Active Energy (kwh)"); - case 67: return F("Total Reactive Energy (kVArh)"); - case 68: return F("Import Active Energy (kWh) L1"); - case 69: return F("Import Active Energy (kWh) L2"); - case 70: return F("Import Active Energy (kWh) L3"); - case 71: return F("Export Active Energy (kWh) L1"); - case 72: return F("Export Active Energy (kWh) L2"); - case 73: return F("Export Active Energy (kWh) L3"); - case 74: return F("Total Active Energy (kWh) L1"); - case 75: return F("Total Active Energy (kWh) L2"); - case 76: return F("Total Active Energy (kWh) L3"); - case 77: return F("Import Reactive Energy (kVArh) L1"); - case 78: return F("Import Reactive Energy (kVArh) L2"); - case 79: return F("Import Reactive Energy (kVArh) L3"); - case 80: return F("Export Reactive Energy (kVArh) L1"); - case 81: return F("Export Reactive Energy (kVArh) L2"); - case 82: return F("Export Reactive Energy (kVArh) L3"); - case 83: return F("Total Reactive Energy (kVArh) L1"); - case 84: return F("Total Reactive Energy (kVArh) L2"); - case 85: return F("Total Reactive Energy (kVArh) L3"); - - } + case 0: return F("Voltage (V) Phase 1"); + case 1: return F("Voltage (V) Phase 2"); + case 2: return F("Voltage (V) Phase 3"); + case 3: return F("Current (A) Phase 1"); + case 4: return F("Current (A) Phase 2"); + case 5: return F("Current (A) Phase 3"); + case 6: return F("Power (W) Phase 1"); + case 7: return F("Power (W) Phase 2"); + case 8: return F("Power (W) Phase 3"); + case 9: return F("Active Apparent Power (VA) Phase 1"); + case 10: return F("Active Apparent Power (VA) Phase 2"); + case 11: return F("Active Apparent Power (VA) Phase 3"); + case 12: return F("Reactive Apparent Power (VAr) Phase 1"); + case 13: return F("Reactive Apparent Power (VAr) Phase 2"); + case 14: return F("Reactive Apparent Power (VAr) Phase 3"); + case 15: return F("Power Factor (cos-phi) Phase 1"); + case 16: return F("Power Factor (cos-phi) Phase 2"); + case 17: return F("Power Factor (cos-phi) Phase 3"); + case 18: return F("Phase Angle (Degrees) Phase 1"); + case 19: return F("Phase Angle (Degrees) Phase 2"); + case 20: return F("Phase Angle (Degrees) Phase 3"); + case 21: return F("Average line to neutral volts (V)"); + case 22: return F("Average line Current (A)"); + case 23: return F("Sum of line Currents (A)"); + case 24: return F("Total System Power (W)"); + case 25: return F("Total System Active Apparent Power (VA)"); + case 26: return F("Total System Reactive Apparent Power (VAr)"); + case 27: return F("Total System Power Factor (cos-phi)"); + case 28: return F("Total System Phase Angle (Degrees)"); + case 29: return F("Frequency of Supply Voltages (Hz)"); + case 30: return F("Import Active Energy since last reset (kWh/MWh)"); + case 31: return F("Export Active Energy since last reset (kWh/MWh)"); + case 32: return F("Import Reactive Energy since last reset (kVArh/MVArh)"); + case 33: return F("Export Reactive Energy since last reset (kVArh/MVArh)"); + case 34: return F("VAh since last Reset (kVAh/MVAh)"); + case 35: return F("Ah since last Reset (Ah/kAh)"); + case 36: return F("Total System Power Demand (W)"); + case 37: return F("Maximum Total System Power Demand (W)"); + case 38: return F("Total System VA demand (VA)"); + case 39: return F("Maximum Total System VA Demand (VA)"); + case 40: return F("Neutral Current Demand (A)"); + case 41: return F("Maximum Neutral Current Demand (A)"); + case 42: return F("Line 1 to Line 2 Volts (V)"); + case 43: return F("Line 2 to Line 3 Volts (V)"); + case 44: return F("Line 3 to Line 1 Volts (V)"); + case 45: return F("Average Line to Line Volts (V)"); + case 46: return F("Neutral Current (A)"); + case 47: return F("L/N Volts THD (%) Phase 1"); + case 48: return F("L/N Volts THD (%) Phase 2"); + case 49: return F("L/N Volts THD (%) Phase 3"); + case 50: return F("Current THD (%) Phase 1 "); + case 51: return F("Current THD (%) Phase 2"); + case 52: return F("Current THD (%) Phase 3"); + case 53: return F("Average Line to Neutral Volts THD (cos-phi)"); + case 54: return F("Average Line Current THD (%)"); + case 55: return F("Total System Power Factor (%)"); + case 56: return F("Current Demand (A) Phase 1 "); + case 57: return F("Current Demand (A) Phase 2"); + case 58: return F("Current Demand (A) Phase 3"); + case 59: return F("Maximum Current Demand (A) Phase 1 "); + case 60: return F("Maximum Current Demand (A) Phase 2"); + case 61: return F("Maximum Current Demand (A) Phase 3"); + case 62: return F("Line 1 to Line 2 Volts THD (%)"); + case 63: return F("Line 2 to Line 3 Volts THD (%)"); + case 64: return F("Line 3 to Line 1 Volts THD (%)"); + case 65: return F("Average Line to Line Volts THD (%)"); + case 66: return F("Total Active Energy (kwh)"); + case 67: return F("Total Reactive Energy (kVArh)"); + case 68: return F("Import Active Energy (kWh) L1"); + case 69: return F("Import Active Energy (kWh) L2"); + case 70: return F("Import Active Energy (kWh) L3"); + case 71: return F("Export Active Energy (kWh) L1"); + case 72: return F("Export Active Energy (kWh) L2"); + case 73: return F("Export Active Energy (kWh) L3"); + case 74: return F("Total Active Energy (kWh) L1"); + case 75: return F("Total Active Energy (kWh) L2"); + case 76: return F("Total Active Energy (kWh) L3"); + case 77: return F("Import Reactive Energy (kVArh) L1"); + case 78: return F("Import Reactive Energy (kVArh) L2"); + case 79: return F("Import Reactive Energy (kVArh) L3"); + case 80: return F("Export Reactive Energy (kVArh) L1"); + case 81: return F("Export Reactive Energy (kVArh) L2"); + case 82: return F("Export Reactive Energy (kVArh) L3"); + case 83: return F("Total Reactive Energy (kVArh) L1"); + case 84: return F("Total Reactive Energy (kVArh) L2"); + case 85: return F("Total Reactive Energy (kVArh) L3"); + } } return F(""); } -const __FlashStringHelper * p078_getQueryValueString(byte query, byte model) { - if (model == 0) { //SDM220 & SDM120CT & SDM120 +const __FlashStringHelper* p078_getQueryValueString(byte query, byte model) { + if (model == 0) { // SDM220 & SDM120CT & SDM120 switch (query) { case 0: return F("V"); case 1: return F("A"); @@ -658,15 +675,14 @@ const __FlashStringHelper * p078_getQueryValueString(byte query, byte model) { case 5: return F("cos-phi"); case 6: return F("Degrees"); case 7: return F("Hz"); - case 8: return F("kWh/MWh"); + case 8: case 9: return F("kWh/MWh"); - case 10: return F("kVArh/MVArh"); + case 10: case 11: return F("kVArh/MVArh"); case 12: return F("kWh"); case 13: return F("kVArh"); - } - } else if (model == 1) { //SDM230 + } else if (model == 1) { // SDM230 switch (query) { case 0: return F("V"); case 1: return F("A"); @@ -676,36 +692,36 @@ const __FlashStringHelper * p078_getQueryValueString(byte query, byte model) { case 5: return F("cos-phi"); case 6: return F("Degrees"); case 7: return F("Hz"); - case 8: return F("kWh/MWh"); + case 8: case 9: return F("kWh/MWh"); - case 10: return F("kVArh/MVArh"); + case 10: case 11: return F("kVArh/MVArh"); - case 12: return F("W"); - case 13: return F("W"); - case 14: return F("W"); - case 15: return F("W"); - case 16: return F("W"); + case 12: + case 13: + case 14: + case 15: + case 16: case 17: return F("W"); - case 18: return F("A"); + case 18: case 19: return F("A"); case 20: return F("kWh"); case 21: return F("kVArh"); case 22: return F("kWh"); case 23: return F("kVArh"); } - } else if (model == 2) { //SDM72D + } else if (model == 2) { // SDM72D switch (query) { - case 0: return F("W"); - case 1: return F("kWh/MWh"); - case 2: return F("kWh/MWh"); - case 3: return F("kWh"); - case 4: return F("kWh"); - case 5: return F("kWh"); - case 6: return F("kWh"); - case 7: return F("W"); - case 8: return F("W"); + case 0: return F("W"); + case 1: + case 2: return F("kWh/MWh"); + case 3: + case 4: + case 5: + case 6: return F("kWh"); + case 7: + case 8: return F("W"); } - } else if (model == 3) { //DDM18SD + } else if (model == 3) { // DDM18SD switch (query) { case 0: return F("V"); case 1: return F("A"); @@ -716,31 +732,31 @@ const __FlashStringHelper * p078_getQueryValueString(byte query, byte model) { case 6: return F("kWh"); case 7: return F("kVArh"); } - } else if (model == 4) { //SDM630 + } else if (model == 4) { // SDM630 switch (query) { - case 0: return F("V"); - case 1: return F("V"); + case 0: + case 1: case 2: return F("V"); - case 3: return F("A"); - case 4: return F("A"); + case 3: + case 4: case 5: return F("A"); - case 6: return F("W"); - case 7: return F("W"); + case 6: + case 7: case 8: return F("W"); - case 9: return F("VA"); - case 10: return F("VA"); + case 9: + case 10: case 11: return F("VA"); - case 12: return F("VAr"); - case 13: return F("VAr"); + case 12: + case 13: case 14: return F("VAr"); - case 15: return F("cos-phi"); - case 16: return F("cos-phi"); + case 15: + case 16: case 17: return F("cos-phi"); - case 18: return F("Degrees"); - case 19: return F("Degrees"); + case 18: + case 19: case 20: return F("Degrees"); case 21: return F("V"); - case 22: return F("A"); + case 22: case 23: return F("A"); case 24: return F("W"); case 25: return F("VA"); @@ -748,70 +764,70 @@ const __FlashStringHelper * p078_getQueryValueString(byte query, byte model) { case 27: return F("cos-phi"); case 28: return F("Degrees"); case 29: return F("Hz"); - case 30: return F("kWh/MWh"); + case 30: case 31: return F("kWh/MWh"); - case 32: return F("kVArh/MVArh"); + case 32: case 33: return F("kVArh/MVArh"); case 34: return F("kVAh/MVAh"); case 35: return F("Ah/kAh"); - case 36: return F("W"); + case 36: case 37: return F("W"); - case 38: return F("VA"); + case 38: case 39: return F("VA"); - case 40: return F("A"); + case 40: case 41: return F("A"); - case 42: return F("V"); - case 43: return F("V"); - case 44: return F("V"); + case 42: + case 43: + case 44: case 45: return F("V"); case 46: return F("A"); - case 47: return F("%"); - case 48: return F("%"); - case 49: return F("%"); - case 50: return F("%"); - case 51: return F("%"); - case 52: return F("%"); - case 53: return F("%"); + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: case 54: return F("%"); case 55: return F("cos-phi"); - case 56: return F("A"); - case 57: return F("A"); - case 58: return F("A"); - case 59: return F("A"); - case 60: return F("A"); + case 56: + case 57: + case 58: + case 59: + case 60: case 61: return F("A"); - case 62: return F("%"); - case 63: return F("%"); - case 64: return F("%"); + case 62: + case 63: + case 64: case 65: return F("%"); case 66: return F("kWh"); case 67: return F("kVArh"); - case 68: return F("kWh"); - case 69: return F("kWh"); - case 70: return F("kWh"); - case 71: return F("kWh"); - case 72: return F("kWh"); - case 73: return F("kWh"); - case 74: return F("kWh"); - case 75: return F("kWh"); + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: case 76: return F("kWh"); - case 77: return F("kVArh"); - case 78: return F("kVArh"); - case 79: return F("kVArh"); - case 80: return F("kVArh"); - case 81: return F("kVArh"); - case 82: return F("kVArh"); - case 83: return F("kVArh"); - case 84: return F("kVArh"); + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: case 85: return F("kVArh"); } } return F(""); } - int p078_storageValueToBaudrate(byte baudrate_setting) { unsigned int baudrate = 9600; + switch (baudrate_setting) { case 0: baudrate = 1200; break; case 1: baudrate = 2400; break; @@ -823,6 +839,4 @@ int p078_storageValueToBaudrate(byte baudrate_setting) { return baudrate; } - - #endif // USES_P078 From 22e7fd58dfe3165738ab469fdd2628d6e862893a Mon Sep 17 00:00:00 2001 From: TD-er Date: Sat, 17 Jul 2021 15:21:36 +0200 Subject: [PATCH 06/24] [Eastron] Fix merge issues --- src/_P078_Eastron.ino | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/src/_P078_Eastron.ino b/src/_P078_Eastron.ino index f9803a0f1..b8f4819cb 100644 --- a/src/_P078_Eastron.ino +++ b/src/_P078_Eastron.ino @@ -103,7 +103,7 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) uint8_t choice = PCONFIG(i + P078_QUERY1_CONFIG_POS); safe_strncpy( ExtraTaskSettings.TaskDeviceValueNames[i], - p078_getQueryValueString(choice), + p078_getQueryValueString(choice, P078_MODEL), sizeof(ExtraTaskSettings.TaskDeviceValueNames[i])); } else { ZERO_FILL(ExtraTaskSettings.TaskDeviceValueNames[i]); @@ -115,7 +115,7 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_GET_DEVICEGPIONAMES: { serialHelper_getGpioNames(event); - event->String3 = formatGpioName_output_optional("DE"); + event->String3 = formatGpioName_output_optional(F("DE")); break; } @@ -211,8 +211,8 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) options[i] = p078_getQueryString(i, P078_MODEL); } - for (byte i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { - const byte pconfigIndex = i + P078_QUERY1_CONFIG_POS; + for (uint8_t i = 0; i < P078_NR_OUTPUT_VALUES; ++i) { + const uint8_t pconfigIndex = i + P078_QUERY1_CONFIG_POS; sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, nrOptions, options); } } @@ -270,25 +270,6 @@ boolean Plugin_078(uint8_t function, struct EventStruct *event, String& string) break; } - case PLUGIN_GET_DEVICEVALUENAMES: - { - int model = P078_MODEL; - - for (byte i = 0; i < VARS_PER_TASK; ++i) { - if (i < P078_NR_OUTPUT_VALUES) { - byte choice = PCONFIG(i + P078_QUERY1_CONFIG_POS); - safe_strncpy( - ExtraTaskSettings.TaskDeviceValueNames[i], - p078_getQueryValueString(choice, model), - sizeof(ExtraTaskSettings.TaskDeviceValueNames[i])); - } else { - ZERO_FILL(ExtraTaskSettings.TaskDeviceValueNames[i]); - } - } - break; - } - - case PLUGIN_EXIT: { Plugin_078_init = false; @@ -347,9 +328,9 @@ float p078_readVal(uint8_t query, uint8_t node, unsigned int model) { log += node; log += ','; log += model; - log += ") "; + log += F(") "); log += p078_getQueryString(query, model); - log += ": "; + log += F(": "); log += _tempvar; addLog(LOG_LEVEL_INFO, log); } From 0eabf1d2531692c602c6e04b2a2af248b0a8584b Mon Sep 17 00:00:00 2001 From: TD-er Date: Thu, 27 Jul 2023 22:11:07 +0200 Subject: [PATCH 07/24] [ESP32 Serial] Fix serial tasks not working after save or restart task [ESP32 Serial] Do not cache baud rate between end() and begin() --- .../Port_ESPEasySerial_HardwareSerial.cpp | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/lib/ESPEasySerial/Port_ESPEasySerial_HardwareSerial.cpp b/lib/ESPEasySerial/Port_ESPEasySerial_HardwareSerial.cpp index 2046ec8d2..103326019 100644 --- a/lib/ESPEasySerial/Port_ESPEasySerial_HardwareSerial.cpp +++ b/lib/ESPEasySerial/Port_ESPEasySerial_HardwareSerial.cpp @@ -4,76 +4,6 @@ #include "ESPEasySerialType.h" -#ifdef ESP32 - -// Temporary work-around for bug in ESP32 code, where the pin matrix is not cleaned up between calling end() and begin() -// Work-around is to keep track of the last used pins for a serial port, -// as it is likely that a node will always use the same pins most of the time. -// If not, a reboot may be OK to fix it. -// Another idea is to swap pins among UART ports. -// e.g. use the same pins on Serial1 if it was used on Serial2 before. - -// PR to fix it: https://github.com/espressif/arduino-esp32/pull/5385 -// See: https://github.com/espressif/arduino-esp32/issues/3878 - - -static int receivePin0 = -1; -static int transmitPin0 = -1; -static int receivePin1 = -1; -static int transmitPin1 = -1; -static int receivePin2 = -1; -static int transmitPin2 = -1; - -bool pinsChanged(ESPEasySerialPort port, - int receivePin, - int transmitPin) -{ - switch (port) { - case ESPEasySerialPort::serial0: return receivePin != receivePin0 || transmitPin != transmitPin0; - # if SOC_UART_NUM > 1 - case ESPEasySerialPort::serial1: return receivePin != receivePin1 || transmitPin != transmitPin1; - # endif // if SOC_UART_NUM > 1 - # if SOC_UART_NUM > 2 - case ESPEasySerialPort::serial2: return receivePin != receivePin2 || transmitPin != transmitPin2; - # endif // if SOC_UART_NUM > 2 - default: - // No other hardware serial ports - break; - } - return false; -} - -void setPinsCache(ESPEasySerialPort port, - int receivePin, - int transmitPin) -{ - switch (port) { - case ESPEasySerialPort::serial0: - receivePin0 = receivePin; - transmitPin0 = transmitPin; - break; - # if SOC_UART_NUM > 1 - case ESPEasySerialPort::serial1: - receivePin1 = receivePin; - transmitPin1 = transmitPin; - break; - # endif // if SOC_UART_NUM > 1 - - # if SOC_UART_NUM > 2 - case ESPEasySerialPort::serial2: - receivePin2 = receivePin; - transmitPin2 = transmitPin; - break; - - # endif // if SOC_UART_NUM > 2 - default: - // No other hardware serial ports - break; - } -} - -#endif // ifdef ESP32 - Port_ESPEasySerial_HardwareSerial_t::Port_ESPEasySerial_HardwareSerial_t() {} Port_ESPEasySerial_HardwareSerial_t::~Port_ESPEasySerial_HardwareSerial_t() {} @@ -184,8 +114,6 @@ void Port_ESPEasySerial_HardwareSerial_t::begin(unsigned long baud) // Timeout added for 1.0.1 // See: https://github.com/espressif/arduino-esp32/commit/233d31bed22211e8c85f82bcf2492977604bbc78 // getHW()->begin(baud, config, _config.receivePin, _config.transmitPin, invert, timeout_ms); - if (pinsChanged(_config.port, _config.receivePin, _config.transmitPin) || (_config.baud != baud)) { - setPinsCache(_config.port, _config.receivePin, _config.transmitPin); _config.baud = baud; // Allow to flush data from the serial buffers @@ -204,7 +132,6 @@ void Port_ESPEasySerial_HardwareSerial_t::begin(unsigned long baud) _serial->begin(baud, _config.config, _config.receivePin, _config.transmitPin, _config.inverse_logic); _serial->flush(); - } } #endif // ifdef ESP32 From 13b0d1233e1f4de5e1cffac908ad0d257d3386ec Mon Sep 17 00:00:00 2001 From: TD-er Date: Tue, 1 Aug 2023 02:22:42 +0200 Subject: [PATCH 08/24] [Eastron] Update SDM library to v2.2.2 --- lib/SDM_Energy_Meter/README.md | 197 +++++++--- lib/SDM_Energy_Meter/SDM.cpp | 156 +++++--- lib/SDM_Energy_Meter/SDM.h | 337 +++++++++++------- lib/SDM_Energy_Meter/SDM_Config_User.h | 99 +++-- .../sdm630_influxdb/sdm630_influxdb.ino | 292 +++++++++++++++ .../sdm_live_page_esp32_hwserial/index_page.h | 79 ++++ .../sdm_live_page_esp32_hwserial.ino | 218 +++++++++++ .../index_page.h | 0 .../sdm_live_page_esp8266_hwserial.ino} | 24 +- .../examples/sdm_simple/sdm_simple.ino | 43 ++- lib/SDM_Energy_Meter/keywords.txt | 6 + lib/SDM_Energy_Meter/library.json | 31 -- lib/SDM_Energy_Meter/library.properties | 9 +- 13 files changed, 1183 insertions(+), 308 deletions(-) create mode 100644 lib/SDM_Energy_Meter/examples/sdm630_influxdb/sdm630_influxdb.ino create mode 100644 lib/SDM_Energy_Meter/examples/sdm_live_page_esp32_hwserial/index_page.h create mode 100644 lib/SDM_Energy_Meter/examples/sdm_live_page_esp32_hwserial/sdm_live_page_esp32_hwserial.ino rename lib/SDM_Energy_Meter/examples/{sdm_live_page => sdm_live_page_esp8266_hwserial}/index_page.h (100%) rename lib/SDM_Energy_Meter/examples/{sdm_live_page/sdm_live_page.ino => sdm_live_page_esp8266_hwserial/sdm_live_page_esp8266_hwserial.ino} (86%) delete mode 100644 lib/SDM_Energy_Meter/library.json diff --git a/lib/SDM_Energy_Meter/README.md b/lib/SDM_Energy_Meter/README.md index 7728266ec..3f85fcc14 100644 --- a/lib/SDM_Energy_Meter/README.md +++ b/lib/SDM_Energy_Meter/README.md @@ -1,6 +1,4 @@ -## WARNING! library initialization changed! ## -old library version is available at [old_template branch](https://github.com/reaper7/SDM_Energy_Meter/tree/old_template)
-## Library for reading SDM120 SDM220 SDM230 SDM630 Modbus Energy meters. ## +## Library for reading SDM72 SDM120 SDM220 SDM230 SDM630 DDM18SD Modbus Energy meters. ## ### SECTIONS: ### #### 1. [INTRODUCTION](#introduction) #### @@ -8,15 +6,20 @@ #### 3. [CONFIGURING](#configuring) #### #### 4. [INITIALIZING](#initializing) #### #### 5. [READING](#reading) #### -#### 6. [DEBUGING](#debuging) #### +#### 6. [PROBLEMS](#problems) #### #### 7. [CREDITS](#credits) #### --- ### Introduction: ### This library allows you reading SDM module(s) using: -- [x] Hardware Serial (recommended option, smallest number of reads errors) or -- [x] Software Serial ([library for ESP8266](https://github.com/plerup/espsoftwareserial)) +- [x] Hardware Serial (recommended option, smallest number of reads errors, especially for esp8266) or +- [x] Software Serial, attached as core libraries for ESP8266 and AVR or as external lib for ESP32
+ (the new version of esp Software Serial library
+ has a different initialization compared to avr!
+ This version of SDM library (>=2.2.2) works only with esp Software Serial 8.0.1 or higher!!!
+ If you have an older esp Software Serial version
+ then use other SDM library, details below the Credits section
)
you also need rs232<->rs485 converter: - [x] with automatic flow direction control (look at images below) or @@ -24,13 +27,14 @@ you also need rs232<->rs485 converter: (in this case MAX485 DE and RE pins must be connected together to one of uC pin
and this pin must be passed when initializing the library
) -_Tested on Wemos D1 Mini with Arduino IDE 1.8.3-1.9.0b & ESP8266 core 2.3.0-2.4.1_ +_Tested on Wemos D1 Mini with Arduino IDE 1.8.3-1.8.10 & ESP8266 core 2.3.0-2.5.2_ --- ### Screenshots: ### -

+
+

live page example (extended) screenshot

@@ -39,14 +43,26 @@ _Tested on Wemos D1 Mini with Arduino IDE 1.8.3-1.9.0b & ESP8266 core 2.3.0-2.4. ### Configuring: ### Default configuration is specified in the [SDM.h](https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L18) file, and parameters are set to:
-Software Serial, baud 4800, uart config SERIAL_8N1, without DE/RE pin.
+Software Serial mode, baud 4800, uart config SERIAL_8N1, without DE/RE pin,
+uart pins for esp32 hwserial and esp32/esp8266/avr swserial as NOT_A_PIN (-1).

+For esp32 hwserial this means using the default pins for the selected uart port,
+specified in the core library (HardwareSerial.cpp).
+For swserial option (esp32/esp8266/avr) is necessary
+to specify the pin numbers, as described below.
User can set the parameters in two ways: - by editing the [SDM_Config_User.h](https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM_Config_User.h) file - by passing values during initialization (section below) +[SDM_Config_User.h](https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM_Config_User.h) file includes also two parameters that can be adjusted depending on your needs: +- WAITING_TURNAROUND_DELAY (default set to 200ms) defines the time (after sending the query) for the response from the slave device. + If the slave device does not send the required number of bytes (FRAMESIZE) within this time, an SDM_ERR_TIMEOUT error will be returned. +- RESPONSE_TIMEOUT (default set to 500ms) defines the time (after sending the request and receiving the reply) to a possible response + from other slave devices on the bus, during this time it will not be possible to execute another query. + It is a protection time for devices that are not able to quickly respond to inquiries. + NOTE for Hardware Serial mode: to force the Hardware Serial mode,
-user must edit the corresponding entry in [SDM_Config_User.h](https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM_Config_User.h#L13) file.
+user must edit the corresponding entry in [SDM_Config_User.h](https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM_Config_User.h#L17) file.
adding #define USE_HARDWARESERIAL to the main ino file is not enough.
--- @@ -58,20 +74,31 @@ initialization is limited to passing serial port reference (software or hardware and looks as follows: ```cpp //lib init when Software Serial is used: -#include #include +#include -SoftwareSerial swSerSDM(13, 15); - -// _software serial reference +// for ESP8266 and ESP32 +SoftwareSerial swSerSDM; +// _______________________________software serial reference // | SDM sdm(swSerSDM); +// for AVR +SoftwareSerial swSerSDM(SDM_RX_PIN, SDM_TX_PIN); +// | |_tx pin definition(from SDM_Config_User.h) +// |_____________rx pin definition(from SDM_Config_User.h) +// +// _______________________________software serial reference +// | +SDM sdm(swSerSDM); +``` + +```cpp //lib init when Hardware Serial is used: #include -// _hardware serial reference +// _________________________________hardware serial reference // | SDM sdm(Serial); ``` @@ -79,28 +106,63 @@ If the user wants to temporarily change the configuration during the initializat then can pass additional parameters as below: ```cpp //lib init when Software Serial is used: -#include #include +#include -SoftwareSerial swSerSDM(13, 15); +// for ESP8266 and ESP32 +SoftwareSerial swSerSDM; +// ________________________________________software serial reference +// | __________________________________baudrate(optional, default from SDM_Config_User.h) +// | | _______________________dere pin for max485(optional, default from SDM_Config_User.h) +// | | | _________software uart config(optional, default from SDM_Config_User.h) +// | | | | _____rx pin number(optional, default from SDM_Config_User.h) +// | | | | | _tx pin number(optional, default from SDM_Config_User.h) +// | | | | | | +SDM sdm(swSerSDM, 9600, NOT_A_PIN, SWSERIAL_8N1, 13, 15); -// __________________software serial reference -// | ____________baudrate(optional, default from SDM_Config_User.h) -// | | _dere pin for max485(optional, default from SDM_Config_User.h) + +// for AVR +SoftwareSerial swSerSDM(10, 11); +// ________________________________________software serial reference +// | __________________________________baudrate(optional, default from SDM_Config_User.h) +// | | _______________________dere pin for max485(optional, default from SDM_Config_User.h) // | | | SDM sdm(swSerSDM, 9600, NOT_A_PIN); +``` - +```cpp //lib init when Hardware Serial is used: #include -// _____________________________________hardware serial reference -// | _______________________________baudrate(optional, default from SDM_Config_User.h) -// | | ____________________dere pin for max485(optional, default from SDM_Config_User.h) -// | | | ________hardware uart config(optional, default from SDM_Config_User.h) -// | | | | _swap hw serial pins from 3/1 to 13/15(optional, default from SDM_Config_User.h) +// for ESP8266 +// ______________________________________hardware serial reference +// | ________________________________baudrate(optional, default from SDM_Config_User.h) +// | | _____________________dere pin for max485(optional, default from SDM_Config_User.h) +// | | | _________hardware uart config(optional, default from SDM_Config_User.h) +// | | | | __swap hw serial pins from 3/1 to 13/15(optional, default from SDM_Config_User.h) // | | | | | SDM sdm(Serial, 9600, NOT_A_PIN, SERIAL_8N1, false); + + +// for ESP32 +// ______________________________________hardware serial reference +// | ________________________________baudrate(optional, default from SDM_Config_User.h) +// | | _____________________dere pin for max485(optional, default from SDM_Config_User.h) +// | | | _________hardware uart config(optional, default from SDM_Config_User.h) +// | | | | _____rx pin number(optional, default from SDM_Config_User.h) +// | | | | | _tx pin number(optional, default from SDM_Config_User.h) +// | | | | | | +SDM sdm(Serial, 9600, NOT_A_PIN, SERIAL_8N1, 13, 15); + + +// for AVR +// ______________________________________hardware serial reference +// | ________________________________baudrate(optional, default from SDM_Config_User.h) +// | | _____________________dere pin for max485(optional, default from SDM_Config_User.h) +// | | | _________hardware uart config(optional, default from SDM_Config_User.h) +// | | | | +// | | | | +SDM sdm(Serial, 9600, NOT_A_PIN, SERIAL_8N1); ``` NOTE for ESP8266: when GPIO15 is used (especially for swapped hardware serial):
some converters (like mine) have built-in pullup resistors on TX/RX lines from rs232 side,
@@ -111,22 +173,22 @@ to ensure low level on GPIO15 by built-in in most ESP8266 modules pulldown resis --- ### Reading: ### -List of available registers for SDM120/220/230/630:
-https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L50 +List of available registers for SDM72/120/220/230/630:
+https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L103 ```cpp //reading voltage from SDM with slave address 0x01 (default) -// __________register name -// | -float voltage = sdm.readVal(SDM220T_VOLTAGE); +// ____register name +// | +float voltage = sdm.readVal(SDM_PHASE_1_VOLTAGE); //reading power from 1st SDM with slave address ID = 0x01 //reading power from 2nd SDM with slave address ID = 0x02 //useful with several meters on RS485 line -// __________register name -// | ____SDM device ID -// | | -float power1 = sdm.readVal(SDM220T_POWER, 0x01); -float power2 = sdm.readVal(SDM220T_POWER, 0x02); +// _______register name +// | SDM device ID +// | | +float power1 = sdm.readVal(SDM_PHASE_1_POWER, 0x01); +float power2 = sdm.readVal(SDM_PHASE_1_POWER, 0x02); ``` NOTE: if you reading multiple SDM devices on the same RS485 line,
remember to set the same transmission parameters on each device,
@@ -134,7 +196,7 @@ only ID must be different for each SDM device.
--- -### Debuging: ### +### Problems: ### Sometimes readVal return NaN value (not a number),
this means that the requested value could not be read from the sdm module for various reasons.
@@ -159,46 +221,83 @@ The most common problems are: - compilation error for hardware serial mode
https://github.com/reaper7/SDM_Energy_Meter/issues/23
https://github.com/reaper7/SDM_Energy_Meter/issues/24
+- SDM630 Modbus V2 serial stopbit problem
+ https://github.com/reaper7/SDM_Energy_Meter/issues/49
+- Subsequent inquiries for slow slaves
+ https://github.com/reaper7/SDM_Energy_Meter/issues/50
You can get last error code using function: ```cpp //get last error code -// __________optional parameter, -// | true -> read and reset error code -// | false or no parameter -> read error code -// | but not reset stored code (for future checking) -// | will be overwriten when next error occurs +// ______optional parameter, +// | true -> read and reset error code +// | false or no parameter -> read error code +// | but not reset stored code (for future checking) +// | will be overwriten when next error occurs uint16_t lasterror = sdm.getErrCode(true); //clear error code also available with: sdm.clearErrCode(); ``` Errors list returned by getErrCode:
-https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L142
+https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L86
You can also check total number of errors using function: ```cpp //get total errors counter -// _________optional parameter, -// | true -> read and reset errors counter -// | false or no parameter -> read errors counter -// | but not reset stored counter (for future checking) +// _____optional parameter, +// | true -> read and reset errors counter +// | false or no parameter -> read errors counter +// | but not reset stored counter (for future checking) uint16_t cnterrors = sdm.getErrCount(true); //clear errors counter also available with: sdm.clearErrCount(); ``` +And finally you can read the counter of correctly made readings: +```cpp +//get total success counter +// ___optional parameter, +// | true -> read and reset success counter +// | false or no parameter -> read success counter +// | but not reset stored counter (for future checking) +uint16_t cntsuccess = sdm.getSuccCount(true); + +//clear success counter also available with: +sdm.clearSuccCount(); +``` + --- ### Credits: ### +contribution to this project:
:+1: ESP SoftwareSerial library by Peter Lerup (https://github.com/plerup/espsoftwareserial)
:+1: crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino)
-:+1: new registers for SDM120 and SDM630 by bart.e (https://github.com/beireken/SDM220t)
+:+1: new registers for SDM120 and SDM630 by bart.e (https://github.com/reaper7/SDM_Energy_Meter/pull/3)
+:+1: new registers for SDM72 by jegaha (https://github.com/reaper7/SDM_Energy_Meter/pull/34)
+:+1: new registers for SDM120CT by JeroenSt (https://github.com/reaper7/SDM_Energy_Meter/pull/41)
+:+1: new registers for DDM18SD by JeroenSt (https://github.com/reaper7/SDM_Energy_Meter/pull/44)
+:+1: additional SDM630 registers and influxdb example by AndersV209 (https://github.com/reaper7/SDM_Energy_Meter/pull/45)
+:+1: new registers for SDM72DM V2 by datjan (https://github.com/reaper7/SDM_Energy_Meter/pull/62)
+:+1: compatibility with EspSoftwareSerial >= 8.0.1 by maxpautsch (https://github.com/reaper7/SDM_Energy_Meter/pull/75)
+ +other projects based on or using this library
+:point_right: BZ40i Energy Meter by adlerweb (https://github.com/adlerweb/BZ40i_Energy_Meter)
+:point_right: DDS238 Energy Meter by E-NINA (https://github.com/E-NINA/dds238_Energy_Meter)
+:point_right: ESPEasy by TD-er (https://github.com/TD-er/ESPEasy)
+:point_right: Sonoff-Tasmota by arendst (https://github.com/arendst/Sonoff-Tasmota)
--- -**2016-2018 Reaper7** +library version for old esp software serial (6.0.0 - 7.0.1) is available at [old_esp_swserial_600_701 branch](https://github.com/reaper7/SDM_Energy_Meter/tree/old_esp_swserial_600_701)
+library version for old esp software serial (5.2.0 - 5.4.0) is available at [old_esp_swserial_520_540 branch](https://github.com/reaper7/SDM_Energy_Meter/tree/old_esp_swserial_520_540)
+library version for old esp software serial (< 5.2.0) is available at [old_esp_swserial_lib branch](https://github.com/reaper7/SDM_Energy_Meter/tree/old_esp_swserial_lib)
+old template library version is available at [old_template branch](https://github.com/reaper7/SDM_Energy_Meter/tree/old_template)
+ +--- + +**2016-2023 Reaper7** [paypal.me/reaper7md](https://www.paypal.me/reaper7md) diff --git a/lib/SDM_Energy_Meter/SDM.cpp b/lib/SDM_Energy_Meter/SDM.cpp index 25d04cd8b..0336427d1 100644 --- a/lib/SDM_Energy_Meter/SDM.cpp +++ b/lib/SDM_Energy_Meter/SDM.cpp @@ -1,46 +1,79 @@ -/* Library for reading SDM 120/220/230/630 Modbus Energy meters. +/* Library for reading SDM 72/120/220/230/630 Modbus Energy meters. * Reading via Hardware or Software Serial library & rs232<->rs485 converter -* 2016-2018 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.9.0-beta & 2.4.1 esp8266 core) -* crc calculation by Jaime Garc�a (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/) +* 2016-2023 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.8.10 & 2.5.2 esp8266 core) +* crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/) */ //------------------------------------------------------------------------------ #include "SDM.h" //------------------------------------------------------------------------------ -#ifdef USE_HARDWARESERIAL +#if defined ( USE_HARDWARESERIAL ) +#if defined ( ESP8266 ) SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config, bool swapuart) : sdmSer(serial) { this->_baud = baud; - this->_config = config; this->_dere_pin = dere_pin; + this->_config = config; this->_swapuart = swapuart; } +#elif defined ( ESP32 ) +SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config, int8_t rx_pin, int8_t tx_pin) : sdmSer(serial) { + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_config = config; + this->_rx_pin = rx_pin; + this->_tx_pin = tx_pin; +} +#else +SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config) : sdmSer(serial) { + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_config = config; +} +#endif +#else +#if defined ( ESP8266 ) || defined ( ESP32 ) +SDM::SDM(ESPeasySerial& serial, long baud, int dere_pin, int config, int8_t rx_pin, int8_t tx_pin) : sdmSer(serial) { + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_config = config; + this->_rx_pin = rx_pin; + this->_tx_pin = tx_pin; +} #else SDM::SDM(ESPeasySerial& serial, long baud, int dere_pin) : sdmSer(serial) { this->_baud = baud; this->_dere_pin = dere_pin; } #endif +#endif SDM::~SDM() { } void SDM::begin(void) { -#ifdef USE_HARDWARESERIAL - #ifdef ESP8266 - sdmSer.begin(_baud, (SerialConfig)_config); - #else - sdmSer.begin(_baud, _config); - #endif +#if defined ( USE_HARDWARESERIAL ) +#if defined ( ESP8266 ) + sdmSer.begin(_baud, (SerialConfig)_config); +#elif defined ( ESP32 ) + sdmSer.begin(_baud, _config, _rx_pin, _tx_pin); +#else + sdmSer.begin(_baud, _config); +#endif +#else +#if defined ( ESP8266 ) || defined ( ESP32 ) + sdmSer.begin(_baud, (EspSoftwareSerial::Config)_config, _rx_pin, _tx_pin); #else sdmSer.begin(_baud); #endif -#ifdef USE_HARDWARESERIAL - #ifdef ESP8266 - if (_swapuart) - sdmSer.swap(); - #endif #endif - if (_dere_pin != NOT_A_PIN) //set output pin mode for DE/RE pin when used (for control MAX485) - pinMode(_dere_pin, OUTPUT); + +#if defined ( USE_HARDWARESERIAL ) && defined ( ESP8266 ) + if (_swapuart) + sdmSer.swap(); +#endif + if (_dere_pin != NOT_A_PIN) { + pinMode(_dere_pin, OUTPUT); //set output pin mode for DE/RE pin when used (for control MAX485) + } + dereSet(LOW); //set init state to receive from SDM -> DE Disable, /RE Enable (for control MAX485) } float SDM::readVal(uint16_t reg, uint8_t node) { @@ -58,16 +91,13 @@ float SDM::readVal(uint16_t reg, uint8_t node) { sdmarr[6] = lowByte(temp); sdmarr[7] = highByte(temp); -#ifndef USE_HARDWARESERIAL +#if !defined ( USE_HARDWARESERIAL ) sdmSer.listen(); //enable softserial rx interrupt #endif - while (sdmSer.available() > 0) { //read serial if any old data is available - sdmSer.read(); - } + flush(); //read serial if any old data is available - if (_dere_pin != NOT_A_PIN) //transmit to SDM -> DE Enable, /RE Disable (for control MAX485) - digitalWrite(_dere_pin, HIGH); + dereSet(HIGH); //transmit to SDM -> DE Enable, /RE Disable (for control MAX485) delay(2); //fix for issue (nan reading) by sjfaustino: https://github.com/reaper7/SDM_Energy_Meter/issues/7#issuecomment-272111524 @@ -75,13 +105,12 @@ float SDM::readVal(uint16_t reg, uint8_t node) { sdmSer.flush(); //clear out tx buffer - if (_dere_pin != NOT_A_PIN) //receive from SDM -> DE Disable, /RE Enable (for control MAX485) - digitalWrite(_dere_pin, LOW); + dereSet(LOW); //receive from SDM -> DE Disable, /RE Enable (for control MAX485) - resptime = millis() + MAX_MILLIS_TO_WAIT; + resptime = millis(); while (sdmSer.available() < FRAMESIZE) { - if (resptime < millis()) { + if (millis() - resptime > msturnaround) { readErr = SDM_ERR_TIMEOUT; //err debug (4) break; } @@ -90,7 +119,7 @@ float SDM::readVal(uint16_t reg, uint8_t node) { if (readErr == SDM_ERR_NO_ERROR) { //if no timeout... - if(sdmSer.available() >= FRAMESIZE) { + if (sdmSer.available() >= FRAMESIZE) { for(int n=0; n 0) { //read redundant serial bytes, if any - sdmSer.read(); - } - -#ifndef USE_HARDWARESERIAL - sdmSer.end(); //disable softserial rx interrupt +#if !defined ( USE_HARDWARESERIAL ) + sdmSer.stopListening(); //disable softserial rx interrupt #endif return (res); @@ -142,15 +172,15 @@ uint16_t SDM::getErrCode(bool _clear) { return (_tmp); } -uint16_t SDM::getErrCount(bool _clear) { - uint16_t _tmp = readingerrcount; +uint32_t SDM::getErrCount(bool _clear) { + uint32_t _tmp = readingerrcount; if (_clear == true) clearErrCount(); return (_tmp); } -uint16_t SDM::getSuccCount(bool _clear) { - uint16_t _tmp = readingsuccesscount; +uint32_t SDM::getSuccCount(bool _clear) { + uint32_t _tmp = readingsuccesscount; if (_clear == true) clearSuccCount(); return (_tmp); @@ -168,11 +198,37 @@ void SDM::clearSuccCount() { readingsuccesscount = 0; } -uint16_t SDM::calculateCRC(uint8_t *array, uint8_t num) { +void SDM::setMsTurnaround(uint16_t _msturnaround) { + if (_msturnaround < SDM_MIN_DELAY) + msturnaround = SDM_MIN_DELAY; + else if (_msturnaround > SDM_MAX_DELAY) + msturnaround = SDM_MAX_DELAY; + else + msturnaround = _msturnaround; +} + +void SDM::setMsTimeout(uint16_t _mstimeout) { + if (_mstimeout < SDM_MIN_DELAY) + mstimeout = SDM_MIN_DELAY; + else if (_mstimeout > SDM_MAX_DELAY) + mstimeout = SDM_MAX_DELAY; + else + mstimeout = _mstimeout; +} + +uint16_t SDM::getMsTurnaround() { + return (msturnaround); +} + +uint16_t SDM::getMsTimeout() { + return (mstimeout); +} + +uint16_t SDM::calculateCRC(uint8_t *array, uint8_t len) { uint16_t _crc, _flag; _crc = 0xFFFF; - for (uint8_t i = 0; i < num; i++) { - _crc = _crc ^ array[i]; + for (uint8_t i = 0; i < len; i++) { + _crc ^= (uint16_t)array[i]; for (uint8_t j = 8; j; j--) { _flag = _crc & 0x0001; _crc >>= 1; @@ -182,3 +238,17 @@ uint16_t SDM::calculateCRC(uint8_t *array, uint8_t num) { } return _crc; } + +void SDM::flush(unsigned long _flushtime) { + unsigned long flushstart = millis(); + while (sdmSer.available() || (millis() - flushstart < _flushtime)) { + if (sdmSer.available()) //read serial if any old data is available + sdmSer.read(); + delay(1); + } +} + +void SDM::dereSet(bool _state) { + if (_dere_pin != NOT_A_PIN) + digitalWrite(_dere_pin, _state); //receive from SDM -> DE Disable, /RE Enable (for control MAX485) +} diff --git a/lib/SDM_Energy_Meter/SDM.h b/lib/SDM_Energy_Meter/SDM.h index 0253e3c44..72b78a363 100644 --- a/lib/SDM_Energy_Meter/SDM.h +++ b/lib/SDM_Energy_Meter/SDM.h @@ -1,6 +1,6 @@ -/* Library for reading SDM 120/220/230/630 Modbus Energy meters. +/* Library for reading SDM 72/120/220/230/630 Modbus Energy meters. * Reading via Hardware or Software Serial library & rs232<->rs485 converter -* 2016-2018 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.9.0-beta & 2.4.1 esp8266 core) +* 2016-2023 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.8.10 & 2.5.2 esp8266 core) * crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/) */ //------------------------------------------------------------------------------ @@ -9,38 +9,78 @@ //------------------------------------------------------------------------------ #include #include -#ifdef USE_HARDWARESERIAL +#if defined ( USE_HARDWARESERIAL ) #include #else #include -// #include #endif //------------------------------------------------------------------------------ //DEFAULT CONFIG (DO NOT CHANGE ANYTHING!!! for changes use SDM_Config_User.h): //------------------------------------------------------------------------------ -#ifndef SDM_UART_BAUD - #define SDM_UART_BAUD 4800 //default baudrate +#if !defined ( SDM_UART_BAUD ) + #define SDM_UART_BAUD 4800 // default baudrate #endif -#ifndef DERE_PIN - #define DERE_PIN NOT_A_PIN //default digital pin for control MAX485 DE/RE lines (connect DE & /RE together to this pin) +#if !defined ( DERE_PIN ) + #define DERE_PIN NOT_A_PIN // default digital pin for control MAX485 DE/RE lines (connect DE & /RE together to this pin) #endif -#ifdef USE_HARDWARESERIAL +#if defined ( USE_HARDWARESERIAL ) - #ifndef SDM_UART_CONFIG - #define SDM_UART_CONFIG SERIAL_8N1 //default hardware uart config + #if !defined ( SDM_UART_CONFIG ) + #define SDM_UART_CONFIG SERIAL_8N1 // default hardware uart config #endif - #ifndef SWAPHWSERIAL - #define SWAPHWSERIAL 0 //(only esp8266) when hwserial used, then swap uart pins from 3/1 to 13/15 (default not swap) + #if defined ( ESP8266 ) && !defined ( SWAPHWSERIAL ) + #define SWAPHWSERIAL 0 // (only esp8266) when hwserial used, then swap uart pins from 3/1 to 13/15 (default not swap) + #endif + + #if defined ( ESP32 ) + #if !defined ( SDM_RX_PIN ) + #define SDM_RX_PIN -1 // use default rx pin for selected port + #endif + #if !defined ( SDM_TX_PIN ) + #define SDM_TX_PIN -1 // use default tx pin for selected port + #endif + #endif + +#else + + #if defined ( ESP8266 ) || defined ( ESP32 ) + #if !defined ( SDM_UART_CONFIG ) + #define SDM_UART_CONFIG SWSERIAL_8N1 // default softwareware uart config for esp8266/esp32 + #endif + #endif + +// #if !defined ( SDM_RX_PIN ) || !defined ( SDM_TX_PIN ) +// #error "SDM_RX_PIN and SDM_TX_PIN must be defined in SDM_Config_User.h for Software Serial option)" +// #endif + + #if !defined ( SDM_RX_PIN ) + #define SDM_RX_PIN -1 + #endif + #if !defined ( SDM_TX_PIN ) + #define SDM_TX_PIN -1 #endif #endif -#ifndef MAX_MILLIS_TO_WAIT - #define MAX_MILLIS_TO_WAIT 500 //default max time to wait for response from SDM. Try to get as low as possible with higest possible Baud Rate to decrease loop time. +#if !defined ( WAITING_TURNAROUND_DELAY ) + #define WAITING_TURNAROUND_DELAY 200 // time in ms to wait for process current request #endif + +#if !defined ( RESPONSE_TIMEOUT ) + #define RESPONSE_TIMEOUT 500 // time in ms to wait for return response from all devices before next request +#endif + +#if !defined ( SDM_MIN_DELAY ) + #define SDM_MIN_DELAY 20 // minimum value (in ms) for WAITING_TURNAROUND_DELAY and RESPONSE_TIMEOUT +#endif + +#if !defined ( SDM_MAX_DELAY ) + #define SDM_MAX_DELAY 5000 // maximum value (in ms) for WAITING_TURNAROUND_DELAY and RESPONSE_TIMEOUT +#endif + //------------------------------------------------------------------------------ #define SDM_ERR_NO_ERROR 0 // no error @@ -60,108 +100,109 @@ #define SDM_B_06 0x02 // BYTE 6 // BYTES 3 & 4 (BELOW) -//----------------------------------------------------------------------------------------------------------------------------------------------------------- -// REGISTERS LIST FOR SDM DEVICES | -//----------------------------------------------------------------------------------------------------------------------------------------------------------- -// REGISTER NAME REGISTER ADDRESS UNIT | SDM630 | SDM230 | SDM220 | SDM120CT| SDM120 | SDM72D | -//----------------------------------------------------------------------------------------------------------------------------------------------------------- -#define SDM_PHASE_1_VOLTAGE 0x0000 // V | 1 | 1 | 1 | 1 | 1 | | -#define SDM_PHASE_2_VOLTAGE 0x0002 // V | 1 | | | | | | -#define SDM_PHASE_3_VOLTAGE 0x0004 // V | 1 | | | | | | -#define SDM_PHASE_1_CURRENT 0x0006 // A | 1 | 1 | 1 | 1 | 1 | | -#define SDM_PHASE_2_CURRENT 0x0008 // A | 1 | | | | | | -#define SDM_PHASE_3_CURRENT 0x000A // A | 1 | | | | | | -#define SDM_PHASE_1_POWER 0x000C // W | 1 | 1 | 1 | 1 | 1 | | -#define SDM_PHASE_2_POWER 0x000E // W | 1 | | | | | | -#define SDM_PHASE_3_POWER 0x0010 // W | 1 | | | | | | -#define SDM_PHASE_1_APPARENT_POWER 0x0012 // VA | 1 | 1 | 1 | 1 | 1 | | -#define SDM_PHASE_2_APPARENT_POWER 0x0014 // VA | 1 | | | | | | -#define SDM_PHASE_3_APPARENT_POWER 0x0016 // VA | 1 | | | | | | -#define SDM_PHASE_1_REACTIVE_POWER 0x0018 // VAr | 1 | 1 | 1 | 1 | 1 | | -#define SDM_PHASE_2_REACTIVE_POWER 0x001A // VAr | 1 | | | | | | -#define SDM_PHASE_3_REACTIVE_POWER 0x001C // VAr | 1 | | | | | | -#define SDM_PHASE_1_POWER_FACTOR 0x001E // | 1 | 1 | 1 | 1 | 1 | | -#define SDM_PHASE_2_POWER_FACTOR 0x0020 // | 1 | | | | | | -#define SDM_PHASE_3_POWER_FACTOR 0x0022 // | 1 | | | | | | -#define SDM_PHASE_1_ANGLE 0x0024 // Degrees | 1 | 1 | 1 | 1 | | | -#define SDM_PHASE_2_ANGLE 0x0026 // Degrees | 1 | | | | | | -#define SDM_PHASE_3_ANGLE 0x0028 // Degrees | 1 | | | | | | -#define SDM_AVERAGE_L_TO_N_VOLTS 0x002A // V | 1 | | | | | | -#define SDM_AVERAGE_LINE_CURRENT 0x002E // A | 1 | | | | | | -#define SDM_SUM_LINE_CURRENT 0x0030 // A | 1 | | | | | | -#define SDM_TOTAL_SYSTEM_POWER 0x0034 // W | 1 | | | | | 1 | -#define SDM_TOTAL_SYSTEM_APPARENT_POWER 0x0038 // VA | 1 | | | | | | -#define SDM_TOTAL_SYSTEM_REACTIVE_POWER 0x003C // VAr | 1 | | | | | | -#define SDM_TOTAL_SYSTEM_POWER_FACTOR 0x003E // | 1 | | | | | | -#define SDM_TOTAL_SYSTEM_PHASE_ANGLE 0x0042 // Degrees | 1 | | | | | | -#define SDM_FREQUENCY 0x0046 // Hz | 1 | 1 | 1 | 1 | 1 | | -#define SDM_IMPORT_ACTIVE_ENERGY 0x0048 // kWh/MWh | 1 | 1 | 1 | 1 | 1 | 1 | -#define SDM_EXPORT_ACTIVE_ENERGY 0x004A // kWh/MWh | 1 | 1 | 1 | 1 | 1 | 1 | -#define SDM_IMPORT_REACTIVE_ENERGY 0x004C // kVArh/MVArh | 1 | 1 | 1 | 1 | 1 | | -#define SDM_EXPORT_REACTIVE_ENERGY 0x004E // kVArh/MVArh | 1 | 1 | 1 | 1 | 1 | | -#define SDM_VAH_SINCE_LAST_RESET 0x0050 // kVAh/MVAh | 1 | | | | | | -#define SDM_AH_SINCE_LAST_RESET 0x0052 // Ah/kAh | 1 | | | | | | -#define SDM_TOTAL_SYSTEM_POWER_DEMAND 0x0054 // W | 1 | 1 | | | | | -#define SDM_MAXIMUM_TOTAL_SYSTEM_POWER_DEMAND 0x0056 // W | 1 | 1 | | | | | -#define SDM_CURRENT_SYSTEM_POSITIVE_POWER_DEMAND 0x0058 // W | | 1 | | | | | -#define SDM_MAXIMUM_SYSTEM_POSITIVE_POWER_DEMAND 0x005A // W | | 1 | | | | | -#define SDM_CURRENT_SYSTEM_REVERSE_POWER_DEMAND 0x005C // W | | 1 | | | | | -#define SDM_MAXIMUM_SYSTEM_REVERSE_POWER_DEMAND 0x005E // W | | 1 | | | | | -#define SDM_TOTAL_SYSTEM_VA_DEMAND 0x0064 // VA | 1 | | | | | | -#define SDM_MAXIMUM_TOTAL_SYSTEM_VA_DEMAND 0x0066 // VA | 1 | | | | | | -#define SDM_NEUTRAL_CURRENT_DEMAND 0x0068 // A | 1 | | | | | | -#define SDM_MAXIMUM_NEUTRAL_CURRENT 0x006A // A | 1 | | | | | | -#define SDM_LINE_1_TO_LINE_2_VOLTS 0x00C8 // V | 1 | | | | | | -#define SDM_LINE_2_TO_LINE_3_VOLTS 0x00CA // V | 1 | | | | | | -#define SDM_LINE_3_TO_LINE_1_VOLTS 0x00CC // V | 1 | | | | | | -#define SDM_AVERAGE_LINE_TO_LINE_VOLTS 0x00CE // V | 1 | | | | | | -#define SDM_NEUTRAL_CURRENT 0x00E0 // A | 1 | | | | | | -#define SDM_PHASE_1_LN_VOLTS_THD 0x00EA // % | 1 | | | | | | -#define SDM_PHASE_2_LN_VOLTS_THD 0x00EC // % | 1 | | | | | | -#define SDM_PHASE_3_LN_VOLTS_THD 0x00EE // % | 1 | | | | | | -#define SDM_PHASE_1_CURRENT_THD 0x00F0 // % | 1 | | | | | | -#define SDM_PHASE_2_CURRENT_THD 0x00F2 // % | 1 | | | | | | -#define SDM_PHASE_3_CURRENT_THD 0x00F4 // % | 1 | | | | | | -#define SDM_AVERAGE_LINE_TO_NEUTRAL_VOLTS_THD 0x00F8 // % | 1 | | | | | | -#define SDM_AVERAGE_LINE_CURRENT_THD 0x00FA // % | 1 | | | | | | -#define SDM_TOTAL_SYSTEM_POWER_FACTOR_INV 0x00FE // | 1 | | | | | | -#define SDM_PHASE_1_CURRENT_DEMAND 0x0102 // A | 1 | 1 | | | | | -#define SDM_PHASE_2_CURRENT_DEMAND 0x0104 // A | 1 | | | | | | -#define SDM_PHASE_3_CURRENT_DEMAND 0x0106 // A | 1 | | | | | | -#define SDM_MAXIMUM_PHASE_1_CURRENT_DEMAND 0x0108 // A | 1 | 1 | | | | | -#define SDM_MAXIMUM_PHASE_2_CURRENT_DEMAND 0x010A // A | 1 | | | | | | -#define SDM_MAXIMUM_PHASE_3_CURRENT_DEMAND 0x010C // A | 1 | | | | | | -#define SDM_LINE_1_TO_LINE_2_VOLTS_THD 0x014E // % | 1 | | | | | | -#define SDM_LINE_2_TO_LINE_3_VOLTS_THD 0x0150 // % | 1 | | | | | | -#define SDM_LINE_3_TO_LINE_1_VOLTS_THD 0x0152 // % | 1 | | | | | | -#define SDM_AVERAGE_LINE_TO_LINE_VOLTS_THD 0x0154 // % | 1 | | | | | | -#define SDM_TOTAL_ACTIVE_ENERGY 0x0156 // kWh | 1 | 1 | 1 | 1 | 1 | 1 | -#define SDM_TOTAL_REACTIVE_ENERGY 0x0158 // kVArh | 1 | 1 | 1 | 1 | 1 | | -#define SDM_L1_IMPORT_ACTIVE_ENERGY 0x015A // kWh | 1 | | | | | | -#define SDM_L2_IMPORT_ACTIVE_ENERGY 0x015C // kWh | 1 | | | | | | -#define SDM_L3_IMPORT_ACTIVE_ENERGY 0x015E // kWh | 1 | | | | | | -#define SDM_L1_EXPORT_ACTIVE_ENERGY 0x0160 // kWh | 1 | | | | | | -#define SDM_L2_EXPORT_ACTIVE_ENERGY 0x0162 // kWh | 1 | | | | | | -#define SDM_L3_EXPORT_ACTIVE_ENERGY 0x0164 // kWh | 1 | | | | | | -#define SDM_L1_TOTAL_ACTIVE_ENERGY 0x0166 // kWh | 1 | | | | | | -#define SDM_L2_TOTAL_ACTIVE_ENERGY 0x0168 // kWh | 1 | | | | | | -#define SDM_L3_TOTAL_ACTIVE_ENERGY 0x016a // kWh | 1 | | | | | | -#define SDM_L1_IMPORT_REACTIVE_ENERGY 0x016C // kVArh | 1 | | | | | | -#define SDM_L2_IMPORT_REACTIVE_ENERGY 0x016E // kVArh | 1 | | | | | | -#define SDM_L3_IMPORT_REACTIVE_ENERGY 0x0170 // kVArh | 1 | | | | | | -#define SDM_L1_EXPORT_REACTIVE_ENERGY 0x0172 // kVArh | 1 | | | | | | -#define SDM_L2_EXPORT_REACTIVE_ENERGY 0x0174 // kVArh | 1 | | | | | | -#define SDM_L3_EXPORT_REACTIVE_ENERGY 0x0176 // kVArh | 1 | | | | | | -#define SDM_L1_TOTAL_REACTIVE_ENERGY 0x0178 // kVArh | 1 | | | | | | -#define SDM_L2_TOTAL_REACTIVE_ENERGY 0x017A // kVArh | 1 | | | | | | -#define SDM_L3_TOTAL_REACTIVE_ENERGY 0x017C // kVArh | 1 | | | | | | -#define SDM_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY 0x0180 // kWh | | 1 | | | | 1 | -#define SDM_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY 0x0182 // kVArh | | 1 | | | | | -#define SDM_CURRENT_RESETTABLE_IMPORT_ENERGY 0x0184 // kWh | | | | | | 1 | -#define SDM_CURRENT_RESETTABLE_EXPORT_ENERGY 0x0186 // kWh | | | | | | 1 | -#define SDM_IMPORT_POWER 0x0500 // W | | | | | | 1 | -#define SDM_EXPORT_POWER 0x0502 // W | | | | | | 1 | -//----------------------------------------------------------------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// REGISTERS LIST FOR SDM DEVICES | +//--------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// REGISTER NAME REGISTER ADDRESS UNIT | SDM630 | SDM230 | SDM220 | SDM120CT| SDM120 | SDM72D | SDM72 V2| +//--------------------------------------------------------------------------------------------------------------------------------------------------------------------- +#define SDM_PHASE_1_VOLTAGE 0x0000 // V | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_PHASE_2_VOLTAGE 0x0002 // V | 1 | | | | | | 1 | +#define SDM_PHASE_3_VOLTAGE 0x0004 // V | 1 | | | | | | 1 | +#define SDM_PHASE_1_CURRENT 0x0006 // A | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_PHASE_2_CURRENT 0x0008 // A | 1 | | | | | | 1 | +#define SDM_PHASE_3_CURRENT 0x000A // A | 1 | | | | | | 1 | +#define SDM_PHASE_1_POWER 0x000C // W | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_PHASE_2_POWER 0x000E // W | 1 | | | | | | 1 | +#define SDM_PHASE_3_POWER 0x0010 // W | 1 | | | | | | 1 | +#define SDM_PHASE_1_APPARENT_POWER 0x0012 // VA | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_PHASE_2_APPARENT_POWER 0x0014 // VA | 1 | | | | | | 1 | +#define SDM_PHASE_3_APPARENT_POWER 0x0016 // VA | 1 | | | | | | 1 | +#define SDM_PHASE_1_REACTIVE_POWER 0x0018 // VAr | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_PHASE_2_REACTIVE_POWER 0x001A // VAr | 1 | | | | | | 1 | +#define SDM_PHASE_3_REACTIVE_POWER 0x001C // VAr | 1 | | | | | | 1 | +#define SDM_PHASE_1_POWER_FACTOR 0x001E // | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_PHASE_2_POWER_FACTOR 0x0020 // | 1 | | | | | | 1 | +#define SDM_PHASE_3_POWER_FACTOR 0x0022 // | 1 | | | | | | 1 | +#define SDM_PHASE_1_ANGLE 0x0024 // Degrees | 1 | 1 | 1 | 1 | | | | +#define SDM_PHASE_2_ANGLE 0x0026 // Degrees | 1 | | | | | | | +#define SDM_PHASE_3_ANGLE 0x0028 // Degrees | 1 | | | | | | | +#define SDM_AVERAGE_L_TO_N_VOLTS 0x002A // V | 1 | | | | | | 1 | +#define SDM_AVERAGE_LINE_CURRENT 0x002E // A | 1 | | | | | | 1 | +#define SDM_SUM_LINE_CURRENT 0x0030 // A | 1 | | | | | | 1 | +#define SDM_TOTAL_SYSTEM_POWER 0x0034 // W | 1 | | | | | 1 | 1 | +#define SDM_TOTAL_SYSTEM_APPARENT_POWER 0x0038 // VA | 1 | | | | | | 1 | +#define SDM_TOTAL_SYSTEM_REACTIVE_POWER 0x003C // VAr | 1 | | | | | | 1 | +#define SDM_TOTAL_SYSTEM_POWER_FACTOR 0x003E // | 1 | | | | | | 1 | +#define SDM_TOTAL_SYSTEM_PHASE_ANGLE 0x0042 // Degrees | 1 | | | | | | | +#define SDM_FREQUENCY 0x0046 // Hz | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_IMPORT_ACTIVE_ENERGY 0x0048 // kWh/MWh | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +#define SDM_EXPORT_ACTIVE_ENERGY 0x004A // kWh/MWh | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +#define SDM_IMPORT_REACTIVE_ENERGY 0x004C // kVArh/MVArh | 1 | 1 | 1 | 1 | 1 | | | +#define SDM_EXPORT_REACTIVE_ENERGY 0x004E // kVArh/MVArh | 1 | 1 | 1 | 1 | 1 | | | +#define SDM_VAH_SINCE_LAST_RESET 0x0050 // kVAh/MVAh | 1 | | | | | | | +#define SDM_AH_SINCE_LAST_RESET 0x0052 // Ah/kAh | 1 | | | | | | | +#define SDM_TOTAL_SYSTEM_POWER_DEMAND 0x0054 // W | 1 | 1 | | | | | | +#define SDM_MAXIMUM_TOTAL_SYSTEM_POWER_DEMAND 0x0056 // W | 1 | 1 | | | | | | +#define SDM_CURRENT_SYSTEM_POSITIVE_POWER_DEMAND 0x0058 // W | | 1 | | | | | | +#define SDM_MAXIMUM_SYSTEM_POSITIVE_POWER_DEMAND 0x005A // W | | 1 | | | | | | +#define SDM_CURRENT_SYSTEM_REVERSE_POWER_DEMAND 0x005C // W | | 1 | | | | | | +#define SDM_MAXIMUM_SYSTEM_REVERSE_POWER_DEMAND 0x005E // W | | 1 | | | | | | +#define SDM_TOTAL_SYSTEM_VA_DEMAND 0x0064 // VA | 1 | | | | | | | +#define SDM_MAXIMUM_TOTAL_SYSTEM_VA_DEMAND 0x0066 // VA | 1 | | | | | | | +#define SDM_NEUTRAL_CURRENT_DEMAND 0x0068 // A | 1 | | | | | | | +#define SDM_MAXIMUM_NEUTRAL_CURRENT 0x006A // A | 1 | | | | | | | +#define SDM_LINE_1_TO_LINE_2_VOLTS 0x00C8 // V | 1 | | | | | | 1 | +#define SDM_LINE_2_TO_LINE_3_VOLTS 0x00CA // V | 1 | | | | | | 1 | +#define SDM_LINE_3_TO_LINE_1_VOLTS 0x00CC // V | 1 | | | | | | 1 | +#define SDM_AVERAGE_LINE_TO_LINE_VOLTS 0x00CE // V | 1 | | | | | | 1 | +#define SDM_NEUTRAL_CURRENT 0x00E0 // A | 1 | | | | | | 1 | +#define SDM_PHASE_1_LN_VOLTS_THD 0x00EA // % | 1 | | | | | | | +#define SDM_PHASE_2_LN_VOLTS_THD 0x00EC // % | 1 | | | | | | | +#define SDM_PHASE_3_LN_VOLTS_THD 0x00EE // % | 1 | | | | | | | +#define SDM_PHASE_1_CURRENT_THD 0x00F0 // % | 1 | | | | | | | +#define SDM_PHASE_2_CURRENT_THD 0x00F2 // % | 1 | | | | | | | +#define SDM_PHASE_3_CURRENT_THD 0x00F4 // % | 1 | | | | | | | +#define SDM_AVERAGE_LINE_TO_NEUTRAL_VOLTS_THD 0x00F8 // % | 1 | | | | | | | +#define SDM_AVERAGE_LINE_CURRENT_THD 0x00FA // % | 1 | | | | | | | +#define SDM_TOTAL_SYSTEM_POWER_FACTOR_INV 0x00FE // | 1 | | | | | | | +#define SDM_PHASE_1_CURRENT_DEMAND 0x0102 // A | 1 | 1 | | | | | | +#define SDM_PHASE_2_CURRENT_DEMAND 0x0104 // A | 1 | | | | | | | +#define SDM_PHASE_3_CURRENT_DEMAND 0x0106 // A | 1 | | | | | | | +#define SDM_MAXIMUM_PHASE_1_CURRENT_DEMAND 0x0108 // A | 1 | 1 | | | | | | +#define SDM_MAXIMUM_PHASE_2_CURRENT_DEMAND 0x010A // A | 1 | | | | | | | +#define SDM_MAXIMUM_PHASE_3_CURRENT_DEMAND 0x010C // A | 1 | | | | | | | +#define SDM_LINE_1_TO_LINE_2_VOLTS_THD 0x014E // % | 1 | | | | | | | +#define SDM_LINE_2_TO_LINE_3_VOLTS_THD 0x0150 // % | 1 | | | | | | | +#define SDM_LINE_3_TO_LINE_1_VOLTS_THD 0x0152 // % | 1 | | | | | | | +#define SDM_AVERAGE_LINE_TO_LINE_VOLTS_THD 0x0154 // % | 1 | | | | | | | +#define SDM_TOTAL_ACTIVE_ENERGY 0x0156 // kWh | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +#define SDM_TOTAL_REACTIVE_ENERGY 0x0158 // kVArh | 1 | 1 | 1 | 1 | 1 | | 1 | +#define SDM_L1_IMPORT_ACTIVE_ENERGY 0x015A // kWh | 1 | | | | | | | +#define SDM_L2_IMPORT_ACTIVE_ENERGY 0x015C // kWh | 1 | | | | | | | +#define SDM_L3_IMPORT_ACTIVE_ENERGY 0x015E // kWh | 1 | | | | | | | +#define SDM_L1_EXPORT_ACTIVE_ENERGY 0x0160 // kWh | 1 | | | | | | | +#define SDM_L2_EXPORT_ACTIVE_ENERGY 0x0162 // kWh | 1 | | | | | | | +#define SDM_L3_EXPORT_ACTIVE_ENERGY 0x0164 // kWh | 1 | | | | | | | +#define SDM_L1_TOTAL_ACTIVE_ENERGY 0x0166 // kWh | 1 | | | | | | | +#define SDM_L2_TOTAL_ACTIVE_ENERGY 0x0168 // kWh | 1 | | | | | | | +#define SDM_L3_TOTAL_ACTIVE_ENERGY 0x016a // kWh | 1 | | | | | | | +#define SDM_L1_IMPORT_REACTIVE_ENERGY 0x016C // kVArh | 1 | | | | | | | +#define SDM_L2_IMPORT_REACTIVE_ENERGY 0x016E // kVArh | 1 | | | | | | | +#define SDM_L3_IMPORT_REACTIVE_ENERGY 0x0170 // kVArh | 1 | | | | | | | +#define SDM_L1_EXPORT_REACTIVE_ENERGY 0x0172 // kVArh | 1 | | | | | | | +#define SDM_L2_EXPORT_REACTIVE_ENERGY 0x0174 // kVArh | 1 | | | | | | | +#define SDM_L3_EXPORT_REACTIVE_ENERGY 0x0176 // kVArh | 1 | | | | | | | +#define SDM_L1_TOTAL_REACTIVE_ENERGY 0x0178 // kVArh | 1 | | | | | | | +#define SDM_L2_TOTAL_REACTIVE_ENERGY 0x017A // kVArh | 1 | | | | | | | +#define SDM_L3_TOTAL_REACTIVE_ENERGY 0x017C // kVArh | 1 | | | | | | | +#define SDM_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY 0x0180 // kWh | | 1 | | | | 1 | 1 | +#define SDM_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY 0x0182 // kVArh | | 1 | | | | | | +#define SDM_CURRENT_RESETTABLE_IMPORT_ENERGY 0x0184 // kWh | | | | | | 1 | 1 | +#define SDM_CURRENT_RESETTABLE_EXPORT_ENERGY 0x0186 // kWh | | | | | | 1 | 1 | +#define SDM_NET_KWH 0x018C // kWh | | | | | | | 1 | +#define SDM_IMPORT_POWER 0x0500 // W | | | | | | 1 | 1 | +#define SDM_EXPORT_POWER 0x0502 // W | | | | | | 1 | 1 | +//--------------------------------------------------------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------- // REGISTERS LIST FOR DDM DEVICE | @@ -189,40 +230,70 @@ //--------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------------------------------------------- + class SDM { public: -#ifdef USE_HARDWARESERIAL +#if defined ( USE_HARDWARESERIAL ) // hardware serial + #if defined ( ESP8266 ) // on esp8266 SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG, bool swapuart = SWAPHWSERIAL); -#else + #elif defined ( ESP32 ) // on esp32 + SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG, int8_t rx_pin = SDM_RX_PIN, int8_t tx_pin = SDM_TX_PIN); + #else // on avr + SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG); + #endif +#else // software serial + #if defined ( ESP8266 ) || defined ( ESP32 ) // on esp8266/esp32 + SDM(ESPeasySerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG, int8_t rx_pin = SDM_RX_PIN, int8_t tx_pin = SDM_TX_PIN); + #else // on avr SDM(ESPeasySerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN); + #endif #endif virtual ~SDM(); void begin(void); - float readVal(uint16_t reg, uint8_t node = SDM_B_01); //read value from register = reg and from deviceId = node - uint16_t getErrCode(bool _clear = false); //return last errorcode (optional clear this value, default false) - uint16_t getErrCount(bool _clear = false); //return total errors count (optional clear this value, default false) - uint16_t getSuccCount(bool _clear = false); //return total success count (optional clear this value, default false) - void clearErrCode(); //clear last errorcode - void clearErrCount(); //clear total errors count - void clearSuccCount(); //clear total success count + float readVal(uint16_t reg, uint8_t node = SDM_B_01); // read value from register = reg and from deviceId = node + uint16_t getErrCode(bool _clear = false); // return last errorcode (optional clear this value, default flase) + uint32_t getErrCount(bool _clear = false); // return total errors count (optional clear this value, default flase) + uint32_t getSuccCount(bool _clear = false); // return total success count (optional clear this value, default false) + void clearErrCode(); // clear last errorcode + void clearErrCount(); // clear total errors count + void clearSuccCount(); // clear total success count + void setMsTurnaround(uint16_t _msturnaround = WAITING_TURNAROUND_DELAY); // set new value for WAITING_TURNAROUND_DELAY (ms), min=SDM_MIN_DELAY, max=SDM_MAX_DELAY + void setMsTimeout(uint16_t _mstimeout = RESPONSE_TIMEOUT); // set new value for RESPONSE_TIMEOUT (ms), min=SDM_MIN_DELAY, max=SDM_MAX_DELAY + uint16_t getMsTurnaround(); // get current value of WAITING_TURNAROUND_DELAY (ms) + uint16_t getMsTimeout(); // get current value of RESPONSE_TIMEOUT (ms) private: -#ifdef USE_HARDWARESERIAL +#if defined ( USE_HARDWARESERIAL ) HardwareSerial& sdmSer; #else ESPeasySerial& sdmSer; #endif -#ifdef USE_HARDWARESERIAL +#if defined ( USE_HARDWARESERIAL ) int _config = SDM_UART_CONFIG; + #if defined ( ESP8266 ) bool _swapuart = SWAPHWSERIAL; + #elif defined ( ESP32 ) + int8_t _rx_pin = -1; + int8_t _tx_pin = -1; + #endif +#else + #if defined ( ESP8266 ) || defined ( ESP32 ) + int _config = SDM_UART_CONFIG; + #endif + int8_t _rx_pin = -1; + int8_t _tx_pin = -1; #endif long _baud = SDM_UART_BAUD; int _dere_pin = DERE_PIN; - uint16_t readingerrcode = SDM_ERR_NO_ERROR; //4 = timeout; 3 = not enough bytes; 2 = number of bytes OK but bytes b0,b1 or b2 wrong, 1 = crc error - uint16_t readingerrcount = 0; //total errors couter - uint32_t readingsuccesscount = 0; - uint16_t calculateCRC(uint8_t *array, uint8_t num); + uint16_t readingerrcode = SDM_ERR_NO_ERROR; // 4 = timeout; 3 = not enough bytes; 2 = number of bytes OK but bytes b0,b1 or b2 wrong, 1 = crc error + uint16_t msturnaround = WAITING_TURNAROUND_DELAY; + uint16_t mstimeout = RESPONSE_TIMEOUT; + uint32_t readingerrcount = 0; // total errors counter + uint32_t readingsuccesscount = 0; // total success counter + uint16_t calculateCRC(uint8_t *array, uint8_t len); + void flush(unsigned long _flushtime = 0); // read serial if any old data is available or for a given time in ms + void dereSet(bool _state = LOW); // for control MAX485 DE/RE pins, LOW receive from SDM, HIGH transmit to SDM }; -#endif //SDM_h +#endif // SDM_h diff --git a/lib/SDM_Energy_Meter/SDM_Config_User.h b/lib/SDM_Energy_Meter/SDM_Config_User.h index 6a9091ca7..e6595f826 100644 --- a/lib/SDM_Energy_Meter/SDM_Config_User.h +++ b/lib/SDM_Energy_Meter/SDM_Config_User.h @@ -1,36 +1,93 @@ -/* Library for reading SDM 120/220/230/630 Modbus Energy meters. +/* Library for reading SDM 72/120/220/230/630 Modbus Energy meters. * Reading via Hardware or Software Serial library & rs232<->rs485 converter -* 2016-2018 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.9.0-beta & 2.4.1 esp8266 core) -* crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/) +* 2016-2023 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.8.10 & 2.5.2 esp8266 core) +* crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/) */ -//USER CONFIG: + +/* +* USER CONFIG: +*/ + //------------------------------------------------------------------------------ + /* -#undef USE_HARDWARESERIAL //undefine USE_HARDWARESERIAL -*/ -// or -/* -#define USE_HARDWARESERIAL //define USE_HARDWARESERIAL +* define or undefine USE_HARDWARESERIAL (uncomment only one or none) */ +//#undef USE_HARDWARESERIAL +//#define USE_HARDWARESERIAL + //------------------------------------------------------------------------------ + /* -#define SDM_UART_BAUD 9600 //define user baudrate +* define user baudrate */ +//#define SDM_UART_BAUD 9600 + //------------------------------------------------------------------------------ + /* -#define DERE_PIN NOT_A_PIN //define user DERE_PIN for control MAX485 DE/RE lines (connect DE & /RE together to this pin) -*/ -//------------------------------------------------------------------------------ -#ifdef USE_HARDWARESERIAL -/* - #define SDM_UART_CONFIG SERIAL_8N1 //define user SDM_UART_CONFIG -*/ -/* - #define SWAPHWSERIAL 0 //define user SWAPHWSERIAL, if true(1) then swap uart pins from 3/1 to 13/15 (only ESP8266) +* define user SDM_RX_PIN and SDM_TX_PIN for esp/avr Software Serial option +* or ESP32 with Hardware Serial if default core pins are not suitable */ +#if defined ( USE_HARDWARESERIAL ) + #if defined ( ESP32 ) + #define SDM_RX_PIN 13 + #define SDM_TX_PIN 15 + #endif +#else + #if defined ( ESP8266 ) || defined ( ESP32 ) + #define SDM_RX_PIN 13 + #define SDM_TX_PIN 15 + #else + #define SDM_RX_PIN 10 + #define SDM_TX_PIN 11 + #endif #endif + //------------------------------------------------------------------------------ + /* -#define MAX_MILLIS_TO_WAIT 500 //define user MAX_MILLIS_TO_WAIT to wait for response from SDM +* define user DERE_PIN for control MAX485 DE/RE lines (connect DE & /RE together to this pin) */ -//------------------------------------------------------------------------------ \ No newline at end of file +//#define DERE_PIN NOT_A_PIN + +//------------------------------------------------------------------------------ + +#if defined ( USE_HARDWARESERIAL ) + + /* + * define user SDM_UART_CONFIG for hardware serial + */ + //#define SDM_UART_CONFIG SERIAL_8N1 + + //---------------------------------------------------------------------------- + + /* + * define user SWAPHWSERIAL, if true(1) then swap uart pins from 3/1 to 13/15 (only ESP8266) + */ + //#define SWAPHWSERIAL 0 + +#else + + /* + * define user SDM_UART_CONFIG for software serial + */ + //#define SDM_UART_CONFIG SWSERIAL_8N1 + +#endif + +//------------------------------------------------------------------------------ + +/* +* define user WAITING_TURNAROUND_DELAY time in ms to wait for process current request +*/ +//#define WAITING_TURNAROUND_DELAY 200 + +//------------------------------------------------------------------------------ + +/* +* define user RESPONSE_TIMEOUT time in ms to wait for return response from all devices before next request +*/ +//#define RESPONSE_TIMEOUT 500 + +//------------------------------------------------------------------------------ diff --git a/lib/SDM_Energy_Meter/examples/sdm630_influxdb/sdm630_influxdb.ino b/lib/SDM_Energy_Meter/examples/sdm630_influxdb/sdm630_influxdb.ino new file mode 100644 index 000000000..9952ae4af --- /dev/null +++ b/lib/SDM_Energy_Meter/examples/sdm630_influxdb/sdm630_influxdb.ino @@ -0,0 +1,292 @@ +/* WEMOS D1 Mini + ______________________________ + | L T L T L T L T L T L T | + | | + RST| 1|TX HSer + A0| 3|RX HSer + D0|16 5|D1 + D5|14 4|D2 + D6|12 10kPUP_0|D3 +RX SSer/HSer swap D7|13 LED_10kPUP_2|D4 +TX SSer/HSer swap D8|15 |GND + 3V3|__ |5V + | | + |___________________________| +*/ + +//REMEMBER! uncomment #define USE_HARDWARESERIAL +//in SDM_Config_User.h file if you want to use hardware uart + +#include //import SDM library +#include +#include +#include +#include +#include +#include //https://github.com/tobiasschuerg/InfluxDB-Client-for-Arduino + + + +// WiFi Parameters +const char* ssid = "SSID"; +const char* password = "PASS"; +#define HOSTNAME "SDM630" // Friedly hostname + + + +// InfluxDB v2 server url, e.g. https://eu-central-1-1.aws.cloud2.influxdata.com (Use: InfluxDB UI -> Load Data -> Client Libraries) +// InfluxDB v1 server url "http://192.168.10.2:8086" +#define INFLUXDB_URL "http://INFLUXDB IP:8086" +// InfluxDB v2 server or cloud API authentication token (Use: InfluxDB UI -> Load Data -> Tokens ->