Skip to content

steefan85/ABB_B23_Energy_Meter

ย 
ย 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Library for reading ABB B23 Modbus Energy meters.

SECTIONS:


Introduction:

This library allows you reading ABB B23 energy meter(s) using:

  • Hardware Serial (recommended option, smallest number of reads errors, especially for esp8266) or
  • Software Serial, attached as core libraries for esp8266 and avr
    (the new version of esp Software Serial library
    has a different initialization compared to avr!
    This version of ABB_B23 library (>=1.1.0) works only with esp Software Serial 6.0.0 or higher!
    If you have an older esp Software Serial version
    use library version 1.0.x
    )

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
    )

Configuring:

Default configuration is specified in the ABB_B23.h file, and parameters are set to:
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:

ABB_B23_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 ABB_B23_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 ABB_B23_Config_User.h file.
adding #define USE_HARDWARESERIAL to the main ino file is not enough.

Keep in mind you need to set your ABB_B23 to RTU-mode with the same baudrate as defined here, for example "BAU r4.8k".


Initializing:

If the user configuration is specified in the ABB_B23_Config_User.h file
or if the default configuration from the ABB_B23.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 <ABB_B23.h>
#include <SoftwareSerial.h>

// for ESP8266 and ESP32
SoftwareSerial swSerABB_B23;
//              _______________________________software serial reference
//             |
ABB_B23 ABB_B23(swSerABB_B23);


// for AVR
SoftwareSerial swSerABB_B23(ABB_B23_RX_PIN, ABB_B23_TX_PIN);
//                               |           |_tx pin definition(from ABB_B23_Config_User.h)
//                               |_____________rx pin definition(from ABB_B23_Config_User.h)
//
//              _______________________________software serial reference
//             |
ABB_B23 ABB_B23(swSerABB_B23);
//lib init when Hardware Serial is used:
#include <ABB_B23.h>

//            _________________________________hardware serial reference
//           |
ABB_B23 ABB_B23(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 <ABB_B23.h>
#include <SoftwareSerial.h>

// for ESP8266 and ESP32
SoftwareSerial swSerABB_B23;
//              ________________________________________software serial reference
//             |      __________________________________baudrate(optional, default from ABB_B23_Config_User.h)
//             |     |           _______________________dere pin for max485(optional, default from ABB_B23_Config_User.h)
//             |     |          |              _________software uart config(optional, default from ABB_B23_Config_User.h)
//             |     |          |             |    _____rx pin number(optional, default from ABB_B23_Config_User.h)
//             |     |          |             |   |    _tx pin number(optional, default from ABB_B23_Config_User.h)
//             |     |          |             |   |   | 
ABB_B23 ABB_B23(swSerABB_B23, 9600, NOT_A_PIN, SWSERIAL_8N1, 13, 15);


// for AVR
SoftwareSerial swSerABB_B23(10, 11);
//              ________________________________________software serial reference
//             |      __________________________________baudrate(optional, default from ABB_B23_Config_User.h)   
//             |     |           _______________________dere pin for max485(optional, default from ABB_B23_Config_User.h)
//             |     |          |
ABB_B23 ABB_B23(swSerABB_B23, 9600, NOT_A_PIN);
//lib init when Hardware Serial is used:
#include <ABB_B23.h>

// for ESP8266
//            ______________________________________hardware serial reference
//           |      ________________________________baudrate(optional, default from ABB_B23_Config_User.h)
//           |     |           _____________________dere pin for max485(optional, default from ABB_B23_Config_User.h)
//           |     |          |            _________hardware uart config(optional, default from ABB_B23_Config_User.h)
//           |     |          |           |       __swap hw serial pins from 3/1 to 13/15(optional, default from ABB_B23_Config_User.h)
//           |     |          |           |      |
ABB_B23 ABB_B23(Serial, 9600, NOT_A_PIN, SERIAL_8N1, false);


// for ESP32
//            ______________________________________hardware serial reference
//           |      ________________________________baudrate(optional, default from ABB_B23_Config_User.h)
//           |     |           _____________________dere pin for max485(optional, default from ABB_B23_Config_User.h)
//           |     |          |            _________hardware uart config(optional, default from ABB_B23_Config_User.h)
//           |     |          |           |    _____rx pin number(optional, default from ABB_B23_Config_User.h)
//           |     |          |           |   |    _tx pin number(optional, default from ABB_B23_Config_User.h)
//           |     |          |           |   |   | 
ABB_B23 ABB_B23(Serial, 9600, NOT_A_PIN, SERIAL_8N1, 13, 15);


// for AVR
//            ______________________________________hardware serial reference
//           |      ________________________________baudrate(optional, default from ABB_B23_Config_User.h)
//           |     |           _____________________dere pin for max485(optional, default from ABB_B23_Config_User.h)
//           |     |          |            _________hardware uart config(optional, default from ABB_B23_Config_User.h)
//           |     |          |           |
//           |     |          |           |
ABB_B23 ABB_B23(Serial, 9600, NOT_A_PIN, SERIAL_8N1);

NOTE for ESP8266: when GPIO15 is used (especially for swapped hardware serial):
some converters 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 ABB B23:
https://github.com/steefan85/ABB_B23_Energy_Meter/blob/master/ABB_B23.h#L88

//reading voltage from ABB_B23 with slave address 0x01 (default)
//                                      __________register name
//                                     |
float voltage = ABB_B23.readVal(ABB_B23_U_SYSTEM);

//reading power from 1st ABB_B23 with slave address ID = 0x01
//reading power from 2nd ABB_B23 with slave address ID = 0x02
//useful with several meters on RS485 line
//                                      __________register name
//                                     |      ____ABB_B23 device ID  
//                                     |     |
float power1 = ABB_B23.readVal(ABB_B23_P_SYSTEM, 0x01);
float power2 = ABB_B23.readVal(ABB_B23_P_SYSTEM, 0x02);

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


Problems:

Sometimes readVal return NaN value (not a number),
this means that the requested value could not be read from the ABB_B23 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:

  • weak or poorly filtered power supply / LDO, causing NaN readings and ESP crashes
  • faulty or incorrectly prepared converter
  • faulty esp module
  • many users report that between each readings should be placed delay(50);
  • using GPIO15 without checking signal level (note above)
  • compilation error for hardware serial mode

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 = ABB_B23.getErrCode(true);

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

Errors list returned by getErrCode:
https://github.com/steefan85/ABB_B23_Energy_Meter/blob/master/ABB_B23.h#L243

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 = ABB_B23.getErrCount(true);

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

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

Credits:

๐Ÿ‘ ABB_B23_Energy_Meter library by adlerweb (https://github.com/adlerweb/ABB_B23_Energy_Meter)
๐Ÿ‘ 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)
๐Ÿ‘ influxdb example by AndersV209 (reaper7#45)

About

reading ABB B23 Modbus energy meters from ESP8266

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 87.9%
  • C 12.1%