# Modbus RTU

> Modbus over a serial bus, with the physical line modeled explicitly and shared by its unit-addressed devices.

The Modbus RTU driver talks to Modbus devices on a serial bus — RS-485 or RS-232,
reached through a physical COM port, a USB adapter or a virtual/redirected port.
Because the bus is physically shared, the topology is
**Driver → Line → Device → Tag**: the **line** owns everything electrical (port,
baud, format, timing), and each **device** on it owns only its unit address,
polling and tags.

## Serial line {#serial-line}

| Field | Meaning | Default |
| --- | --- | --- |
| **Name** | Friendly name for the bus. Editable at any time. | required |
| **Serial port** | The operating-system port, for example `COM3`. The field is free text — physical, virtual and redirected ports all work — and the arrow beside it offers the ports Windows currently detects (with a **Refresh** for adapter hot-plug); the detected list is a convenience, never a whitelist. | `COM1` |
| **Baud** | Bit rate shared by every device on the bus. | 9600 |
| **Serial format** | Closed choice of `8N1`, `8N2`, `8E1`, `8E2`, `8O1`, `8O2`: the digit is data bits, the letter parity (`N` none, `E` even, `O` odd), the last digit stop bits. Other widths, mark/space parity and 1.5 stop bits are not supported. | `8E1` |
| **Response timeout (ms)** | Longest wait for one unit's response, 100 to 60,000. Longer timeouts accommodate slow equipment but make missing units, and discovery, slower to identify. | 1000 |
| **Minimum transaction interval (ms)** | Line-wide compatibility pacing, 0 to 1000. Zero keeps only the automatic protocol silence; a positive value can raise, never reduce, it. | 0 |

The protocol itself requires silence between frames, and the line always enforces
it: at or below 19,200 baud the automatic silence is 3.5 character times computed
from the configured format; above 19,200 baud it is the fixed 1.75 ms the
specification recommends. The effective silence is the **greater** of that
automatic floor and the configured interval — never their sum — and the panel
shows both values. Raising the interval deliberately slows every unit on the
line; it is a compatibility aid, not a repair for wiring, termination, grounding
or noise.

A new line starts **disabled** so its physical settings can be configured first.
Each physical port belongs to at most one line, compared case-insensitively and
even while lines are disabled. The name and the transaction interval stay
editable while the line runs (a timing edit takes effect without cycling the
port); the port, baud, format and response timeout are locked while the line is
enabled — disable and save it first. Disabling a line stops communication for all
of its devices without changing their individual Enabled choices.

The line reports the physical transport separately from its devices: **Off**,
**Idle** (no enabled device), **Connecting**, **Online**, or **Port failure**
with a diagnostic. Deleting an empty line removes only the line; deleting one
that contains devices asks for explicit confirmation and deletes those devices
and their tags too.

## Device {#device}

| Field | Meaning | Default |
| --- | --- | --- |
| **Serial line** | Fixed — a device is created under its line and inherits the physical tuple, shown read-only in the panel. Add the device under the intended line. | — |
| **Unit ID** | The device's Modbus address on the bus, 1 to 247, unique within the line (disabled devices included). | 1 |
| **Poll interval (ms)** | Default polling rate for tags that do not override it. | 1000 |

The internal runtime address is
`modbus+rtu://<line-id>/<port>/<baud>/<format>/<timeout>/<unitId>/<interval>` —
it carries the line's stable identity and complete physical settings, never its
friendly name.

## Shared line behavior {#shared-line-behavior}

The driver opens **one serial session per line** and serializes every request
from every device through a single dispatcher, so reads and writes never overlap
on the bus. A pending write takes the next free turn with bounded priority:
writes are served promptly, but sustained writing cannot starve polling. Each
unit's timeouts are isolated with progressive backoff, so one silent device slows
only itself. A CRC-valid Modbus exception is a per-request error on that tag —
the line stays healthy. Only a physical I/O failure (the port disappearing, the
adapter unplugged) invalidates the shared session and starts one coordinated
reopen for the whole line. The last device released closes the port.

## Tag addressing {#tag-addressing}

Tag addressing is identical to [Modbus TCP](driver-modbus-tcp): a **Register
class** (`HoldingRegister`, `InputRegister`, `Coil`, `DiscreteInput`, derived by
default from the tag's type and access), a 0-based **Register number**, an
automatic **Quantity** (Boolean 1 register, Int32 and Float 2, String 4; the box is
drawn on String tags only, because every other width is fixed), and the two
independent byte-order boxes, both defaulting to most-significant-first. The
supported value types are the same four — Boolean, Int32, Float and String — and
the read/write function codes and the four wire layouts are documented on the
[Modbus TCP](driver-modbus-tcp) page and apply unchanged here.

## Discovery {#discovery}

Discovery probes a unit-id range over an existing line and lives on that line's
panel:

| Field | Meaning | Default |
| --- | --- | --- |
| **Unit ID start** | First unit id to probe, 1 to 247. | 1 |
| **Unit ID end** | Last unit id, ascending from the start. | 32 |

The scan reloads the line's saved physical settings, opens the port once, and
probes the range **sequentially** with Read Basic Device Identification
(function 43/14), pacing every probe with the line's effective inter-frame
silence. It never tries setting combinations and never reads registers. A
CRC-valid Modbus exception proves a unit is present without claiming identity; a
timeout or an invalid frame does not.

A line that is in use is never interrupted or toggled automatically — disable it
before scanning, and re-enable it yourself afterwards. Canceling closes the
serial session and leaves any results already shown as transient candidates
until you explicitly add them. A unit id that is already configured is marked as
such and opens the existing device instead of creating a duplicate; results
carry no tags — registers are configured after **Add**.

Discovery and line configuration share one fail-fast reservation per physical
port, so a scan and a settings change cannot fight over the port: the loser is
told which operation holds it.

## Limits worth knowing {#limits-worth-knowing}

- The four value types are the wire codec's whole vocabulary; wide integers and
  Double are not offered.
- Throughput is a bus property: every device on the line shares one request
  stream, paced by the effective inter-frame silence, so many devices or a raised
  interval lengthen every poll cycle.
