Skip to content

Modbus Reader. Reads modbus data and sends that to an mqtt server.

License

Notifications You must be signed in to change notification settings

mats-bergstrom/mbrdr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mbrdr -- Modbus Reader

Reads data from a Huawei SUN2000 Solar Inverter and publishes the data
using MQTT.

This program is intended to be running on a Raspberry Pi.

Regarding the Huawei SSUN2000, the on-line fora are full of
suggestions on how to read out data with confidence but no real good
infomration seems to be available.  The Huawei responces indicate they
do not have any idea why reading data using modbus sometimes works,
sometimes not.

After experimening, I managed to cook up an algorithm that seems to
work (so far).  In pseudo code it looks like:

1    Establish a TCP connection.
2    Sleep 5 s.
3    For each parameter to read
4    	 read a parameter
5		send a modbus package
6		read the responce with a timeout of 5 s.
7	 sleep 2 s before reading the the next parameter

I.E. the modbus slave (renamed server some time ago) cannot cope with
incoming requests too quickly.

1: It needs a delay of several seconds after a TCP connection is
   established bef ore the first request is received, too quick and it
   does not respond at all, 5 s seems to have a very log failure rate.
2: The slave also needs a very long time before it responds, using a 5 s
   time-out gives a very low failure rate.
3: Requests must be separated by a long duration.  2 s gives a very low
   failure rate.

Note that ANY fault in the timing or using the wrong modbus id results
in no responce at all (time-out).

Also, if the device status is "Idle" (state code=0xa000) some
parameters are not red out correctly, e.g. the internal temperature
and on top of this, reading too many times will fail.  To avoid that
the program closes the TCP connection and reopens it.

To provide an inverter in the 1500-2000 USD range with this kind
timing issues and other quirks is really weird.

I used libmodbus for the modbus communication.  It works great but as
I prefer static linking for this I added a few scripts to build and
create a static library to link with.


A description of the modbus registers for my inverter (SUN2000-10KTL-M0)
can be found in:
https://www.photovoltaikforum.com/core/attachment/180219-solar-inverter-modbus-interface-definitions-v3-0-pdf/

To build:
	git clone https://github.com/mats-bergstrom/mbrdr.git
	cd mbrdr
	make-cfgf
	make-libmodbus
	make

To control:
	sudo systemctl start mbrdr
	sudo systemctl stop mbrdr
	sudo systemctl status mbrdr -n 100


Options:
	-v	Verbose mode.
	-n	No-active mode. Does not send mqtt topics.
	-m	No-modbus mode. Does not read modbus.

The config file:

	# Configuration for mbrdr
	#		broker address	port	mqtt id
	mqtt		127.0.0.1	1883	mbrdr-test
	#
	# modbus data	slave address	port	slave id
	modbus		127.0.0.1	502	1
	#
	# Time outs (s)	connect	read	write
	delays		5	5	2
	#
	# Intervals between reads in a given state (s)
	#		ACTIVE	IDLE	STANDBY
	intervals	120	900	120

The mqtt and modbus lines should be self explanatory.

The delays line sets the delay after a connect, the read time out and
delay between TCP writes to read a parameter.
The intervals are the intervals between the modbus device is polled
for data when it is in the ACTIVE, IDLE, and STANDBY states.


The parameters to read out and publish are in a hard-coded table (see below)
add/remove/change according to your needs.

typedef struct {
    uint16_t	addr;			/* modbus address to read */
    uint16_t	len;			/* no of words to read */
    uint32_t	gain;			/* gain of data */
    conv_t	conv;			/* data type and conversion */
    const char* fmt;			/* format conversion */
    const char*	topic;			/* topic of data */
} param_t;

param_t tab[] =
    {
     /* Always have status first */
     { 32089, 1,    1, conv_U1, "%02x",  "sun/status"		}, /*must be 0*/
     { 32087, 1,   10, conv_F,  "%.1lf", "sun/internalTemp"	}, /*must be 1*/
     { 32080, 2, 1000, conv_F,  "%.3lf", "sun/activePower"	},
     { 32064, 2, 1000, conv_F,  "%.3lf", "sun/inputPower"	},
     { 32106, 2,  100, conv_F,  "%.2lf", "sun/accEnergy"	},
     { 32114, 2,  100, conv_F,  "%.2lf", "sun/dailyEnergy"	},
     
     { 0,0,0,0,0,0}			/* Terminator */
};

About

Modbus Reader. Reads modbus data and sends that to an mqtt server.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages