RS485 / Modbus RTU
The Eziwan Gateway features a native RS485/RS232 port on the terminal block. This interface allows you to collect data from your sensors, PLCs, and meters using the Modbus RTU protocol—and publish it to the cloud without a separate gateway.
Physical Connection
RS485 Terminal Block Wiring
Terminal Block Pins
| Pin | Signal | Description |
|---|---|---|
| A | RS485+ | Positive differential line |
| B | RS485− | Negative differential line |
| GND | Ground | Common reference |
Reversing A and B causes communication errors but does not damage the equipment. If no device responds, test by reversing A and B.
Termination Resistors
On an RS485 bus with multiple slaves:
- 120Ω on the first and last devices on the bus
- The Eziwan Gateway has an internal jumper to enable termination (hardware documentation)
- On intermediate devices: termination disabled
Configuring Modbus Polling
Via the Eziwan dashboard
Device → Configuration → RS485 / Modbus
Graphical interface: Add each slave and each register, and set the polling interval and the target MQTT topic.
Via the API / YAML
# Configuration RS485 + Modbus RTU
rs485:
enabled: true
baud_rate: 9600 # 1200, 2400, 4800, 9600, 19200, 38400, 115200
parity: none # none, even, odd
data_bits: 8 # 7 ou 8
stop_bits: 1 # 1 ou 2
polling_interval_sec: 10 # Overall polling interval (seconds)
modbus:
slaves:
- slave_id: 1
name: "Compteur énergie Schneider PM2200"
timeout_ms: 1000
retries: 3
registers:
- address: "0x0048"
type: holding # holding, input, coil, discrete_input
format: float32_abcd
tag: active_power
unit: kW
scale: 1.0
mqtt_topic: "site/usine-01/energie/puissance_active"
- address: "0x004A"
type: holding
format: float32_abcd
tag: reactive_power
unit: kVAr
scale: 1.0
mqtt_topic: "site/usine-01/energie/puissance_reactive"
- address: "0x0156"
type: holding
format: float32_abcd
tag: energy_total_kwh
unit: kWh
scale: 1.0
mqtt_topic: "site/usine-01/energie/index_kwh"
- slave_id: 2
name: "Capteur température / humidité"
timeout_ms: 500
registers:
- address: "0x0001"
type: input
format: int16
tag: temperature
unit: "°C"
scale: 0.1 # Valeur brute 245 → 24,5°C
mqtt_topic: "site/usine-01/environnement/temperature"
- address: "0x0002"
type: input
format: uint16
tag: humidity
unit: "%RH"
scale: 0.1
mqtt_topic: "site/usine-01/environnement/humidite"
- slave_id: 3
name: "Automate Schneider TM3 — Station de pompage"
polling_interval_sec: 30 # Override the global interval
registers:
- address: "0x0000"
type: holding
format: uint16
tag: pump_status
unit: ""
# 0=off, 1=on, 2=fault
mqtt_topic: "site/pompe-01/etat/pompe"
- address: "0x0001"
type: holding
format: int16
tag: pressure_bar
unit: bar
scale: 0.01
mqtt_topic: "site/pompe-01/mesures/pression"
- address: "0x0002"
type: holding
format: uint16
tag: flow_m3h
unit: "m³/h"
scale: 0.1
mqtt_topic: "site/pompe-01/mesures/debit"
Supported Log Formats
| Format | Description | Registers |
|---|---|---|
int16 | 16-bit signed integer | 1 |
uint16 | 16-bit unsigned integer | 1 |
int32_abcd | 32-bit signed integer, big-endian | 2 |
int32_cdab | 32-bit signed integer, little-endian | 2 |
uint32_abcd | 32-bit unsigned integer, big-endian | 2 |
float32_abcd | IEEE 754 float, big-endian | 2 |
float32_cdab | IEEE 754 float, little-endian (Schneider) | 2 |
float32_badc | IEEE 754 float, mid-big-endian | 2 |
coil | Modbus coil (1 bit) | 1 coil |
bit | Extract a bit from a uint16 register | 1 |
If the values read appear to be inconsistent (e.g., 1234 read as 12340000), try float32_cdab instead of float32_abcd. The convention varies by manufacturer.
MQTT Publication
Modbus data is automatically published to the Eziwan MQTT broker:
Topic Structure
eziwan/{device_id}/modbus/{slave_id}/{tag_name}
Example:
eziwan/d_a1b2c3d4/modbus/1/active_power
JSON Payload
{
"value": 42.7,
"unit": "kW",
"timestamp": "2025-06-15T14:23:45.123Z",
"slave_id": 1,
"register": "0x0048",
"quality": "good"
}
The "quality" field can take the following values:
"good"— read successful"timeout"— slave did not respond"error"— Modbus error (code included in"error_code")
Subscribe from your system
# Subscribe to all tags on a site
mosquitto_sub -h mqtt.eziwan.com -p 8883 \
--cert client.crt --key client.key --cafile ca.crt \
-t "eziwan/d_a1b2c3d4/modbus/#"
# Subscribe to a specific tag
mosquitto_sub -h mqtt.eziwan.com -p 8883 \
--cert client.crt --key client.key --cafile ca.crt \
-t "eziwan/d_a1b2c3d4/modbus/1/active_power"
Equipment Tested
| Manufacturer | Model | Protocol | Notes |
|---|---|---|---|
| Schneider Electric | PM2100, PM2200 | Modbus RTU | Energy meter — float32 |
| Schneider Electric | TM3, TM2 | Modbus RTU | PLC — coils + holding registers |
| Siemens | SENTRON PAC 3200 | Modbus RTU | Energy meter |
| Carlo Gavazzi | EM24, EM340 | Modbus RTU | Three-phase/single-phase meter |
| ABB | B23, B24 | Modbus RTU | Energy meter |
| Wago | 750-xxx | Modbus RTU | I/O bus coupler |
| Phoenix Contact | ILB ETH 2TX | Modbus TCP | Via TCP bridge |
| Hager | ECR380D | Modbus RTU | Energy meter |
| Eastron | SDM630 | Modbus RTU | Three-phase meter |
| Generic | Any Modbus RTU | Modbus RTU | Slave ID 1–247 |
Troubleshooting
Communication Test from Eziwan
Dashboard → Device → Tools → Modbus Test
Enter the slave ID, type, and register address → Eziwan sends a read request and displays the raw response in real time. Ideal for diagnostics without physical access to the site.
Modbus Error Codes
| Code | Meaning | Solution |
|---|---|---|
TIMEOUT | Slave not responding | Check wiring, baud rate, slave ID, termination |
01 | Function not supported | Use holding instead of input (or vice versa) |
02 | Invalid register address | Check the register in the equipment documentation |
03 | Invalid data value | Value outside the allowed range |
04 | Internal slave fault | Check the equipment log |
Wiring Checklist
If no slave responds:
- Check the A/B polarity (try reversing it)
- Check the baud rate (9600 is the most common)
- Verify that the slave IDs are unique on the bus
- Enable the 120Ω termination on the first and last devices
- Test with a single slave (isolate the problem)
- Measure the A−B differential voltage: must be > 200 mV in standby mode
Reference Differential Voltage
Bus in standby mode (no transmission):
V(A−B) > +200 mV → polarisation correcte
Pendant transmission :
V(A−B) > +1.5V → signal dominant (1 logique)
V(A−B) < −1.5V → signal récessif (0 logique)
Do you have Modbus TCP devices (on an Ethernet network)? Eziwan also supports the Modbus TCP → MQTT bridge. See the Modbus TCP documentation →
- Email: support@eziwan.com — response within 4 business hours
- Guided Setup: Schedule a technical onboarding session →
Frequently Asked Questions
How many devices can be connected to a single RS-485 bus?
32 slaves per segment without a repeater, over a maximum length of approximately 1,200 m at 9,600 baud. Beyond that, divide the system into multiple buses or add repeaters.
Is a terminating resistor necessary?
On long or high-speed buses, yes: 120 Ω at each end prevents reflections that corrupt the frames. On a short bus (a few meters, 9,600 baud), its absence often goes unnoticed—until the day it stops working.
What polling rate should you choose?
Adjust the polling frequency to match the process dynamics: every 10 to 60 seconds for energy or level measurements, and every 1 to 5 seconds for machine monitoring. Polling too frequently on a slow bus causes a cascade of timeouts.
How do you mix equipment with different speeds?
Do not mix serial settings on the same bus: all slaves must share the same baud rate, parity, and stop bits. Otherwise, distribute them across the gateway's various RS-485 ports.
Related Resources
- RS485 Gateway to the Cloud — the solution page
- RS485 / Modbus over 4G — collecting data from a serial bus via cellular
- Modbus to the Cloud — the overview
- Complete Modbus Guide — registers, functions, and troubleshooting
- MQTT and RS-485 in Practice — the in-depth article