![]() |
rasProject_01 / weSweetHome
R. 77 2025-03-07
process control / RasPi software by weinert-automation
|
Modbus functions for Raspberry Pis. More...
#include "weUtil.h"
Data Structures | |
struct | modRS_t |
Structure for Modbus RS485 (RTU). 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 , 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... | |
int | parseModPort (const char *str) |
Parse string as Modbus port 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... | |
Modbus functions for Raspberry Pis.
Revision history
This was a supplementary (basic) library. The functions and structures defined here did 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 parseModPort | ( | const char * | str | ) |
Parse string as Modbus port with checks.
502 or 1024..65535
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 |