Modbus
Read and write Modbus TCP and RTU devices
- Category
- Industrial
- Kind
- source
- Capabilities
- StreamsAssetsCommandsOperationsEntities
- Runs on
- Linux x64Linux ARM64macOS Apple siliconmacOS IntelWindows x64
Read and write PLCs, power meters, sensors and process controllers over Modbus TCP or serial (RTU). One connector covers any Modbus device: you describe yours with a register map. No code needed.
What you get
- Live readings — each mapped value is its own channel, scaled into engineering units.
- Setpoints — values marked writable can be set from Trellis via
ch.write(path, value). Each write is read back, so you see what the device took. - One device per input, named by its Device name. Channels read
/modbus/plc1/….
Setup
- Note the device's address and unit ID (usually
1). The standard Modbus TCP port is 502. For an RTU device, note its serial port (/dev/ttyUSB0,COM3) and line settings. - In Inputs, choose Add input, pick modbus, and fill in:
- Device name — a short label, e.g.
plc1 - Connection —
192.168.1.60:502, or the serial port for RTU - Transport —
tcp(default) orrtu. RTU uses Serial baud rate / parity / stop bits / data bits (default 9600 8N1). - Model — pick a built-in map, or paste your device's map into Register map. Each entry names a value, its address, type and scaling.
- Device name — a short label, e.g.
- Press Test connection. It reads the first mapped register, so a pass means the device answered.
- Channels appear on Live. Writable entries are available in Trellis.
- In the Channels table, give a channel a name and unit, such as
temp→bearing temperature,degC.
Register map example
[
{"alias": "temp", "address": 0, "kind": "input", "dtype": "i16",
"scale": {"gain": 0.1, "offset": 0}, "unit": "degC"},
{"alias": "pump_speed_sp", "address": 10, "kind": "holding",
"dtype": "u16", "unit": "rpm", "writable": true}
]
- Addresses are zero-based: a manual's
40001is address0. - Types:
u16,i16,u32,i32,f32, andboolfor coils and discrete inputs. - For a 32-bit value sent low word first, set
word_swap.
Dead-man (heartbeat)
If this computer hangs, loses power or loses the network, a Modbus output keeps its last value. A dead-man lets your PLC take over. While a test setup is deployed, Phloem keeps changing a heartbeat register. Your PLC drives its outputs safe when the heartbeat stops changing.
Your PLC needs a few lines of logic, or a drive's communication-loss setting:
- The heartbeat is one holding register (
u16). 0means "not supervised": do nothing while it reads0.- Any other value must change at least once per timeout. If it does not, drive the outputs to their safe states.
Then fill in the input's Dead-man section:
- Heartbeat register — the alias of that register in your map. Map it
without
writable, so a test setup can never write it. - PLC timeout (s) — the timeout you set in the PLC. Phloem uses it to decide how often to write.
- Outputs the PLC drives safe — the writable aliases your PLC makes safe. Outputs you leave out show as not credited to the dead-man.
{"alias": "heartbeat", "address": 100, "kind": "holding", "dtype": "u16"}
When a setup is undeployed, Phloem writes 0. The PLC stops supervising and
leaves the outputs where they are. Pick a timeout longer than your slowest
write; a few seconds suits most networks.
Notes
- A device we have never seen works as soon as you paste its map.
- Writes are checked against the map before they are sent. Every write is recorded.
#Supports
- Any Modbus-TCP device via a register map (paste your device's map)
- Any Modbus-RTU (serial) device via the same register map
#Connection fields
Every field the Add input form shows for this connector.
| Field | Type | Required | Default |
|---|---|---|---|
Device nameplc1 | Text | Yes | — |
Connection (host:port or serial device)192.168.1.60:502 | /dev/ttyUSB0 | Text | Yes | — |
Transporttcp | rtu | Text | — | tcp |
Serial baud rate (RTU)9600 | Number | — | 9600 |
Serial parity (RTU)none | even | odd | Text | — | none |
Serial stop bits (RTU)1 | 2 | Number | — | 1 |
Serial data bits (RTU)8 | Number | — | 8 |
Unit ID1 | Number | — | 1 |
Model (built-in map)leave empty when pasting a map | Text | — | — |
Register map (JSON)[{"alias":"temp","address":40001,...}] | Text | — | — |
Poll rate (Hz)1 | Number | — | 1 |
| Heartbeat register (alias) The alias of a one-word holding register your PLC watches. Map it read-only: the connector writes it, a document never can. Empty = no dead-man. heartbeat | Text | — | — |
| PLC timeout (s) How long your PLC waits on an unchanged heartbeat before it drives the outputs safe — the value configured in the PLC. 2 | Number | — | — |
| Outputs the PLC drives safe The writable aliases your PLC drives to a safe state when the heartbeat stops. valve, pump_speed_sp | Text | — | — |
Updated