# Building a pymodbus Plug for PLCs and Modbus Devices
URL: /guides/pymodbus-plug
Control fixtures, chambers and power meters over Modbus TCP or RTU from an OpenHTF plug with pymodbus — connect, read holding registers into measurements, write coils to actuate a fixture, decode 32-bit floats, and handle Modbus exceptions.
Fixtures and environmental equipment usually expose Modbus: a PLC that clamps the DUT, a thermal chamber, a programmable load, a power meter. pymodbus speaks Modbus TCP and RTU; an OpenHTF plug turns register reads into measurements and coil writes into fixture actions.
Examples use pymodbus 3.x's synchronous client.
pymodbus 3.9 renamed the `slave=` keyword to `device_id=`. Check `pymodbus.__version__` and use the one your install expects.
The phase group guarantees `release_dut` runs even when `power_and_measure` fails; the plug's `tearDown()` is a second safety net if the process dies mid-phase.
Swap the client; the rest of the plug is identical:
**Addresses are zero-based in pymodbus.** A device manual's "register 40101" is holding register address 100.
**Data types.** Modbus only knows 16-bit registers; ints, floats and word order (big/little endian) are conventions of each device. `struct` makes the conversion explicit and testable.
**Check `isError()`** on every response; a Modbus exception response is not a Python exception.
**Timeouts.** `timeout=2` on the client plus phase `timeout_s` in `PhaseOptions` bounds a dead PLC.
**Shared devices.** If a chamber is shared by several stations, one plug per station is fine for reads; coordinate writes outside OpenHTF.
**Environmental profiles.** For a thermal cycle, combine `write_register` setpoints with a monitor sampling `temperature_c()` and `consistent_end_dimension_pivot_validate` (validators) to prove the chamber settled.