Communication – not all Modbus implementations are equal

Image Description

Peter Humaj

January 27 2025, 6 min read

Today's blog will be about one of the most widespread and seemingly simplest protocols – the Modbus protocol. But is its implementation so trivial?

I recently participated in the upgrade of a SCADA application that is over 20 years old. It was not implemented by my colleagues from Ipesoft, but by one of our OEM partners – using Ipesoft D2000 technology. How do I know how old it is? I found several backups of the configuration database on the application server – the oldest was from January 2001.

The upgrade also included replacing several protocols. The new application server no longer has an RSLinx OPC server, but the communication with CompactLogix is ​​handled by the D2000 implementation of the Ethernet/IP protocol.

We also replaced the OEM implementation of the Modbus protocol with the D2000 Modbus Client protocol. Here, I want to stop and compare the OEM and our protocol implementation.

Identification

To identify it, it was enough to turn on logging on the line and look at the logs provided by D2000 KomAPI (the D2000 Kom process interface for creating custom communication drivers).

Figure 1 - Readout of values from one station with OEM Modbus protocol

The figure above shows the reading of points from one communication station. The logs always contain a request and a response. This is clearly a Modbus protocol. We can parse the first response for example:

<02><04><00><23><00><01><C0><33>

<02> - station number

<04> - Modbus protocol function (Read Input Registers)

<00><23> - register address (0023 i.e. 35 decimally)

<00><01> - number of registers (0001 i.e. 1 register)

<C0><33> - checksum (CRC)

Note that in the figure, functions 3 and 4 (Read Holding/Input Registers) are used for reading, and a single register is read at a time.

Parsing the response:

<02><04><02><00><21><3D><28>

<02> - station number

<04> - Modbus protocol function (Read Input Registers)

<02> - number of data bytes in the response

<00><21> - register data (0021 i.e. 33 decimally)

<3D><28> - checksum (CRC)

The following figure shows how the addressing of the I/O tags looked:

Figure 2 - Configuration of 40 I/O tags on a station with OEM Modbus protocol.

The implementers chose the address format 0xAABBCCDD. When comparing the addresses of the I/O tags with the communication logs, we quickly figured out that the last four digits (CCDD) indicate the Modbus address of the point (the tenth point from the bottom has the address 0023 and corresponds to the request and response that we analyzed). The first two digits (AA) determine the Modbus protocol function:

  • 01 corresponds to function 3 (Read Holding Registers)
  • 02 corresponds to function 4 (Read Input Registers)

What about the BB digits? For binary variables, they determine the bit number in the register (00-0F).

But let's notice something else: to read the values ​​of 40 points, 40 requests and 40 responses are required. Some of the requests and responses are even completely identical - the following figure highlights 3 sections with repeated identical requests and responses. Why is this so? Multiple I/O tags have the same addresses (e.g. 0034) and differ only in the bit number. The OEM implementation ignores this fact and does not attempt any optimization - a separate reading is performed for each I/O tag.

Figure 3 - Sections with identical requests and responses (reading addresses 0x34, 0x33, and 0x32).

Address conversion

After upgrading and converting the addresses to the D2000 Modbus Client protocol (we used simple Excel for the conversion), the I/O tags look like this:

Figure 4 - I/O tags at the station with D2000 Modbus Client protocol.

The first letter in the address (U) indicates the interpretation of the register as an Unsigned number. The following number (3 or 4) directly determines the Modbus function. In the case of output points, a dash and the number of the write function (6=Write Single Register) follow. The dot is followed by a hash character - indicating that the address is in hexadecimal format (without the hash it would be decimal). We have deliberately left the address in hexadecimal notation for easier user orientation. In the case of binary variables, the address is also followed by a dot and a bit number (0-15).

Comparison of communications

And now the most interesting part: what do the Modbus Client protocol logs look like? I deliberately turned on the Full Debug station parameter, which causes the values ​​of individual I/O tags to be printed as well. The lines starting with RQ> are requests (sent data), the lines starting with IN> are received responses. The other lines are auxiliary debugging statements.

Figure 5- Logs of reading 40 I/O tags on a station with D2000 Modbus Client protocol.

We can see that only two requests are performed to read the 40 I/O tags. The first one (3rd line of the log) reads 16 registers starting with address 20 (i.e. addresses 20-35) using Modbus function 4 (Read Input Registers). This read fills 12 integer I/O tags (each is filled from only one register), i.e. 4 registers that were not used were also read.

The second request reads 3 registers starting with address 50 (i.e. addresses 50-52) using Modbus function 3 (Read Holding Registers). This read fills 28 binary I/O tags.

So let's recapitulate - two reads of our implementation versus 40 reads of the OEM Modbus protocol. It can be seen that our implementation performs optimizations and combines the reading of multiple registers into one request. This makes more efficient use of the serial line, so the registers are read faster. In this particular application, reading is done with a period of 5 minutes (so speed is not crucial). But what is important – communication is done via the GPRS network (Modbus over TCP), while payments depend on the amount of data transferred. So the multiple reduction of data means lower monthly payments for each such Modbus communication. This particular application contained 7 identical stations, which differed only in the IP address of the end device.

Can the behavior of the Ipesoft implementation of the Modbus protocol be influenced in any way? The Max. Registers parameter specifies how many registers will be read in one request. If we reduce the default value of 100 to 1, we will get behavior similar to the OEM protocol (but even in that case, only one read would be performed for all binary variables with the same register address).

Another useful parameter is Skip Unconfigured. This allows you to not read addresses that are not defined in the D2000 configuration. So if there were I/O tags with addresses 2,3,5,6,7 but not with address 4, two reads would be performed: from addresses 2-3 and 5-7. What is this parameter good for? Some devices respond with an error code to a read request that contains addresses that they do not have defined (in our case, address 4). So instead of data, they return an error code (exception). The Ipesoft Modbus Server implementation does not have such a feature - it returns zeros for undefined addresses.

Conclusion

You can see that not all Modbus implementations are equal. Some implementations may be functional, correct – but not optimal in a specific deployment. This is also an example of how the development of D2000 is optimized at various levels – including the implementation of communication protocols – to result in a functional and tuned system. Ideally, with comfortable debugging options.

January 27, 2025, Ing. Peter Humaj, www.ipesoft.com

Subscription was successful

Thank you for submitting form.

Image Description

Your message was successfully sent.

Thank you for submitting the form.

Image Description

Your message was successfully sent.

Thank you for submitting the form.

Image Description

Your message was successfully sent.

Thank you for submitting the form.

Image Description