← All guides
Industrial commsPublished · 10 min read

Modbus RTU vs Modbus TCP: what actually differs, and which to use

Equipment manuals say "supports Modbus" and leave you to work out whether that means RTU or TCP. The relationship is simpler than the names suggest: the command you send is exactly the same, and only the wrapper around it changes. That single difference is what decides your wiring, your update rate, how many devices you can hang off one line, and how you debug it.

Same command, different wrapper

Modbus dates to 1979 and is deliberately plain: "read N registers starting at address A from device X" is most of it. RTU and TCP are two envelopes for that same letter.

The green part is the actual command. RTU adds an address in front and a CRC behind; TCP adds a 7-byte header.

Because of that, function codes are shared. When a manual says "read with 03, write with 16", it applies to both transports.

CodeWhat it doesTarget
01Read coilsOutput bits (on/off)
02Read discrete inputsInput bits (read-only)
03Read holding registers16-bit values (the common one)
04Read input registers16-bit values (read-only)
05 / 06Write single coil / registerOne value
15 / 16Write multiple coils / registersA contiguous block
💡

If you remember one line: **RTU checks itself with a CRC; TCP delegates that to TCP.** There is no CRC in a Modbus TCP frame at all — a classic source of confusion when reading a packet capture.

Wiring and topology

RTU chains devices along one line; TCP gives each its own drop. This is what decides the field work.

RTU usually runs over two RS-485 wires. Devices chain along one pair, which is cheap and reaches well past a kilometre at 9600 bps. The cost is that everyone shares the line, so the master can only talk to one device at a time.

  • Fit **120 Ω terminators** at both ends of the line. Without them reflections cause intermittent errors — fine on a short bench run, broken once the cable gets long.
  • Get A/B (D+/D-) polarity right. Vendors label these inconsistently, so swapping the pair is the fastest test.
  • A large **ground potential difference** between devices makes the link flaky. Run a common signal ground with the pair.
  • Slave addresses run 1–247. Two devices sharing an address will collide on every reply.

TCP gives each device an IP and a port on a switch. If the plant network already exists there is almost no new cabling, and several clients can talk to the same device at once. In exchange you get the 100 m per-segment limit and switches and IPs to manage.

How much faster is it, really?

What you feel is not raw bit rate but the time for one round trip. Work it out for RTU at 9600 bps: with 8N1 each byte carries 10 bits, so 960 bytes per second — roughly 1 ms per byte.

text
request 8 bytes + response 9 bytes = 17 bytes  ~ 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

With ten slaves that is two or three updates per device per second. Plenty for temperature or flow; not enough when you need tens of milliseconds. On Ethernet the same exchange is typically 1–5 ms and devices can be polled in parallel, so update periods drop to single digits.

RTU (RS-485)TCP (Ethernet)
Round tripTens of msA few ms
Parallel requestsNo — strictly in turnYes — per device
Distance~1.2 km (further at lower speed)100 m per segment, extended by switches
Cabling costOne pair, daisy-chainedA drop per device plus a switch
Integrity checkCRC in the frameHandled by TCP
Debug toolsSerial monitor, scopeWireshark and friends

The addressing trap

Most lost hours are not about the protocol but the address. When a manual says 40001, the number that goes on the wire is 0. The 40001–49999 notation is a legacy way of naming holding registers; frames carry a zero-based offset.

Manual saysAddress on the wireFunction code
40001003 holding register
401009903
30001004 input register
00001001 coil
⚠️

32-bit values (temperature ×100, totalised flow) span two registers, and which half comes first varies by device. If a reading is wildly large or unexpectedly negative, the arithmetic is usually fine and the **word order** is reversed — swap the two registers and recombine.

In Python, only two lines change

Since the command is the same, so is the code. With pymodbus only the client constructor differs.

python
# 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)          # e.g. [258, 16000]
client.close()
ℹ️

This is pymodbus 3.x. Version 2.x used unit=1 instead of slave=1, so check your version first if the example fails (pip show pymodbus).

To practise without hardware, run a Modbus server on your PC and point a client at it on the same machine. The robot communication track walks through exactly that setup.

Which one should you pick?

SituationPickWhy
New build, network already in placeTCPNo new cabling, faster, parallel access
Existing RS-485 instrumentationRTUKeeps the devices you already own
Devices hundreds of metres awayRTUEthernet stops at 100 m per segment
Monitoring at tens of millisecondsTCPPolling cannot keep that period
Many cheap sensors on one runRTULowest cost per device
A mix of bothGatewayConvert TCP↔RTU and unify at one side

With a gateway, the Unit ID is the key: the value in the TCP request is passed through as the RS-485 slave address behind it, so it has to match the device address to get an answer.

When nothing answers

RTU

  1. 1Match the serial parameters exactly — baud rate, parity, stop bits. 9600 8N1 against 9600 8E1 gives you nothing at all.
  2. 2Swap A/B. Vendor labelling is inconsistent and this is a common cause.
  3. 3Check for duplicate slave addresses, and whether the manual's addresses are 0- or 1-based.
  4. 4Check the 120 Ω terminators at both ends and the common ground — the usual suspects behind intermittent errors.
  5. 5Still nothing: connect a single slave directly. If one works and several fail, it is wiring or termination.

TCP

  1. 1ping the device first, then check that port 502 is open — firewalls block it regularly.
  2. 2Check the Unit ID. Some devices expect something other than 1, and behind a gateway it must match the serial address.
  3. 3Check the connection limit. Cheap devices accept one or two sockets and refuse you if another program already holds them.
  4. 4Capture with Wireshark: is the request going out unanswered, or coming back as an exception (function code + 0x80)? Exception 02 means a bad address, 03 a bad quantity.

FAQ

Q. Can RTU and TCP devices coexist in one system?

Yes. A Modbus gateway (TCP↔RTU) lets the supervisory software speak only TCP while the gateway polls the RS-485 devices behind it. The Unit ID in the TCP request becomes the serial slave address.

Q. What about Modbus ASCII?

An older variant that sends the same commands as readable characters. Frames are about twice as long and therefore slower; almost nobody chooses it for new work. You mainly meet it on inherited equipment.

Q. How do I secure it?

Standard Modbus has neither authentication nor encryption — anything readable is also writable. Keep the plant network separate from the office network and require a VPN for remote access. A TLS-based Modbus/TCP Security spec exists, but device support is still thin.

Q. How many devices fit on one RS-485 line?

Electrically, 32 with classic transceivers, and 128–256 with modern ones. In practice the polling cycle limits you first: every extra device stretches the time before each one is read again.

Q. Replies break only now and then.

Intermittent faults are usually electrical. Missing terminators, ground potential differences, and comms cable run alongside motor or inverter wiring are the three big causes. Separate the cable from power runs and ground the shield at one end only. Raising the timeout just hides the symptom.

More guides