I have developed a few flows for third parties that have mainly involved decoding Modbus data.
However I have never used Modbus in a live environment and needed to get familiar with the basics in order to develop and test these flows.
These are my working notes from my efforts to create these flows and in particular an MQTT to Modbus bridge.
If you are new to Modbus you may find them useful.
This is a very good video that covers the basics and following are my notes.
The first Modbus protocol was based on RS-485 physical layer (shielded twisted pair). This is called Modbus RTU (Remote Terminal Unit).
This is a multi-point network (32 connection nodes per bus extendable to a larger number of nodes through RS-485 repeater which occupies one node).
Modbus Over TCP/IP
There are two variants:
- Modbus RTU over TCP – Uses Encapsularion
- Modbus MBAP -uses a modifed MBAP( Modbus application header)
A modbus device needs to be configured to use the correct variant. Modbus MBAP is the most popular.
How it Works
Modbus uses a master slave architecture using command/response protocol.
Commands are simple requests to read or write data to a coil or register.
Modbus uses 4 data tables to store data, and Data storage uses 16 bits.
Data can be stored as single bits or as a 16 bit register.
There are two tables for single bit values (known as coils) a read only table and a read/write table, and there are two tables for 16 bit values(known as registers) a read only table and a read/write table.
Each table can hold 9999 values.
Coils or contacts are 1 bit and have an address of 0 to 027E
Registers are 16 bit and have an address of 0 to 027E
The starting address of each table is as follows
|Coil/Register Numbers||Type||Table Name||Data Addresses||Data Type|
|1-9999||Read-Write||Discrete Output Coils||0000 to 270E||Boolean|
|10001-19999||Read-Only||Discrete Input Coils||0000 to 270E||Boolean|
|30001-39999||Read-Only||Analogue Input Registers||0000 to 270E||Unsigned Word|
|40001-49999||Read-Write||Analogue Output Holding Registers||0000 to 270E||Unsigned Word|
Note: Modbus commands do not include the register numbers but only the offset from the start address.
The following table shows the common commands
|Function Code||Action||Table Name|
|01||Read||Discrete Output Coils|
|05||Write single||Discrete Output Coil|
|15||Write multiple||Discrete Output Coils|
|02||Read||Discrete Input Contacts|
|04||Read||Analogue Input Registers|
|03||Read||Analogue Output Holding Registers|
|06||Write single||Analogue Output Holding Register|
|16||Write multiple||Analogue Output Holding Registers|
Although modbus doesn’t support 32 bit values they can be created by combining 2 *16 bit registers.
Network Byte Order and System Byte Order
Network Byte Order refers to how bytes are arranged when sending data over a network. ( TCP/IP is generally Big Endian ).
This means most significant byte is sent first.
System or Host Byte Order refers to how bytes are arranged when stored in memory on the host system.
MODBUS generally uses a ‘big-endian’ format for addresses and data items.
This means that when a numerical quantity larger than a single byte is transmitted, the MOST significant byte is sent first.
However this is not guaranteed and so it is important to know how your devices transmit data.
For the RTU interface we have
Slave Address +Function Code+Offset Address +Number of Registers+ CRC (Cyclic redundancy check)
For the TCP interface we use the MBAP header which is 7 bytes and we drop the slave address and CRC.
MBAP+Function Code+Offset Address +Number of Registers