drivers/modbus: add initial support (v4) - #22455
Conversation
This adds initial support for the protocol data unit (PDU) part of the Modbus specification. It provides support for both server and client mode (formerly master and slave), while also supporting multiple servers simultaneously. The following function codes are supported: * MODBUS_FC_READ_COILS * MODBUS_FC_READ_DISCRETE_INPUTS * MODBUS_FC_READ_HOLDING_REGISTERS * MODBUS_FC_READ_INPUT_REGISTERS * MODBUS_FC_WRITE_SINGLE_COIL * MODBUS_FC_WRITE_SINGLE_HOLDING_REGISTER * MODBUS_FC_WRITE_MULTIPLE_COILS * MODBUS_FC_WRITE_MULTIPLE_HOLDING_REGISTERS
This commit provides the application data unit (ADU) part of the Modbus RTU specification. The implementation provides a 'recv' and 'send' implementation that takes care of the framing, timing and error checking. Any received frame (of interest) is then offloaded to the generic part that parses the protocol data unit (PDU).
This commit adds the unit tests for the Modbus module.
This application will test the Modbus transport implementations.
This example will demonstrate how to implement a Modbus server, that wraps around SAUL switches and buttons.
|
This is how I manually started the 8 node test:
And this is when I made it fail (bottom right):
This was my ASCII/RTU set-up (@AnnsAnns wants to see real hardware setups):
Schematically, it is like this: This was the set-up of interacting with a real energy meter (a real Modbus device). Unfortunately it isn't that big, but it is the second thing from the left mounted on the rail:
This is Modbus TCP running on real hardware, even though you don't see the ethernet cable:
Here are video's of the tests a few of the many tests I ran:
|
Don't worry I trust you and your code but cool to see regardless 😆, I can also assume that you have a working dev environment? /s |
|
And the test results. I ran the tests for Modbus ASCII, Modbus RTU, Modbus TCP and the unit tests. I ran it on several boards, to check for differences in timing and stability (basically the 8 node setup above). All test have ran for a short but long enough time (1-2 minutes). TCP was limited to native only, and the example on the Seeeduino Arch Pro (the only board I have with TCP). (the tables scroll horizontally) ASCII
RTU
TCP
Unit tests
Footnotes(1): Secondary UART is limited to 9600 baud. |
There was a problem hiding this comment.
It is noted that this is a rather complex test now, especially with ASCII, RTU and TCP support. I did try to split this file into multiple pieces, but the net result was more lines of code.
That said, this test has been really valuable.
There was a problem hiding this comment.
How much more is "more"?
IMO three smaller tests would be more desirable if someone wants to write a Modbus application and take the test as a foundation.
There was a problem hiding this comment.
I tried to split it in a test part, thread part and 'the rest'. But that adds several headers, and a lot of external declarations because of shared state. Let's say 100+ lines.
A better example for an application is examples/advanced/modbus_saul to be honest.
There was a problem hiding this comment.
The file itself grew from 1007 lines in V3 to 1246 in V4 btw.





Contribution description
Fourth
Thirdtime is the charm, I hope, again.This is not a complete rewrite, as was the case with #22032. But it does decouple the framing (ADU) from the transports (PDU) as suggested by @kfessel, making it significant enough for a new PR. And while at it, I also added support for ASCII and TCP transports.
Features that are included:
Changes
Compared to the previous PRs, the main changes are:
V4:
V3:
errno.honesTesting procedure
I have added three applications to test this driver. My suggestion is to focus on
tests/drivers/modbusandtests/drivers/modbus_transport.tests/drivers/modbus
These are the unit tests for the Modbus PDU layer.
tests/drivers/modbus_transport
This test application provides a shell, with commands to either start a server, a client or both (loopback). This will test the Modbus ASCII, RTU or TCP transport, and proper parsing of the Modbus protocol data units (PDUs).
To run this test in loopback mode, you need a board with at least three UARTs (stdio + server + client). For separated server and client mode, two boards are sufficient. TCP does not support loopback mode
It also includes a 'misbehave' option for servers, to check how a client reacts to misbehaving servers.
See the README.md for more details.
tests/advanced/modbus_saul
This is an example application that demonstrates how to build a Modbus server that wraps around SAUL. Buttons are exposed as 'coils' to read, while LEDs are exposed as 'coils' to write.
To run this application, you need one board for the server, and a USB <-> RS-485 to connect it to a computer. I used qmodbus to interact with the server from the computer.
It also supports Modbus ASCII and TCP. The latter makes it possible to run this natively.
See the README.md for more details.
Bonus: Eastron SDM120
OK, this isn't really part of this branch, but demonstrates how the driver can be used as a client.
The source code can be found in this Gist.
Issues/PRs references
Successor of #22032, #20386, #19819 and #13913
Declaration of AI-Tools / LLMs usage:
AI-Tools / LLMs that were used are: