rasProject_01 / weSweetHome
R. 240
process control / RasPi software by weinert-automation
|
Modbus functions for Raspberry Pis. More...
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... | |
Modbus functions for Raspberry Pis.
Revision history
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 enum modRS485state_t 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).
enum 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).
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.
modTCP | pointer to modTCP_t structure to be used |
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.
modTCP | pointer to modTCP_t structure to be used |
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.
modTCP | pointer to modTCP_t structure to be used |
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.
modTCP | pointer to modTCP_t structure to be used |
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.
dest | the strtring to copy the IP address to |
src | the IP string to copy to dest; NULL acts as "0.0.0.0" |
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.
str | the string to parse as (decimal) modPort; NULL acts as 502 |
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.
modRS | pointer to modRS_t structure to be used |
currentSlave | 1..247 sets the slave number; sets .currentSlave |
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.
modRS | pointer to modRS_t structure to be used |
currentSlave | if 1..247; sets the slave number to be used next and changes .currentSlave |
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.
modRS | pointer to modRS_t structure to be used |
currentSlave | if 1..247; sets .currentSlave |
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.
modRS | pointer to modRS_t structure to be used |
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()
dest | the dual registers to store the result in |
source | the dual registers with the potentially wrong endianess |
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()
dest | the array of dual registers to store the result in |
source | the array of dual registers with potentially wrong endianess |
n | the number of dual registers to treat |
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.
dest | the array of characters to store the result in |
source | the array registers with wrong character sorting |
n | the number of dual registers to treat |