Modbus RTU slave se simulovanými senzory
Projekt Qenex_Serial_ModbusSlave_SimulatedSensors.qproj najdete ve složce
Examples vedle QInsight.exe.
Co ukázka předvádí
- QInsight jako Modbus RTU slave (unit 2) na sériovém portu — driver Serial Port (COM) + protokol Modbus Slave. Master čte z holding registrů 0 a 1 aktuální hodnoty dvou proměnných.
- Simulované senzory ze skriptu: periodický Python skript (2 s) posouvá po pilovém průběhu teplotu oleje 0–150 °C a tlak oleje 1000–2500 kPa.
- Dvojí zápis každé hodnoty: do proměnné slave (pro mastera) a do její virtuální kopie (pro controly), protože zápis ze skriptu na protokolu zařízení nikdy nevyvolá událost pro UI.
- Obnovu spojení driveru Serial Port po odpojení převodníku.
Co potřebujete
- Modbus RTU master — např. qModMaster: unit 2, holding registry od adresy 0, počet 2 (FC03), RTU, 9600 Bd, 8 bitů, bez parity, 1 stop bit.
- Sériovou cestu k masteru: dvojici spárovaných COM portů na jednom PC (virtuální null-modem pár), nebo dva převodníky USB/RS-485 — jeden pro QInsight, druhý pro mastera.
- Co upravit: v driveru Serial Port změňte
port=COM6na port použitý ve vašem počítači. Rámování aunitId=2nechte, nebo změňte shodně na obou stranách. Skripty vyžadují nastavený Python.
Projekt
Drivery a protokoly
Driver Serial Port Driver (SerialPortDriver):
| Parametr | Hodnota | Význam |
|---|---|---|
port | COM6 | jméno COM portu — upravte podle svého počítače |
baudRate | 9600 | komunikační rychlost |
dataBits | 8 | počet datových bitů |
parity | none | bez parity |
stopBits | 1 | jeden stop bit |
handshake | none | bez řízení toku |
reconnectDelayMs | 2000 | prodleva před dalším pokusem o otevření portu po chybě |
reconnectAttempts | -1 | pokusy bez omezení počtu, viz Obnova spojení |
Pod ním protokol Modbus Slave (RTU/TCP) (ModbusSlaveProtocol):
| Parametr | Hodnota | Význam |
|---|---|---|
mode | rtu | rámování RTU (CRC16, sériová linka) |
unitId | 2 | vlastní adresa slave — master ji musí uvést v dotazu |
respondToAnyUnit | false | dotazy na jinou unit adresu slave ignoruje |
Druhá dvojice Virtual Data Driver (VirtualDataDriver, v UI Virtual
Variables Host) + Virtual Variables (VirtualDataProtocol) nemá žádná
nastavení a nese obě zobrazovací kopie. Projekt nemá žádné události: slave
eventRef nepotřebuje, virtuální proměnné dostávají vzorky zápisem skriptu.
Proměnné
| Proměnná | Namespace | Typ | Protokol | Registr / Comm params | Prezentace |
|---|---|---|---|---|---|
OilTemp | /Modbus | ushort | Modbus Slave | holding registr 0, wordOrder="big", direction="read" | Temperature |
OilPressure | /Modbus | ushort | Modbus Slave | holding registr 1, wordOrder="big", direction="read" | Pressure |
OilTempView | /Virtual | double | Virtual Variables | — (virtuální, bez parametrů) | Temperature |
OilPressureView | /Virtual | double | Virtual Variables | — (virtuální, bez parametrů) | Pressure |
Proměnné slave jsou ushort, každá tedy obsadí jeden registr, a master je
čte (direction="read"). Prezentace Temperature (0–150 °C) a Pressure
(1000–2500 kPa), obě s formátem {0:F0}, používají jedinou lineární konverzi
Raw (multiplier=1, offset=0) — inženýrská hodnota se rovná surové (raw) hodnotě.
Skripty
Oba skripty jsou blokující, bez timeoutu a jen pro runtime. init.py
(Startup) nastaví výchozí stav simulace a hned ho publikuje do registrů
slave i do zobrazovacích kopií:
# Startup script: initial state of the simulated sensors.
# The periodic script (simulate.py) ramps the values from here; the globals persist
# between script runs inside one runtime session.
oil_temp = 0.0 # degC, ramps 0 .. 150
oil_pressure = 1000.0 # kPa, ramps 1000 .. 2500
direction = 1 # +1 ramping up, -1 ramping down
# Publish the initial values right away, both to the slave registers and to the display copies.
OilTemp.EngValue = oil_temp
OilPressure.EngValue = oil_pressure
OilTempView.EngValue = oil_temp
OilPressureView.EngValue = oil_pressure
simulate.py (Periodic, period=2;unit=s) každé 2 s posune obě
veličiny o krok a na krajích rozsahu otočí směr:
# Periodic script (period=2;unit=s): saw-tooth ramp of the simulated sensors.
# Temperature moves 1 degC per step between 0 and 150, pressure 10 kPa per step between
# 1000 and 2500, so one sweep up takes 5 minutes; at either end the direction flips.
#
# Every value is written twice on purpose:
# - OilTemp / OilPressure are the Modbus slave variables. The slave serves their current
# value to the master (holding registers 0 and 1). A script write never raises a UI event
# on a device protocol, so these two are not shown in any control.
# - OilTempView / OilPressureView are virtual variables. The Virtual Data protocol publishes
# every script write to the UI, so the graph and signal controls follow them.
oil_temp += direction * 1.0
oil_pressure += direction * 10.0
if oil_temp >= 150.0 or oil_pressure >= 2500.0:
oil_temp, oil_pressure, direction = 150.0, 2500.0, -1
elif oil_temp <= 0.0 or oil_pressure <= 1000.0:
oil_temp, oil_pressure, direction = 0.0, 1000.0, 1
OilTemp.EngValue = oil_temp
OilPressure.EngValue = oil_pressure
OilTempView.EngValue = oil_temp
OilPressureView.EngValue = oil_pressure
Stav simulace je uložen v běžných pythonovských proměnných — skripty projektu
sdílejí jeden prostor, takže hodnoty
zůstávají zachovány mezi běhy a init.py je při startu runtime vynuluje. Krok 1 °C
a 10 kPa po 2 s dává 150 kroků na průběh, tedy 5 minut nahoru a 5 dolů.
Proč dvojí zápis. OilTemp a OilPressure patří protokolu Modbus Slave:
zápis skriptu jejich hodnotu uloží a slave ji poskytuje masterovi, ale na
protokolu zařízení zápis ze skriptu
nikdy nevyvolá událost pro UI
— v controlech by se hodnoty těchto proměnných neaktualizovaly. Proto skript tutéž hodnotu
zapíše i do OilTempView a OilPressureView na protokolu
Virtual Variables, který každý
zápis publikuje jako vzorek s časovou značkou. Zápis přes EngValue je
s konverzí 1:1 totéž jako raw; u ushort se hodnota převádí na celé číslo,
což kroky 1,0 a 10,0 splňují.
Workspace
Workspace Simulated sensors má tři controly, všechny navázané na
virtuální kopie, ne na proměnné slave: Graph
„Simulated sensors (virtual copies of the slave registers)“ s oknem 300 s
(OilTempView červeně na levé ose 0–150, OilPressureView modře na pravé
ose 1000–2500) a dva Single-Signal
controly (obnova 250 ms) s aktuální teplotou a tlakem.
Co uvidíte a co vyzkoušet
- Po Start runtime kreslí graf pilový průběh (okno 300 s = jeden průběh nahoru) a Single-Signal controly ukazují aktuální hodnoty. Master čte z registru 0 teplotu a z registru 1 tlak — tytéž hodnoty, po 2 s o 1 °C a 10 kPa jinak.
- Dotaz na jinou unit adresu než 2 zůstane bez odpovědi
(
respondToAnyUnit=false); čtení zasahující do registru 2 a vyšších slave odmítne jako celek. - Odpojte a znovu připojte převodník. Driver Serial Port přejde do stavu
Faulted, v logu se objevují varování s číslem pokusu a driver se pokouší port
otevřít každé 2 s (
reconnectDelayMs=2000) bez omezení (reconnectAttempts=-1); skript i graf běží dál. Po opětovném připojení driver port automaticky otevře a master čte aktuální hodnoty bez zásahu obsluhy. - Zkraťte periodu skriptu (
period=500;unit=ms) nebo změňte krok vsimulate.py— master ani workspace se měnit nemusí.
Související kapitoly
- Serial Port (COM) a Obnova spojení — parametry driveru.
- Modbus Slave (RTU/TCP) — nastavení protokolu a parametry proměnných.
- Virtual Variables — vzorky ze zápisů skriptu.
- Přístup k proměnným a Přehled skriptů.
- Modbus RTU master po sériové lince — opačná role na téže lince; Modbus TCP slave na TCP serveru — tentýž slave přes TCP.

