[{"data":1,"prerenderedAt":1300},["ShallowReactive",2],{"docs-nav-docs_en":3,"docs-page-\u002Fen\u002Fexamples\u002Fserial-modbus-slave":367,"docs-surround-\u002Fen\u002Fexamples\u002Fserial-modbus-slave":1297},[4],{"title":5,"path":6,"stem":7,"children":8},"En","\u002Fen","en",[9,13,41,58,76,103,157,171,190,211,238,283,303],{"title":10,"path":6,"stem":11,"navTitle":12},"QInsight Documentation","en\u002Findex","Overview",{"title":14,"navTitle":15,"path":16,"stem":17,"children":18,"page":40},"Getting Started",null,"\u002Fen\u002Fgetting-started","en\u002F01.getting-started",[19,23,27,31,36],{"title":20,"path":21,"stem":22,"navTitle":20},"What is QENEX Suite","\u002Fen\u002Fgetting-started\u002Fwhat-is-qenex-suite","en\u002F01.getting-started\u002F1.what-is-qenex-suite",{"title":24,"path":25,"stem":26,"navTitle":24},"What is QInsight","\u002Fen\u002Fgetting-started\u002Fwhat-is-qinsight","en\u002F01.getting-started\u002F2.what-is-qinsight",{"title":28,"path":29,"stem":30,"navTitle":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F01.getting-started\u002F3.installation",{"title":32,"path":33,"stem":34,"navTitle":35},"The QInsight user interface","\u002Fen\u002Fgetting-started\u002Fthe-qinsight-interface","en\u002F01.getting-started\u002F4.the-qinsight-interface","User interface",{"title":37,"path":38,"stem":39,"navTitle":37},"Licensing","\u002Fen\u002Fgetting-started\u002Flicensing","en\u002F01.getting-started\u002F5.licensing",false,{"title":42,"navTitle":15,"path":43,"stem":44,"children":45,"page":40},"First Project","\u002Fen\u002Ffirst-project","en\u002F02.first-project",[46,50,54],{"title":47,"path":48,"stem":49,"navTitle":47},"Create a project","\u002Fen\u002Ffirst-project\u002Fcreate-a-project","en\u002F02.first-project\u002F1.create-a-project",{"title":51,"path":52,"stem":53,"navTitle":51},"Project structure","\u002Fen\u002Ffirst-project\u002Fproject-structure","en\u002F02.first-project\u002F2.project-structure",{"title":55,"path":56,"stem":57,"navTitle":55},"Project password","\u002Fen\u002Ffirst-project\u002Fproject-password","en\u002F02.first-project\u002F3.project-password",{"title":59,"navTitle":15,"path":60,"stem":61,"children":62,"page":40},"Connecting a Device","\u002Fen\u002Fconnecting-a-device","en\u002F03.connecting-a-device",[63,67,71],{"title":64,"path":65,"stem":66,"navTitle":64},"Add a driver","\u002Fen\u002Fconnecting-a-device\u002Fadd-a-driver","en\u002F03.connecting-a-device\u002F1.add-a-driver",{"title":68,"path":69,"stem":70,"navTitle":68},"Add a protocol","\u002Fen\u002Fconnecting-a-device\u002Fadd-a-protocol","en\u002F03.connecting-a-device\u002F2.add-a-protocol",{"title":72,"path":73,"stem":74,"navTitle":75},"Link a driver and a protocol","\u002Fen\u002Fconnecting-a-device\u002Flink-driver-and-protocol","en\u002F03.connecting-a-device\u002F3.link-driver-and-protocol","Linking",{"title":77,"navTitle":15,"path":78,"stem":79,"children":80,"page":40},"Variables","\u002Fen\u002Fvariables","en\u002F04.variables",[81,85,90,94,99],{"title":82,"path":83,"stem":84,"navTitle":82},"What is a variable","\u002Fen\u002Fvariables\u002Fwhat-is-a-variable","en\u002F04.variables\u002F1.what-is-a-variable",{"title":86,"path":87,"stem":88,"navTitle":89},"Conversion and presentation","\u002Fen\u002Fvariables\u002Fconversion-and-presentation","en\u002F04.variables\u002F2.conversion-and-presentation","Conversion & presentation",{"title":91,"path":92,"stem":93,"navTitle":91},"Add a variable","\u002Fen\u002Fvariables\u002Fadd-a-variable","en\u002F04.variables\u002F3.add-a-variable",{"title":95,"path":96,"stem":97,"navTitle":98},"Matrix variable (array, curve, map)","\u002Fen\u002Fvariables\u002Fmatrix-variable","en\u002F04.variables\u002F4.matrix-variable","Matrix variable",{"title":100,"path":101,"stem":102,"navTitle":100},"Events","\u002Fen\u002Fvariables\u002Fevents","en\u002F04.variables\u002F5.events",{"title":104,"navTitle":15,"path":105,"stem":106,"children":107,"page":40},"Visualization","\u002Fen\u002Fvisualization","en\u002F05.visualization",[108,113,118,122,127,132,137,142,147,152],{"title":109,"path":110,"stem":111,"navTitle":112},"Create a workspace","\u002Fen\u002Fvisualization\u002Fcreate-a-workspace","en\u002F05.visualization\u002F1.create-a-workspace","Workspace",{"title":114,"path":115,"stem":116,"navTitle":117},"Writing values to the device","\u002Fen\u002Fvisualization\u002Fwrite-to-device","en\u002F05.visualization\u002F10.write-to-device","Writing to the device",{"title":119,"path":120,"stem":121,"navTitle":119},"Add a control","\u002Fen\u002Fvisualization\u002Fadd-a-control","en\u002F05.visualization\u002F2.add-a-control",{"title":123,"path":124,"stem":125,"navTitle":126},"Bind a control to a variable","\u002Fen\u002Fvisualization\u002Fbind-a-control","en\u002F05.visualization\u002F3.bind-a-control","Bind a control",{"title":128,"path":129,"stem":130,"navTitle":131},"Graph — signal time course","\u002Fen\u002Fvisualization\u002Fgraph-control","en\u002F05.visualization\u002F4.graph-control","Graph",{"title":133,"path":134,"stem":135,"navTitle":136},"XY Graph — signal versus signal","\u002Fen\u002Fvisualization\u002Fxy-graph-control","en\u002F05.visualization\u002F5.xy-graph-control","XY Graph",{"title":138,"path":139,"stem":140,"navTitle":141},"Gauge — instantaneous value indicator","\u002Fen\u002Fvisualization\u002Fgauge-control","en\u002F05.visualization\u002F6.gauge-control","Gauge",{"title":143,"path":144,"stem":145,"navTitle":146},"Single-Signal — a value with a caption","\u002Fen\u002Fvisualization\u002Fsignal-control","en\u002F05.visualization\u002F7.signal-control","Single-Signal",{"title":148,"path":149,"stem":150,"navTitle":151},"Watch Table — a table of variables","\u002Fen\u002Fvisualization\u002Fwatch-table-control","en\u002F05.visualization\u002F8.watch-table-control","Watch Table",{"title":153,"path":154,"stem":155,"navTitle":156},"Matrix control — maps and calibration","\u002Fen\u002Fvisualization\u002Fmatrix-control","en\u002F05.visualization\u002F9.matrix-control","Matrix control",{"title":158,"navTitle":15,"path":159,"stem":160,"children":161,"page":40},"Running and Monitoring","\u002Fen\u002Frunning","en\u002F06.running",[162,166],{"title":163,"path":164,"stem":165,"navTitle":163},"Start and stop","\u002Fen\u002Frunning\u002Fstart-and-stop","en\u002F06.running\u002F1.start-and-stop",{"title":167,"path":168,"stem":169,"navTitle":170},"Watching live data","\u002Fen\u002Frunning\u002Fwatching-live-data","en\u002F06.running\u002F2.watching-live-data","Live data",{"title":172,"navTitle":15,"path":173,"stem":174,"children":175,"page":40},"Logging and Replay","\u002Fen\u002Flogging-and-replay","en\u002F07.logging-and-replay",[176,180,185],{"title":177,"path":178,"stem":179,"navTitle":177},"Logging data","\u002Fen\u002Flogging-and-replay\u002Flogging-data","en\u002F07.logging-and-replay\u002F1.logging-data",{"title":181,"path":182,"stem":183,"navTitle":184},"Replaying a log","\u002Fen\u002Flogging-and-replay\u002Freplaying-a-log","en\u002F07.logging-and-replay\u002F2.replaying-a-log","Replay",{"title":186,"path":187,"stem":188,"navTitle":189},"Exporting data","\u002Fen\u002Flogging-and-replay\u002Fexporting-data","en\u002F07.logging-and-replay\u002F3.exporting-data","Export",{"title":191,"navTitle":15,"path":192,"stem":193,"children":194,"page":40},"Python Scripts","\u002Fen\u002Fpython-scripts","en\u002F08.python-scripts",[195,199,203,207],{"title":196,"path":197,"stem":198,"navTitle":12},"Scripts overview","\u002Fen\u002Fpython-scripts\u002Fscripts-overview","en\u002F08.python-scripts\u002F1.scripts-overview",{"title":200,"path":201,"stem":202,"navTitle":200},"Accessing variables","\u002Fen\u002Fpython-scripts\u002Faccessing-variables","en\u002F08.python-scripts\u002F2.accessing-variables",{"title":204,"path":205,"stem":206,"navTitle":204},"Example script","\u002Fen\u002Fpython-scripts\u002Fexample-script","en\u002F08.python-scripts\u002F3.example-script",{"title":208,"path":209,"stem":210,"navTitle":208},"CSV post-processing","\u002Fen\u002Fpython-scripts\u002Fcsv-post-processing","en\u002F08.python-scripts\u002F4.csv-post-processing",{"title":212,"navTitle":15,"path":213,"stem":214,"children":215,"page":40},"Custom extensions","\u002Fen\u002Fcustom-extensions","en\u002F09.custom-extensions",[216,220,224,228,233],{"title":217,"path":218,"stem":219,"navTitle":217},"Custom driver","\u002Fen\u002Fcustom-extensions\u002Fcustom-driver","en\u002F09.custom-extensions\u002F1.custom-driver",{"title":221,"path":222,"stem":223,"navTitle":221},"Custom protocol","\u002Fen\u002Fcustom-extensions\u002Fcustom-protocol","en\u002F09.custom-extensions\u002F2.custom-protocol",{"title":225,"path":226,"stem":227,"navTitle":225},"Custom Control","\u002Fen\u002Fcustom-extensions\u002Fcustom-control","en\u002F09.custom-extensions\u002F3.custom-control",{"title":229,"path":230,"stem":231,"navTitle":232},"Complete example — ISS position","\u002Fen\u002Fcustom-extensions\u002Fiss-example","en\u002F09.custom-extensions\u002F4.iss-example","Example ISS",{"title":234,"path":235,"stem":236,"navTitle":237},"Complete example — temperature sensor","\u002Fen\u002Fcustom-extensions\u002Ftemp-sensor-example","en\u002F09.custom-extensions\u002F5.temp-sensor-example","Example temp sensor",{"title":239,"navTitle":15,"path":240,"stem":241,"children":242,"page":40},"QFW SDK","\u002Fen\u002Fdevice-sdk","en\u002F10.device-sdk",[243,248,253,258,263,268,273,278],{"title":244,"path":245,"stem":246,"navTitle":247},"QFW SDK — introduction","\u002Fen\u002Fdevice-sdk\u002Fintroduction","en\u002F10.device-sdk\u002F1.introduction","Introduction",{"title":249,"path":250,"stem":251,"navTitle":252},"XCP in the QFW SDK","\u002Fen\u002Fdevice-sdk\u002Fxcp","en\u002F10.device-sdk\u002F2.xcp","XCP",{"title":254,"path":255,"stem":256,"navTitle":257},"Integration step by step: XCP on TCP with FreeRTOS + lwIP","\u002Fen\u002Fdevice-sdk\u002Fintegration-tcp","en\u002F10.device-sdk\u002F3.integration-tcp","Integration: XCP on TCP",{"title":259,"path":260,"stem":261,"navTitle":262},"XCP on classic CAN — what changes","\u002Fen\u002Fdevice-sdk\u002Fcan","en\u002F10.device-sdk\u002F4.can","XCP on classic CAN",{"title":264,"path":265,"stem":266,"navTitle":267},"Integration without an RTOS: XCP on TCP from the main loop","\u002Fen\u002Fdevice-sdk\u002Fbaremetal","en\u002F10.device-sdk\u002F5.baremetal","Integration without an RTOS",{"title":269,"path":270,"stem":271,"navTitle":272},"The engine contract","\u002Fen\u002Fdevice-sdk\u002Fengine-contract","en\u002F10.device-sdk\u002F6.engine-contract","Engine contract",{"title":274,"path":275,"stem":276,"navTitle":277},"Variable addresses for QInsight","\u002Fen\u002Fdevice-sdk\u002Fvariable-addresses","en\u002F10.device-sdk\u002F7.variable-addresses","Variable addresses",{"title":279,"path":280,"stem":281,"navTitle":282},"Troubleshooting the SDK integration","\u002Fen\u002Fdevice-sdk\u002Ftroubleshooting","en\u002F10.device-sdk\u002F8.troubleshooting","Troubleshooting",{"title":284,"navTitle":15,"path":285,"stem":286,"children":287,"page":40},"Reference","\u002Fen\u002Freference","en\u002F11.reference",[288,292,296,300],{"title":289,"path":290,"stem":291,"navTitle":289},"Drivers","\u002Fen\u002Freference\u002Fdrivers","en\u002F11.reference\u002F1.drivers",{"title":293,"path":294,"stem":295,"navTitle":293},"Protocols","\u002Fen\u002Freference\u002Fprotocols","en\u002F11.reference\u002F2.protocols",{"title":297,"path":298,"stem":299,"navTitle":297},"Controls","\u002Fen\u002Freference\u002Fcontrols","en\u002F11.reference\u002F3.controls",{"title":282,"path":301,"stem":302,"navTitle":282},"\u002Fen\u002Freference\u002Ftroubleshooting","en\u002F11.reference\u002F4.troubleshooting",{"title":304,"navTitle":15,"path":305,"stem":306,"children":307,"page":40},"Examples","\u002Fen\u002Fexamples","en\u002F12.examples",[308,312,317,322,327,331,335,339,343,347,352,357,362],{"title":309,"path":310,"stem":311,"navTitle":309},"Simulation: all signals","\u002Fen\u002Fexamples\u002Fsimulation-all-signals","en\u002F12.examples\u002F01.simulation-all-signals",{"title":313,"path":314,"stem":315,"navTitle":316},"Modbus RTU master over a serial line","\u002Fen\u002Fexamples\u002Fserial-modbus-master","en\u002F12.examples\u002F02.serial-modbus-master","Modbus RTU master",{"title":318,"path":319,"stem":320,"navTitle":321},"Modbus RTU slave with simulated sensors","\u002Fen\u002Fexamples\u002Fserial-modbus-slave","en\u002F12.examples\u002F03.serial-modbus-slave","Modbus RTU slave",{"title":323,"path":324,"stem":325,"navTitle":326},"Modbus TCP master over a TCP client","\u002Fen\u002Fexamples\u002Ftcp-client-modbus-master","en\u002F12.examples\u002F04.tcp-client-modbus-master","Modbus TCP master",{"title":328,"path":329,"stem":330,"navTitle":328},"Modbus TCP slave on the TCP Server","\u002Fen\u002Fexamples\u002Ftcp-server-modbus-slave","en\u002F12.examples\u002F05.tcp-server-modbus-slave",{"title":332,"path":333,"stem":334,"navTitle":332},"Bit field and a script","\u002Fen\u002Fexamples\u002Fbit-field-script","en\u002F12.examples\u002F08.bit-field-script",{"title":336,"path":337,"stem":338,"navTitle":336},"Two ECUs at once","\u002Fen\u002Fexamples\u002Ftwo-ecus","en\u002F12.examples\u002F09.two-ecus",{"title":340,"path":341,"stem":342,"navTitle":340},"ISS position live","\u002Fen\u002Fexamples\u002Fiss-live-tracking","en\u002F12.examples\u002F10.iss-live-tracking",{"title":344,"path":345,"stem":346,"navTitle":344},"Simulated thermometer","\u002Fen\u002Fexamples\u002Fsimul-temp-measure","en\u002F12.examples\u002F11.simul-temp-measure",{"title":348,"path":349,"stem":350,"navTitle":351},"JSON signals from a Python generator","\u002Fen\u002Fexamples\u002Fjson-signal-python","en\u002F12.examples\u002F12.json-signal-python","JSON signals from Python",{"title":353,"path":354,"stem":355,"navTitle":356},"Raw CAN frames from a Raspberry Pi","\u002Fen\u002Fexamples\u002Fraw-can-python","en\u002F12.examples\u002F13.raw-can-python","Raw CAN from a Raspberry Pi",{"title":358,"path":359,"stem":360,"navTitle":361},"XCP on TCP on a NUCLEO-H723ZG: measurement, stimulation and calibration maps","\u002Fen\u002Fexamples\u002Ftcp-client-xcp-nucleo-maps","en\u002F12.examples\u002F14.tcp-client-xcp-nucleo-maps","XCP on TCP on NUCLEO-H723ZG",{"title":363,"path":364,"stem":365,"navTitle":366},"XCP on CAN on a NUCLEO-H723ZG: measurement, stimulation and calibration maps","\u002Fen\u002Fexamples\u002Fcan-xcp-nucleo-maps","en\u002F12.examples\u002F15.can-xcp-nucleo-maps","XCP on CAN on NUCLEO-H723ZG",{"id":368,"title":318,"body":369,"description":1292,"extension":1293,"meta":1294,"navTitle":321,"navigation":962,"path":319,"seo":1295,"stem":320,"__hash__":1296},"docs_en\u002Fen\u002F12.examples\u002F03.serial-modbus-slave.md",{"type":370,"value":371,"toc":1280},"minimark",[372,376,388,393,433,437,484,488,493,504,649,659,717,739,742,867,896,900,910,994,1006,1125,1136,1169,1172,1192,1196,1236,1240,1276],[373,374,318],"h1",{"id":375},"modbus-rtu-slave-with-simulated-sensors",[377,378,379,380,384,385,387],"p",{},"You will find the project ",[381,382,383],"code",{},"Qenex_Serial_ModbusSlave_SimulatedSensors.qproj","\nin the ",[381,386,304],{}," folder next to QInsight.exe.",[389,390,392],"h2",{"id":391},"what-the-example-shows","What the example shows",[394,395,396,415,421,427],"ul",{},[397,398,399,403,404,409,410,414],"li",{},[400,401,402],"strong",{},"QInsight as a Modbus RTU slave"," (unit 2) on a serial port — the\n",[405,406,408],"a",{"href":407},"\u002Freference\u002Fdrivers#serial-port-com","Serial Port (COM)"," driver + the\n",[405,411,413],{"href":412},"\u002Freference\u002Fprotocols#modbus-slave-rtutcp","Modbus Slave"," protocol. A master\nreads the live values of two variables from holding registers 0 and 1.",[397,416,417,420],{},[400,418,419],{},"Simulated sensors from a script",": a periodic Python script (2 s) ramps an\noil temperature 0–150 °C and an oil pressure 1000–2500 kPa along a saw-tooth.",[397,422,423,426],{},[400,424,425],{},"A double write"," of every value: into the slave variable (for the master)\nand into its virtual copy (for the controls), because a script write never\nraises a UI event on a device protocol.",[397,428,429,432],{},[400,430,431],{},"Reconnection"," of the Serial Port driver after the converter is unplugged.",[389,434,436],{"id":435},"what-you-need","What you need",[394,438,439,460,466],{},[397,440,441,444,445,448,449,452,453,455,456,459],{},[400,442,443],{},"A Modbus RTU master"," — e.g. qModMaster: unit ",[400,446,447],{},"2",", holding registers\nfrom address ",[400,450,451],{},"0",", count ",[400,454,447],{}," (FC03), RTU, ",[400,457,458],{},"9600 Bd, 8 bits, no parity,\n1 stop bit",".",[397,461,462,465],{},[400,463,464],{},"A serial path to the master",": a pair of linked COM ports on one PC\n(a virtual null-modem pair), or two USB\u002FRS-485 converters — one for\nQInsight, one for the master.",[397,467,468,471,472,475,476,479,480,459],{},[400,469,470],{},"What to adapt",": in the Serial Port driver replace ",[381,473,474],{},"port=COM6"," with your\nport. Keep the framing and ",[381,477,478],{},"unitId=2",", or change them identically on both\nsides. The scripts need a ",[405,481,483],{"href":482},"\u002Fpython-scripts\u002Fscripts-overview","configured Python",[389,485,487],{"id":486},"the-project","The project",[489,490,492],"h3",{"id":491},"drivers-and-protocols","Drivers and protocols",[377,494,495,496,499,500,503],{},"The ",[400,497,498],{},"Serial Port Driver"," (",[381,501,502],{},"SerialPortDriver","):",[505,506,507,523],"table",{},[508,509,510],"thead",{},[511,512,513,517,520],"tr",{},[514,515,516],"th",{},"Parameter",[514,518,519],{},"Value",[514,521,522],{},"Meaning",[524,525,526,542,557,572,587,602,616,631],"tbody",{},[511,527,528,534,539],{},[529,530,531],"td",{},[381,532,533],{},"port",[529,535,536],{},[381,537,538],{},"COM6",[529,540,541],{},"COM port name — replace with the one on your PC",[511,543,544,549,554],{},[529,545,546],{},[381,547,548],{},"baudRate",[529,550,551],{},[381,552,553],{},"9600",[529,555,556],{},"communication speed",[511,558,559,564,569],{},[529,560,561],{},[381,562,563],{},"dataBits",[529,565,566],{},[381,567,568],{},"8",[529,570,571],{},"number of data bits",[511,573,574,579,584],{},[529,575,576],{},[381,577,578],{},"parity",[529,580,581],{},[381,582,583],{},"none",[529,585,586],{},"no parity",[511,588,589,594,599],{},[529,590,591],{},[381,592,593],{},"stopBits",[529,595,596],{},[381,597,598],{},"1",[529,600,601],{},"one stop bit",[511,603,604,609,613],{},[529,605,606],{},[381,607,608],{},"handshake",[529,610,611],{},[381,612,583],{},[529,614,615],{},"no flow control",[511,617,618,623,628],{},[529,619,620],{},[381,621,622],{},"reconnectDelayMs",[529,624,625],{},[381,626,627],{},"2000",[529,629,630],{},"pause before the next attempt to open the port after a failure",[511,632,633,638,643],{},[529,634,635],{},[381,636,637],{},"reconnectAttempts",[529,639,640],{},[381,641,642],{},"-1",[529,644,645,646],{},"attempts without limit, see ",[405,647,431],{"href":648},"\u002Freference\u002Fdrivers#reconnection",[377,650,651,652,655,656,503],{},"Under it the ",[400,653,654],{},"Modbus Slave (RTU\u002FTCP)"," protocol (",[381,657,658],{},"ModbusSlaveProtocol",[505,660,661,671],{},[508,662,663],{},[511,664,665,667,669],{},[514,666,516],{},[514,668,519],{},[514,670,522],{},[524,672,673,688,702],{},[511,674,675,680,685],{},[529,676,677],{},[381,678,679],{},"mode",[529,681,682],{},[381,683,684],{},"rtu",[529,686,687],{},"RTU framing (CRC16, serial line)",[511,689,690,695,699],{},[529,691,692],{},[381,693,694],{},"unitId",[529,696,697],{},[381,698,447],{},[529,700,701],{},"the slave's own address — the master must use it in its requests",[511,703,704,709,714],{},[529,705,706],{},[381,707,708],{},"respondToAnyUnit",[529,710,711],{},[381,712,713],{},"false",[529,715,716],{},"requests for any other unit address are ignored",[377,718,719,720,499,723,726,727,730,731,734,735,738],{},"The second pair, ",[400,721,722],{},"Virtual Data Driver",[381,724,725],{},"VirtualDataDriver",", shown as\nVirtual Variables Host in the UI) + ",[400,728,729],{},"Virtual Variables","\n(",[381,732,733],{},"VirtualDataProtocol","), has no settings and carries the two display copies.\nThe project has no events: the slave needs no ",[381,736,737],{},"eventRef"," and the virtual\nvariables get their samples from script writes.",[489,740,77],{"id":741},"variables",[505,743,744,766],{},[508,745,746],{},[511,747,748,751,754,757,760,763],{},[514,749,750],{},"Variable",[514,752,753],{},"Namespace",[514,755,756],{},"Type",[514,758,759],{},"Protocol",[514,761,762],{},"Register \u002F Comm params",[514,764,765],{},"Presentation",[524,767,768,800,826,848],{},[511,769,770,775,780,783,785,797],{},[529,771,772],{},[381,773,774],{},"OilTemp",[529,776,777],{},[381,778,779],{},"\u002FModbus",[529,781,782],{},"ushort",[529,784,413],{},[529,786,787,788,790,791,790,794],{},"holding register ",[381,789,451],{},", ",[381,792,793],{},"wordOrder=\"big\"",[381,795,796],{},"direction=\"read\"",[529,798,799],{},"Temperature",[511,801,802,807,811,813,815,823],{},[529,803,804],{},[381,805,806],{},"OilPressure",[529,808,809],{},[381,810,779],{},[529,812,782],{},[529,814,413],{},[529,816,787,817,790,819,790,821],{},[381,818,598],{},[381,820,793],{},[381,822,796],{},[529,824,825],{},"Pressure",[511,827,828,833,838,841,843,846],{},[529,829,830],{},[381,831,832],{},"OilTempView",[529,834,835],{},[381,836,837],{},"\u002FVirtual",[529,839,840],{},"double",[529,842,729],{},[529,844,845],{},"— (virtual, no parameters)",[529,847,799],{},[511,849,850,855,859,861,863,865],{},[529,851,852],{},[381,853,854],{},"OilPressureView",[529,856,857],{},[381,858,837],{},[529,860,840],{},[529,862,729],{},[529,864,845],{},[529,866,825],{},[377,868,869,870,872,873,875,876,878,879,881,882,885,886,499,889,790,892,895],{},"The slave variables are ",[381,871,782],{},", so each occupies one register, and the\nmaster reads them (",[381,874,796],{},"). The presentations ",[381,877,799],{},"\n(0–150 °C) and ",[381,880,825],{}," (1000–2500 kPa), both with the format ",[381,883,884],{},"{0:F0}",", use\nthe single linear conversion ",[381,887,888],{},"Raw",[381,890,891],{},"multiplier=1",[381,893,894],{},"offset=0",") — the\nengineering value equals the raw one.",[489,897,899],{"id":898},"scripts","Scripts",[377,901,902,903,730,906,909],{},"Both scripts are blocking, without a timeout and for runtime only. ",[381,904,905],{},"init.py",[400,907,908],{},"Startup",") sets the initial state of the simulation and publishes it right\naway, into the slave registers and into the display copies:",[911,912,917],"pre",{"className":913,"code":914,"language":915,"meta":916,"style":916},"language-python shiki shiki-themes github-light github-dark-default","# Startup script: initial state of the simulated sensors.\n# The periodic script (simulate.py) ramps the values from here; the globals persist\n# between script runs inside one runtime session.\noil_temp = 0.0          # degC, ramps 0 .. 150\noil_pressure = 1000.0   # kPa, ramps 1000 .. 2500\ndirection = 1           # +1 ramping up, -1 ramping down\n\n# Publish the initial values right away, both to the slave registers and to the display copies.\nOilTemp.EngValue = oil_temp\nOilPressure.EngValue = oil_pressure\nOilTempView.EngValue = oil_temp\nOilPressureView.EngValue = oil_pressure\n","python","",[381,918,919,927,933,939,945,951,957,964,970,976,982,988],{"__ignoreMap":916},[920,921,924],"span",{"class":922,"line":923},"line",1,[920,925,926],{},"# Startup script: initial state of the simulated sensors.\n",[920,928,930],{"class":922,"line":929},2,[920,931,932],{},"# The periodic script (simulate.py) ramps the values from here; the globals persist\n",[920,934,936],{"class":922,"line":935},3,[920,937,938],{},"# between script runs inside one runtime session.\n",[920,940,942],{"class":922,"line":941},4,[920,943,944],{},"oil_temp = 0.0          # degC, ramps 0 .. 150\n",[920,946,948],{"class":922,"line":947},5,[920,949,950],{},"oil_pressure = 1000.0   # kPa, ramps 1000 .. 2500\n",[920,952,954],{"class":922,"line":953},6,[920,955,956],{},"direction = 1           # +1 ramping up, -1 ramping down\n",[920,958,960],{"class":922,"line":959},7,[920,961,963],{"emptyLinePlaceholder":962},true,"\n",[920,965,967],{"class":922,"line":966},8,[920,968,969],{},"# Publish the initial values right away, both to the slave registers and to the display copies.\n",[920,971,973],{"class":922,"line":972},9,[920,974,975],{},"OilTemp.EngValue = oil_temp\n",[920,977,979],{"class":922,"line":978},10,[920,980,981],{},"OilPressure.EngValue = oil_pressure\n",[920,983,985],{"class":922,"line":984},11,[920,986,987],{},"OilTempView.EngValue = oil_temp\n",[920,989,991],{"class":922,"line":990},12,[920,992,993],{},"OilPressureView.EngValue = oil_pressure\n",[377,995,996,499,999,790,1002,1005],{},[381,997,998],{},"simulate.py",[400,1000,1001],{},"Periodic",[381,1003,1004],{},"period=2;unit=s",") moves both quantities one\nstep every 2 s and flips the direction at the ends of the range:",[911,1007,1009],{"className":913,"code":1008,"language":915,"meta":916,"style":916},"# Periodic script (period=2;unit=s): saw-tooth ramp of the simulated sensors.\n# Temperature moves 1 degC per step between 0 and 150, pressure 10 kPa per step between\n# 1000 and 2500, so one sweep up takes 5 minutes; at either end the direction flips.\n#\n# Every value is written twice on purpose:\n#  - OilTemp \u002F OilPressure are the Modbus slave variables. The slave serves their current\n#    value to the master (holding registers 0 and 1). A script write never raises a UI event\n#    on a device protocol, so these two are not shown in any control.\n#  - OilTempView \u002F OilPressureView are virtual variables. The Virtual Data protocol publishes\n#    every script write to the UI, so the graph and signal controls follow them.\noil_temp += direction * 1.0\noil_pressure += direction * 10.0\n\nif oil_temp >= 150.0 or oil_pressure >= 2500.0:\n    oil_temp, oil_pressure, direction = 150.0, 2500.0, -1\nelif oil_temp \u003C= 0.0 or oil_pressure \u003C= 1000.0:\n    oil_temp, oil_pressure, direction = 0.0, 1000.0, 1\n\nOilTemp.EngValue = oil_temp\nOilPressure.EngValue = oil_pressure\nOilTempView.EngValue = oil_temp\nOilPressureView.EngValue = oil_pressure\n",[381,1010,1011,1016,1021,1026,1031,1036,1041,1046,1051,1056,1061,1066,1071,1076,1082,1088,1094,1100,1105,1110,1115,1120],{"__ignoreMap":916},[920,1012,1013],{"class":922,"line":923},[920,1014,1015],{},"# Periodic script (period=2;unit=s): saw-tooth ramp of the simulated sensors.\n",[920,1017,1018],{"class":922,"line":929},[920,1019,1020],{},"# Temperature moves 1 degC per step between 0 and 150, pressure 10 kPa per step between\n",[920,1022,1023],{"class":922,"line":935},[920,1024,1025],{},"# 1000 and 2500, so one sweep up takes 5 minutes; at either end the direction flips.\n",[920,1027,1028],{"class":922,"line":941},[920,1029,1030],{},"#\n",[920,1032,1033],{"class":922,"line":947},[920,1034,1035],{},"# Every value is written twice on purpose:\n",[920,1037,1038],{"class":922,"line":953},[920,1039,1040],{},"#  - OilTemp \u002F OilPressure are the Modbus slave variables. The slave serves their current\n",[920,1042,1043],{"class":922,"line":959},[920,1044,1045],{},"#    value to the master (holding registers 0 and 1). A script write never raises a UI event\n",[920,1047,1048],{"class":922,"line":966},[920,1049,1050],{},"#    on a device protocol, so these two are not shown in any control.\n",[920,1052,1053],{"class":922,"line":972},[920,1054,1055],{},"#  - OilTempView \u002F OilPressureView are virtual variables. The Virtual Data protocol publishes\n",[920,1057,1058],{"class":922,"line":978},[920,1059,1060],{},"#    every script write to the UI, so the graph and signal controls follow them.\n",[920,1062,1063],{"class":922,"line":984},[920,1064,1065],{},"oil_temp += direction * 1.0\n",[920,1067,1068],{"class":922,"line":990},[920,1069,1070],{},"oil_pressure += direction * 10.0\n",[920,1072,1074],{"class":922,"line":1073},13,[920,1075,963],{"emptyLinePlaceholder":962},[920,1077,1079],{"class":922,"line":1078},14,[920,1080,1081],{},"if oil_temp >= 150.0 or oil_pressure >= 2500.0:\n",[920,1083,1085],{"class":922,"line":1084},15,[920,1086,1087],{},"    oil_temp, oil_pressure, direction = 150.0, 2500.0, -1\n",[920,1089,1091],{"class":922,"line":1090},16,[920,1092,1093],{},"elif oil_temp \u003C= 0.0 or oil_pressure \u003C= 1000.0:\n",[920,1095,1097],{"class":922,"line":1096},17,[920,1098,1099],{},"    oil_temp, oil_pressure, direction = 0.0, 1000.0, 1\n",[920,1101,1103],{"class":922,"line":1102},18,[920,1104,963],{"emptyLinePlaceholder":962},[920,1106,1108],{"class":922,"line":1107},19,[920,1109,975],{},[920,1111,1113],{"class":922,"line":1112},20,[920,1114,981],{},[920,1116,1118],{"class":922,"line":1117},21,[920,1119,987],{},[920,1121,1123],{"class":922,"line":1122},22,[920,1124,993],{},[377,1126,1127,1128,1132,1133,1135],{},"The simulation state lives in plain Python variables — the scripts of a\nproject ",[405,1129,1131],{"href":1130},"\u002Fpython-scripts\u002Faccessing-variables","share one scope",", so the values\nsurvive between runs and ",[381,1134,905],{}," resets them on runtime start. A step of\n1 °C and 10 kPa every 2 s gives 150 steps per sweep, i.e. 5 minutes up and\n5 down.",[377,1137,1138,1141,1142,1144,1145,1147,1148,1152,1153,1144,1155,1157,1158,1161,1162,1165,1166,1168],{},[400,1139,1140],{},"Why the double write."," ",[381,1143,774],{}," and ",[381,1146,806],{}," belong to the Modbus\nSlave protocol: a script write stores their value and the slave serves it to\nthe master, but on a device protocol a script write\n",[405,1149,1151],{"href":1150},"\u002Fpython-scripts\u002Faccessing-variables#writing-vs-displaying-virtual-variables","never raises a UI event","\n— in the controls these variables would not move. That is why the script\nwrites the same value into ",[381,1154,832],{},[381,1156,854],{}," on the\n",[405,1159,729],{"href":1160},"\u002Freference\u002Fprotocols#virtual-variables"," protocol, which\npublishes every write as a timestamped sample. Writing through ",[381,1163,1164],{},"EngValue","\nequals raw with the 1:1 conversion; for ",[381,1167,782],{}," the value is converted to an\ninteger, which the steps of 1.0 and 10.0 satisfy.",[489,1170,112],{"id":1171},"workspace",[377,1173,495,1174,1177,1178,1181,1182,1184,1185,1187,1188,1191],{},[400,1175,1176],{},"Simulated sensors"," workspace has three controls, all bound to the\nvirtual copies, not to the slave variables: a\n",[405,1179,131],{"href":1180},"\u002Fvisualization\u002Fgraph-control"," \"Simulated sensors (virtual copies of\nthe slave registers)\" with a 300 s window (",[381,1183,832],{}," in red on the left\naxis 0–150, ",[381,1186,854],{}," in blue on the right axis 1000–2500) and two\n",[405,1189,146],{"href":1190},"\u002Fvisualization\u002Fsignal-control"," controls (250 ms refresh) with\nthe current temperature and pressure.",[389,1193,1195],{"id":1194},"what-you-will-see-and-what-to-try","What you will see and what to try",[394,1197,1198,1205,1212,1226],{},[397,1199,1200,1201,1204],{},"After ",[400,1202,1203],{},"Start"," of the runtime the graph draws the saw-tooth (the 300 s\nwindow = one sweep up) and the Single-Signal controls show the current\nvalues. The master reads the temperature from register 0 and the pressure\nfrom register 1 — the same values, changing by 1 °C and 10 kPa every 2 s.",[397,1206,1207,1208,1211],{},"A request for any unit address other than 2 gets no reply\n(",[381,1209,1210],{},"respondToAnyUnit=false","); a read touching register 2 and above is\nrejected by the slave as a whole.",[397,1213,1214,1217,1218,1221,1222,1225],{},[400,1215,1216],{},"Unplug and replug the converter."," The Serial Port driver goes Faulted,\nwarnings with the attempt number appear in the log and the port is retried\nevery 2 s (",[381,1219,1220],{},"reconnectDelayMs=2000",") without limit\n(",[381,1223,1224],{},"reconnectAttempts=-1","); the script and the graph keep running. Once\nreplugged, the driver reopens the port by itself and the master reads the\nlive values again without any operator action.",[397,1227,1228,1229,1232,1233,1235],{},"Shorten the script period (",[381,1230,1231],{},"period=500;unit=ms",") or change the step in\n",[381,1234,998],{}," — neither the master nor the workspace needs any change.",[389,1237,1239],{"id":1238},"related-chapters","Related chapters",[394,1241,1242,1250,1255,1260,1266],{},[397,1243,1244,1246,1247,1249],{},[405,1245,408],{"href":407}," and\n",[405,1248,431],{"href":648}," — driver parameters.",[397,1251,1252,1254],{},[405,1253,654],{"href":412}," —\nprotocol settings and per-variable parameters.",[397,1256,1257,1259],{},[405,1258,729],{"href":1160}," — samples born\nfrom script writes.",[397,1261,1262,1246,1264,459],{},[405,1263,200],{"href":1130},[405,1265,196],{"href":482},[397,1267,1268,1271,1272,1275],{},[405,1269,313],{"href":1270},"\u002Fexamples\u002Fserial-modbus-master"," —\nthe opposite role on the same line; ",[405,1273,328],{"href":1274},"\u002Fexamples\u002Ftcp-server-modbus-slave","\n— the same slave over TCP.",[1277,1278,1279],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":916,"searchDepth":935,"depth":935,"links":1281},[1282,1283,1284,1290,1291],{"id":391,"depth":929,"text":392},{"id":435,"depth":929,"text":436},{"id":486,"depth":929,"text":487,"children":1285},[1286,1287,1288,1289],{"id":491,"depth":935,"text":492},{"id":741,"depth":935,"text":77},{"id":898,"depth":935,"text":899},{"id":1171,"depth":935,"text":112},{"id":1194,"depth":929,"text":1195},{"id":1238,"depth":929,"text":1239},"A complete project in which QInsight acts as a Modbus RTU slave on a serial port — a periodic script simulates oil temperature and pressure, a master reads them from holding registers and a graph shows their virtual copies.","md",{},{"title":318,"description":1292},"8zQeQitvspagmEFa9DzBdbO7J_ymJvE_RecSw4mwNXU",[1298,1299],{"title":313,"path":314,"stem":315,"navTitle":316,"children":-1},{"title":323,"path":324,"stem":325,"navTitle":326,"children":-1},1791554568268]