/dds238_Energy_Meter

reading DDS238-4 W; DDS238 4 ZN/S; DDS238 2 ZN/S; DDS238 1 ZN Modbus Energy meters from arduino (esp8266, avr)

Primary LanguageC++

Library for reading DDS238-4 W; DDS238 4 ZN/S; DDS238 2 ZN/S; DDS238 1 ZN Modbus Energy meters.

SECTIONS:


Introduction:

This library allows you reading dds238 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 DDS238-4 Wemos d1 mini->ESP8266 with Arduino 1.8.9-beta & 2.3.0 esp8266 core


Screenshots:



live page example (extended) screenshot


Configuring:

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

User can set the parameters in two ways:

NOTE for Hardware Serial mode: to force the Hardware Serial mode,
user must edit the corresponding entry in dds238_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 dds238_Config_User.h file
or if the default configuration from the dds238.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 <dds238.h>

SoftwareSerial swSerdds238(13, 15);

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

//            _hardware serial reference
//           |
dds238 dds238(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 <dds238.h>

SoftwareSerial swSerdds238(13, 15);

//              __________________software serial reference
//             |      ____________baudrate(optional, default from dds238_Config_User.h)   
//             |     |           _dere pin for max485(optional, default from dds238_Config_User.h)
//             |     |          |
dds238 dds238(swSerdds238, 9600, NOT_A_PIN);
//lib init when Hardware Serial is used:
#include <dds238.h>

// for ESP8266
//            _____________________________________hardware serial reference
//           |      _______________________________baudrate(optional, default from dds238_Config_User.h)
//           |     |           ____________________dere pin for max485(optional, default from dds238_Config_User.h)
//           |     |          |            ________hardware uart config(optional, default from dds238_Config_User.h)
//           |     |          |           |       _swap hw serial pins from 3/1 to 13/15(optional, default from dds238_Config_User.h)
//           |     |          |           |      |
dds238 dds238(Serial, 9600, NOT_A_PIN, SERIAL_8N1, false);


// for ESP32
//            ____________________________________________hardware serial reference
//           |      ______________________________________baudrate(optional, default from dds238_Config_User.h)
//           |     |           ___________________________dere pin for max485(optional, default from dds238_Config_User.h)
//           |     |          |            _______________hardware uart config(optional, default from dds238_Config_User.h)
//           |     |          |           |       ________rx pin number(optional)
//           |     |          |           |      |       _tx pin number(optional)
//           |     |          |           |      |      | 
dds238 dds238(Serial, 9600, NOT_A_PIN, SERIAL_8N1, rxpin, txpin);


// for AVR
//            _____________________________________hardware serial reference
//           |      _______________________________baudrate(optional, default from dds238_Config_User.h)
//           |     |           ____________________dere pin for max485(optional, default from dds238_Config_User.h)
//           |     |          |            ________hardware uart config(optional, default from dds238_Config_User.h)
//           |     |          |           |
//           |     |          |           |
dds238 dds238(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 DDS238-4 W; DDS238 4 ZN/S; DDS238 2 ZN/S; DDS238 1 ZN:
https://github.com/E-NINA/dds238_Energy_Meter/blob/master/dd238.h#L52

//reading voltage from dds238 with slave address 0x01 (default)
//                                      __________register name
//                                     |        __Data length type
//                                     |       |
float voltage = dds238.readVal(dds238_VOLTAGE, 2);

//reading power from 1st dds238 with slave address ID = 0x01
//reading power from 2nd dds238 with slave address ID = 0x02
//useful with several meters on RS485 line
//                                      ___________register name
//                                     |     ______Data length type
//                                     |    |     _dds238 device ID  
//                                     |    |    |
float power1 = dds238.readVal(dds238_POWER, 2, 0x01);
float power2 = dds238.readVal(dds238_POWER, 2, 0x02);

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


Problems:

Sometimes readVal return NaN value (not a number),
this means that the requested value could not be read from the dds238 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 = dds238.getErrCode(true);

//clear error code also available with:
dds238.clearErrCode();

Errors list returned by getErrCode:
https://github.com/E-NINA/dds238_Energy_Meter/blob/master/dd238.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 = dds238.getErrCount(true);

//clear errors counter also available with:
dds238.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 = dds238.getSuccCount(true);

//clear success counter also available with:
dds238.clearSuccCount();

Credits:

👍 SDM_Energy_Meter library by Reaper7 (https://github.com/reaper7/SDM_Energy_Meter)
👍 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)