Usually the MODBUS protocoll only supports registers based on 16-bit values. If you want to transfer custom datatypes like double, float etc. via the modbus a simple trick can be used.
My solution for variable datatypes is simple.
- Define a c-type
- Initialize the modbus using this datatype
Below you can find sample code for the client as well as for the master side.
Define datatype
#ifndef _MB_SlaveData3_H
#define _MB_SlaveData3_H
typedef struct {
double waterTemp;
unsigned int waterLevel;
unsigned int waterLevelRaw;
unsigned int chipVcc;
unsigned int chipTemp;
}
t_MB_SlaveData3;
#endif
Initialize MODBUS
Slave side
#include <MB_SlaveData3.h>
t_MB_SlaveData3 modBusRegisters;
void setup() {
modbus_configure(MODBUS_BAUD, MODBUS_SLAVE_ID, MODBUS_TXENABLEPIN, sizeof modBusRegisters / sizeof (unsigned int) );
Master side
#include <MB_SlaveData3.h>
// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
PACKET1,
// leave this last entry
TOTAL_NO_OF_PACKETS,
};
// this is my custom datatype transfered via modbus
t_MB_SlaveData3 modbusSlave1;
// Create an array of Packets for modbus_update()
Packet packets[TOTAL_NO_OF_PACKETS];
// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];
void modbus_setup(void) {
packet1->id = 1;
packet1->function = READ_HOLDING_REGISTERS;
packet1->address = 0;
packet1->no_of_registers = sizeof (modbusSlave1) / sizeof (unsigned int);
packet1->register_array = (unsigned int*) &modbusSlave1;
packet1->packetReceived = 0;
// Initialize communication settings etc...
modbus_configure(MODBUS_BAUD, MODBUS_TIMEOUT, MODBUS_POLLING, MODBUS_RETRYCOUNT, MODBUS_TXENABLEPIN, packets, TOTAL_NO_OF_PACKETS);
}