You have a SCADA system on an Ethernet network speaking Modbus TCP/IP. You also have dozens of field devices — energy meters, VFDs, PLCs, temperature controllers — connected via RS-485 speaking Modbus RTU.
They cannot talk to each other directly. Modbus RTU uses serial communication with CRC-16 error checking. Modbus TCP uses Ethernet with a TCP/IP stack and an MBAP header. The frame formats are different. The physical layers are different.
But the core protocol is the same. The function codes, the register addresses, and the data model are identical. You just need something in the middle to translate the framing.
That is what a Modbus RTU to TCP gateway does. It receives a Modbus TCP request from the SCADA master, strips the MBAP header, adds the slave address and CRC, and sends the resulting Modbus RTU frame out on the RS-485 bus. When the slave responds, it does the reverse.
This guide explains exactly how the translation works at the frame level, how to set up a gateway, and how to avoid the common problems that cause timeouts and data errors.
Table of Contents
1. Modbus RTU vs Modbus TCP: What Changes and What Stays the Same
What Stays the Same
The application layer is identical:
- Function codes (FC 01–06, FC 15–16, etc.)
- Register addresses (0x0000–0xFFFF)
- Data encoding (big-endian, 16-bit registers)
- Exception codes (01–06)
If you read holding register 40001 using FC 03, the PDU (Protocol Data Unit) is exactly the same in RTU and TCP.
What Changes
| Feature | Modbus RTU | Modbus TCP |
|---|---|---|
| Physical layer | RS-485 / RS-232 (serial) | Ethernet (TCP/IP) |
| Addressing | Slave address (1–247) | IP address + Unit Identifier |
| Error checking | CRC-16 (2 bytes appended) | TCP checksum (handled by TCP/IP stack) |
| Frame header | None (slave address is byte 1) | MBAP header (7 bytes prepended) |
| Frame delimiter | Silence gaps (T3.5 timing) | TCP stream with MBAP length field |
| Port | COM port (serial) | TCP port 502 |
| Connections | One master on the bus | Multiple TCP clients to one server |
| Speed | 9600–115200 baud | 10/100/1000 Mbps Ethernet |
2. How Frame Translation Works (Byte by Byte)
This is the core of RTU-to-TCP conversion. Here is what happens to a real frame.
Example: Read 3 holding registers from slave 6, starting at register 108
Modbus TCP request (from SCADA master on Ethernet):
| Field | Bytes | Value | Meaning |
|---|---|---|---|
| Transaction ID | 2 | 00 01 | Unique ID for this request |
| Protocol ID | 2 | 00 00 | Always 0x0000 for Modbus |
| Length | 2 | 00 06 | 6 bytes follow |
| Unit ID | 1 | 06 | Target slave address |
| Function Code | 1 | 03 | Read Holding Registers |
| Start Address | 2 | 00 6B | Register 108 (address 107) |
| Quantity | 2 | 00 03 | Read 3 registers |
Full TCP frame: 00 01 00 00 00 06 06 03 00 6B 00 03
What the Gateway Does
- Strips the MBAP header (first 6 bytes: Transaction ID, Protocol ID, Length).
- Keeps the Unit ID as the slave address.
- Keeps the PDU (function code + data) unchanged.
- Calculates and appends CRC-16.
Resulting Modbus RTU frame (sent on RS-485):
| Field | Bytes | Value | Meaning |
|---|---|---|---|
| Slave ID | 1 | 06 | Slave address 6 |
| Function Code | 1 | 03 | Read Holding Registers |
| Start Address | 2 | 00 6B | Register 108 |
| Quantity | 2 | 00 03 | Read 3 registers |
| CRC-16 | 2 | 75 A0 | Calculated CRC |
Full RTU frame: 06 03 00 6B 00 03 75 A0
The Reverse Trip
The RTU slave responds:
RTU response: 06 03 06 02 2B 00 00 00 64 23 4A
The gateway:
- Strips the CRC (last 2 bytes).
- Prepends the MBAP header (using the original Transaction ID from the request).
- Sends the TCP response back to the SCADA master.
TCP response: 00 01 00 00 00 09 06 03 06 02 2B 00 00 00 64
The PDU (03 06 02 2B 00 00 00 64) is identical in both frames. Only the wrapper changes.
3. Conversion Methods: Hardware Gateway vs Software Gateway
Hardware Gateway
A dedicated physical device with an Ethernet port and one or more RS-485/RS-232 serial ports.
Examples: Moxa MGate MB3170, Anybus AB7702, ICP DAS tGW-700 series, Digi Connect, Red Lion DA30D.
Best for:
- Permanent field installations
- Industrial environments (DIN-rail, wide temperature, isolated serial ports)
- Connecting multiple RS-485 buses (multi-port gateways)
Software Gateway
Software running on a PC, industrial PC, or embedded Linux device that converts between Modbus TCP and a serial port.
Examples: mbusd (open-source Linux), Modbus Tools (Windows), Modbus Poll + virtual COM port, custom Python scripts using pymodbus or libmodbus.
Best for:
- Development and testing
- Temporary setups
- When a PC or embedded system is already present on site
Comparison
| Feature | Hardware Gateway | Software Gateway |
|---|---|---|
| Reliability | High (dedicated, no OS updates) | Medium (depends on host OS) |
| Latency | Low and predictable | Variable (depends on CPU load) |
| Installation | DIN-rail, standalone | Needs a PC or server |
| Cost | $100–$500 per unit | Free to low cost |
| Multi-port | 1–16 serial ports per unit | Depends on available COM ports |
| Industrial rating | Wide temperature, isolated I/O | Typically office-grade |
4. Step-by-Step: Configure a Hardware Gateway
This is the generic process. Specific steps vary by vendor but the parameters are the same.
Step 1. Connect the Hardware
- Connect the Ethernet port of the gateway to your SCADA network.
- Connect the RS-485 port of the gateway to your Modbus RTU bus (A/B wires).
- Apply power (typically 12–48 VDC or 24 VAC).
Step 2. Assign an IP Address
Access the gateway’s web interface (most use DHCP by default, or a fixed default IP). Set a static IP address on the same subnet as your SCADA master.
Step 3. Configure the Serial Port
| Parameter | Setting | Notes |
|---|---|---|
| Baud rate | Must match all RTU slaves | Common: 9600, 19200, 38400, 115200 |
| Data bits | 8 | Standard for Modbus RTU |
| Parity | Even (most common) or None | Must match all slaves |
| Stop bits | 1 | Standard |
| Mode | RS-485 (2-wire) or RS-232 | Match your physical wiring |
Step 4. Set the Gateway Mode
Most gateways support two modes:
- Modbus TCP Server → Modbus RTU Master (most common): The gateway listens on TCP port 502. SCADA sends TCP requests. The gateway converts them to RTU and polls the serial bus.
- Modbus RTU Slave → Modbus TCP Client: The gateway acts as an RTU slave on the serial bus and as a TCP client that pushes data to a TCP server. Less common.
Select the first mode for standard SCADA-to-field-device communication.
Step 5. Configure Slave Address Mapping
The gateway must know which Unit Identifier in the TCP request maps to which slave address on the RS-485 bus.
Option A — Transparent pass-through: The Unit ID in the TCP request is used directly as the RTU slave address. No mapping needed. This is the default on most gateways.
Option B — Fixed mapping table: You define which TCP Unit ID maps to which RTU slave address. Useful when you need to remap addresses.
Step 6. Set Timeouts
| Timeout | Typical Value | Purpose |
|---|---|---|
| RTU response timeout | 500–2000 ms | How long the gateway waits for an RTU slave response |
| TCP connection timeout | 5–30 s | How long a TCP connection can remain idle |
| Inter-frame gap | Auto (T3.5) | Silence between RTU frames (calculated from baud rate) |
Step 7. Test
Send a Modbus TCP request from your SCADA system to the gateway’s IP on port 502. Verify that the gateway forwards it to the correct RTU slave and returns the response.
5. Step-by-Step: Configure a Software Gateway
Using mbusd (Open-Source, Linux)
mbusd is a lightweight Modbus TCP to RTU gateway daemon for Linux.
Install:
sudo apt install mbusd
Or build from source: https://github.com/3cky/mbusd
Run:
mbusd -d -L /var/log/mbusd.log -p /dev/ttyUSB0 -s 9600 -m 8N1 -P 502
| Flag | Meaning |
|---|---|
| -d | Run as daemon |
| -p /dev/ttyUSB0 | Serial port device |
| -s 9600 | Baud rate |
| -m 8N1 | 8 data bits, No parity, 1 stop bit |
| -P 502 | Listen on TCP port 502 |
mbusd passes the Unit Identifier from the TCP request directly as the RTU slave address.
Using Python (pymodbus)
For quick testing or custom logic:
python
from pymodbus.server import StartTcpServer
from pymodbus.client import ModbusSerialClient
from pymodbus.datastore import ModbusServerContext
from pymodbus.datastore.remote import RemoteSlaveContext
# Connect to RTU bus
rtu_client = ModbusSerialClient(
port='/dev/ttyUSB0',
baudrate=9600,
parity='E',
stopbits=1
)
# Create a gateway context that forwards TCP requests to RTU
store = RemoteSlaveContext(rtu_client)
context = ModbusServerContext(slaves=store, single=True)
# Start TCP server on port 502
StartTcpServer(context=context, address=("0.0.0.0", 502))
This creates a transparent TCP-to-RTU bridge. Every TCP request received on port 502 is forwarded to the serial bus.
6. Unit Identifier and Slave Address Mapping
The Unit Identifier (byte 7 of the MBAP header) in Modbus TCP maps to the slave address in Modbus RTU.
| Scenario | Unit ID | Behavior |
|---|---|---|
| Direct pass-through | 1–247 | Unit ID = RTU slave address |
| Gateway is the only slave | 255 or 0 | Gateway responds from its own data store |
| Broadcast | 0 | Gateway sends to all RTU slaves (no response expected) |
Common Problem
Your SCADA system sends Unit ID = 0 or Unit ID = 255, and the gateway does not know which RTU slave to address. The result: no response, timeout.
Fix: Set the SCADA master to use the actual slave address (1–247) as the Unit ID for every device behind the gateway.
7. Timeout Management Across the Bridge
Timeouts are the most common source of failures in RTU-to-TCP bridging. The gateway introduces delay because it must:
- Receive the full TCP request.
- Convert and transmit the RTU request on the serial bus.
- Wait for the RTU slave to respond (serial communication is slow).
- Convert the RTU response back to TCP.
- Send the TCP response.
The Rule
SCADA TCP timeout > gateway RTU timeout + serial transmission time + slave processing time
Example Calculation
- Baud rate: 9600
- RTU frame size: ~20 bytes
- Serial transmission time: ~20 ms
- Slave processing time: ~50 ms
- Gateway RTU timeout: 1000 ms
Total worst case: ~1070 ms
Set the SCADA TCP timeout to at least 2000 ms (double the worst case).
Typical Values
| Parameter | Setting |
|---|---|
| SCADA TCP response timeout | 2000–5000 ms |
| Gateway RTU response timeout | 500–1000 ms |
| Gateway RTU retries | 1–2 |
If the SCADA TCP timeout is shorter than the total round-trip time through the gateway, the SCADA system will close the request before the response arrives — even though the slave did respond.
8. Multiple Masters and Connection Handling
Modbus RTU allows only one master on the serial bus. But Modbus TCP allows multiple clients to connect to the same server.
This creates a conflict: if two SCADA clients send TCP requests to the gateway at the same time, the gateway cannot send two RTU requests simultaneously on the same serial bus.
How Gateways Handle This
Most gateways use a request queue. TCP requests are queued and sent to the RTU bus one at a time, in order. The second request waits until the first RTU response returns.
Implications
- With many TCP clients polling frequently, the queue grows and response times increase.
- Some gateways limit the number of simultaneous TCP connections (typically 4–32).
- High poll rates from multiple clients can overload a slow serial bus.
Best Practices
- Use one SCADA master per gateway (or minimize the number of TCP clients).
- Reduce poll frequency for non-critical data.
- Use separate gateway ports for separate RS-485 buses to avoid queuing.
9. Bridging Modbus RTU to Modbus TCP Over a WAN
When the SCADA master and the RTU devices are in different locations (e.g., a control center monitoring remote sites), the TCP connection runs over a WAN — cellular, VPN, MPLS, or satellite.
Challenges
- Higher latency — 100–500 ms round-trip on cellular, 600+ ms on satellite. Timeouts must be increased.
- Packet loss — TCP retransmissions add delay. Use VPN with stable connections.
- Security — Modbus TCP has no encryption or authentication. Always use a VPN tunnel or encrypted link.
Recommended Architecture
[SCADA Master] --(Ethernet/VPN)--> [RTU Site Router] --(LAN)--> [Modbus Gateway] --(RS-485)--> [Field Devices]
At the remote site, the gateway connects to the local RS-485 bus. The site router provides VPN connectivity back to the control center. The SCADA master connects to the gateway’s IP address through the VPN.
Timeout Settings for WAN
| Parameter | LAN | Cellular/VPN | Satellite |
|---|---|---|---|
| SCADA TCP timeout | 2000 ms | 5000–10000 ms | 15000–30000 ms |
| Gateway RTU timeout | 1000 ms | 1000 ms | 1000 ms |
| Poll interval | 1–5 s | 10–30 s | 30–60 s |
10. Troubleshooting Common Conversion Problems
| Problem | Cause | Fix |
|---|---|---|
| SCADA shows timeout on all devices | Gateway serial settings do not match RTU slaves | Verify baud rate, parity, stop bits match exactly on gateway and all slaves |
| One slave responds, others timeout | Wrong slave address or Unit ID mapping | Check that SCADA sends the correct Unit ID for each slave |
| CRC errors on serial side | Wiring problem (A/B swapped, no termination) | Check RS-485 wiring, add 120Ω termination at both ends |
| Data values are wrong (garbled) | Byte order mismatch for 32-bit values | Check float/long byte order: AB CD vs CD AB vs BA DC vs DC BA |
| Intermittent timeouts under load | SCADA poll rate too fast for serial bus | Reduce poll frequency or split devices across multiple gateway ports |
| Gateway works on LAN but not over VPN | SCADA TCP timeout too short for WAN latency | Increase SCADA timeout to 5000+ ms |
| Exception code 0x0B (Gateway Target Device Failed to Respond) | RTU slave did not respond within gateway timeout | Increase gateway RTU response timeout. Check if slave is powered and connected. |
| All registers return zero | Gateway is responding from its own empty data store instead of forwarding to RTU | Set gateway mode to transparent pass-through. Verify Unit ID is not 0 or 255. |
Summary
Converting Modbus RTU to Modbus TCP is not a protocol change — it is a framing change. The function codes, register addresses, and data values are identical. Only the wrapper around the PDU changes: MBAP header + TCP/IP on one side, slave address + CRC on the other.
A gateway handles this translation transparently. The key things to get right:
- Serial port settings (baud rate, parity, stop bits) must match every RTU slave exactly
- Unit Identifier in TCP must map correctly to RTU slave addresses
- SCADA TCP timeout must be longer than the total round-trip through the gateway
- Limit the number of TCP clients per gateway to avoid serial bus congestion
Get these four things right and the conversion is invisible to both the SCADA master and the RTU slaves.
Test Your Modbus Frames
Need to decode or build Modbus RTU and TCP frames? Use our free Online Modbus Frame Decoder & Encoder Tool to verify frame structure, CRC values, and function codes.
