I/O Binding¶
Address Examples: %IX0.0, %QX0.0, %IW0, %QW0¶
Use %IX0.0 when you need a concrete boolean input example, %QX0.0 for a
boolean output example, %IW0 for a word input example, and %QW0 for a word
output example. This page covers those address forms and how symbolic variables
bind to physical I/O channels.
Guide¶
truST PLC I/O Binding Guide¶
This guide explains how to map hardware I/O to Structured Text variables using the Web UI
or io.toml and IEC addresses (%IX, %QX, %MX).
Tip: The Web UI supports driver selection, GPIO pin mapping, Modbus/TCP settings, and safe‑state outputs under I/O → I/O configuration (no manual file editing needed).
1) Addressing Basics¶
Use IEC-style addresses in ST:
VAR_GLOBAL
InSignal AT %IX0.0 : BOOL;
OutSignal AT %QX0.0 : BOOL;
END_VAR
%I= input,%Q= output,%M= memoryX= bit address (use for GPIO and discrete I/O)
Marker (%M) address variants:
- %MX<byte>.<bit> (bit, BOOL), example: %MX0.7
- %MB<byte> (byte), example: %MB12
- %MW<byte> (word), example: %MW50
- %MD<byte> (double word), example: %MD200
- %ML<byte> (long word), example: %ML8
- %M* (wildcard, resolved by VAR_CONFIG)
Runtime cycle semantics for %M bindings:
- Cycle start: %M process image is read into bound variables.
- Cycle end: bound variable values are written back to %M process image.
2) io.toml Structure (v1)¶
Single-driver form (legacy + still supported):
[io]
driver = "simulated"
params = {}
Multi-driver form (composed drivers, executed in order):
[io]
drivers = [
{ name = "modbus-tcp", params = { address = "192.168.0.10:502", unit_id = 1, input_start = 0, output_start = 0, timeout_ms = 500, on_error = "fault" } },
{ name = "mqtt", params = { broker = "192.168.0.20:1883", topic_in = "line/in", topic_out = "line/out", reconnect_ms = 500, keep_alive_s = 5, allow_insecure_remote = true } }
]
Rule:
- Use either io.driver + io.params or io.drivers (do not mix both in one file).
Optional safe state outputs:
[[io.safe_state]]
address = "%QX0.0"
value = "FALSE"
If io.toml is missing, the runtime uses system IO config:
- Linux/macOS: /etc/trust/io.toml
- Windows: C:\\ProgramData\\truST\\io.toml
3) GPIO Example (Raspberry Pi)¶
[io]
driver = "gpio"
[io.params]
backend = "sysfs"
inputs = [
{ address = "%IX0.0", line = 17, debounce_ms = 5 }
]
outputs = [
{ address = "%QX0.0", line = 27, initial = false }
]
[[io.safe_state]]
address = "%QX0.0"
value = "FALSE"
4) Loopback (Local Testing)¶
[io]
driver = "loopback"
params = {}
This copies outputs to inputs for local testing without hardware.
5) Modbus/TCP Example¶
[io]
driver = "modbus-tcp"
[io.params]
address = "192.168.0.10:502"
unit_id = 1
input_start = 0
output_start = 0
timeout_ms = 500
on_error = "fault"
6) MQTT Example¶
[io]
driver = "mqtt"
[io.params]
broker = "192.168.0.20:1883"
topic_in = "line/in"
topic_out = "line/out"
reconnect_ms = 500
keep_alive_s = 5
allow_insecure_remote = true
7) Transport Gating Notes (Critical)¶
EtherCAT hardware transport (non-mock adapter):
- requires build feature
ethercat-wire - supported on unix targets only in this build
adapter = "mock"remains valid for deterministic local/CI validation
OPC UA wire server:
- requires build feature
opcua-wire - if
[runtime.opcua].enabled = truewithoutopcua-wire, runtime startup fails with a feature-disabled error - when enabled, configure either:
allow_anonymous = true(local commissioning only), orallow_anonymous = falseplus bothusernameandpassword
Communication examples with step-by-step commissioning flow:
examples/communication/modbus_tcp/README.mdexamples/communication/mqtt/README.mdexamples/communication/opcua/README.mdexamples/communication/ethercat/README.mdexamples/communication/ethercat_field_validated_es/README.mdexamples/communication/gpio/README.mdexamples/communication/multi_driver/README.md
8) Validate + Inspect¶
EtherCAT backend details (module chain profile, diagnostics, and hardware setup):
docs/guides/ETHERCAT_BACKEND_V1.md.
Validate a project folder:
trust-runtime validate --project <project-folder>
Read current I/O snapshot:
trust-runtime ctl --project <project-folder> io-read
Write output (for testing):
trust-runtime ctl --project <project-folder> io-write %QX0.0 TRUE