Modbus TCP slave na TCP serveru
Projekt Examples\Qenex_TcpServer_ModbusSlave_HoldingRegisters.qproj najdete
ve složce Examples vedle QInsight.exe.
Co ukázka předvádí
QInsight tu není master, ale slave: driver TCP Server naslouchá na
portu 502 a protokol Modbus Slave (RTU/TCP) v režimu tcp vystavuje dvě
proměnné jako holding registry 0 a 1 pod unit adresou 2. Skutečné zařízení
žádné není — hodnoty registrů generuje periodický Python skript, který
každé 2 s posune simulovanou teplotu oleje (0–150 °C) a tlak oleje
(1000–2500 kPa) o krok nahoru nebo dolů. Externí Modbus TCP master, který
se k QInsight připojí, čte pilovitě rostoucí a klesající hodnoty.
Druhá polovina ukázky je zobrazení: zápis skriptu do proměnné protokolu zařízení se v controlech neprojeví (nevzniká vzorek signálu). Skript proto každou hodnotu zapisuje dvakrát — do slave proměnné pro mastera a do virtuální proměnné, kterou kreslí graf a signal controly. Na projektu je tak vidět i to, jak se TCP Server chová při výpadku klienta: odpojený kabel zjistí keepalive, server se vrátí k naslouchání a master se po obnovení znovu připojí.
Co potřebujete
- QInsight s nastaveným Pythonem — skripty jsou jádrem ukázky, viz Nastavení Pythonu.
- Modbus TCP master jako protějšek, například qModMaster. Připojte
ho na IP adresu počítače s QInsight, port 502, unit 2, a nechte
ho číst holding registry od adresy 0, počet 2. Díky
respondToAnyUnit=trueslave odpoví i na jinou unit adresu. - Master může běžet na stejném PC — pak se připojuje na
127.0.0.1. - Při masteru na jiném počítači musí firewall na PC s QInsight povolit příchozí spojení na port 502 (lokální strana QInsight, vzdálená master). Obnovu spojení po výpadku vždy iniciuje master (klient), server jen naslouchá.
- Port 502 nesmí obsazovat jiný program; jinak se driver opakovaně pokouší port otevřít (viz Obnova spojení) a spustí se, jakmile se port uvolní.
Projekt
Drivery a protokoly
Projekt má dvě dvojice driver + protokol.
TCP Server (TcpServerDriver) s nastavením
bindAddress=0.0.0.0;port=502;reconnectDelayMs=1000;reconnectAttempts=-1;keepAliveMs=5000:
| Parametr | Hodnota | Význam v ukázce |
|---|---|---|
bindAddress | 0.0.0.0 | naslouchá na všech rozhraních — master se připojí přes libovolnou IP adresu PC i přes 127.0.0.1 |
port | 502 | standardní port Modbus TCP |
reconnectDelayMs | 1000 | prodleva mezi pokusy o otevření naslouchacího portu |
reconnectAttempts | -1 | pokouší se port otevřít bez omezení počtu pokusů (obsazený port, chybějící adresa) |
keepAliveMs | 5000 | keepalive na přijatém spojení: po 5 s bez provozu spojení ověřuje, odpojený klient se zjistí během několika sekund |
Pod ním Modbus Slave (RTU/TCP) (ModbusSlaveProtocol) s nastavením
mode=tcp;unitId=2;respondToAnyUnit=true:
| Parametr | Hodnota | Význam v ukázce |
|---|---|---|
mode | tcp | rámování Modbus TCP (MBAP), odpovídá driveru TCP Server |
unitId | 2 | vlastní adresa slave |
respondToAnyUnit | true | slave odpoví bez ohledu na unit adresu v dotazu — nastaveno výslovně, protože předvyplněná šablona obsahuje false |
Druhá dvojice Virtual Variables Host (VirtualDataDriver) +
Virtual Variables (VirtualDataProtocol) nemá žádná nastavení; nese
zobrazovací kopie obou registrů.
Proměnné
| Proměnná | Namespace | Typ | Protokol | Comm params | Role |
|---|---|---|---|---|---|
OilTemp | /Modbus | ushort | Modbus Slave | registerType="holdingRegister";address="0";wordOrder="big";direction="read" | holding registr 0 čtený masterem |
OilPressure | /Modbus | ushort | Modbus Slave | registerType="holdingRegister";address="1";wordOrder="big";direction="read" | holding registr 1 čtený masterem |
OilTempView | /Virtual | double | Virtual Variables | — | zobrazovací kopie OilTemp pro graf a signal control |
OilPressureView | /Virtual | double | Virtual Variables | — | zobrazovací kopie OilPressure pro graf a signal control |
Slave proměnné jsou ushort — jeden 16bitový registr, do kterého se
rozsahy 0–150 i 1000–2500 vejdou bez přepočtu. Prezentace Temperature
(0–150, °C) a Pressure (1000–2500, kPa) používají obě lineární
konverzi Raw s multiplier=1, offset=0 a formát {0:F0}; inženýrská
hodnota se rovná surové (raw) hodnotě, master tedy čte přímo stupně a kilopascaly.
Stejné prezentace mají i virtuální kopie, takže graf a signal controly
ukazují tytéž jednotky a rozsahy.
Žádná ze slave proměnných není navázaná na control — vzhledem k tomu, že zápis skriptu na protokolu zařízení nevyvolá událost pro UI, by v něm nic neukazovala.
Skripty
Projekt má dva skripty, oba jen pro runtime (ne pro replay), blokující, bez timeoutu.
init.py v režimu Startup nastaví výchozí stav simulace a hned zapíše
počáteční hodnoty. Pythonovské globální proměnné oil_temp, oil_pressure
a direction jsou uloženy ve sdíleném prostoru skriptů,
takže jsou periodickému skriptu dostupné:
# 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 v režimu Periodic s parametry period=2;unit=s posune
každé 2 s teplotu o 1 °C a tlak o 10 kPa; na horní nebo dolní mezi obě
veličiny nastaví na krajní hodnotu a otočí směr. Oba rozsahy mají 150
kroků, jeden průběh nahoru trvá 5 minut:
# 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
Dvojí zápis je záměrný a představuje podstatu celé ukázky. Zápis do OilTemp
a OilPressure pouze uloží hodnotu, kterou Modbus Slave při dalším dotazu
předá masterovi — protokol zařízení z tohoto zápisu žádný vzorek pro UI
nevytvoří. Zápis do OilTempView a OilPressureView naopak protokol
Virtual Variables publikuje jako vzorek s časovou značkou zápisu, a právě
ten vidí graf a signal controly. Kdyby skript zapisoval jen do slave
proměnných, master by data četl správně, ale workspace by zůstal prázdný;
kdyby zapisoval jen do virtuálních, ukazovalo by se všechno, ale master by
četl nuly.
Workspace
Workspace Simulated sensors obsahuje tři controly, všechny navázané na virtuální kopie:
- Graph „Simulated sensors (virtual copies of the slave registers)“
s časovým oknem 300 s (přesně jeden průběh rampy) a dvěma svislými osami
s pevným rozsahem: vlevo 0–150 pro
OilTempView(červená), vpravo 1000–2500 proOilPressureView(modrá). - Dva Signal controly (obnova 250 ms) pro
OilTempViewaOilPressureView, jen pro čtení.
Co uvidíte a co vyzkoušet
- Spusťte runtime. Graf začne kreslit dvě pily: teplota od 0 °C nahoru, tlak od 1000 kPa nahoru; po 5 minutách se obě otočí.
- Připojte master na port 502, unit 2, a čtěte holding registry 0 a 1. Master ukazuje tytéž hodnoty jako signal controly a každé 2 s se posune o 1 a o 10. Slave hodnoty pouze poskytuje; mezi dotazy master nic neposílá a driver nečinnost na spojení za chybu nepovažuje.
- Odpojte síťový kabel na straně masteru (nebo masteru odpojte síť). Po 5 s
bez provozu začne keepalive spojení ověřovat a za několik dalších sekund se v okně Logs
objeví varování
client … lost. Server se vrátí k naslouchání, driver zůstává spuštěný; korektní odpojení masteru by se zapsalo jakoclient … disconnected. Rampa běží dál — skript ani virtuální proměnné na klientovi nezávisí. - Kabel znovu připojte. Master se automaticky znovu připojí a čte hodnoty, které mezitím dále rostly; na straně QInsight není třeba nic dělat.
- Připojte druhý master, zatímco první ještě drží spojení: nové příchozí spojení nahradí to stávající — TCP Server obsluhuje jednoho klienta. Odpojeného mastera tak nahradí nový bez čekání na keepalive.
Související kapitoly
- TCP Server a
Obnova spojení — parametry
driveru, keepalive, hlášení
client … lostaclient … disconnected. - Modbus Slave (RTU/TCP) — nastavení slave, parametry registrů a chování při zápisu od mastera.
- Virtual Variables — proč se zobrazení realizuje přes virtuální kopie.
- Přístup k proměnným — zápis
přes
EngValuea sdílený prostor skriptů. - Přehled skriptů — režimy Startup
a Periodic, parametr
period. - Sledování živých dat — okna Logs a Script-Logs.
- Grafy a Signal control.

