코딩나우(하늘아래)Equipment manuals say "supports Modbus" and leave you to work out whether that means RTU or TCP. The...
Equipment manuals say "supports Modbus" and leave you to work out whether that means RTU or TCP. The names make it sound like two protocols. It is one protocol with two envelopes.
The command you send — read these registers, write that coil — is byte-for-byte identical. Only the wrapper differs, and every practical consequence (wiring, update rate, device count, how you debug) falls out of that one difference.
RTU [ slave addr 1B ][ function code + data N B ][ CRC 2B ]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TCP [ txn id 2B ][ proto 2B ][ length 2B ][ unit id 1B ][ function code + data N B ]
\________________ MBAP header, 7 bytes ____________/
The part under the carets is the PDU, and it is the same in both. RTU frames are delimited by 3.5 character times of silence and carry a CRC. TCP frames have no CRC at all — TCP already guarantees integrity, which trips people up when they go hunting for one in a packet capture.
Because the PDU is shared, so are the function codes:
| Code | Does | Target |
|---|---|---|
01 |
Read coils | Output bits |
02 |
Read discrete inputs | Input bits (read-only) |
03 |
Read holding registers | 16-bit values — the common one |
04 |
Read input registers | 16-bit values (read-only) |
05 / 06
|
Write single coil / register | One value |
15 / 16
|
Write multiple | A contiguous block |
RTU runs over two RS-485 wires, daisy-chained. Cheap, and it reaches past a kilometre at 9600 bps. Everyone shares the line, so the master polls one device at a time.
TCP gives each device an IP on a switch. No new cabling if the network already exists, and several clients can talk at once — in exchange for the 100 m per-segment limit and IPs to manage.
Not raw bit rate — round-trip time. RTU at 9600 bps, 8N1, is 10 bits per byte, so roughly 1 ms per byte:
request 8 B + response 9 B = 17 B ~ 18 ms
+ inter-frame silence (3.5 chars) x2 ~ 7 ms
+ device processing ~ 5-20 ms
-----------------------------------------------
one round trip ~ 30-45 ms -> 20-30 per second
Ten slaves on that bus means two or three updates per device per second. Fine for temperature or flow; useless when you need tens of milliseconds. The same exchange on Ethernet is 1-5 ms, and devices can be polled in parallel.
When the manual says 40001, the number that goes on the wire is 0.
| Manual says | On the wire | Function code |
|---|---|---|
40001 |
0 |
03 holding register |
40100 |
99 |
03 |
30001 |
0 |
04 input register |
00001 |
0 |
01 coil |
And when a 32-bit value spans two registers, which half comes first is device-specific. A reading that is wildly large or unexpectedly negative is almost always reversed word order, not bad arithmetic — swap the two registers and recombine.
# pip install pymodbus
from pymodbus.client import ModbusSerialClient, ModbusTcpClient
# RTU - serial port
client = ModbusSerialClient(port="COM3", baudrate=9600,
parity="N", stopbits=1, bytesize=8)
# TCP - IP address (this line instead of the one above)
# client = ModbusTcpClient("192.168.0.50", port=502)
client.connect()
rr = client.read_holding_registers(address=0, count=2, slave=1)
print(rr.registers)
client.close()
That is pymodbus 3.x; version 2.x used unit=1 instead of slave=1.
RTU
TCP
ping first, then check port 502 — firewalls block it regularly.Longer version with diagrams, plus a free robot-communication track that builds a Modbus server and client on a single PC:
What tripped you up the first time you wired up Modbus? For me it was terminators — everything worked on the bench and fell apart in the panel.