├── README.md
├── sdm
├── SDM_Config_User.h
├── sdm_esphome.h
└── SDM.h
├── Example NodeMcu ESP8266
└── Example ESP32 wrover
/README.md:
--------------------------------------------------------------------------------
1 | # ESPHome+SDM630
2 |
3 | # 1. About
4 | This repository is an instruction how to use energy meter SDM630 Modbus V2 with ESP32/8266 loaded with ESPHome. Program is meant to read all needed data from the counter if you need something more feel free to modify the code.
5 |
6 | # 2. Needed things to start
7 |
8 | 1. SDM630 Modbus V2 can be bought from Aliexpress example link below:
9 | https://pl.aliexpress.com/item/32755125115.html?spm=a2g0s.9042311.0.0.7f515c0fyqdQLy
10 | 2. Modbus konwerter from RS485 to UART
11 | https://pl.aliexpress.com/item/1005001346792286.html?spm=a2g0o.productlist.0.0.379b6239Khooh1&algo_pvid=null&algo_expid=null&btsid=2100bdcf16209689305085851eb468&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_
12 | 3. ESP board can be ESP8266 or ESP32
13 | 4. Home Assistant with ESPHome addon installed
14 |
15 | # 3. Connection diagram
16 | Wemos D1 ESP32
17 | 
18 |
19 | Wemos D1 ESP8266
20 | 
21 |
22 | Usually any board which is compatible with ESPHome should work. Only connect TX port of ESP to TX of converter, RX to RX, A+ from converter to A+ of SDM630, B- to B- and G to G.
23 |
24 | # 4. Programming
25 | 1. Download folder SDM and paste it into below location of your Home Assistant server
26 | \\\your_Home_Assistant_address\config\esphome\custom_components
27 | If folder custom_components doesn't exist create it.
28 | 2. Create New node according to your board type. Paste example code to your node and modify it according to your code and configuration!!
29 | 3. Validate code, compile and upload it.
30 | 4. Rememmber that RS converter and SDM630 need to be connected and powered on, otherwise in logs you will see nothing and ESP board will be resetting and unavailable. So the best way to test is the code working, connect ing SDM630 normal cable with plug to wall socket and make connection according to diagram in point 3
31 | 5. If we have brand new ESP it is necessary to download Firmware generated in ESPHome and upload it with below tool:
32 | https://github.com/esphome/esphome-flasher/releases/tag/v1.3.0
33 |
--------------------------------------------------------------------------------
/sdm/SDM_Config_User.h:
--------------------------------------------------------------------------------
1 | /* Library for reading SDM 72/120/220/230/630 Modbus Energy meters.
2 | * Reading via Hardware or Software Serial library & rs232<->rs485 converter
3 | * 2016-2019 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.8.10 & 2.5.2 esp8266 core)
4 | * crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/)
5 | */
6 |
7 | /*
8 | * USER CONFIG:
9 | */
10 |
11 | //------------------------------------------------------------------------------
12 |
13 | /*
14 | * define or undefine USE_HARDWARESERIAL (uncomment only one or none)
15 | */
16 | //#undef USE_HARDWARESERIAL
17 | #define USE_HARDWARESERIAL
18 |
19 | //------------------------------------------------------------------------------
20 |
21 | /*
22 | * define user baudrate
23 | */
24 | //#define SDM_UART_BAUD 9600
25 |
26 | //------------------------------------------------------------------------------
27 |
28 | /*
29 | * define user SDM_RX_PIN and SDM_TX_PIN for esp/avr Software Serial option
30 | * or ESP32 with Hardware Serial if default core pins are not suitable
31 | */
32 | #if defined ( USE_HARDWARESERIAL )
33 | #if defined ( ESP32 )
34 | #define SDM_RX_PIN 13
35 | #define SDM_TX_PIN 15
36 | #endif
37 | #else
38 | #if defined ( ESP8266 ) || defined ( ESP32 )
39 | #define SDM_RX_PIN 13
40 | #define SDM_TX_PIN 15
41 | #else
42 | #define SDM_RX_PIN 10
43 | #define SDM_TX_PIN 11
44 | #endif
45 | #endif
46 |
47 | //------------------------------------------------------------------------------
48 |
49 | /*
50 | * define user DERE_PIN for control MAX485 DE/RE lines (connect DE & /RE together to this pin)
51 | */
52 | //#define DERE_PIN NOT_A_PIN
53 |
54 | //------------------------------------------------------------------------------
55 |
56 | #if defined ( USE_HARDWARESERIAL )
57 |
58 | /*
59 | * define user SDM_UART_CONFIG for hardware serial
60 | */
61 | //#define SDM_UART_CONFIG SERIAL_8N1
62 |
63 | //----------------------------------------------------------------------------
64 |
65 | /*
66 | * define user SWAPHWSERIAL, if true(1) then swap uart pins from 3/1 to 13/15 (only ESP8266)
67 | */
68 | //#define SWAPHWSERIAL 0
69 |
70 | #else
71 |
72 | /*
73 | * define user SDM_UART_CONFIG for software serial
74 | */
75 | //#define SDM_UART_CONFIG SWSERIAL_8N1
76 |
77 | #endif
78 |
79 | //------------------------------------------------------------------------------
80 |
81 | /*
82 | * define user MAX_MILLIS_TO_WAIT to wait for response from SDM
83 | */
84 | //#define MAX_MILLIS_TO_WAIT 500
85 |
86 | //------------------------------------------------------------------------------
--------------------------------------------------------------------------------
/Example NodeMcu ESP8266:
--------------------------------------------------------------------------------
1 | substitutions:
2 | devicename: test
3 | friendly_name: node_test
4 | ip_address: !secret test
5 |
6 | esphome:
7 | name: $devicename
8 | platform: ESP8266
9 | board: nodemcuv2
10 | includes:
11 | - custom_components/sdm/SDM_Config_User.h
12 | - custom_components/sdm/SDM.h
13 | - custom_components/sdm/sdm_esphome.h
14 |
15 |
16 | wifi:
17 | ssid: !secret wifi_id
18 | password: !secret wifi_pwd
19 | manual_ip:
20 | static_ip: ${ip_address}
21 | gateway: 192.168.0.1
22 | subnet: 255.255.255.0
23 |
24 | # Enable fallback hotspot (captive portal) in case wifi connection fails
25 |
26 | # Enable logging
27 | logger:
28 | level: DEBUG
29 | baud_rate: 0
30 | # level: VERY_VERBOSE
31 | esp8266_store_log_strings_in_flash: False
32 |
33 | # Enable Home Assistant API
34 | api:
35 |
36 | ota:
37 |
38 | # Enable Home Assistant API
39 |
40 | time:
41 | - platform: homeassistant
42 | id: homeassistant_time
43 |
44 |
45 | uart:
46 | tx_pin: TX
47 | rx_pin: RX
48 | baud_rate: 9600
49 | stop_bits: 1
50 |
51 | binary_sensor:
52 | # https://esphome.io/components/binary_sensor/status.html
53 | - platform: status
54 | name: "SDM630 Status"
55 |
56 | sensor:
57 | - platform: uptime
58 | name: "SDM630 Uptime Sensor"
59 |
60 | - platform: custom
61 | lambda: |-
62 | auto sdm_sensors = new SDMComponent();
63 | App.register_component(sdm_sensors);
64 | return {sdm_sensors->voltage_sensor_1,sdm_sensors->voltage_sensor_2,sdm_sensors->voltage_sensor_3, sdm_sensors->current_sensor_1,sdm_sensors->current_sensor_2,sdm_sensors->current_sensor_3,sdm_sensors->power_sensor_1,sdm_sensors->power_sensor_2,sdm_sensors->power_sensor_3,sdm_sensors->vars_sensor_1,sdm_sensors->vars_sensor_2,sdm_sensors->vars_sensor_3, sdm_sensors->frequency_sensor,sdm_sensors->active_energy_import_sensor,sdm_sensors->active_energy_export_sensor,sdm_sensors->reactive_energy_import_sensor,sdm_sensors->reactive_energy_export_sensor,sdm_sensors->import_kwh_sensor_1,sdm_sensors->import_kwh_sensor_2,sdm_sensors->import_kwh_sensor_3,sdm_sensors->export_kwh_sensor_1,sdm_sensors->export_kwh_sensor_2,sdm_sensors->export_kwh_sensor_3,sdm_sensors->power_factor_sensor_1,sdm_sensors->power_factor_sensor_2,sdm_sensors->power_factor_sensor_3,sdm_sensors->energy_total_sensor_1,sdm_sensors->energy_total_sensor_2,sdm_sensors->energy_total_sensor_3};
65 | sensors:
66 | - name: "Voltage Phase 1"
67 | unit_of_measurement: V
68 | accuracy_decimals: 1
69 | - name: "Voltage Phase 2"
70 | unit_of_measurement: V
71 | accuracy_decimals: 1
72 | - name: "Voltage Phase 3"
73 | unit_of_measurement: V
74 | accuracy_decimals: 1
75 |
76 | - name: "Current Phase 1"
77 | unit_of_measurement: A
78 | accuracy_decimals: 2
79 | - name: "Current Phase 2"
80 | unit_of_measurement: A
81 | accuracy_decimals: 2
82 | - name: "Current Phase 3"
83 | unit_of_measurement: A
84 | accuracy_decimals: 2
85 |
86 | - name: "Power Phase 1"
87 | unit_of_measurement: W
88 | accuracy_decimals: 2
89 | id: power_1
90 | - name: "Power Phase 2"
91 | unit_of_measurement: W
92 | accuracy_decimals: 2
93 | id: power_2
94 | - name: "Power Phase 3"
95 | unit_of_measurement: W
96 | accuracy_decimals: 2
97 | id: power_3
98 |
99 | - name: "VArs Phase 1"
100 | unit_of_measurement: VAr
101 | accuracy_decimals: 2
102 | - name: "VArs Phase 2"
103 | unit_of_measurement: VAr
104 | accuracy_decimals: 2
105 | - name: "VArs Phase 3"
106 | unit_of_measurement: VAr
107 | accuracy_decimals: 2
108 |
109 | - name: "Frequency"
110 | unit_of_measurement: Hz
111 | accuracy_decimals: 1
112 |
113 | - name: "Active Energy Import"
114 | unit_of_measurement: Wh
115 | accuracy_decimals: 2
116 | - name: "Active Energy Export"
117 | unit_of_measurement: Wh
118 | accuracy_decimals: 2
119 | - name: "Reactive Energy Import"
120 | unit_of_measurement: VARh
121 | accuracy_decimals: 2
122 | - name: "Reactive Energy Export"
123 | unit_of_measurement: VARh
124 | accuracy_decimals: 2
125 |
126 | - name: "Import Phase 1"
127 | unit_of_measurement: kWh
128 | accuracy_decimals: 2
129 | - name: "Import Phase 2"
130 | unit_of_measurement: kWh
131 | accuracy_decimals: 2
132 | - name: "Import Phase 3"
133 | unit_of_measurement: kWh
134 | accuracy_decimals: 2
135 |
136 | - name: "Export Phase 1"
137 | unit_of_measurement: kWh
138 | accuracy_decimals: 2
139 | - name: "Export Phase 2"
140 | unit_of_measurement: kWh
141 | accuracy_decimals: 2
142 | - name: "Export Phase 3"
143 | unit_of_measurement: kWh
144 | accuracy_decimals: 2
145 |
146 | - name: "Power Factor Phase 1"
147 | accuracy_decimals: 2
148 | - name: "Power Factor Phase 2"
149 | accuracy_decimals: 2
150 | - name: "Power Factor Phase 3"
151 | accuracy_decimals: 2
152 |
153 | - name: "Energy Total Phase 1"
154 | unit_of_measurement: kWh
155 | accuracy_decimals: 2
156 | - name: "Energy Total Phase 2"
157 | unit_of_measurement: kWh
158 | accuracy_decimals: 2
159 | - name: "Energy Total Phase 3"
160 | unit_of_measurement: kWh
161 | accuracy_decimals: 2
162 | #tu gdzies jest blad
163 | - platform: total_daily_energy
164 | name: "Daily Energy Phase 1"
165 | icon: "mdi:counter"
166 | power_id: power_1
167 | filters:
168 | # Multiplication factor from W to kW is 0.001
169 | - multiply: 0.001
170 | unit_of_measurement: kWh
171 | - platform: total_daily_energy
172 | name: "Daily Energy Phase 2"
173 | icon: "mdi:counter"
174 | power_id: power_2
175 | filters:
176 | # Multiplication factor from W to kW is 0.001
177 | - multiply: 0.001
178 | unit_of_measurement: kWh
179 | - platform: total_daily_energy
180 | name: "Daily Energy Phase 3"
181 | icon: "mdi:counter"
182 | power_id: power_3
183 | filters:
184 | # Multiplication factor from W to kW is 0.001
185 | - multiply: 0.001
186 | unit_of_measurement: kWh
187 |
--------------------------------------------------------------------------------
/sdm/sdm_esphome.h:
--------------------------------------------------------------------------------
1 | #include "esphome.h"
2 |
3 | class SDMComponent : public PollingComponent {
4 | public:
5 | SDM sdm = SDM(Serial, 9600, NOT_A_PIN, SERIAL_8N1, false);
6 | /*Voltage*/
7 | Sensor *voltage_sensor_1 = new Sensor();
8 | Sensor *voltage_sensor_2 = new Sensor();
9 | Sensor *voltage_sensor_3 = new Sensor();
10 | /*Current*/
11 | Sensor *current_sensor_1 = new Sensor();
12 | Sensor *current_sensor_2 = new Sensor();
13 | Sensor *current_sensor_3 = new Sensor();
14 | Sensor *currentsum_sensor = new Sensor();
15 | //Power
16 | Sensor *power_sensor_1 = new Sensor();
17 | Sensor *power_sensor_2 = new Sensor();
18 | Sensor *power_sensor_3 = new Sensor();
19 | Sensor *powersum_sensor = new Sensor();
20 | //Vars
21 | Sensor *vars_sensor_1 = new Sensor();
22 | Sensor *vars_sensor_2 = new Sensor();
23 | Sensor *vars_sensor_3 = new Sensor();
24 | Sensor *varssum_sensor = new Sensor();
25 | //frequency
26 | Sensor *frequency_sensor = new Sensor();
27 | //import export energy
28 | Sensor *active_energy_import_sensor = new Sensor();
29 | Sensor *active_energy_export_sensor = new Sensor();
30 | Sensor *reactive_energy_import_sensor = new Sensor();
31 | Sensor *reactive_energy_export_sensor = new Sensor();
32 | Sensor *import_kwh_sensor_1 = new Sensor();
33 | Sensor *import_kwh_sensor_2 = new Sensor();
34 | Sensor *import_kwh_sensor_3 = new Sensor();
35 | Sensor *importsum_kwh_sensor = new Sensor();
36 | Sensor *export_kwh_sensor_1 = new Sensor();
37 | Sensor *export_kwh_sensor_2 = new Sensor();
38 | Sensor *export_kwh_sensor_3 = new Sensor();
39 | Sensor *exportsum_kwh_sensor = new Sensor();
40 | //power factor
41 | Sensor *power_factor_sensor_1 = new Sensor();
42 | Sensor *power_factor_sensor_2 = new Sensor();
43 | Sensor *power_factor_sensor_3 = new Sensor();
44 | Sensor *power_factor_total_sensor = new Sensor();
45 | //Energy kWh
46 | Sensor *energy_total_sensor_1 = new Sensor();
47 | Sensor *energy_total_sensor_2 = new Sensor();
48 | Sensor *energy_total_sensor_3 = new Sensor();
49 | Sensor *energy_totalsum_sensor = new Sensor();
50 |
51 | SDMComponent() : PollingComponent(15000) {}
52 |
53 | void setup() override {
54 | ESP_LOGD("SDM", "Setup completed");
55 | }
56 |
57 | void update() override {
58 | // ESP_LOGD("SDM", "Start reading");
59 | float voltage1 = sdm.readVal(SDM630_VOLTAGE1);
60 | float voltage2 = sdm.readVal(SDM630_VOLTAGE2);
61 | float voltage3 = sdm.readVal(SDM630_VOLTAGE3);
62 | // ESP_LOGD("SDM", "Voltages %f %f %f", voltage1, voltage2, voltage3);
63 | voltage_sensor_1->publish_state(voltage1);
64 | voltage_sensor_2->publish_state(voltage2);
65 | voltage_sensor_3->publish_state(voltage3);
66 |
67 | float current1 = sdm.readVal(SDM630_CURRENT1);
68 | float current2 = sdm.readVal(SDM630_CURRENT2);
69 | float current3 = sdm.readVal(SDM630_CURRENT3);
70 | float currentsum = sdm.readVal(SDM630_CURRENTSUM);
71 | current_sensor_1->publish_state(current1);
72 | current_sensor_2->publish_state(current2);
73 | current_sensor_3->publish_state(current3);
74 | currentsum_sensor->publish_state(currentsum);
75 |
76 | float power1 = sdm.readVal(SDM630_POWER1);
77 | float power2 = sdm.readVal(SDM630_POWER2);
78 | float power3 = sdm.readVal(SDM630_POWER3);
79 | float powersum = sdm.readVal(SDM630_POWERTOTAL);
80 | power_sensor_1->publish_state(power1);
81 | power_sensor_2->publish_state(power2);
82 | power_sensor_3->publish_state(power3);
83 | powersum_sensor->publish_state(powersum);
84 |
85 | float vars1 = sdm.readVal(SDM630_VOLT_AMPS_REACTIVE1);
86 | float vars2 = sdm.readVal(SDM630_VOLT_AMPS_REACTIVE2);
87 | float vars3 = sdm.readVal(SDM630_VOLT_AMPS_REACTIVE3);
88 | float varssum = sdm.readVal(SDM630_VOLT_AMPS_REACTIVE_TOTAL);
89 | vars_sensor_1->publish_state(vars1);
90 | vars_sensor_2->publish_state(vars2);
91 | vars_sensor_3->publish_state(vars3);
92 | varssum_sensor->publish_state(varssum);
93 |
94 | float import1 = sdm.readVal(SDM630_IMPORT1);
95 | float import2 = sdm.readVal(SDM630_IMPORT2);
96 | float import3 = sdm.readVal(SDM630_IMPORT3);
97 | // ESP_LOGD("SDM", "Imports %f %f %f", import1, import2, import3);
98 | import_kwh_sensor_1->publish_state(import1);
99 | import_kwh_sensor_2->publish_state(import2);
100 | import_kwh_sensor_3->publish_state(import3);
101 | importsum_kwh_sensor->publish_state(import1 + import2 + import3);
102 |
103 | float export1 = sdm.readVal(SDM630_EXPORT1);
104 | float export2 = sdm.readVal(SDM630_EXPORT2);
105 | float export3 = sdm.readVal(SDM630_EXPORT3);
106 | // ESP_LOGD("SDM", "Exports %f %f %f", export1, export2, export3);
107 | export_kwh_sensor_1->publish_state(export1);
108 | export_kwh_sensor_2->publish_state(export2);
109 | export_kwh_sensor_3->publish_state(export3);
110 | exportsum_kwh_sensor->publish_state(export1 + export2 + export3);
111 |
112 | float frequency = sdm.readVal(SDM630_FREQUENCY);
113 | frequency_sensor->publish_state(frequency);
114 |
115 | float active_ene_import = sdm.readVal(SDM630_IMPORT_ACTIVE_ENERGY);
116 | float active_ene_export = sdm.readVal(SDM630_EXPORT_ACTIVE_ENERGY);
117 | float reactive_ene_import = sdm.readVal(SDM630_IMPORT_REACTIVE_ENERGY);
118 | float reactive_ene_export = sdm.readVal(SDM630_EXPORT_REACTIVE_ENERGY);
119 | active_energy_import_sensor->publish_state(active_ene_import);
120 | active_energy_export_sensor->publish_state(active_ene_export);
121 | reactive_energy_import_sensor->publish_state(reactive_ene_import);
122 | reactive_energy_export_sensor->publish_state(reactive_ene_export);
123 |
124 | float power_factor1 = sdm.readVal(SDM630_POWER_FACTOR1);
125 | float power_factor2 = sdm.readVal(SDM630_POWER_FACTOR2);
126 | float power_factor3 = sdm.readVal(SDM630_POWER_FACTOR3);
127 | float power_factor_total = sdm.readVal(SDM630_POWER_FACTOR_TOTAL);
128 | power_factor_sensor_1->publish_state(power_factor1);
129 | power_factor_sensor_2->publish_state(power_factor2);
130 | power_factor_sensor_3->publish_state(power_factor3);
131 | power_factor_total_sensor->publish_state(power_factor_total);
132 |
133 | float ene_total1 = sdm.readVal(SDM630_TOTAL_ENERGY1);
134 | float ene_total2 = sdm.readVal(SDM630_TOTAL_ENERGY2);
135 | float ene_total3 = sdm.readVal(SDM630_TOTAL_ENERGY3);
136 | //ESP_LOGD("SDM", "Energy totals %f %f %f", ene_total1, ene_total1, ene_total1);
137 | energy_total_sensor_1->publish_state(ene_total1);
138 | energy_total_sensor_2->publish_state(ene_total2);
139 | energy_total_sensor_3->publish_state(ene_total3);
140 | energy_totalsum_sensor->publish_state(ene_total1 + ene_total2 + ene_total3);
141 |
142 | // ESP_LOGD("SDM", "End reading");
143 | }
144 | };
145 |
--------------------------------------------------------------------------------
/Example ESP32 wrover:
--------------------------------------------------------------------------------
1 | substitutions:
2 | devicename: sdm630
3 | friendly_name: ttgo_sdm630
4 | ip_address: !secret sdm630
5 |
6 | esphome:
7 | name: $devicename
8 | platform: ESP32
9 | board: esp-wrover-kit
10 | includes:
11 | - custom_components/sdm/SDM_Config_User.h
12 | - custom_components/sdm/SDM.h
13 | - custom_components/sdm/sdm_esphome.h
14 |
15 | wifi:
16 | ssid: !secret wifi_id
17 | password: !secret wifi_pwd
18 | manual_ip:
19 | static_ip: ${ip_address}
20 | gateway: 192.168.0.1
21 | subnet: 255.255.255.0
22 |
23 | # Enable fallback hotspot (captive portal) in case wifi connection fails
24 | #ap:
25 | # ssid: "Home Lights Notify"
26 | #password: "YiwdlGqxsCgP"
27 |
28 | #captive_portal:
29 |
30 | # Enable logging
31 | logger:
32 | level: DEBUG
33 | baud_rate: 0
34 |
35 | # Enable Home Assistant API
36 | api:
37 |
38 | uart:
39 | - id: modbus_uart
40 | tx_pin: TX
41 | rx_pin: RX
42 | baud_rate: 9600
43 | stop_bits: 1
44 |
45 | ota:
46 |
47 | time:
48 | - platform: homeassistant
49 | id: homeassistant_time
50 |
51 | binary_sensor:
52 | # https://esphome.io/components/binary_sensor/status.html
53 | - platform: status
54 | name: "SDM630 Status"
55 |
56 | sensor:
57 | - platform: uptime
58 | name: "SDM630 Uptime Sensor"
59 |
60 | - platform: custom
61 | lambda: |-
62 | auto sdm_sensors = new SDMComponent();
63 | App.register_component(sdm_sensors);
64 | return {sdm_sensors->voltage_sensor_1,sdm_sensors->voltage_sensor_2,sdm_sensors->voltage_sensor_3, sdm_sensors->current_sensor_1,sdm_sensors->current_sensor_2,sdm_sensors->current_sensor_3,sdm_sensors->currentsum_sensor, sdm_sensors->power_sensor_1,sdm_sensors->power_sensor_2,sdm_sensors->power_sensor_3,sdm_sensors->powersum_sensor,sdm_sensors->vars_sensor_1,sdm_sensors->vars_sensor_2,sdm_sensors->vars_sensor_3,sdm_sensors->varssum_sensor, sdm_sensors->frequency_sensor,sdm_sensors->active_energy_import_sensor,sdm_sensors->active_energy_export_sensor,sdm_sensors->reactive_energy_import_sensor,sdm_sensors->reactive_energy_export_sensor,sdm_sensors->import_kwh_sensor_1,sdm_sensors->import_kwh_sensor_2,sdm_sensors->import_kwh_sensor_3,sdm_sensors->importsum_kwh_sensor,sdm_sensors->export_kwh_sensor_1,sdm_sensors->export_kwh_sensor_2,sdm_sensors->export_kwh_sensor_3,sdm_sensors->exportsum_kwh_sensor,sdm_sensors->power_factor_sensor_1,sdm_sensors->power_factor_sensor_2,sdm_sensors->power_factor_sensor_3,sdm_sensors->power_factor_total_sensor,sdm_sensors->energy_total_sensor_1,sdm_sensors->energy_total_sensor_2,sdm_sensors->energy_total_sensor_3,sdm_sensors->energy_totalsum_sensor};
65 | sensors:
66 | - name: "Voltage Phase 1"
67 | unit_of_measurement: V
68 | accuracy_decimals: 1
69 | - name: "Voltage Phase 2"
70 | unit_of_measurement: V
71 | accuracy_decimals: 1
72 | - name: "Voltage Phase 3"
73 | unit_of_measurement: V
74 | accuracy_decimals: 1
75 |
76 | - name: "Current Phase 1"
77 | unit_of_measurement: A
78 | accuracy_decimals: 2
79 | - name: "Current Phase 2"
80 | unit_of_measurement: A
81 | accuracy_decimals: 2
82 | - name: "Current Phase 3"
83 | unit_of_measurement: A
84 | accuracy_decimals: 2
85 | - name: "Current Sum"
86 | unit_of_measurement: A
87 | accuracy_decimals: 2
88 |
89 | - name: "Power Phase 1"
90 | unit_of_measurement: W
91 | accuracy_decimals: 2
92 | id: power_1
93 | - name: "Power Phase 2"
94 | unit_of_measurement: W
95 | accuracy_decimals: 2
96 | id: power_2
97 | - name: "Power Phase 3"
98 | unit_of_measurement: W
99 | accuracy_decimals: 2
100 | id: power_3
101 | - name: "Power Sum"
102 | unit_of_measurement: W
103 | accuracy_decimals: 2
104 | id: power_sum
105 |
106 | - name: "VArs Phase 1"
107 | unit_of_measurement: VAr
108 | accuracy_decimals: 2
109 | - name: "VArs Phase 2"
110 | unit_of_measurement: VAr
111 | accuracy_decimals: 2
112 | - name: "VArs Phase 3"
113 | unit_of_measurement: VAr
114 | accuracy_decimals: 2
115 | - name: "VArs Sum"
116 | unit_of_measurement: VAr
117 | accuracy_decimals: 2
118 |
119 | - name: "Frequency"
120 | unit_of_measurement: Hz
121 | accuracy_decimals: 1
122 |
123 | - name: "Active Energy Import"
124 | unit_of_measurement: Wh
125 | accuracy_decimals: 2
126 | - name: "Active Energy Export"
127 | unit_of_measurement: Wh
128 | accuracy_decimals: 2
129 | - name: "Reactive Energy Import"
130 | unit_of_measurement: VARh
131 | accuracy_decimals: 2
132 | - name: "Reactive Energy Export"
133 | unit_of_measurement: VARh
134 | accuracy_decimals: 2
135 |
136 | - name: "Import Phase 1"
137 | unit_of_measurement: kWh
138 | accuracy_decimals: 2
139 | - name: "Import Phase 2"
140 | unit_of_measurement: kWh
141 | accuracy_decimals: 2
142 | - name: "Import Phase 3"
143 | unit_of_measurement: kWh
144 | accuracy_decimals: 2
145 | - name: "Import Sum"
146 | unit_of_measurement: kWh
147 | accuracy_decimals: 2
148 |
149 | - name: "Export Phase 1"
150 | unit_of_measurement: kWh
151 | accuracy_decimals: 2
152 | - name: "Export Phase 2"
153 | unit_of_measurement: kWh
154 | accuracy_decimals: 2
155 | - name: "Export Phase 3"
156 | unit_of_measurement: kWh
157 | accuracy_decimals: 2
158 | - name: "Export Sum"
159 | unit_of_measurement: kWh
160 | accuracy_decimals: 2
161 |
162 | - name: "Power Factor Phase 1"
163 | accuracy_decimals: 2
164 | - name: "Power Factor Phase 2"
165 | accuracy_decimals: 2
166 | - name: "Power Factor Phase 3"
167 | accuracy_decimals: 2
168 | - name: "Power Factor Sum"
169 | accuracy_decimals: 2
170 |
171 | - name: "Energy Total Phase 1"
172 | unit_of_measurement: kWh
173 | accuracy_decimals: 2
174 | - name: "Energy Total Phase 2"
175 | unit_of_measurement: kWh
176 | accuracy_decimals: 2
177 | - name: "Energy Total Phase 3"
178 | unit_of_measurement: kWh
179 | accuracy_decimals: 2
180 | - name: "Energy Total Sum"
181 | unit_of_measurement: kWh
182 | accuracy_decimals: 2
183 |
184 | #Auto create daily total energy counter for each Phase
185 | - platform: total_daily_energy
186 | name: "Daily Energy Phase 1"
187 | icon: "mdi:counter"
188 | power_id: power_1
189 | filters:
190 | # Multiplication factor from W to kW is 0.001
191 | - multiply: 0.001
192 | unit_of_measurement: kWh
193 | - platform: total_daily_energy
194 | name: "Daily Energy Phase 2"
195 | icon: "mdi:counter"
196 | power_id: power_2
197 | filters:
198 | # Multiplication factor from W to kW is 0.001
199 | - multiply: 0.001
200 | unit_of_measurement: kWh
201 | - platform: total_daily_energy
202 | name: "Daily Energy Phase 3"
203 | icon: "mdi:counter"
204 | power_id: power_3
205 | filters:
206 | # Multiplication factor from W to kW is 0.001
207 | - multiply: 0.001
208 | unit_of_measurement: kWh
209 | - platform: total_daily_energy
210 | name: "Daily Energy Sum"
211 | icon: "mdi:counter"
212 | power_id: power_sum
213 | filters:
214 | # Multiplication factor from W to kW is 0.001
215 | - multiply: 0.001
216 | unit_of_measurement: kWh
217 |
--------------------------------------------------------------------------------
/sdm/SDM.h:
--------------------------------------------------------------------------------
1 | /* Library for reading SDM 72/120/220/230/630 Modbus Energy meters.
2 | * Reading via Hardware or Software Serial library & rs232<->rs485 converter
3 | * 2016-2019 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.8.10 & 2.5.2 esp8266 core)
4 | * crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/)
5 | */
6 | //------------------------------------------------------------------------------
7 | #ifndef SDM_h
8 | #define SDM_h
9 | #define USE_HARDWARESERIAL
10 | //------------------------------------------------------------------------------
11 | #include
12 | #include
13 | #if defined ( USE_HARDWARESERIAL )
14 | #include
15 | #else
16 | #include
17 | #endif
18 | //------------------------------------------------------------------------------
19 | //DEFAULT CONFIG (DO NOT CHANGE ANYTHING!!! for changes use SDM_Config_User.h):
20 | //------------------------------------------------------------------------------
21 | #if !defined ( SDM_UART_BAUD )
22 | #define SDM_UART_BAUD 4800 //default baudrate
23 | #endif
24 |
25 | #if !defined ( DERE_PIN )
26 | #define DERE_PIN NOT_A_PIN //default digital pin for control MAX485 DE/RE lines (connect DE & /RE together to this pin)
27 | #endif
28 |
29 | #if defined ( USE_HARDWARESERIAL )
30 |
31 | #if !defined ( SDM_UART_CONFIG )
32 | #define SDM_UART_CONFIG SERIAL_8N1 //default hardware uart config
33 | #endif
34 |
35 | #if defined ( ESP8266 ) && !defined ( SWAPHWSERIAL )
36 | #define SWAPHWSERIAL 0 //(only esp8266) when hwserial used, then swap uart pins from 3/1 to 13/15 (default not swap)
37 | #endif
38 |
39 | #if defined ( ESP32 )
40 | #if !defined ( SDM_RX_PIN )
41 | #define SDM_RX_PIN -1 //use default rx pin for selected port
42 | #endif
43 | #if !defined ( SDM_TX_PIN )
44 | #define SDM_TX_PIN -1 //use default tx pin for selected port
45 | #endif
46 | #endif
47 |
48 | #else
49 |
50 | #if defined ( ESP8266 ) || defined ( ESP32 )
51 | #if !defined ( SDM_UART_CONFIG )
52 | #define SDM_UART_CONFIG SWSERIAL_8N1 //default softwareware uart config for esp8266/esp32
53 | #endif
54 | #endif
55 |
56 | // #if !defined ( SDM_RX_PIN ) || !defined ( SDM_TX_PIN )
57 | // #error "SDM_RX_PIN and SDM_TX_PIN must be defined in SDM_Config_User.h for Software Serial option)"
58 | // #endif
59 |
60 | #if !defined ( SDM_RX_PIN )
61 | #define SDM_RX_PIN -1
62 | #endif
63 | #if !defined ( SDM_TX_PIN )
64 | #define SDM_TX_PIN -1
65 | #endif
66 |
67 | #endif
68 |
69 | #if !defined ( MAX_MILLIS_TO_WAIT )
70 | #define MAX_MILLIS_TO_WAIT 500 //default max time to wait for response from SDM
71 | #endif
72 | //------------------------------------------------------------------------------
73 | #define FRAMESIZE 9 //size of out/in array
74 | #define SDM_REPLY_BYTE_COUNT 0x04 //number of bytes with data
75 |
76 | #define SDM_B_01 0x01 //BYTE 1 -> slave address (default value 1 read from node 1)
77 | #define SDM_B_02 0x04 //BYTE 2 -> function code (default value 0x04 read from 3X input registers)
78 | //BYTES 3 & 4 (BELOW)
79 | //SDM 72 registers
80 | #define SDM72_TOTAL_POWER 0x0034 //W
81 | #define SDM72_IMPORT_ENERGY 0x0048 //kWh
82 | #define SDM72_EXPORT_ENERGY 0x004A //kWh
83 | #define SDM72_TOTAL_ENERGY 0x0156 //kWh
84 | #define SDM72_SETABLE_TOTAL_ENERGY 0x0180 //kWh
85 | #define SDM72_SETABLE_IMPORT_ENERGY 0x0184 //kWh
86 | #define SDM72_SETABLE_EXPORT_ENERGY 0x0186 //kWh
87 | #define SDM72_IMPORT_POWER 0x0500 //W
88 | #define SDM72_EXPORT_POWER 0x0502 //W
89 | //SDM 120C registers
90 | // https://bg-etech.de/download/manual/SDM120C-Modbus-DE.pdf
91 | #define SDM120C_VOLTAGE 0x0000 //V
92 | #define SDM120C_CURRENT 0x0006 //A
93 | #define SDM120C_POWER 0x000C //W
94 | #define SDM120C_ACTIVE_APPARENT_POWER 0x0012 //VA
95 | #define SDM120C_REACTIVE_APPARENT_POWER 0x0018 //VAR
96 | #define SDM120C_POWER_FACTOR 0x001E //
97 | #define SDM120C_FREQUENCY 0x0046 //Hz
98 | #define SDM120C_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
99 | #define SDM120C_EXPORT_ACTIVE_ENERGY 0x004A //Wh
100 | #define SDM120C_TOTAL_ACTIVE_ENERGY 0x0156 //Wh
101 | //SDM 120 & SDM 120CT registers
102 | // http://www.eastroneurope.com/media/_system/tech_specs/3914/SDM120%20PROTOCOL.pdf
103 | // http://www.eastroneurope.com/media/_system/tech_specs/3915/SDM120CT%20PROTOCOL.pdf
104 | #define SDM120CT_VOLTAGE 0x0000 //V
105 | #define SDM120CT_CURRENT 0x0006 //A
106 | #define SDM120CT_POWER 0x000C //W
107 | #define SDM120CT_APPARENT_POWER 0x0012 //VA
108 | #define SDM120CT_REACTIVE_POWER 0x0018 //VAr
109 | #define SDM120CT_POWER_FACTOR 0x001E //None
110 | #define SDM120CT_PHASE_ANGLE 0x0024 //Degrees
111 | #define SDM120CT_FREQUENCY 0x0046 //Hz
112 | #define SDM120CT_IMPORT_ACTIVE_ENERGY 0x0048 //kWh
113 | #define SDM120CT_EXPORT_ACTIVE_ENERGY 0x004A //kWh
114 | #define SDM120CT_IMPORT_REACTIVE_ENERGY 0x004C //kVArh
115 | #define SDM120CT_EXPORT_REACTIVE_ENERGY 0x004E //kVARh
116 | #define SDM120CT_TOTAL_ACTIVE_ENERGY 0x0156 //kWh
117 | #define SDM120CT_TOTAL_REACTIVE_ENERGY 0x0158 //Kvarh
118 | //SDM 220 registers
119 | #define SDM220T_VOLTAGE 0x0000 //V
120 | #define SDM220T_CURRENT 0x0006 //A
121 | #define SDM220T_POWER 0x000C //W
122 | #define SDM220T_ACTIVE_APPARENT_POWER 0x0012 //VA
123 | #define SDM220T_REACTIVE_APPARENT_POWER 0x0018 //VAR
124 | #define SDM220T_POWER_FACTOR 0x001E //
125 | #define SDM220T_PHASE_ANGLE 0x0024 //DEGREE
126 | #define SDM220T_FREQUENCY 0x0046 //Hz
127 | #define SDM220T_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
128 | #define SDM220T_EXPORT_ACTIVE_ENERGY 0x004A //Wh
129 | #define SDM220T_IMPORT_REACTIVE_ENERGY 0x004C //VARh
130 | #define SDM220T_EXPORT_REACTIVE_ENERGY 0x004E //VARh
131 | #define SDM220T_TOTAL_ACTIVE_ENERGY 0x0156 //Wh
132 | #define SDM220T_TOTAL_REACTIVE_ENERGY 0x0158 //VARh
133 | //SDM 230 registers
134 | #define SDM230_VOLTAGE 0x0000 //V
135 | #define SDM230_CURRENT 0x0006 //A
136 | #define SDM230_POWER 0x000C //W
137 | #define SDM230_ACTIVE_APPARENT_POWER 0x0012 //VA
138 | #define SDM230_REACTIVE_APPARENT_POWER 0x0018 //VAR
139 | #define SDM230_POWER_FACTOR 0x001E //
140 | #define SDM230_PHASE_ANGLE 0x0024 //DEGREE
141 | #define SDM230_FREQUENCY 0x0046 //Hz
142 | #define SDM230_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
143 | #define SDM230_EXPORT_ACTIVE_ENERGY 0x004A //Wh
144 | #define SDM230_IMPORT_REACTIVE_ENERGY 0x004C //VARh
145 | #define SDM230_EXPORT_REACTIVE_ENERGY 0x004E //VARh
146 | #define SDM230_TOTAL_SYSTEM_POWER_DEMAND 0x0054 //W
147 | #define SDM230_MAXIMUM_SYSTEM_POWER_DEMAND 0x0056 //W
148 | #define SDM230_CURRENT_POSITIVE_POWER_DEMAND 0x0058 //W
149 | #define SDM230_MAXIMUM_POSITIVE_POWER_DEMAND 0x005A //W
150 | #define SDM230_CURRENT_REVERSE_POWER_DEMAND 0x005C //W
151 | #define SDM230_MAXIMUM_REVERSE_POWER_DEMAND 0x005E //W
152 | #define SDM230_CURRENT_DEMAND 0x0102 //Amps
153 | #define SDM230_MAXIMUM_CURRENT_DEMAND 0x0108 //Amps
154 | #define SDM230_TOTAL_ACTIVE_ENERGY 0x0156 //kwh
155 | #define SDM230_TOTAL_REACTIVE_ENERGY 0x0158 //kvarh
156 | #define SDM230_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY 0x0180 //Wh
157 | #define SDM230_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY 0x0182 //VARh
158 | //SDM 630 registers
159 | #define SDM630_VOLTAGE1 0x0000 //V
160 | #define SDM630_VOLTAGE2 0x0002 //V
161 | #define SDM630_VOLTAGE3 0x0004 //V
162 | #define SDM630_CURRENT1 0x0006 //A
163 | #define SDM630_CURRENT2 0x0008 //A
164 | #define SDM630_CURRENT3 0x000A //A
165 | #define SDM630_CURRENTSUM 0x0030 //A
166 | #define SDM630_POWER1 0x000C //W
167 | #define SDM630_POWER2 0x000E //W
168 | #define SDM630_POWER3 0x0010 //W
169 | #define SDM630_POWERTOTAL 0x0034 //W
170 | #define SDM630_VOLT_AMPS1 0x0012 //VA
171 | #define SDM630_VOLT_AMPS2 0x0014 //VA
172 | #define SDM630_VOLT_AMPS3 0x0016 //VA
173 | #define SDM630_VOLT_AMPS_TOTAL 0x0038 //VA
174 | #define SDM630_VOLT_AMPS_REACTIVE1 0x0018 //VAr
175 | #define SDM630_VOLT_AMPS_REACTIVE2 0x001A //VAr
176 | #define SDM630_VOLT_AMPS_REACTIVE3 0x001C //VAr
177 | #define SDM630_VOLT_AMPS_REACTIVE_TOTAL 0x003C //VAr
178 | #define SDM630_POWER_FACTOR1 0x001E
179 | #define SDM630_POWER_FACTOR2 0x0020
180 | #define SDM630_POWER_FACTOR3 0x0022
181 | #define SDM630_POWER_FACTOR_TOTAL 0x003E
182 | #define SDM630_PHASE_ANGLE1 0x0024 //Degrees
183 | #define SDM630_PHASE_ANGLE2 0x0026 //Degrees
184 | #define SDM630_PHASE_ANGLE3 0x0028 //Degrees
185 | #define SDM630_PHASE_ANGLE_TOTAL 0x0042 //Degrees
186 | #define SDM630_VOLTAGE_AVERAGE 0x002A //V
187 | #define SDM630_CURRENT_AVERAGE 0x002E //A
188 | #define SDM630_FREQUENCY 0x0046 //HZ
189 | #define SDM630_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
190 | #define SDM630_EXPORT_ACTIVE_ENERGY 0x004A //Wh
191 | #define SDM630_IMPORT_REACTIVE_ENERGY 0x004C //VARh
192 | #define SDM630_EXPORT_REACTIVE_ENERGY 0x004E //VARh
193 | #define SDM630_TOTAL_SYSTEM_POWER_DEMAND 0x0054 //W
194 | #define SDM630_MAXIMUM_TOTAL_SYSTEM_POWER 0x0056 //W
195 | #define SDM630_PHASE_1_LN_VOLTS_THD 0x00EA //%
196 | #define SDM630_PHASE_2_LN_VOLTS_THD 0x00EC //%
197 | #define SDM630_PHASE_3_LN_VOLTS_THD 0x00EE //%
198 | #define SDM630_AVERAGE_VOLTS_THD 0x00F8 //%
199 | #define SDM630_PHASE_1_CURRENT_THD 0x00F0 //%
200 | #define SDM630_PHASE_2_CURRENT_THD 0x00F2 //%
201 | #define SDM630_PHASE_3_CURRENT_THD 0x00F4 //%
202 | #define SDM630_AVERAGE_CURRENT_THD 0x00FA //%
203 | #define SDM630_IMPORT1 0x015a //kWh
204 | #define SDM630_IMPORT2 0x015c //kWh
205 | #define SDM630_IMPORT3 0x015e //kWh
206 | #define SDM630_EXPORT1 0x0160 //kWh
207 | #define SDM630_EXPORT2 0x0162 //kWh
208 | #define SDM630_EXPORT3 0x0164 //kWh
209 | #define SDM630_TOTAL_ENERGY1 0x0166 //kWh
210 | #define SDM630_TOTAL_ENERGY2 0x0168 //kWh
211 | #define SDM630_TOTAL_ENERGY3 0x016a //kWh
212 |
213 | #define SDM_B_05 0x00 //BYTE 5
214 | #define SDM_B_06 0x02 //BYTE 6
215 | //------------------------------------------------------------------------------
216 | #define SDM_ERR_NO_ERROR 0 //no error
217 | #define SDM_ERR_CRC_ERROR 1 //crc error
218 | #define SDM_ERR_WRONG_BYTES 2 //bytes b0,b1 or b2 wrong
219 | #define SDM_ERR_NOT_ENOUGHT_BYTES 3 //not enough bytes from sdm
220 | #define SDM_ERR_TIMEOUT 4 //timeout
221 | //------------------------------------------------------------------------------
222 | class SDM {
223 | public:
224 | #if defined ( USE_HARDWARESERIAL ) //hardware serial
225 | #if defined ( ESP8266 ) // on esp8266
226 | SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG, bool swapuart = SWAPHWSERIAL);
227 | #elif defined ( ESP32 ) // on esp32
228 | 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);
229 | #else // on avr
230 | SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG);
231 | #endif
232 | #else //software serial
233 | #if defined ( ESP8266 ) || defined ( ESP32 ) // on esp8266/esp32
234 | SDM(SoftwareSerial& 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);
235 | #else // on avr
236 | SDM(SoftwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN);
237 | #endif
238 | #endif
239 | virtual ~SDM();
240 |
241 | void begin(void);
242 | float readVal(uint16_t reg, uint8_t node = SDM_B_01); //read value from register = reg and from deviceId = node
243 | uint16_t getErrCode(bool _clear = false); //return last errorcode (optional clear this value, default flase)
244 | uint16_t getErrCount(bool _clear = false); //return total errors count (optional clear this value, default flase)
245 | uint16_t getSuccCount(bool _clear = false); //return total success count (optional clear this value, default false)
246 | void clearErrCode(); //clear last errorcode
247 | void clearErrCount(); //clear total errors count
248 | void clearSuccCount(); //clear total success count
249 |
250 | private:
251 | #if defined ( USE_HARDWARESERIAL )
252 | HardwareSerial& sdmSer;
253 | #else
254 | SoftwareSerial& sdmSer;
255 | #endif
256 |
257 | #if defined ( USE_HARDWARESERIAL )
258 | int _config = SDM_UART_CONFIG;
259 | #if defined ( ESP8266 )
260 | bool _swapuart = SWAPHWSERIAL;
261 | #elif defined ( ESP32 )
262 | int8_t _rx_pin = -1;
263 | int8_t _tx_pin = -1;
264 | #endif
265 | #else
266 | #if defined ( ESP8266 ) || defined ( ESP32 )
267 | int _config = SDM_UART_CONFIG;
268 | #endif
269 | int8_t _rx_pin = -1;
270 | int8_t _tx_pin = -1;
271 | #endif
272 | long _baud = SDM_UART_BAUD;
273 | int _dere_pin = DERE_PIN;
274 | 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
275 | uint16_t readingerrcount = 0; //total errors counter
276 | uint32_t readingsuccesscount = 0; //total success counter
277 | uint16_t calculateCRC(uint8_t *array, uint8_t num);
278 | void flush(); //read serial if any old data is available
279 | void dereSet(bool _state = LOW); //for control MAX485 DE/RE pins, LOW receive from SDM, HIGH transmit to SDM
280 | };
281 | #endif //SDM_h
282 |
283 | //------------------------------------------------------------------------------
284 | #if defined ( USE_HARDWARESERIAL )
285 | #if defined ( ESP8266 )
286 | SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config, bool swapuart) : sdmSer(serial) {
287 | this->_baud = baud;
288 | this->_dere_pin = dere_pin;
289 | this->_config = config;
290 | this->_swapuart = swapuart;
291 | }
292 | #elif defined ( ESP32 )
293 | SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config, int8_t rx_pin, int8_t tx_pin) : sdmSer(serial) {
294 | this->_baud = baud;
295 | this->_dere_pin = dere_pin;
296 | this->_config = config;
297 | this->_rx_pin = rx_pin;
298 | this->_tx_pin = tx_pin;
299 | }
300 | #else
301 | SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config) : sdmSer(serial) {
302 | this->_baud = baud;
303 | this->_dere_pin = dere_pin;
304 | this->_config = config;
305 | }
306 | #endif
307 | #else
308 | #if defined ( ESP8266 ) || defined ( ESP32 )
309 | SDM::SDM(SoftwareSerial& serial, long baud, int dere_pin, int config, int8_t rx_pin, int8_t tx_pin) : sdmSer(serial) {
310 | this->_baud = baud;
311 | this->_dere_pin = dere_pin;
312 | this->_config = config;
313 | this->_rx_pin = rx_pin;
314 | this->_tx_pin = tx_pin;
315 | }
316 | #else
317 | SDM::SDM(SoftwareSerial& serial, long baud, int dere_pin) : sdmSer(serial) {
318 | this->_baud = baud;
319 | this->_dere_pin = dere_pin;
320 | }
321 | #endif
322 | #endif
323 |
324 | SDM::~SDM() {
325 | }
326 |
327 | void SDM::begin(void) {
328 | #if defined ( USE_HARDWARESERIAL )
329 | #if defined ( ESP8266 )
330 | sdmSer.begin(_baud, (SerialConfig)_config);
331 | #elif defined ( ESP32 )
332 | sdmSer.begin(_baud, _config, _rx_pin, _tx_pin);
333 | #else
334 | sdmSer.begin(_baud, _config);
335 | #endif
336 | #else
337 | #if defined ( ESP8266 ) || defined ( ESP32 )
338 | sdmSer.begin(_baud, (SoftwareSerialConfig)_config, _rx_pin, _tx_pin);
339 | #else
340 | sdmSer.begin(_baud);
341 | #endif
342 | #endif
343 |
344 | #if defined ( USE_HARDWARESERIAL ) && defined ( ESP8266 )
345 | if (_swapuart)
346 | sdmSer.swap();
347 | #endif
348 | if (_dere_pin != NOT_A_PIN) {
349 | pinMode(_dere_pin, OUTPUT); //set output pin mode for DE/RE pin when used (for control MAX485)
350 | }
351 | dereSet(LOW); //set init state to receive from SDM -> DE Disable, /RE Enable (for control MAX485)
352 | }
353 |
354 | float SDM::readVal(uint16_t reg, uint8_t node) {
355 | uint16_t temp;
356 | unsigned long resptime;
357 | uint8_t sdmarr[FRAMESIZE] = {node, SDM_B_02, 0, 0, SDM_B_05, SDM_B_06, 0, 0, 0};
358 | float res = NAN;
359 | uint16_t readErr = SDM_ERR_NO_ERROR;
360 |
361 | sdmarr[2] = highByte(reg);
362 | sdmarr[3] = lowByte(reg);
363 |
364 | temp = calculateCRC(sdmarr, FRAMESIZE - 3); //calculate out crc only from first 6 bytes
365 |
366 | sdmarr[6] = lowByte(temp);
367 | sdmarr[7] = highByte(temp);
368 |
369 | #if !defined ( USE_HARDWARESERIAL )
370 | sdmSer.listen(); //enable softserial rx interrupt
371 | #endif
372 |
373 | flush(); //read serial if any old data is available
374 |
375 | dereSet(HIGH); //transmit to SDM -> DE Enable, /RE Disable (for control MAX485)
376 |
377 | delay(2); //fix for issue (nan reading) by sjfaustino: https://github.com/reaper7/SDM_Energy_Meter/issues/7#issuecomment-272111524
378 |
379 | sdmSer.write(sdmarr, FRAMESIZE - 1); //send 8 bytes
380 |
381 | sdmSer.flush(); //clear out tx buffer
382 |
383 | dereSet(LOW); //receive from SDM -> DE Disable, /RE Enable (for control MAX485)
384 |
385 | resptime = millis() + MAX_MILLIS_TO_WAIT;
386 |
387 | while (sdmSer.available() < FRAMESIZE) {
388 | if (resptime < millis()) {
389 | readErr = SDM_ERR_TIMEOUT; //err debug (4)
390 | break;
391 | }
392 | yield();
393 | }
394 |
395 | if (readErr == SDM_ERR_NO_ERROR) { //if no timeout...
396 |
397 | if(sdmSer.available() >= FRAMESIZE) {
398 |
399 | for(int n=0; n>= 1;
481 | if (_flag)
482 | _crc ^= 0xA001;
483 | }
484 | }
485 | return _crc;
486 | }
487 |
488 | void SDM::flush() {
489 | uint8_t _i = 0;
490 | while (sdmSer.available() && _i++ < 10) { //read serial if any old data is available
491 | sdmSer.read();
492 | delay(1);
493 | }
494 | }
495 |
496 | void SDM::dereSet(bool _state) {
497 | if (_dere_pin != NOT_A_PIN)
498 | digitalWrite(_dere_pin, _state); //receive from SDM -> DE Disable, /RE Enable (for control MAX485)
499 | }
500 |
--------------------------------------------------------------------------------