Protocol: Modbus

Getting Started

This page is the reference section for the Modbus Protocol in SHIP.

If you’re just getting started, you may want to start with App Note AN0500 – Using Modbus in SHIP: A Step-by-Step Tutorial.

What is Modbus?

Modbus is a very simple master/slave communications protocol operated traditionally over point-to-point RS232 or multi-drop RS485 networks.

It is designed to be operated in half-duplex mode, with one device, and one device only, designated the master that is responsible for polling and directing all the slaves. Slaves cannot spontaneously initiate data messages: they must be polled by the master. Similarly, slaves cannot talk peer-to-peer to another slave. The master must poll one slave, gather data, and re-send it to another.

Every slave on a given network must have a unique identification number (slave ID). Slaves may respond to more than one slave ID (acting as multiple slaves in one physical device), but no slave IDs can overlap. Slaves can be simple devices, like sensors or actuators, often with a tiny DIP switch to manually select from a range of slave IDs. More sophisticated slaves can implement front-panel selectable slave IDs.

The master has no id (although in some networks 0 is reserved for the master). This is because the slaves do not need to address the master explicitly, they always just respond to requests from the master.

Protocol Modes

Modbus is a very simple set of packet protocol. When the packet is decoded, regardless of the protocol transmission “mode”, it contains exactly the same message contents. Software decoders can be written with various decoder/encoder front ends for the different transmission modes and the rest of the software can be unified.

When Modbus is transmitted over RS232, RS422, and RS485 type serial networks, there are two standard transmission modes: ASCII or RTU (binary). The serial network must be designated ASCII or RTU. You cannot mix modes on the same network. There is no negotiation process and auto-baud capabilities do not exist. The type must be set by the network/system designer once and all devices on the network must be manually set to the correct speed.

When Modbus is transmitted over TCP/IP, the Modbus TCP mode is used.

For more information on the protocol, see the list of modbus references.

ASCII

MODBUS_SLAVE_ASCII is a human-readable ASCII transmission format and is easy to debug on a sniffer terminal device (a device that only listens but does not drive the RS232 or RS485 cable) since a terminal program would display the packets. It is very easy to parse in software, with unique start (‘:’) and end-packet characters (CR-LF), but because every byte is sent as a hex-ascii value (for example, an ‘a’ is sent as two bytes ‘2’ and ‘1’, representing hex 0x21 which is an ‘a’), it is half the speed of a binary transmission protocol.

Every master-initiated packet looks like this:
Modbus ASCII Packet Format (Master Packet)
Name Bytes Description
Start 1":" (ASCII 0x3A) start-of-packet character
Slave ID 2ASCII of slave id (for example, slave id 0x2F is sent as two characters "2" and "F")
Function Code 2ASCII of command (called a "function code", or "FCxx" where xx is the code)
Data variesCommand specific data as a sequence of ASCII characters (2 per byte), in MSB format
Checksum2Simple 8-bit checksum
End2CR-LF sequence terminating packet
Every slave responds with a modified version of the packet:
Modbus ASCII Packet Format (Slave Response)
NameBytesDescription
Start 1":" (ASCII 0x3A) start-of-packet character
Slave ID2ASCII of slave id
Function Code 3ASCII of command with high bit set if error
DatavariesCommand specific response data
Checksum2Simple 8-bit checksum
End2CR-LF sequence terminating packet

Modbus ASCII mode has several advantages:

  • easy to debug on a sniffer terminal device (a device that only listens but does not drive the RS232 or RS485 cable) since a terminal program can display the packets in a human readable format, 1 packet per line
  • easy to parse and stay synchronized in software, with a unique start character (‘:’) and end sequence (CR-LF)
  • smaller/simpler software for the 8-bit checksum calculation than the 16-bit CRC used in RTU mode

and a few disadvantages:

  • half the speed of RTU: every byte is sent as a hex-ASCII value , it is half the speed of a binary transmission protocol.
  • less robust than RTU: an 8-bit checksum is far more susceptible to missing errors than the RTU’s 16-bit CRC
RTU
Modbus RTU is a binary transmission format. Every master-initiated packet looks like this:
Modbus RTU Packet Format (Master Packet)
NameBytesDescription
Slave ID1The byte ID of the slave to target
Function Code 1The command (called a "function code", or "FCxx" where xx is the code)
DatavariesCommand specific data as a sequence of bytes, in MSB format where appropriate
CRC216-bit CRC
Every slave responds with a modified version of the packet:
Modbus ASCII Packet Format (Slave Response)
NameBytesDescription
Slave ID1The byte ID of the slave to target
Function Code 1Same FC as master requested; high bit is set if error
DatavariesCommand specific response data as a sequence of bytes, in MSB format where appropriate
CRC216-bit CRC

Modbus RTU mode has advantages:

  • faster than Modbus ASCII: one byte per character rather than two
  • more robust to noise than ASCII: the 16-bit CRC is better at detecting bit errors than the ASCII 8-bit checksum

and a few disadvantages:

  • trickier to write software to stay synchronized in a noisy environment: no start/end sequences
  • CRC requires more software on the slave to generate/test
  • harder to to debug on a sniffer terminal device: typically needs a packet decoder program

TCP

Although not currently natively supported in SHIP, Modbus packets can also be sent over TCP/IP connections to enable server and cloud connectivity. Often the SIM will be set up as a Modbus master controlling a slave (such as a motor, pump, or PLC). With the addition of a very simple UART to WiFi bridge and a server-based Modbus slave implementation, the SIM can now be “cloud connected” and send and receive information from a server. In this mode, for example, the SIM can supply a cloud-based application with motor or equipment status and both the GUI on the SIM and the cloud application can control the equipment.

Modbus TCP Packet Format (Master Packet)
NameBytesDescription
Sequence #2Since TCP/IP can deliver out-of-order, this enables in-order handling by master and slave.
Protocol ID20x0000 means Modbus/TCP
Length2Number of bytes after this point in the packet
Slave ID1Slave Address 0x01..0xFE (0xFF if not used)
Function Code1Standard Modbus Function Code
Data(varies)FCxx specific command or response data
Modbus TCP Packet Format (Slave Response)
NameBytesDescription
Sequence #2Same sequence number from master packet.
Protocol ID20x0000 means Modbus/TCP
Length2Number of bytes after this point in the packet
Slave ID1Slave Address 0x01..0xFE (0xFF if not used)
Function Code1Modbus Function Code (high bit set if error)
Data(varies)FCxx specific command or response data

Function Codes

Wikipedia has a complete list of common Modbus Function Codes. However the basic codes are:
Modbus Basic Function Codes
FCNameDescriptionSHIPEngine Support
0x01Read Coil Get the state of one Boolean outputv4.0.180+
0x02Read InputGet the state of one Boolean inputv4.0.180+
0x03Read Holding RegistersGet the values of a sequence of 16-bit outputsv4.0.180+ (single mode)
0x04Read Input RegistersGet the values of a sequence of 16-bit inputsv4.0.180+ (single mode)
0x05Force Single CoilSet the state of one Boolean outputv4.0.180+
0x06Preset Single RegisterSet the values of one 16-bit outputv4.0.180+
0x0FForce Multiple Coil Set the state of a sequence of Boolean outputs-
0x10Preset Multiple RegistersSet the values of a sequence of 16-bit outputs-

Function codes are often represented as “FCxx”, for example FC01. Note that when represented in this fashion, the code is always represented in decimal (base 10). So FC16, for instance, is function code 16 decimal or 0x10 hex: the Preset Multiple Registers command.

Slave Variables

Each slave has a (typically fixed) set of boolean and/or 16-bit inputs and outputs that it uses. The documentation for the slave will publish a table of these “variables” and permitted FCs.

For example a simple modbus-enabled temperature sensor might have a very simple published interface:
Example Temperature Sensor Modbus Interface
VariableAddressTypeDirection FCs PermittedDescription
Temperature0x200016-bitinputFC02Current temperature in degrees C (signed 16-bit value)
Calibrate0x4000BooleanoutputFC05When sent as true, will force a calibration cycle in the sensor

The direction is the Modbus direction with respect to the master, so an “input” is an input to the master and an “output” is an output to a slave from the master.

This is a very simple command-set to implement in the sensor. The addresses could even be ignored, since there is only one 16-bit input and one Boolean output — any FC02 could fetch the temperature and any FC05 could force the recalibration.

Programmable Logic Controllers (PLCs), such as the inexpensive Automation Direct Click Series publish a complete list of all addresses, data types, and function codes permitted to access the PLC.

Polling

Modbus is a single-master/multiple-slave protocol. While the actual physical transmission mechanism (e.g. RS232, Ethernet, WiFi, RS485) may be half or full duplex, the protocol is a command-response protocol.

The master initiates a request by sending a command packet to a slave. The targeted slave then replies with a response packet. There is a 1:1 relationship between master and slave packets (unless an error occurs).

Within each packet (master request or slave response), when used over a serial channel, the packet is not interactive. There is no concept of byte-by-byte ACK/NAK type traffic. The whole request is pushed in one direction in one burst and the whole reply is pushed back in one burst.

In the Modbus TCP protocol, since TCP/IP can get packets mixed up and out of sequence depending on network latency, there is an extra sequence number in each packet. Each end is responsible for (optionally) handling packets out of order.

The master is therefore responsible for polling all its slaves, and within each slave all the variables it needs to know. There is no way for a slave to send an alarm or value proactively — it must be polled by the master at a frequency acceptable to the event. If a slave has an input Boolean indicating, for example, it is overheating, then the master must poll the slave (and specifically, get this Boolean value) at a sufficient rate such that the latency of display/response is acceptable for the system.

Such algorithms in the master can get fairly sophisticated. For example, the master can have a “slow poll” mechanism where every slave and every input/output value is polled over some period of time. When an output needs to be changed, the master can interleave a set request to the target slave in between the slow poll cycle requests. A simpler master might poll all connected slaves and only once per polling cycle allow a “set” to be sent out to a slave. There are many variations possible, including fast polling of a specific slave combined with slow polling of other slaves. Or, for example, a specific variable at a slave (like the overheat example above) might be polled at one frequency while the rest of the slaves/variables are polled at another.

For this reason, master-side software implementations may be larger and more complicated than slave-side software implementations. SHIPEngine supports both master and slave modes, including support for poll timing at any level and even simultaneous master and slave support over separate communications channels.

References

More Information
Debugging Tools
Embedded Software