rasProject_01 / weSweetHome  R. 240
process control       /     RasPi software         by   weinert-automation
Loading...
Searching...
No Matches
weModbus.h File Reference

Modbus functions for Raspberry Pis. More...

#include <modbus-private.h>
#include <modbus.h>
#include "weUtil.h"

Data Structures

struct  modRS_t
 Structure for Modbus RS485 (RTU). More...
 
struct  modTCP_t
 Structure for Modbus TCP. More...
 

Typedefs

typedef enum modRS485state_t modRS485state_t
 A definition for possible states of a Modbus RS485 interface. More...
 

Enumerations

enum  modRS485state_t {
  RS_OFF , RS_ON , RS_INICOM , RS_ERR_ANY ,
  RS_ERR_CTX , RS_ERR_CON , RS_ERR_SLA , RS_ERR_BAD
}
 A definition for possible states of a Modbus RS485 interface. More...
 

Functions

void modRSclose (modRS_t *modRS)
 Close a Modbus RS link and destroy the (libmodbus) structure. More...
 
int modRSconnect (modRS_t *modRS, int currentSlave)
 Connect a the Modbus (libmodbus) structure for RS485 (RTU). More...
 
int modRSctxNew (modRS_t *modRS, int currentSlave)
 Make a new Modbus (libmodbus) structure for RS485. More...
 
int modRSswitchSlave (modRS_t *modRS, int currentSlave)
 Switch the slave on a connected Modbus (libmodbus) structure for RS485. More...
 
void modTCPclose (modTCP_t *modTCP)
 Close a Modbus TCP and destroy the (libmodbus) structure. More...
 
int modTCPconnect (modTCP_t *modTCP)
 Connect a the Modbus (libmodbus) structure for TCP. More...
 
int modTCPctxNew (modTCP_t *modTCP)
 Make a new Modbus (libmodbus) structure for TCP. More...
 
int modTCPlisten (modTCP_t *modTCP)
 Listen at the Modbus (libmodbus) structure for TCP. More...
 
int parseModPort (const char *str)
 Parse a string as Modbus TCP port number with checks. More...
 
void reg2val32 (dualReg_t *const dest, dualReg_t const *const source)
 Copy float (32 bit) Modbus input to correctly ordered value. More...
 
uint16_t regs2string (char *dest, uint16_t *source, int n)
 Copy a sequence of character pairs from registers to a string. More...
 
void regs2vals32 (float *const dest, dualReg_t const *const source, int const n)
 Copy n float (32 bit) Modbus input to correctly ordered values. More...
 
int setIP4add (char *dest, const char *src)
 Set an IPv4 address as string with syntax checks. More...
 

Detailed Description

Modbus functions for Raspberry Pis.

Copyright (c) 2019 Albrecht Weinert
weinert-automation.de a-weinert.de
/ / /\
/ /___ / \ |
\ /____\ /____\ | _|__
\ /\ / \ / \| |
\/ \/ \__/ \__/|_

Revision history

Rev. 236 2.02.2021
Rev. 38 22.08.2017 : new
Rev. 187 14.10.2018 : minor typos
Rev. 191 15.02.2019 : minor comment text changes
Rev. 212 04.08.2019 : regs2string added
Rev. 216 31.08.2019 : modRS_t int conErr removed (never used)
Structure for Modbus RS485 (RTU).
Definition: weModbus.h:174
uint16_t regs2string(char *dest, uint16_t *source, int n)
Copy a sequence of character pairs from registers to a string.
Definition: weModbus.c:78

This is a supplementary (basic) library. The functions and structures defined here will work with Stéphane Raimbault's Modbus library libmodbus.

Some structures and utilities are to support smart meters like e.g. SDM230Modbus, SMD630Modbus and SDM538Modbus as servers/slaves, especially their handling of (32 bit) float values.

Typedef Documentation

◆ modRS485state_t

A definition for possible states of a Modbus RS485 interface.

With Modbus TCP one has not to handle the (Ethernet or WLAN) interface. One just has to listen at a port or connect to IPadress:port. The handling of multiple connections on the network is done by the operating system and the network infrastructure.

With an RS485 "bus" connecting Modbus devices it's different. Every device's software has to handle the physical interface. Usually only Modbus devices can be at that "bus" — 2 to 247. The communication is client request --> server response (as always), but request response pairs to/from different servers cannot overlap. (Additionally the telegrams are short and slow.)

Hence with RS485 (RTU) the handling of multiple (server) connections has to be implemented in the client application, and the RS485 interface/bus state has to be separated from (multiple) server-link states.
With RS232 the complications and disadvantages are the same while being restricted to point to point (P2P, no bus).

Enumeration Type Documentation

◆ modRS485state_t

A definition for possible states of a Modbus RS485 interface.

With Modbus TCP one has not to handle the (Ethernet or WLAN) interface. One just has to listen at a port or connect to IPadress:port. The handling of multiple connections on the network is done by the operating system and the network infrastructure.

With an RS485 "bus" connecting Modbus devices it's different. Every device's software has to handle the physical interface. Usually only Modbus devices can be at that "bus" — 2 to 247. The communication is client request --> server response (as always), but request response pairs to/from different servers cannot overlap. (Additionally the telegrams are short and slow.)

Hence with RS485 (RTU) the handling of multiple (server) connections has to be implemented in the client application, and the RS485 interface/bus state has to be separated from (multiple) server-link states.
With RS232 the complications and disadvantages are the same while being restricted to point to point (P2P, no bus).

Enumerator
RS_OFF 

do not use Modbus RS485 link (no ctx structure made)

RS_ON 

may be usable, but totally uninitialised (no com.)

RS_INICOM 

initialised (ready for communication)

RS_ERR_ANY 

no concrete error, lower bound of all error states

RS_ERR_CTX 

no structure made (hopeless when re-occurring)

RS_ERR_CON 

open serial failed

RS_ERR_SLA 

any slave error requiring re-open

RS_ERR_BAD 

recurring error in usage (try conn. re-init)

Function Documentation

◆ modTCPctxNew()

int modTCPctxNew ( modTCP_t modTCP)

Make a new Modbus (libmodbus) structure for TCP.

This function makes a new modTCP.ctx according to .addr and .port; it does NOT check NOR change .mlStat.

Parameters
modTCPpointer to modTCP_t structure to be used
Returns
0 : OK; -1: error

◆ modTCPconnect()

int modTCPconnect ( modTCP_t modTCP)

Connect a the Modbus (libmodbus) structure for TCP.

This function makes a new modTCP.ctx according to .addr and .port, if not yet made. Then it "connects" it. On success 0 is returned. On failure -1 is returned and modTCP.ctx will be destroyed.

This function does NOT check NOR change .mlStat.

Parameters
modTCPpointer to modTCP_t structure to be used
Returns
0 : OK; -1: error

◆ modTCPlisten()

int modTCPlisten ( modTCP_t modTCP)

Listen at the Modbus (libmodbus) structure for TCP.

This function makes a new modTCP.ctx according to .addr and .port, if not yet made. Then it "listens" on it. On success .s >= 0, that is the socket, is returned. On failure -1 is returned and modTCP.ctx will be destroyed. The number of connections is limited to one, here.

This function does NOT check NOR change .mlStat.

Parameters
modTCPpointer to modTCP_t structure to be used
Returns
>=0 : OK, i.e the socket andmodTCP.s; -1: error

◆ modTCPclose()

void modTCPclose ( modTCP_t modTCP)

Close a Modbus TCP and destroy the (libmodbus) structure.

This function closes the connection (if on) and destroys modTCP.ctx (if existing) .mlStat will be set to ML_OFF.

Parameters
modTCPpointer to modTCP_t structure to be used

◆ setIP4add()

int setIP4add ( char *  dest,
const char *  src 
)

Set an IPv4 address as string with syntax checks.

This function sets the parameter dest with src, doing syntactic checks to assure a valid IPv4 address being set.

Parameters
destthe strtring to copy the IP address to
srcthe IP string to copy to dest; NULL acts as "0.0.0.0"
Returns
0: syntax error or dest is NULL, dest unchanged; 1: OK

◆ parseModPort()

int parseModPort ( const char *  str)

Parse a string as Modbus TCP port number with checks.

This function parses the string src as Modbus port number, doing validity checks: src must be a decimal number 502 or 1024..65535.

Parameters
strthe string to parse as (decimal) modPort; NULL acts as 502
Returns
0: syntax error, else valid Modbus port number (see above)

◆ modRSctxNew()

int modRSctxNew ( modRS_t modRS,
int  currentSlave 
)

Make a new Modbus (libmodbus) structure for RS485.

This function makes a new modTCP.ctx according to .addr and .port; it does NOT check NOR change .rsState.

Parameters
modRSpointer to modRS_t structure to be used
currentSlave1..247 sets the slave number; sets .currentSlave
Returns
0 : OK; else: error: -1: modRS null; -2: slave number: -3: no ctx

◆ modRSconnect()

int modRSconnect ( modRS_t modRS,
int  currentSlave 
)

Connect a the Modbus (libmodbus) structure for RS485 (RTU).

This function makes a new modRS.ctx according to .device and else. Then it "connects" it. On success 0 is returned. On failure -1 is returned and modTCP.ctx will be destroyed.

This function does NOT check NOR change .rsState.

Parameters
modRSpointer to modRS_t structure to be used
currentSlaveif 1..247; sets the slave number to be used next and changes .currentSlave

◆ modRSswitchSlave()

int modRSswitchSlave ( modRS_t modRS,
int  currentSlave 
)

Switch the slave on a connected Modbus (libmodbus) structure for RS485.

This function changes nothing on a functional and connected modRS.ctx setting than the slave number.

Modbus RS485 (RTU) can handle multiple slaves on the same serial interface. This has to be one at a time in a pure sequential matter: hence this slave switching.
With RS232 the one slave's number once correctly established would stay fixed.

Unfortunately (by a libmodbus deficiency) a communication error of one slave would require a total new connect (modRSconnect()) for all slaves; switching to a "good slave" won't help.

Parameters
modRSpointer to modRS_t structure to be used
currentSlaveif 1..247; sets .currentSlave
Returns
-1: error wrong parameter or no modRS; 0: no change or no ctx; 1..247: changed currentSlave; OK

◆ modRSclose()

void modRSclose ( modRS_t modRS)

Close a Modbus RS link and destroy the (libmodbus) structure.

This function destroys modRS.ctx (if existing). .rsState will not be changed.

Parameters
modRSpointer to modRS_t structure to be used

◆ reg2val32()

void reg2val32 ( dualReg_t *const  dest,
dualReg_t const *const  source 
)

Copy float (32 bit) Modbus input to correctly ordered value.

This function copies a 32bit (e.g.) float value input from Modbus — with correct byte ordering at 16 bit level (!) — to a correctly ordered (32 bit) value.
Destination and source pointers may be the same, but not NULL.
The swap of the 16-bit parts only occurs, when the platform is little endian.
See also: PLATFlittlE and regs2vals32()

Parameters
destthe dual registers to store the result in
sourcethe dual registers with the potentially wrong endianess

◆ regs2vals32()

void regs2vals32 ( float *const  dest,
dualReg_t const *const  source,
int const  n 
)

Copy n float (32 bit) Modbus input to correctly ordered values.

This function copies n 32bit (e.g.) float values input from Modbus — with correct byte ordering at 16 bit level (!) — to correctly ordered (32 bit) values.
Destination and source pointers may be the same, but not NULL.
The swap of the 16-bit parts only occurs, when the platform is little endian.
See also: PLATFlittlE and reg2val32()

Parameters
destthe array of dual registers to store the result in
sourcethe array of dual registers with potentially wrong endianess
nthe number of dual registers to treat

◆ regs2string()

uint16_t regs2string ( char *  dest,
uint16_t *  source,
int  n 
)

Copy a sequence of character pairs from registers to a string.

Growatt inverter holding registers, for example, deliver strings as pairs of ASCII characters in consecutive registers. If the number of characters is odd the last register holds just one character. Some of those strings in registers are 0-terminated and some are not. In the first case the transfer stops at the 0, in the latter case a 0 is appended to the destination string as n+1st character.
The sequence of the two characters in each register is (as usual with Modbus) in wrong order. Hence, memcopy and consorts would fail.

Parameters
destthe array of characters to store the result in
sourcethe array registers with wrong character sorting
nthe number of dual registers to treat
Returns
the number of characters transfered to dest including the terminating 0