Modbus Protocol Guide
Complete guide to configuring and using Modbus RTU and Modbus TCP with CONPROSYS M2M Gateway and Controller.
Modbus Protocol Guide
Modbus - The universal language of industrial automation
Modbus Protocol Tutorial
What is Modbus?
Modbus is one of the most widely used industrial communication protocols, developed by Modicon (now Schneider Electric) in 1979. CONPROSYS devices support both Modbus RTU (serial) and Modbus TCP (Ethernet).
Modbus communication architecture showing master-slave topology
Protocol Variants
| Variant | Medium | Speed | Cable Length | Use Case |
|---|---|---|---|---|
| Modbus RTU | RS-232/485 | 9600-115200 bps | Up to 1200m | Legacy equipment |
| Modbus TCP | Ethernet | 10/100/1000 Mbps | Network dependent | Modern systems |
| Modbus ASCII | RS-232/485 | 9600-19200 bps | Up to 15m | Debugging |
Modbus RTU Configuration
RS-485 wiring diagram for Modbus RTU multi-drop network
Hardware Setup
RS-485 Wiring
- Connect RS-485 cable with proper polarity:
- A/D+: Data+ (typically green)
- B/D-: Data- (typically yellow)
- GND: Common ground (typically black)
- Add 120Ξ© termination resistor at both network ends
- Use twisted pair cable (22-24 AWG)
- Maximum 32 devices on single bus (standard)
Serial Parameters Configuration
yaml# Typical Modbus RTU Configuration
Port: COM1
Baud Rate: 9600 bps (common: 9600, 19200, 38400, 115200)
Data Bits: 8
Parity: None (common: None, Even, Odd)
Stop Bits: 1
Flow Control: None
# Character Timeout: 1.5 character times
# Frame Timeout: 3.5 character times
Device Discovery Script
python# Python script for Modbus RTU device discovery
import minimalmodbus
import serial
def scan_modbus_devices(port='COM1', baudrate=9600, start_id=1, end_id=247):
"""
Scan for Modbus RTU devices on specified slave ID range
"""
found_devices = []
print(f" Scanning Modbus RTU devices on {port} at {baudrate} baud...")
print(f" Slave ID range: {start_id} to {end_id}\n")
for slave_id in range(start_id, end_id + 1):
try:
instrument = minimalmodbus.Instrument(port, slave_id)
instrument.serial.baudrate = baudrate
instrument.serial.timeout = 0.5
# Try to read holding register 0
value = instrument.read_register(0, 0)
print(f" Device found at Slave ID {slave_id}")
found_devices.append({
'slaveId': slave_id,
'responsive': True,
'testValue': value
})
except Exception as e:
# Device not responding at this ID
pass
print(f"\n Found {len(found_devices)} devices")
return found_devices
# Run scan
devices = scan_modbus_devices('COM1', 9600, 1, 20)
Manual Configuration
Navigate to "Protocols" > "Modbus RTU" in web interface:
ini[Device Settings]
Slave ID = 1
Baud Rate = 9600
Parity = None
Stop Bits = 1
Data Bits = 8
Port = COM1
Response Timeout = 1000ms
Retry Count = 3
Modbus TCP Configuration
Modbus TCP network topology with multiple devices
Network Setup
- Ensure gateway and devices on same network/VLAN
- Configure static IP addresses for devices
- Default Modbus TCP port: 502
- Enable port forwarding if needed
Device Configuration Example
javascript// Node.js Modbus TCP client example
const ModbusRTU = require("modbus-serial");
const client = new ModbusRTU();
async function connectModbusTCP() {
try {
// Connect to Modbus TCP device
await client.connectTCP("192.168.1.100", { port: 502 });
client.setID(1); // Unit ID
client.setTimeout(5000); // 5 second timeout
console.log(" Connected to Modbus TCP device");
// Read 10 holding registers starting at address 0
const data = await client.readHoldingRegisters(0, 10);
console.log(" Register values:", data.data);
// Write single register
await client.writeRegister(0, 12345);
console.log(" Register written successfully");
client.close();
} catch (err) {
console.error(" Error:", err.message);
}
}
connectModbusTCP();
Connection Parameters
json{
"protocol": "modbus-tcp",
"ipAddress": "192.168.1.100",
"port": 502,
"unitId": 1,
"timeout": 5000,
"reconnectInterval": 30000,
"keepAlive": true
}
Register Mapping
Register Types & Address Ranges
| Type | Prefix | Range | Access | Size | Description |
|---|---|---|---|---|---|
| Coil | 0x | 00001-09999 | R/W | 1 bit | Digital outputs |
| Discrete Input | 1x | 10001-19999 | R | 1 bit | Digital inputs |
| Input Register | 3x | 30001-39999 | R | 16 bit | Analog inputs |
| Holding Register | 4x | 40001-49999 | R/W | 16 bit | Configuration/data |
Example Device Map
Device: Temperature/Humidity Sensor
Model: TH-2000
Register Map:
40001 (address 0) - Temperature (INT16, 0.1Β°C resolution)
40002 (address 1) - Humidity (UINT16, 0.1% resolution)
40003 (address 2) - Dew Point (INT16, 0.1Β°C resolution)
40004 (address 3) - Alarm Status (UINT16 bitmask)
40005 (address 4) - Device ID (UINT16)
40006-40010 - Reserved
Coils:
00001 (address 0) - Heater Enable (R/W)
00002 (address 1) - Alarm Reset (W)
Configuration (Holding Registers):
40101 (address 100) - Sample Rate (seconds)
40102 (address 101) - Alarm Threshold High
40103 (address 102) - Alarm Threshold Low
Function Codes
Standard Function Codes
Code Name Description
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
0x01 Read Coils Read 1-2000 coils
0x02 Read Discrete Inputs Read 1-2000 discrete inputs
0x03 Read Holding Registers Read 1-125 registers
0x04 Read Input Registers Read 1-125 registers
0x05 Write Single Coil Write one coil
0x06 Write Single Register Write one register
0x0F Write Multiple Coils Write multiple coils
0x10 Write Multiple Registers Write multiple registers
0x17 Read/Write Multiple Regs Combined read/write
0x2B Read Device Identification Get device info
Code Usage Example
python# Python example using pymodbus
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('192.168.1.100', port=502)
client.connect()
# Function 0x03: Read Holding Registers
result = client.read_holding_registers(address=0, count=10, slave=1)
if not result.isError():
print(f"Registers: {result.registers}")
# Function 0x06: Write Single Register
client.write_register(address=0, value=100, slave=1)
# Function 0x10: Write Multiple Registers
values = [100, 200, 300, 400]
client.write_registers(address=0, values=values, slave=1)
# Function 0x01: Read Coils
coils = client.read_coils(address=0, count=8, slave=1)
if not coils.isError():
print(f"Coil states: {coils.bits}")
client.close()
Data Types
Supported Data Types
Type Size Range Byte Order
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
BOOL 1 bit 0/1 -
INT16 1 register -32,768 to 32,767 AB
UINT16 1 register 0 to 65,535 AB
INT32 2 registers -2,147,483,648 to ... ABCD
UINT32 2 registers 0 to 4,294,967,295 ABCD
FLOAT32 2 registers IEEE 754 ABCD
INT64 4 registers Large integers ABCDEFGH
FLOAT64 4 registers IEEE 754 double ABCDEFGH
STRING N registers ASCII text -
Byte Order Configuration
javascript// Byte order conversion examples
const byteOrders = {
'Big Endian': 'ABCD', // Most significant byte first
'Little Endian': 'DCBA', // Least significant byte first
'Big Endian Swap': 'BADC', // Swap 16-bit words
'Little Endian Swap': 'CDAB' // Reverse order
};
// Example: Read 32-bit float with different byte orders
function readFloat32(buffer, byteOrder) {
const bytes = new Uint8Array(buffer);
let ordered;
switch(byteOrder) {
case 'ABCD': ordered = bytes; break;
case 'DCBA': ordered = bytes.reverse(); break;
case 'BADC': ordered = [bytes[1], bytes[0], bytes[3], bytes[2]]; break;
case 'CDAB': ordered = [bytes[2], bytes[3], bytes[0], bytes[1]]; break;
}
const view = new DataView(new Uint8Array(ordered).buffer);
return view.getFloat32(0);
}
Download Resources
- Modbus Protocol Specification - Complete protocol documentation (2.8MB)
- Device Register Map Template - Excel template (125KB)
- Modbus Testing Tools - ModScan, QModMaster (45MB)
- Troubleshooting Guide - Common issues (1.5MB)
- Sample Code Library - Python, Node.js, C# (2.2MB)
Best Practices
Performance Optimization
- Batch Reads: Read multiple registers in one request
- Optimal Polling: Don't poll faster than device can respond
- Connection Pooling: Reuse TCP connections
- Error Handling: Implement retry logic with backoff
Reliability
- Timeouts: Set appropriate timeouts (1-5 seconds)
- Watchdog: Monitor communication health
- Buffering: Buffer data during network issues
- Logging: Log all errors for diagnostics
Troubleshooting
Common Issues
No Response from Device
- Check physical wiring (RS-485 polarity)
- Verify correct slave ID
- Confirm baud rate matches device
- Check termination resistors
- Verify device is powered on
CRC/LRC Errors
- Check cable quality and shielding
- Reduce baud rate
- Check for electromagnetic interference
- Verify proper grounding
Timeout Errors
- Increase timeout value
- Check network latency
- Verify device is not overloaded
- Check for network congestion
Download Resources
Modbus Protocol Specification
Complete protocol documentation
2.8 MB
Device Register Map Template
Excel template
125 KB
Modbus Testing Tools
ModScan, QModMaster
45 MB
Troubleshooting Guide
Common issues
1.5 MB
Sample Code Library
Python, Node.js, C#
2.2 MB
Modbus Protocol Specification
Complete protocol documentation
2.8 MB
Device Register Map Template
Excel template
125 KB
Modbus Testing Tools
ModScan, QModMaster
45 MB
Troubleshooting Guide
Common issues
1.5 MB
Sample Code Library
Python, Node.js, C#
2.2 MB
