pymodbus vs QModMaster: Script or GUI?

pymodbus is the go-to open-source Python library for Modbus (BSD-3-Clause) — it even shows up in roundups of free Modbus Poll alternatives as the “build your own” option (see the ranaliz.com 2026 list). So: script it in Python, or point-and-click in QModMaster? The honest answer is not either/or. Probe with your eyes first, automate with code second.

When each one wins

  • QModMaster wins at first contact with an unknown device: trying slave IDs, flipping between function codes, watching values update live, and opening the Bus Monitor when the bytes look wrong. Ten minutes in the GUI beats an hour of print-debugging.
  • pymodbus wins the moment the setup works and needs to keep working: scheduled polling, logging to CSV or a database, threshold alerts, and CI tests that verify a device still answers after a firmware update.

The workflow: probe in QModMaster, freeze in pymodbus

  • 1. Probe interactively in QModMaster. Find the slave ID, the right function code and start address, and confirm the values look sane. If floats come back as astronomical numbers, fix the byte order first — see our float byte-order guide.
  • 2. Copy those exact parameters into a pymodbus script. Same host, same port, same slave ID, same addresses — the script below is the direct translation of a working QModMaster session.
  • 3. When the script misbehaves at 3 a.m., reopen QModMaster and its Bus Monitor to see the raw frames again. GUI for diagnosis, script for the daily grind.

Minimal pymodbus script (Modbus TCP)

The direct translation of “read 10 holding registers from slave 1” into pymodbus 3.x:

from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient("192.168.1.100", port=502)
if not client.connect():
    raise SystemExit("TCP connect failed")

# holding registers (FC03), start address 0, 10 registers, slave id 1
rr = client.read_holding_registers(address=0, count=10, device_id=1)
if rr.isError():
    raise SystemExit(f"read failed: {rr}")

print(rr.registers)  # e.g. [9997, 10034, ...]
client.close()

Version note: current pymodbus (3.10+) names the slave parameter device_id. On older 3.x releases it was called slave, and on the 2.x line unit — if you copy examples from the internet, check which name your installed version expects.

For a serial RTU link, the equivalent client is ModbusSerialClient (same pymodbus.client module):

from pymodbus.client import ModbusSerialClient

client = ModbusSerialClient("/dev/ttyUSB0", baudrate=9600,
                            parity="N", stopbits=1, bytesize=8)
client.connect()
rr = client.read_holding_registers(address=0, count=10, device_id=1)
print(rr.registers if not rr.isError() else rr)
client.close()

What to automate first

  • Logging: poll every N seconds, append timestamped rows to CSV. This is the script every solar and energy-meter owner ends up writing.
  • Alerting: read a status register in a loop and send a notification when a fault bit flips.
  • Regression checks: a CI job that reads a known register map and fails the build when a firmware update moves something.

And keep QModMaster installed next to your scripts. The day a device stops answering, the fastest path back to green is still: open the GUI, read one register by hand, and look at the raw frame.

Related Guides

Similar Posts