Skip to content

Modbus Connector

The Modbus connector enables communication with PLCs and industrial devices using the Modbus protocol, supporting both serial (RTU) and TCP/IP connections.

Connector Types:

  • ModbusReader - Read data from Modbus devices
  • ModbusWriter - Write data to Modbus devices
  • ✅ Multiple transport protocols (TCP, RTU, UDP, TLS)
  • ✅ All register types (Holding, Input, Coil, Discrete Input)
  • ✅ Multiple data types (Int16/32/64, UInt16/32/64, Float32/64, ASCII)
  • ✅ Configurable byte and word order
  • ✅ Unit ID support for multi-device networks

Meddle supports the following Modbus transports:

  • TCP - Modbus TCP over Ethernet
  • TCPWithTLS - Modbus TCP with TLS encryption
  • UDP - Modbus over UDP
  • RTU - Modbus RTU over serial
  • RTUOverTCP - Modbus RTU encapsulated in TCP
  • RTUOverUDP - Modbus RTU encapsulated in UDP
{
"type": "ModbusReader",
"config": {
"endpoint": "192.168.1.100:502",
"transport": "TCP",
"pollingRate": 1000,
"defaultUnitId": 1,
"defaultBitOrder": "BigEndian",
"defaultWordOrder": "HighFirst"
},
"variables": [
{
"key": "temperature",
"address": 0,
"registerType": "HoldingRegister",
"dataType": "Float64"
},
{
"key": "pressure",
"address": 4,
"registerType": "HoldingRegister",
"dataType": "Int32"
}
]
}
{
"type": "ModbusReader",
"config": {
"endpoint": "/dev/ttyUSB0",
"transport": "RTU",
"pollingRate": 1000,
"defaultUnitId": 1,
"baudRate": 9600,
"dataBits": 8,
"parity": "None",
"stopBits": 1
},
"variables": [
{
"key": "sensor_value",
"address": 0,
"registerType": "InputRegister",
"dataType": "UInt16"
}
]
}
{
"type": "ModbusWriter",
"config": {
"endpoint": "192.168.1.100:502",
"transport": "TCP",
"defaultUnitId": 1
},
"variables": [
{
"key": "setpoint",
"address": 100,
"registerType": "HoldingRegister",
"dataType": "Float32"
},
{
"key": "enable",
"address": 0,
"registerType": "Coil"
}
]
}

General-purpose registers that can be read and written.

{
"key": "temperature",
"address": 0,
"registerType": "HoldingRegister",
"dataType": "Float64"
}

Function Codes: Read (03), Write Single (06), Write Multiple (16)

Read-only registers typically used for sensor data.

{
"key": "sensor_reading",
"address": 0,
"registerType": "InputRegister",
"dataType": "Int16"
}

Function Code: Read (04)

Single-bit registers for digital outputs.

{
"key": "motor_enable",
"address": 0,
"registerType": "Coil"
}

Function Codes: Read (01), Write Single (05), Write Multiple (15)

Read-only single-bit registers for digital inputs.

{
"key": "limit_switch",
"address": 0,
"registerType": "DiscreteInput"
}

Function Code: Read (02)

// Signed 16-bit integer (-32768 to 32767)
{"dataType": "Int16"} // 1 register
// Unsigned 16-bit integer (0 to 65535)
{"dataType": "UInt16"} // 1 register
// 32-bit float (4 bytes)
{"dataType": "Float32"} // 2 registers
// 64-bit float (8 bytes)
{"dataType": "Float64"} // 4 registers
// ASCII character (1 byte per register)
{"dataType": "AsciiChar"} // 1 register

Modbus devices may use different byte and word ordering. Configure these to match your device:

{
"defaultBitOrder": "BigEndian" // or "LittleEndian"
}
  • BigEndian: Most significant byte first (default, most common)
  • LittleEndian: Least significant byte first

For multi-register values (32-bit, 64-bit):

{
"defaultWordOrder": "HighFirst" // or "LowFirst"
}
  • HighFirst: High word first (default)
  • LowFirst: Low word first
{
"key": "special_value",
"address": 10,
"registerType": "HoldingRegister",
"dataType": "Float32",
"bitOrder": "LittleEndian",
"wordOrder": "LowFirst"
}

For Modbus RTU over serial connections:

{
"endpoint": "/dev/ttyUSB0",
"transport": "RTU",
"baudRate": 9600,
"dataBits": 8,
"parity": "None",
"stopBits": 1,
"timeout": 1000
}

Parameters:

  • baudRate: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
  • dataBits: 7 or 8
  • parity: None, Even, Odd
  • stopBits: 1 or 2
  • timeout: Read timeout in milliseconds

Modbus supports multiple devices on the same network using Unit IDs:

{
"defaultUnitId": 1 // Default for all variables
}

Per-variable override:

{
"key": "device2_temp",
"address": 0,
"registerType": "HoldingRegister",
"dataType": "Float32",
"unitId": 2 // Override for this variable
}
{
"type": "ModbusReader",
"config": {
"endpoint": "192.168.1.50:502",
"transport": "TCP",
"pollingRate": 5000,
"defaultUnitId": 1
},
"variables": [
{
"key": "voltage",
"address": 0,
"registerType": "InputRegister",
"dataType": "Float32"
},
{
"key": "current",
"address": 2,
"registerType": "InputRegister",
"dataType": "Float32"
},
{
"key": "power",
"address": 4,
"registerType": "InputRegister",
"dataType": "Float32"
},
{
"key": "energy",
"address": 6,
"registerType": "InputRegister",
"dataType": "Float64"
}
]
}
{
"type": "ModbusWriter",
"config": {
"endpoint": "192.168.1.100:502",
"transport": "TCP",
"defaultUnitId": 1
},
"variables": [
{
"key": "motor_speed",
"address": 100,
"registerType": "HoldingRegister",
"dataType": "UInt16"
},
{
"key": "motor_start",
"address": 0,
"registerType": "Coil"
},
{
"key": "motor_stop",
"address": 1,
"registerType": "Coil"
}
]
}
{
"type": "ModbusReader",
"config": {
"endpoint": "/dev/ttyUSB0",
"transport": "RTU",
"pollingRate": 1000,
"baudRate": 9600
},
"variables": [
{
"key": "device1_temp",
"address": 0,
"registerType": "HoldingRegister",
"dataType": "Float32",
"unitId": 1
},
{
"key": "device2_temp",
"address": 0,
"registerType": "HoldingRegister",
"dataType": "Float32",
"unitId": 2
},
{
"key": "device3_temp",
"address": 0,
"registerType": "HoldingRegister",
"dataType": "Float32",
"unitId": 3
}
]
}

Solutions:

  • Verify endpoint address and port
  • Check network connectivity
  • Increase timeout value
  • Verify device is powered and responsive

Solutions:

  • Check byte order (BigEndian vs LittleEndian)
  • Verify word order (HighFirst vs LowFirst)
  • Confirm data type matches device specification
  • Verify register address is correct

Solutions:

  • Check serial cable connections
  • Verify baud rate matches device
  • Confirm parity and stop bits settings
  • Check for proper termination resistors
  • Reduce polling rate to avoid bus collisions

Common Modbus exception codes:

  • 01: Illegal Function
  • 02: Illegal Data Address
  • 03: Illegal Data Value
  • 04: Slave Device Failure
  1. Start with Read-Only: Test with Input Registers before writing
  2. Use Appropriate Polling: Don’t poll faster than device can respond
  3. Group Consecutive Registers: More efficient than scattered reads
  4. Document Byte Order: Keep notes on device-specific configurations
  5. Test Unit IDs: Verify each device responds to its Unit ID
  • OPC UA - Alternative industrial protocol
  • Siemens S7 - Direct Siemens PLC communication
  • Filter - Filter Modbus data
  • SQL Writer - Store Modbus data in databases