/SDM_Energy_Meter

reading SDM120 SDM220 SDM230 SDM630 modbus energy meters from arduino (esp8266, avr)

Primary LanguageC++

Library for reading SDM120 SDM220 SDM230 SDM630 Modbus Energy meters.

SECTIONS:


Introduction:

This library allows you reading SDM module(s) using:

  • Hardware Serial (recommended option, smallest number of reads errors, especially for esp8266) or
  • Software Serial (library for ESP8266), attached as libraries for esp8266 and avr

you also need rs232<->rs485 converter:

  • with automatic flow direction control (look at images below) or
  • with additional pins for flow control, like MAX485
    (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


Screenshots:



live page example (extended) screenshot


Configuring:

Default configuration is specified in the SDM.h file, and parameters are set to:
Software Serial, baud 4800, uart config SERIAL_8N1, without DE/RE pin.

User can set the parameters in two ways:

  • by editing the SDM_Config_User.h file
  • by passing values during initialization (section below)

NOTE for Hardware Serial mode: to force the Hardware Serial mode,
user must edit the corresponding entry in SDM_Config_User.h file.
adding #define USE_HARDWARESERIAL to the main ino file is not enough.


Initializing:

If the user configuration is specified in the SDM_Config_User.h file
or if the default configuration from the SDM.h file is suitable
initialization is limited to passing serial port reference (software or hardware)
and looks as follows:

//lib init when Software Serial is used:
#include <SoftwareSerial.h>
#include <SDM.h>

SoftwareSerial swSerSDM(13, 15);

//              _software serial reference
//             |
SDM sdm(swSerSDM);
//lib init when Hardware Serial is used:
#include <SDM.h>

//            _hardware serial reference
//           |
SDM sdm(Serial);

If the user wants to temporarily change the configuration during the initialization process
then can pass additional parameters as below:

//lib init when Software Serial is used:
#include <SoftwareSerial.h>
#include <SDM.h>

SoftwareSerial swSerSDM(13, 15);

//              __________________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);
//lib init when Hardware Serial is used:
#include <SDM.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)
//           |     |          |           |      |       _tx pin number(optional)
//           |     |          |           |      |      | 
SDM sdm(Serial, 9600, NOT_A_PIN, SERIAL_8N1, rxpin, txpin);


// 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,
connection this type of converters to ESP8266 pin GPIO15 block booting process.
In this case you can replace the pull-up resistor on converter with higher value (100k),
to ensure low level on GPIO15 by built-in in most ESP8266 modules pulldown resistor.


Reading:

List of available registers for SDM120/220/230/630:
https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L52

//reading voltage from SDM with slave address 0x01 (default)
//                                      __________register name
//                                     |
float voltage = sdm.readVal(SDM220T_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);

NOTE: if you reading multiple SDM devices on the same RS485 line,
remember to set the same transmission parameters on each device,
only ID must be different for each SDM device.


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.

Please check out open and close issues, maybe the cause of your error is explained or solved there.

The most common problems are:

You can get last error code using function:

//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
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#L161

You can also check total number of errors using function:

//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)
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:

//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:

👍 ESP SoftwareSerial library by Peter Lerup (https://github.com/plerup/espsoftwareserial)
👍 crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino)
👍 new registers for SDM120 and SDM630 by bart.e (https://github.com/beireken/SDM220t)


old library version is available at old_template branch


2016-2019 Reaper7

paypal.me/reaper7md