Modbus RTU master over a serial line
You will find the project Qenex_Serial_ModbusMaster_HoldingRegisters.qproj
in the Examples folder next to QInsight.exe.
What the example shows
QInsight acts here as a Modbus RTU master: the Serial Port (COM)
driver with the Modbus Master protocol in rtu mode reads holding
registers from the slave with address 2 once a second. The example
shows:
- the driver and protocol settings exactly as entered in Project Configuration,
- scalar variables in holding registers (
ushort, one register per variable) with a linear conversion and a unit, - a Matrix variable transferred as one contiguous register block — axes and data cells of a map in a single request,
- writing to the device from the Watch Table (scalars) and from the Matrix control (map cells),
- driver reconnection after the converter is unplugged and the master resuming on its own.
What you need
The counterpart is any Modbus RTU slave with unit id 2 that offers holding registers at addresses 0–12. Without hardware a simulator will do, e.g. pyModSlave: a pair of virtual COM ports (QInsight on one end, the simulator on the other) and, in the simulator, RTU, slave id 2, 9600 Bd, 8N1, holding registers starting at address 0. With a real device a USB/RS-485 converter is enough.
Before starting, adapt in Project Configuration what is specific to your computer and device:
portin the driver settings — the project hasCOM6; enter the port of the converter or your end of the virtual pair,baudRate(andparity,stopBitsif needed) to match the device — the project expects 9600 Bd, 8N1,unitIdin the protocol settings if the slave is not at address 2.
The project
Drivers and protocols
One driver + protocol pair handles the communication. The settings are stored exactly like this:
| Serial Port (COM) driver | Meaning |
|---|---|
port=COM6 | COM port name — change it for your computer |
baudRate=9600 | communication speed |
dataBits=8 | number of data bits |
parity=none | no parity |
stopBits=1 | one stop bit |
handshake=none | no flow control |
reconnectDelayMs=2000 | delay before reopening the port after a failure |
reconnectAttempts=5 | after five consecutive failed attempts the driver stops (the default is -1 = forever) |
| Modbus Master (RTU/TCP) protocol | Meaning |
|---|---|
mode=rtu | RTU framing (CRC16) for a serial line |
unitId=2 | address of the slave the master talks to |
requestTimeoutMs=2000 | response timeout per request |
requestRetries=8 | request repetitions after a timeout, on top of the first attempt (up to 9 transmissions) |
The project also contains two drivers the Modbus example does not need:
Data Log Recorder (file=DataLogs;append=true;flushOnWrite=false;reorderBufferMs=500)
is enabled and records EngTorque and Torque into a .qilog file in
the DataLogs folder next to the project on every run (the matrix is not
logged); Data Log Replay (file=DataLogs\values.qilog;mode=realtime;speed=1;loop=false)
is disabled. If you do not want logging, disable the Data Log Recorder
driver.
Events
The project has a single periodic event Pool500ms with a period of
1000 ms (the name does not match the actual period; the Period
value is what counts). All three variables are bound to it, so once a
second the master sends three separate FC03 requests — one per variable.
Variables
All variables live in the /Modbus namespace, are of type ushort and
share the ModbusSImple presentation: the Pass-through conversion is
linear with multiplier=0.01, offset=0 (engineering value = raw × 0.01,
so raw 12345 is shown as 123.450), unit Nm, format {0:F3}, range
0–65535.
| Variable | Type | Register | Address | Direction | Event | Presentation |
|---|---|---|---|---|---|---|
EngTorque (Engine torque) | scalar ushort | holding | 0 | readWrite | Pool500ms | ModbusSImple (× 0.01, Nm) |
Torque (Torque) | scalar ushort | holding | 1 | read | Pool500ms | ModbusSImple (× 0.01, Nm) |
Drivability (Drivability) | matrix ushort, 3 × 2 | holding | 2 | readWrite | Pool500ms | ModbusSImple on axes and data |
Comm params of the scalars: registerType="holdingRegister";address="0";wordOrder="big";direction="readWrite";eventRef="Pool500ms"
(for Torque address="1", direction="read"). wordOrder has no
effect on single-register values.
Drivability is a Matrix variable — a map
with an X axis Speed [RPM] (3 points), a Y axis Temp. [K] (2 points)
and 6 data cells, 11 values = 22 bytes in total, Endianness be. The
Modbus Master transfers it as a
contiguous block of 11 holding
registers starting at address 2 (addresses 2–12); a read is a single FC03
request, a write sends only the changed cells. The ModbusSImple
presentation is assigned to both axes as well, so the axis values are
displayed with the Nm unit.
Workspace
One workspace (Workspace6904) with five controls:
| Control | Variables | Note |
|---|---|---|
| Graph | EngTorque (red, left axis), Torque (blue, right axis) | 10 s window, both axes auto-scale |
| Signal | EngTorque | 250 ms refresh |
| Signal | Torque | 250 ms refresh |
| Matrix | Drivability | AutoRead, cell written on Enter (WriteOnEnter) |
| Watch Table | Torque, EngTorque | columns Name, Value, Unit, Time, Write |
No control is saved in write mode — writing is switched on at runtime.
What you will see and what to try
- Reading. Start the runtime (Start). The driver opens the COM port and the master starts reading registers 0, 1 and the block 2–12 once a second. Change holding register 0 or 1 in the simulator and watch the value appear within a second in the graph, the Signal control and the Watch Table — divided by one hundred and with Nm.
- Writing a scalar. In the Watch Table switch on write mode for the
EngTorquerow (Write column), enter an engineering value such as123.45and confirm. The master writes the raw value 12345 into register 0 and you will see it in the simulator.Torqueisreadonly, so no write is offered for it. Details in Writing values to the device. - Writing a map cell. Switch the Matrix control to write mode, overwrite a cell or an axis point and confirm with Enter — only the affected register of the 2–12 block goes to the slave.
- Connection loss. Unplug the USB converter (or close the virtual
port) while running. The driver enters the Faulted state, the
master pauses its requests and the driver tries to reopen the port
every 2 s, at most five times. Plug the converter back within those
roughly ten seconds — the driver opens the port, the master resumes
reading on its own and the graph only shows a gap. Once the limit is
exhausted the driver ends in the Stopped state with the error
gave up after 5 reconnect attempt(s)and you restart it with the Start button in its properties (see Driver states and the Start button). SetreconnectAttempts=-1for endless retries. When it is the slave that does not answer (wrongunitId, simulator closed), the port stays open and only the protocol reports the error through its timeout — withrequestTimeoutMs=2000andrequestRetries=8it waits up to 9 × 2 s for a single request.
Related chapters
- Reference — Serial Port (COM) and Reconnection.
- Reference — Modbus Master (RTU/TCP) including Matrix variables.
- Conversion and presentation, Events, Matrix variable.
- Watch Table, Matrix control, Writing values to the device.
- Logging data — what the enabled Data Log Recorder does.

