Communication between industrial processes has led to factories operating with minimal human interaction and almost uninterrupted flow. This progress has allowed humankind to develop increasingly advanced technology in less time, making our lives more comfortable an in incredible pace. All of this is possible thanks to the ancestors of the communication protocols, especially the pioneer called Modbus.
This article will outline a brief introduction to the Modbus operation, allowing you to better understand this widely used industrial protocol. Likewise, at the end of the article, we’ll show you some recommended ready-to-use solutions as well as a software library that can be useful to implement Modbus in your own projects using NetBurner’s development kits.
Modbus is an open-source protocol that operates under the single-master model and has been a standard since approximately 1979. The invention of Modbus triggered a revolution in industrial automation because it allowed communication between numerous parts of the industrial process using devices (controllers, sensors, actuators, HMI, etc.) of various brands and manufacturers.
Modbus is one of the most widely accepted and used protocols in the industry today. Applications such as HVAC, building management systems (BMS), energy systems, etc., are just a few examples. Since its origin, the Modbus’ creators, Modicon (now Schneider Electric), decided to release the intellectual property of the protocol, which has allowed developers around the world to implement the protocol in their own products.
The Modbus protocol is simple to understand. It works over different bus types with high reliability in data transmission. The best part is that it requires very little memory for its operation, making it perfect for implementing in a microcontroller.
Some authors consider Modbus the “Grandfather” of industrial protocols, but I dare say that it’s the Master and Lord of them all.
Over the years, Modbus has been extended to operate in several environments, adding different ways to implement it. The most common are as follows:
- Modbus TCP/IP: It uses Ethernet as the physical layer and TCP/IP protocols for data transmission. It’s based on the client/server model for data communication.
- Modbus over Serial: It uses a serial port and operates with RS-485/RS-422 or RS-232 interfaces for data transmission. It works using the master/slave model. There’re two sub-types:
- Modbus RTU (Remote Terminal Unit): The data sent are in Hexadecimal format.
- Modbus ASCII: The data sent are in ASCII format.
Sometimes Modbus over serial uses radios (e.g., via LoRa) to transmit data wirelessly.
- Modbus Plus: This is a special case since it uses HDLC as the data link layer, allowing data transmission up to 1Mbs. Unlike the previous versions listed, this type of Modbus is Schneider Electric’s proprietary standard.
In industrial applications, it’s common to find different Modbus types interconnected via Gateways. Figure 1 shows an example, the 460ECMC Gateway from our friends at RTA.
Modbus is easy to understand because its implementation is not very complex. The following is a general description of the parts of the Modbus protocol and how it works.
Single-master protocol principle
As mentioned before, Modbus works on a single-master model, which means that a single master (TPC/IP Client) can have several slaves (TPC/IP Servers). The master requests and sends information to its slaves individually. Each one has a unique identifier (Slave number in the Modbus serial type and IP in the Modbus TCP/IP type).
Figure 2 shows an example diagram of the above.
As you can see, the master requests information from one of its slaves, and that slave is the only one that responds. Subsequently, the master writes data to another slave, and only that one receives it.
If the slave device cannot process the data, it’ll respond with an error code in its response message. This article shows the error codes in a later section.
Data distribution (Memory Map)
Before going into the structure of the messages that are sent and received, it’s necessary to understand how Modbus devices store the data.
Each slave device requires memory space to store the data that the master requests or sends. Each location is called a “Register” and is a variable of two bytes in length. It will have write or read properties (or both), depending on the application.
Modbus builds its data model on tables with attributes that define the types of data to be stored. The following table shows the four categories proposed by the protocol:
|Category||Object Type||Access Type||Description|
|Discrete Inputs||One bit||Read-Only||Used for binary data provided by I/O systems, such as on-off selectors, thermocouples, water electrodes, etc.|
|Coils||One bit||Read-Write||Used for binary data that can be altered by application logic, for example, dry contacts, lamps, valves, etc.|
|Input Registers||16-bit word||Read-Only||Used for non-binary information of I/O systems. Such as pressure, humidity, temperature sensors.|
|Holding Registers||16-bit word||Read-Write||Used for non-binary information that can be modified by application logic, e.g., frequency of a variable speed drive, maximum temperature, operating settings, etc.|
Modbus provides an example of a memory map ranging from 0 to 65535 registers (0 to 0xFFFF in hexadecimal), but in the end, the manufacturer chooses the amount and distribution of memory within the device to suit the application. Figure 3 shows an example diagram of how to distribute the data in the memory block of the device. You can see the range of register numbers for each memory block on the right side. The manufacturer defines the quantity and layout of memory depending on the application.
Figure 4 shows an example of a memory map of a Yaskawa variable speed drive. Although some registers appear to be of type Input Registers (read only), the manufacturer decided that all the registers of this drive are of type Holding Register.
Now that we understand how Modbus works in general, we’ll go into the message’s layout. The structure is the same for messages that are sent and received and looks like the following figure.
PDU (Protocol Data Unit) is the name of this and is generic for any type of Modbus, where:
- Function Code: On transmission (master message), this indicates to the slave the action to execute. On reception (slave response), it shows the action performed and exception indicator in case of error.
- Data: Contains information sent to the slave in write functions or the data received in reading functions. It can include register addresses, the amount of data, the current number of bytes sent or received, etc. These fields depend on each function code. In case of error, the first byte of this field will be the exception code.
Sometimes, depending on the type of Modbus or application, extra fields are required in the PDU. This’s known as an ADU (Additional Data Unit).
ADU for Modbus over Serial
Figure 6 shows an example of the ADU when using Modbus over Serial.
- Additional Address: This’s a unique identifier of the Modbus slave. It consists of one byte of data. Number 0 is for broadcast commands, and the protocol reserves 248 to 255 numbers.
- Error Check: This’s the result of the Redundancy Checking algorithm (called (Cyclical Redundancy Check) for Modbus RTU and LRC (Longitudinal Redundancy Check) for Modbus ASCII), calculated from the data that make up the message. It’s used to determine an error when transmitting the message.
When Modbus RTU or Modbus ASCII is used, other considerations need to be made when sending the frame, which you can find here.
ADU for Modbus TCP/IP
On the other hand, when working with Modbus TCP/IP the ADU is quite different, instead of the additional address field and error check, a field called MBAP (MODBUS Application Protocol header) the figure 7 shows an example of this.
Where MBAP contains the following:
- Transaction Identifier: It’s used for transaction pairing. The MODBUS server copies in the response the transaction identifier of the request.
- Protocol Identifier: It’s used for intra-system multiplexing. Where 0 => for Modbus.
- Length: It’s a byte count of the following fields, including the Unit Identifier and data fields.
- Unit Identifier: Typically used to communicate with devices connected to the Modbus TCP/IP server when used as a gateway.
All the information about Modbus TCP/IP implementation can be found here.
The function codes indicate to the slave which action to execute. They consist of 1 byte of information with values from 1-255 in decimal; values between 128 and 255 are for exception codes.
There’re three categories of Modbus function codes:
- Public: These are the function codes approved by the Modbus community, with functions based on the operating principle of the protocol. These are the standard Modbus commands.
- User-Defined: Those that the user defines for a custom application. These codes range between 65-72 and 100-110.
- Reserved: Codes used by companies and are not available for public use. More information is on page 50 of the following document.
It’s important to remember that fields are added to the frame depending on the function code. You can find all the function codes and examples of the data frame from page 10 of the Modbus Application Protocol, found here. This article will only mention the most used ones, based on my experience with HVAC systems.
Function Codes for Coils
The following function codes are used to read and write Coil type registers (binary write/read):
- Read Coils (Function code: 0x01): Read from 1 to 2000 continuous values of coil data from a remote device. The response is packed into registers where the first bit of each represents the status of the coil. Where 1 = ON and 0 = OFF.
- Write Single Coils (Function code: 0x05): Change the value of a Coil register. The value 0xFF00 requests coil ON and 0x0000 requests coil OFF.
Figure 8 shows an example of the frames for reading and writing coils (remember that each register consists of two bytes).
For Discrete Inputs
Discrete inputs are read-only, so these only have the following command:
- Read Discrete Inputs (Function code: 0x02): Read from 1 to 2000 continuous values of Discrete Inputs (read-only binary) from a remote device. The response is packed into registers. The first bit of each register represents the status of a Discrete Input, where 1 = ON and 0 = OFF. Figure 9 shows an example of the frame and its correct answer.
For Holding Registers
The following function codes are used to read and write Holding Registers (non-binary write/read). Based on my experience, these are used by manufacturers the most frequently.
- Read Holding Register (Function code: 0x03): Read continuous Holding Register data from a remote device. The response message consists of two bytes for each register. The binary content is right-justified. Depending on the characteristics of the master device, it can read from 1 to 127 registers simultaneously (125 for Modbus RTU).
- Write Single Holding Register (Function code: 0x06): Write a single value in a Holding Register of a remote device. The response message is an echo of the request after writing the data.
- Write Multiple Holding Register (Function code: 0x10): Write a data block to continuous Holding Register registers. The response consists of the function code, initial address, and the number of registers written.
It’s common to find devices that only support function codes 0x03 and 0x10 for reading and writing Holding Registers; this makes the implementation of Modbus very simple. Sometimes in serial interfaces, you’ll find the function code 0x08 used to perform diagnostics in the serial communication loop.
Figure 10 shows an example of the requests and correct responses for reading and writing Holding Registers should look like.
Exception codes are indicators sent in the response frame by the slaves. These represent errors during communication or interpretation of the data transmitted or requested. Error codes help the master determine what action to take depending on the error reported.
Figure 11 shows the representation of the error response frame.
- Exception Function Code: These differ from a response without error because the function code sent to the response is incremented by 0x80, i.e., if a value greater than 128 in decimal is obtained, it’s established that there was an error in the request. For example, if the request was a data reading of Holding Register type (0x03), the error code will be 0x83.
- Exception Code: This describes to the master the cause of the error. Some of the most common exception codes are as follows:
- Illegal function (0x01): The requested function code is not supported by the slave device.
- Illegal data address (0x02): The requested address is not available on the slave device.
- Data value not allowed (0x03): The amount of data sent or requested is not allowed on the slave device.
- Device busy (0x06): The slave device is not ready to process the new request.
Depending on the application, the user can add more exception codes, like the function codes.
Figure 12 shows an example of an error response. The left side of the image is the request message (Read Holding Registers in this case), and the right side is the error response.
Modbus and NetBurner
The theory is not enough to bring a product to reality. That’s why we have two options for implementing the Modbus protocol using your favorite devices. Yes, of course, we’re talking about NetBurner systems.
If you want to play it safe with a fast time to market and certified devices, the best option is to take a look at the products of our commercial partner. We’ve worked with Realtime Automation for a very long time, and we can’t recommend their off-the-shelf Modbus Gateways enough. The have versions that work over serial (RTU) as well as TCP/IP.
Create your Own
If you’re looking to implement Modbus in your own projects, NetBurner’s characteristics, such as our robust real-time operating system, industrial temperature range, and RoHS compliance make it an ideal candidate for your next design. In addition, combined with RTA’s NetBurner compatible Modbus software library, you can get your own custom application up and running before you know it.
Resources for Modbus Over Serial
To implement Modbus RTU/ASCII, we recommend the following:
- In the following path, you’ll find examples of using the serial port \nburn\examples\serial. Which is necessary for the transmission of data.
- In this path, you’ll find how to use the system timers \nburn\examples\timers. These are necessary to generate inter-frame and inter-character delays and response timeouts.
- In the following article, you’ll find more information about the operation of RS-485/RS-422 or RS-232 interfaces used in industrial devices.
- And a video by John Rinaldi of RTA to learn all about Modbus RTU.
Resources for Modbus TCP/IP
For Modbus TCP/IP, we recommend the following:
Hopefully this article will be useful for those developers who are looking to implement a product for industrial use with this well-known protocol or for those who are curious to learn how things work.
We’d love to hear your comments, suggestions, or ideas for new articles. If you have any questions, please don‘t hesitate to contact us directly at firstname.lastname@example.org we’ll be happy to reply as soon as possible.