[{"data":1,"prerenderedAt":1691},["ShallowReactive",2],{"docs-nav-docs_en":3,"docs-page-\u002Fen\u002Fexamples\u002Fraw-can-python":367,"docs-surround-\u002Fen\u002Fexamples\u002Fraw-can-python":1688},[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":353,"body":369,"description":1683,"extension":1684,"meta":1685,"navTitle":356,"navigation":918,"path":354,"seo":1686,"stem":355,"__hash__":1687},"docs_en\u002Fen\u002F12.examples\u002F13.raw-can-python.md",{"type":370,"value":371,"toc":1670},"minimark",[372,376,381,391,411,460,467,477,487,501,505,569,573,584,590,601,607,621,655,659,664,720,723,726,833,836,839,843,878,882,892,1643,1647,1666],[373,374,353],"h1",{"id":375},"raw-can-frames-from-a-raspberry-pi",[377,378,380],"h2",{"id":379},"what-this-is-about","What this is about",[382,383,384,385,390],"p",{},"The example shows the ",[386,387,389],"a",{"href":388},"\u002Freference\u002Fprotocols#raw-can-frames","Raw CAN Frames","\nprotocol: values in fixed bytes of a CAN frame without any higher layer,\nthe way simple electronics send them and the way a bus looks when you\nmonitor it.",[382,392,393,394,398,399,401,402,405,406,410],{},"The counterpart is the Python script ",[395,396,397],"code",{},"Qenex_RawCan_RandomWalkGenerator.py","\nfrom the ",[395,400,304],{}," folder next to ",[395,403,404],{},"QInsight.exe",". It runs on Linux with\nSocketCAN, typically on a ",[407,408,409],"strong",{},"Raspberry Pi with a CAN HAT",", and:",[412,413,414,437],"ul",{},[415,416,417,420,421,424,425,428,429,432,433,436],"li",{},[407,418,419],{},"sends five random walks"," ",[395,422,423],{},"rnd1"," to ",[395,426,427],{},"rnd5"," on identifiers ",[395,430,431],{},"0x100"," to\n",[395,434,435],{},"0x104",", 50 sets per second; every frame has 8 bytes: a float32 value in\nbytes 0–3 and the float32 generator time in bytes 4–7,",[415,438,439,420,442,424,445,448,449,424,452,455,456,459],{},[407,440,441],{},"accepts frames",[395,443,444],{},"0x180",[395,446,447],{},"0x184"," (new offset of walk 1 to 5) and\n",[395,450,451],{},"0x190",[395,453,454],{},"0x194"," (new step), float32 in bytes 0–3. That is exactly the\nframe QInsight sends when a variable with direction ",[395,457,458],{},"write"," is written.",[382,461,462,463,466],{},"QInsight is on the bus through a ",[407,464,465],{},"PEAK PCAN-USB"," adapter at 250 kbit\u002Fs.",[468,469,474],"pre",{"className":470,"code":472,"language":473},[471],"language-text","Raspberry + CAN HAT  ── 0x100: [float value][float t] ──►  PCAN-USB  ──►  QInsight (graph, watch table)\n                     ◄── 0x180: [float offset]        ──                   write from the watch table\n","text",[395,475,472],{"__ignoreMap":476},"",[382,478,479,480,483,484,486],{},"The project ",[395,481,482],{},"Qenex_CAN_RawCAN_PythonRandomWalks.qproj"," is in the ",[395,485,304],{}," folder.",[382,488,489,496],{},[490,491],"img",{"alt":492,"src":493,"className":494},"The example running: five random walks from the CAN bus, a watch table with writable parameters","\u002Fimg\u002FQInsight_ex_rawcan_light.png",[495],"img-light",[490,497],{"alt":492,"src":498,"className":499},"\u002Fimg\u002FQInsight_ex_rawcan_dark.png",[500],"img-dark",[377,502,504],{"id":503},"what-the-example-shows","What the example shows",[412,506,507,513,534,563],{},[415,508,509,512],{},[407,510,511],{},"Reading"," five walks from the bus on a graph and in signal controls.",[415,514,515,518,519,522,523,525,526,529,530,533],{},[407,516,517],{},"Two variables from one frame",": ",[395,520,521],{},"Rnd1"," reads bytes 0–3 of frame\n",[395,524,431],{},", ",[395,527,528],{},"Rnd1Time"," bytes 4–7 of the same frame (",[395,531,532],{},"offset=\"4\"",").",[415,535,536,539,540,543,544,546,547,543,550,553,554,543,557,559,560,562],{},[407,537,538],{},"Writing"," to the bus: ",[395,541,542],{},"Rnd1Offset"," (",[395,545,444],{},"), ",[395,548,549],{},"Rnd2Offset",[395,551,552],{},"0x181",")\nand ",[395,555,556],{},"Rnd1Step",[395,558,451],{},") have direction ",[395,561,458],{},"; a write from the watch\ntable sends a frame and the walk jumps to the new offset.",[415,564,565,568],{},[407,566,567],{},"Adapter timestamps",": samples carry the receive time of the PCAN-USB,\nnot the moment of processing on the PC.",[377,570,572],{"id":571},"what-you-need","What you need",[382,574,575,576,579,580,583],{},"Very inexpensive hardware is enough on the generator side. The photo shows\nthe setup the example was verified on: a ",[407,577,578],{},"Raspberry Pi Zero"," and a module\nwith the ",[407,581,582],{},"MCP2515"," CAN controller and a TJA1050 bus transceiver, wired to\nthe Raspberry Pi over SPI with a few jumper wires. The module costs a few\neuros and behaves like an ordinary SocketCAN interface in Linux.",[382,585,586],{},[490,587],{"alt":588,"src":589},"Raspberry Pi Zero with an MCP2515 module connected over SPI","\u002Fimg\u002FQInsight_ex_rawcan_pizero_mcp2515.jpg",[382,591,592,593,596,597,600],{},"The MCP2515 module is enabled in Raspberry Pi OS in ",[395,594,595],{},"\u002Fboot\u002Ffirmware\u002Fconfig.txt","\n(",[395,598,599],{},"\u002Fboot\u002Fconfig.txt"," on older systems):",[468,602,605],{"className":603,"code":604,"language":473},[471],"dtparam=spi=on\ndtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25\n",[395,606,604],{"__ignoreMap":476},[382,608,609,612,613,616,617,620],{},[395,610,611],{},"oscillator"," matches the crystal on the module (usually 8 MHz, 16 MHz on some\nmodules) and ",[395,614,615],{},"interrupt"," is the GPIO number the module's INT output is wired\nto. After a reboot the ",[395,618,619],{},"can0"," interface is available. Any other CAN board for\nthe Raspberry Pi, or any Linux computer with a SocketCAN interface, works\njust as well.",[412,622,623,635],{},[415,624,625,626,628,629],{},"A Raspberry Pi with a SocketCAN ",[395,627,619],{}," interface and Python 3; bring the\ninterface up at 250 kbit\u002Fs:",[468,630,633],{"className":631,"code":632,"language":473},[471],"sudo ip link set can0 up type can bitrate 250000\npython3 Qenex_RawCan_RandomWalkGenerator.py\n",[395,634,632],{"__ignoreMap":476},[415,636,637,638,641,642,646,647,650,651,654],{},"A PEAK PCAN-USB on the QInsight PC, bus terminated with 120 Ω. In the\ndriver settings set ",[395,639,640],{},"deviceId"," to the id of your adapter (hexadecimal,\nsee ",[386,643,645],{"href":644},"\u002Freference\u002Fdrivers#peak-can-adapter","PEAK CAN","); ",[395,648,649],{},"bitrate"," stays\n",[395,652,653],{},"250000",".",[377,656,658],{"id":657},"the-project","The project",[660,661,663],"h3",{"id":662},"driver-and-protocol","Driver and protocol",[665,666,667,680],"table",{},[668,669,670],"thead",{},[671,672,673,677],"tr",{},[674,675,676],"th",{},"PCAN-USB driver",[674,678,679],{},"Meaning",[681,682,683,697,707],"tbody",{},[671,684,685,691],{},[686,687,688],"td",{},[395,689,690],{},"deviceId=0xff",[686,692,693,694],{},"adapter id from the PEAK settings — ",[407,695,696],{},"adjust",[671,698,699,704],{},[686,700,701],{},[395,702,703],{},"bitrate=250000",[686,705,706],{},"bus speed, the same as on the Raspberry Pi",[671,708,709,717],{},[686,710,711,525,714],{},[395,712,713],{},"reconnectDelayMs=1000",[395,715,716],{},"reconnectAttempts=-1",[686,718,719],{},"after the adapter is unplugged it retries forever",[382,721,722],{},"The protocol has no settings.",[660,724,77],{"id":725},"variables",[665,727,728,743],{},[668,729,730],{},[671,731,732,735,738,741],{},[674,733,734],{},"Variable",[674,736,737],{},"Type",[674,739,740],{},"Comm params",[674,742,679],{},[681,744,745,766,782,799,816],{},[671,746,747,755,758,763],{},[686,748,749,751,752],{},[395,750,521],{}," … ",[395,753,754],{},"Rnd5",[686,756,757],{},"float",[686,759,760],{},[395,761,762],{},"direction=\"read\";canId=\"0x100\"…\"0x104\";offset=\"0\";byteOrder=\"le\"",[686,764,765],{},"the walks",[671,767,768,772,774,779],{},[686,769,770],{},[395,771,528],{},[686,773,757],{},[686,775,776],{},[395,777,778],{},"direction=\"read\";canId=\"0x100\";offset=\"4\"",[686,780,781],{},"generator time from the second half of the frame",[671,783,784,789,791,796],{},[686,785,786],{},[395,787,788],{},"Params\u002FRnd1Offset",[686,790,757],{},[686,792,793],{},[395,794,795],{},"direction=\"write\";canId=\"0x180\"",[686,797,798],{},"new offset of walk 1",[671,800,801,806,808,813],{},[686,802,803],{},[395,804,805],{},"Params\u002FRnd2Offset",[686,807,757],{},[686,809,810],{},[395,811,812],{},"direction=\"write\";canId=\"0x181\"",[686,814,815],{},"new offset of walk 2",[671,817,818,823,825,830],{},[686,819,820],{},[395,821,822],{},"Params\u002FRnd1Step",[686,824,757],{},[686,826,827],{},[395,828,829],{},"direction=\"write\";canId=\"0x190\"",[686,831,832],{},"step of walk 1",[660,834,112],{"id":835},"workspace",[382,837,838],{},"A graph of all five walks, a watch table with the three writable\nparameters, a signal control of the generator time and five signal\ncontrols of the values.",[377,840,842],{"id":841},"what-you-will-see-and-what-to-try","What you will see and what to try",[412,844,845,855,868,871],{},[415,846,847,848,851,852,854],{},"After ",[407,849,850],{},"Start"," five walks run around their offsets 0, 10, −5, 20 and 5.\n",[395,853,528],{}," grows from the start of the generator.",[415,856,857,858,860,861,864,865,867],{},"Write ",[395,859,542],{}," = 15: walk 1 jumps to 15 and wanders around it; the\ngenerator prints ",[395,862,863],{},"rnd1.O = 15.000",". ",[395,866,556],{}," = 5 makes it wild, 0.1\ncalms it down.",[415,869,870],{},"Unplug the PCAN-USB: the driver reports the adapter loss and retries\nevery second; after plugging it in the data flow again and the\ntimestamps are realigned.",[415,872,873,874,877],{},"Type ",[395,875,876],{},"canId=\"zz\""," into a variable's Comm params and Apply: the variable\nis reported in the log as not communicated with the reason, instead of\nstaying silent.",[377,879,881],{"id":880},"the-generator-script","The generator script",[382,883,884,885,887,888,891],{},"The whole ",[395,886,397],{},"; the frame layout is in\nthe docstring. For your own device take the frame construction\n(",[395,889,890],{},"struct.pack(\"\u003Cff\", value, t)",") and the reading of the control frames.",[468,893,897],{"className":894,"code":895,"language":896,"meta":476,"style":476},"language-python shiki shiki-themes github-light github-dark-default","#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"Random-walk CAN generator - the counterpart of QInsight's Raw CAN Frames protocol.\n\nRuns on a Linux machine with a SocketCAN interface, typically a Raspberry Pi with a CAN HAT\n(QInsight sits on the other end of the bus with a PEAK PCAN-USB adapter):\n\n    sudo ip link set can0 up type can bitrate 250000\n    python3 Qenex_RawCan_RandomWalkGenerator.py              # can0, 50 sets of frames per second\n    python3 Qenex_RawCan_RandomWalkGenerator.py --channel can1 --hz 20\n\nShipped with QInsight in the Examples folder; used by the example\nQenex_CAN_RawCAN_PythonRandomWalks.qproj.\n\nFrames sent (standard 11-bit ids, DLC 8, little-endian):\n    id 0x100 .. 0x104   rnd1 .. rnd5   bytes 0-3 float32 value, bytes 4-7 float32 time t [s]\nEach signal is a random walk: every sample moves by a random step in +-step and a weak\nmean reversion pulls it back towards its offset O, so it never drifts off the chart.\n\nFrames accepted (what QInsight sends for a Raw CAN variable with direction=\"write\"):\n    id 0x180 .. 0x184   bytes 0-3 float32   new offset O of rnd1 .. rnd5\n    id 0x190 .. 0x194   bytes 0-3 float32   new step size of rnd1 .. rnd5\nThe walk jumps to the new offset at once, so a write is visible immediately on the graph.\n\"\"\"\nimport argparse\nimport random\nimport socket\nimport struct\nimport threading\nimport time\n\n# id -> random-walk parameters\n#   O          = offset (the value the walk hovers around)\n#   step       = max size of one random step; each sample moves by +-step\n#   reversion  = mean-reversion strength (0..1); pulls the value back towards O\nSIGNALS = {\n    0x100: {\"O\":  0.0, \"step\": 0.5, \"reversion\": 0.01},\n    0x101: {\"O\": 10.0, \"step\": 1.0, \"reversion\": 0.02},\n    0x102: {\"O\": -5.0, \"step\": 0.3, \"reversion\": 0.015},\n    0x103: {\"O\": 20.0, \"step\": 2.0, \"reversion\": 0.01},\n    0x104: {\"O\":  5.0, \"step\": 0.8, \"reversion\": 0.03},\n}\nOFFSET_ID_BASE = 0x180   # 0x180 + n sets O of the n-th signal\nSTEP_ID_BASE = 0x190     # 0x190 + n sets step of the n-th signal\n\nFRAME_FORMAT = \"=IB3x8s\"  # SocketCAN frame: id (4), dlc (1), padding (3), data (8)\nCAN_EFF_FLAG = 0x80000000\n\nlock = threading.Lock()\nSTATE = {cid: p[\"O\"] for cid, p in SIGNALS.items()}   # current value of every walk\n\n\ndef step_walk(can_id):\n    \"\"\"Advance one random walk by one step and return the new value.\"\"\"\n    with lock:\n        p = SIGNALS[can_id]\n        x = STATE[can_id]\n        x = x + random.uniform(-p[\"step\"], p[\"step\"]) + p[\"reversion\"] * (p[\"O\"] - x)\n        STATE[can_id] = x\n        return x\n\n\ndef build_frame(can_id, value, t):\n    data = struct.pack(\"\u003Cff\", value, t)        # 8 B: float32 value + float32 t\n    return struct.pack(FRAME_FORMAT, can_id, len(data), data)\n\n\ndef apply_frame(raw):\n    \"\"\"A received frame: 0x18n \u002F 0x19n with a float32 sets offset \u002F step of signal n.\"\"\"\n    can_id, dlc, data = struct.unpack(FRAME_FORMAT, raw)\n    if can_id & CAN_EFF_FLAG or dlc \u003C 4:\n        return\n    can_id &= 0x7FF\n    for base, key in ((OFFSET_ID_BASE, \"O\"), (STEP_ID_BASE, \"step\")):\n        n = can_id - base\n        if 0 \u003C= n \u003C len(SIGNALS):\n            signal_id = 0x100 + n\n            value = struct.unpack(\"\u003Cf\", data[:4])[0]\n            with lock:\n                SIGNALS[signal_id][key] = value\n                if key == \"O\":\n                    STATE[signal_id] = value      # jump there, so the write shows at once\n            print(f\"rnd{n + 1}.{key} = {value:.3f}\", flush=True)\n            return\n\n\ndef reader_thread(sock, stop):\n    while not stop.is_set():\n        try:\n            raw = sock.recv(16)\n        except OSError:\n            break\n        if len(raw) == 16:\n            apply_frame(raw)\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Raw CAN random-walk generator for QInsight (SocketCAN).\")\n    parser.add_argument(\"--channel\", default=\"can0\", help=\"SocketCAN interface (default can0)\")\n    parser.add_argument(\"--hz\", type=float, default=50.0, help=\"sets of 5 frames per second (default 50)\")\n    args = parser.parse_args()\n\n    sock = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)\n    sock.bind((args.channel,))\n    stop = threading.Event()\n    threading.Thread(target=reader_thread, args=(sock, stop), daemon=True).start()\n\n    t0 = time.monotonic()\n    period = 1.0 \u002F args.hz\n    next_t = time.monotonic()\n    print(f\"Raw CAN generator on {args.channel}: ids 0x100-0x104 @ {args.hz:g} Hz, \"\n          f\"writes on 0x180-0x184 (offset) and 0x190-0x194 (step). Ctrl+C to stop.\", flush=True)\n    try:\n        while True:\n            t = time.monotonic() - t0\n            for can_id in SIGNALS:                 # 5 frames, one signal each\n                sock.send(build_frame(can_id, step_walk(can_id), t))\n            next_t += period\n            time.sleep(max(0.0, next_t - time.monotonic()))\n    except KeyboardInterrupt:\n        pass\n    finally:\n        stop.set()\n        sock.close()\n\n\nif __name__ == \"__main__\":\n    main()\n","python",[395,898,899,907,913,920,926,932,937,943,949,955,960,966,972,977,983,989,995,1001,1006,1012,1018,1024,1030,1036,1042,1048,1054,1060,1066,1072,1077,1083,1089,1095,1101,1107,1113,1119,1125,1131,1137,1143,1149,1155,1160,1166,1172,1177,1183,1189,1194,1199,1205,1211,1217,1223,1229,1235,1241,1247,1252,1257,1263,1269,1275,1280,1285,1291,1297,1303,1309,1315,1321,1327,1333,1339,1345,1351,1357,1363,1369,1375,1381,1387,1392,1397,1403,1409,1415,1421,1427,1433,1439,1445,1450,1455,1461,1467,1473,1479,1485,1490,1496,1502,1508,1514,1519,1525,1531,1537,1543,1549,1555,1561,1567,1573,1579,1585,1591,1597,1603,1609,1615,1621,1626,1631,1637],{"__ignoreMap":476},[900,901,904],"span",{"class":902,"line":903},"line",1,[900,905,906],{},"#!\u002Fusr\u002Fbin\u002Fenv python3\n",[900,908,910],{"class":902,"line":909},2,[900,911,912],{},"\"\"\"Random-walk CAN generator - the counterpart of QInsight's Raw CAN Frames protocol.\n",[900,914,916],{"class":902,"line":915},3,[900,917,919],{"emptyLinePlaceholder":918},true,"\n",[900,921,923],{"class":902,"line":922},4,[900,924,925],{},"Runs on a Linux machine with a SocketCAN interface, typically a Raspberry Pi with a CAN HAT\n",[900,927,929],{"class":902,"line":928},5,[900,930,931],{},"(QInsight sits on the other end of the bus with a PEAK PCAN-USB adapter):\n",[900,933,935],{"class":902,"line":934},6,[900,936,919],{"emptyLinePlaceholder":918},[900,938,940],{"class":902,"line":939},7,[900,941,942],{},"    sudo ip link set can0 up type can bitrate 250000\n",[900,944,946],{"class":902,"line":945},8,[900,947,948],{},"    python3 Qenex_RawCan_RandomWalkGenerator.py              # can0, 50 sets of frames per second\n",[900,950,952],{"class":902,"line":951},9,[900,953,954],{},"    python3 Qenex_RawCan_RandomWalkGenerator.py --channel can1 --hz 20\n",[900,956,958],{"class":902,"line":957},10,[900,959,919],{"emptyLinePlaceholder":918},[900,961,963],{"class":902,"line":962},11,[900,964,965],{},"Shipped with QInsight in the Examples folder; used by the example\n",[900,967,969],{"class":902,"line":968},12,[900,970,971],{},"Qenex_CAN_RawCAN_PythonRandomWalks.qproj.\n",[900,973,975],{"class":902,"line":974},13,[900,976,919],{"emptyLinePlaceholder":918},[900,978,980],{"class":902,"line":979},14,[900,981,982],{},"Frames sent (standard 11-bit ids, DLC 8, little-endian):\n",[900,984,986],{"class":902,"line":985},15,[900,987,988],{},"    id 0x100 .. 0x104   rnd1 .. rnd5   bytes 0-3 float32 value, bytes 4-7 float32 time t [s]\n",[900,990,992],{"class":902,"line":991},16,[900,993,994],{},"Each signal is a random walk: every sample moves by a random step in +-step and a weak\n",[900,996,998],{"class":902,"line":997},17,[900,999,1000],{},"mean reversion pulls it back towards its offset O, so it never drifts off the chart.\n",[900,1002,1004],{"class":902,"line":1003},18,[900,1005,919],{"emptyLinePlaceholder":918},[900,1007,1009],{"class":902,"line":1008},19,[900,1010,1011],{},"Frames accepted (what QInsight sends for a Raw CAN variable with direction=\"write\"):\n",[900,1013,1015],{"class":902,"line":1014},20,[900,1016,1017],{},"    id 0x180 .. 0x184   bytes 0-3 float32   new offset O of rnd1 .. rnd5\n",[900,1019,1021],{"class":902,"line":1020},21,[900,1022,1023],{},"    id 0x190 .. 0x194   bytes 0-3 float32   new step size of rnd1 .. rnd5\n",[900,1025,1027],{"class":902,"line":1026},22,[900,1028,1029],{},"The walk jumps to the new offset at once, so a write is visible immediately on the graph.\n",[900,1031,1033],{"class":902,"line":1032},23,[900,1034,1035],{},"\"\"\"\n",[900,1037,1039],{"class":902,"line":1038},24,[900,1040,1041],{},"import argparse\n",[900,1043,1045],{"class":902,"line":1044},25,[900,1046,1047],{},"import random\n",[900,1049,1051],{"class":902,"line":1050},26,[900,1052,1053],{},"import socket\n",[900,1055,1057],{"class":902,"line":1056},27,[900,1058,1059],{},"import struct\n",[900,1061,1063],{"class":902,"line":1062},28,[900,1064,1065],{},"import threading\n",[900,1067,1069],{"class":902,"line":1068},29,[900,1070,1071],{},"import time\n",[900,1073,1075],{"class":902,"line":1074},30,[900,1076,919],{"emptyLinePlaceholder":918},[900,1078,1080],{"class":902,"line":1079},31,[900,1081,1082],{},"# id -> random-walk parameters\n",[900,1084,1086],{"class":902,"line":1085},32,[900,1087,1088],{},"#   O          = offset (the value the walk hovers around)\n",[900,1090,1092],{"class":902,"line":1091},33,[900,1093,1094],{},"#   step       = max size of one random step; each sample moves by +-step\n",[900,1096,1098],{"class":902,"line":1097},34,[900,1099,1100],{},"#   reversion  = mean-reversion strength (0..1); pulls the value back towards O\n",[900,1102,1104],{"class":902,"line":1103},35,[900,1105,1106],{},"SIGNALS = {\n",[900,1108,1110],{"class":902,"line":1109},36,[900,1111,1112],{},"    0x100: {\"O\":  0.0, \"step\": 0.5, \"reversion\": 0.01},\n",[900,1114,1116],{"class":902,"line":1115},37,[900,1117,1118],{},"    0x101: {\"O\": 10.0, \"step\": 1.0, \"reversion\": 0.02},\n",[900,1120,1122],{"class":902,"line":1121},38,[900,1123,1124],{},"    0x102: {\"O\": -5.0, \"step\": 0.3, \"reversion\": 0.015},\n",[900,1126,1128],{"class":902,"line":1127},39,[900,1129,1130],{},"    0x103: {\"O\": 20.0, \"step\": 2.0, \"reversion\": 0.01},\n",[900,1132,1134],{"class":902,"line":1133},40,[900,1135,1136],{},"    0x104: {\"O\":  5.0, \"step\": 0.8, \"reversion\": 0.03},\n",[900,1138,1140],{"class":902,"line":1139},41,[900,1141,1142],{},"}\n",[900,1144,1146],{"class":902,"line":1145},42,[900,1147,1148],{},"OFFSET_ID_BASE = 0x180   # 0x180 + n sets O of the n-th signal\n",[900,1150,1152],{"class":902,"line":1151},43,[900,1153,1154],{},"STEP_ID_BASE = 0x190     # 0x190 + n sets step of the n-th signal\n",[900,1156,1158],{"class":902,"line":1157},44,[900,1159,919],{"emptyLinePlaceholder":918},[900,1161,1163],{"class":902,"line":1162},45,[900,1164,1165],{},"FRAME_FORMAT = \"=IB3x8s\"  # SocketCAN frame: id (4), dlc (1), padding (3), data (8)\n",[900,1167,1169],{"class":902,"line":1168},46,[900,1170,1171],{},"CAN_EFF_FLAG = 0x80000000\n",[900,1173,1175],{"class":902,"line":1174},47,[900,1176,919],{"emptyLinePlaceholder":918},[900,1178,1180],{"class":902,"line":1179},48,[900,1181,1182],{},"lock = threading.Lock()\n",[900,1184,1186],{"class":902,"line":1185},49,[900,1187,1188],{},"STATE = {cid: p[\"O\"] for cid, p in SIGNALS.items()}   # current value of every walk\n",[900,1190,1192],{"class":902,"line":1191},50,[900,1193,919],{"emptyLinePlaceholder":918},[900,1195,1197],{"class":902,"line":1196},51,[900,1198,919],{"emptyLinePlaceholder":918},[900,1200,1202],{"class":902,"line":1201},52,[900,1203,1204],{},"def step_walk(can_id):\n",[900,1206,1208],{"class":902,"line":1207},53,[900,1209,1210],{},"    \"\"\"Advance one random walk by one step and return the new value.\"\"\"\n",[900,1212,1214],{"class":902,"line":1213},54,[900,1215,1216],{},"    with lock:\n",[900,1218,1220],{"class":902,"line":1219},55,[900,1221,1222],{},"        p = SIGNALS[can_id]\n",[900,1224,1226],{"class":902,"line":1225},56,[900,1227,1228],{},"        x = STATE[can_id]\n",[900,1230,1232],{"class":902,"line":1231},57,[900,1233,1234],{},"        x = x + random.uniform(-p[\"step\"], p[\"step\"]) + p[\"reversion\"] * (p[\"O\"] - x)\n",[900,1236,1238],{"class":902,"line":1237},58,[900,1239,1240],{},"        STATE[can_id] = x\n",[900,1242,1244],{"class":902,"line":1243},59,[900,1245,1246],{},"        return x\n",[900,1248,1250],{"class":902,"line":1249},60,[900,1251,919],{"emptyLinePlaceholder":918},[900,1253,1255],{"class":902,"line":1254},61,[900,1256,919],{"emptyLinePlaceholder":918},[900,1258,1260],{"class":902,"line":1259},62,[900,1261,1262],{},"def build_frame(can_id, value, t):\n",[900,1264,1266],{"class":902,"line":1265},63,[900,1267,1268],{},"    data = struct.pack(\"\u003Cff\", value, t)        # 8 B: float32 value + float32 t\n",[900,1270,1272],{"class":902,"line":1271},64,[900,1273,1274],{},"    return struct.pack(FRAME_FORMAT, can_id, len(data), data)\n",[900,1276,1278],{"class":902,"line":1277},65,[900,1279,919],{"emptyLinePlaceholder":918},[900,1281,1283],{"class":902,"line":1282},66,[900,1284,919],{"emptyLinePlaceholder":918},[900,1286,1288],{"class":902,"line":1287},67,[900,1289,1290],{},"def apply_frame(raw):\n",[900,1292,1294],{"class":902,"line":1293},68,[900,1295,1296],{},"    \"\"\"A received frame: 0x18n \u002F 0x19n with a float32 sets offset \u002F step of signal n.\"\"\"\n",[900,1298,1300],{"class":902,"line":1299},69,[900,1301,1302],{},"    can_id, dlc, data = struct.unpack(FRAME_FORMAT, raw)\n",[900,1304,1306],{"class":902,"line":1305},70,[900,1307,1308],{},"    if can_id & CAN_EFF_FLAG or dlc \u003C 4:\n",[900,1310,1312],{"class":902,"line":1311},71,[900,1313,1314],{},"        return\n",[900,1316,1318],{"class":902,"line":1317},72,[900,1319,1320],{},"    can_id &= 0x7FF\n",[900,1322,1324],{"class":902,"line":1323},73,[900,1325,1326],{},"    for base, key in ((OFFSET_ID_BASE, \"O\"), (STEP_ID_BASE, \"step\")):\n",[900,1328,1330],{"class":902,"line":1329},74,[900,1331,1332],{},"        n = can_id - base\n",[900,1334,1336],{"class":902,"line":1335},75,[900,1337,1338],{},"        if 0 \u003C= n \u003C len(SIGNALS):\n",[900,1340,1342],{"class":902,"line":1341},76,[900,1343,1344],{},"            signal_id = 0x100 + n\n",[900,1346,1348],{"class":902,"line":1347},77,[900,1349,1350],{},"            value = struct.unpack(\"\u003Cf\", data[:4])[0]\n",[900,1352,1354],{"class":902,"line":1353},78,[900,1355,1356],{},"            with lock:\n",[900,1358,1360],{"class":902,"line":1359},79,[900,1361,1362],{},"                SIGNALS[signal_id][key] = value\n",[900,1364,1366],{"class":902,"line":1365},80,[900,1367,1368],{},"                if key == \"O\":\n",[900,1370,1372],{"class":902,"line":1371},81,[900,1373,1374],{},"                    STATE[signal_id] = value      # jump there, so the write shows at once\n",[900,1376,1378],{"class":902,"line":1377},82,[900,1379,1380],{},"            print(f\"rnd{n + 1}.{key} = {value:.3f}\", flush=True)\n",[900,1382,1384],{"class":902,"line":1383},83,[900,1385,1386],{},"            return\n",[900,1388,1390],{"class":902,"line":1389},84,[900,1391,919],{"emptyLinePlaceholder":918},[900,1393,1395],{"class":902,"line":1394},85,[900,1396,919],{"emptyLinePlaceholder":918},[900,1398,1400],{"class":902,"line":1399},86,[900,1401,1402],{},"def reader_thread(sock, stop):\n",[900,1404,1406],{"class":902,"line":1405},87,[900,1407,1408],{},"    while not stop.is_set():\n",[900,1410,1412],{"class":902,"line":1411},88,[900,1413,1414],{},"        try:\n",[900,1416,1418],{"class":902,"line":1417},89,[900,1419,1420],{},"            raw = sock.recv(16)\n",[900,1422,1424],{"class":902,"line":1423},90,[900,1425,1426],{},"        except OSError:\n",[900,1428,1430],{"class":902,"line":1429},91,[900,1431,1432],{},"            break\n",[900,1434,1436],{"class":902,"line":1435},92,[900,1437,1438],{},"        if len(raw) == 16:\n",[900,1440,1442],{"class":902,"line":1441},93,[900,1443,1444],{},"            apply_frame(raw)\n",[900,1446,1448],{"class":902,"line":1447},94,[900,1449,919],{"emptyLinePlaceholder":918},[900,1451,1453],{"class":902,"line":1452},95,[900,1454,919],{"emptyLinePlaceholder":918},[900,1456,1458],{"class":902,"line":1457},96,[900,1459,1460],{},"def main():\n",[900,1462,1464],{"class":902,"line":1463},97,[900,1465,1466],{},"    parser = argparse.ArgumentParser(description=\"Raw CAN random-walk generator for QInsight (SocketCAN).\")\n",[900,1468,1470],{"class":902,"line":1469},98,[900,1471,1472],{},"    parser.add_argument(\"--channel\", default=\"can0\", help=\"SocketCAN interface (default can0)\")\n",[900,1474,1476],{"class":902,"line":1475},99,[900,1477,1478],{},"    parser.add_argument(\"--hz\", type=float, default=50.0, help=\"sets of 5 frames per second (default 50)\")\n",[900,1480,1482],{"class":902,"line":1481},100,[900,1483,1484],{},"    args = parser.parse_args()\n",[900,1486,1488],{"class":902,"line":1487},101,[900,1489,919],{"emptyLinePlaceholder":918},[900,1491,1493],{"class":902,"line":1492},102,[900,1494,1495],{},"    sock = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)\n",[900,1497,1499],{"class":902,"line":1498},103,[900,1500,1501],{},"    sock.bind((args.channel,))\n",[900,1503,1505],{"class":902,"line":1504},104,[900,1506,1507],{},"    stop = threading.Event()\n",[900,1509,1511],{"class":902,"line":1510},105,[900,1512,1513],{},"    threading.Thread(target=reader_thread, args=(sock, stop), daemon=True).start()\n",[900,1515,1517],{"class":902,"line":1516},106,[900,1518,919],{"emptyLinePlaceholder":918},[900,1520,1522],{"class":902,"line":1521},107,[900,1523,1524],{},"    t0 = time.monotonic()\n",[900,1526,1528],{"class":902,"line":1527},108,[900,1529,1530],{},"    period = 1.0 \u002F args.hz\n",[900,1532,1534],{"class":902,"line":1533},109,[900,1535,1536],{},"    next_t = time.monotonic()\n",[900,1538,1540],{"class":902,"line":1539},110,[900,1541,1542],{},"    print(f\"Raw CAN generator on {args.channel}: ids 0x100-0x104 @ {args.hz:g} Hz, \"\n",[900,1544,1546],{"class":902,"line":1545},111,[900,1547,1548],{},"          f\"writes on 0x180-0x184 (offset) and 0x190-0x194 (step). Ctrl+C to stop.\", flush=True)\n",[900,1550,1552],{"class":902,"line":1551},112,[900,1553,1554],{},"    try:\n",[900,1556,1558],{"class":902,"line":1557},113,[900,1559,1560],{},"        while True:\n",[900,1562,1564],{"class":902,"line":1563},114,[900,1565,1566],{},"            t = time.monotonic() - t0\n",[900,1568,1570],{"class":902,"line":1569},115,[900,1571,1572],{},"            for can_id in SIGNALS:                 # 5 frames, one signal each\n",[900,1574,1576],{"class":902,"line":1575},116,[900,1577,1578],{},"                sock.send(build_frame(can_id, step_walk(can_id), t))\n",[900,1580,1582],{"class":902,"line":1581},117,[900,1583,1584],{},"            next_t += period\n",[900,1586,1588],{"class":902,"line":1587},118,[900,1589,1590],{},"            time.sleep(max(0.0, next_t - time.monotonic()))\n",[900,1592,1594],{"class":902,"line":1593},119,[900,1595,1596],{},"    except KeyboardInterrupt:\n",[900,1598,1600],{"class":902,"line":1599},120,[900,1601,1602],{},"        pass\n",[900,1604,1606],{"class":902,"line":1605},121,[900,1607,1608],{},"    finally:\n",[900,1610,1612],{"class":902,"line":1611},122,[900,1613,1614],{},"        stop.set()\n",[900,1616,1618],{"class":902,"line":1617},123,[900,1619,1620],{},"        sock.close()\n",[900,1622,1624],{"class":902,"line":1623},124,[900,1625,919],{"emptyLinePlaceholder":918},[900,1627,1629],{"class":902,"line":1628},125,[900,1630,919],{"emptyLinePlaceholder":918},[900,1632,1634],{"class":902,"line":1633},126,[900,1635,1636],{},"if __name__ == \"__main__\":\n",[900,1638,1640],{"class":902,"line":1639},127,[900,1641,1642],{},"    main()\n",[377,1644,1646],{"id":1645},"related-chapters","Related chapters",[412,1648,1649,1654,1659],{},[415,1650,1651,1653],{},[386,1652,389],{"href":388}," in the protocol reference",[415,1655,1656,1658],{},[386,1657,645],{"href":644}," in the driver reference",[415,1660,1661,1665],{},[386,1662,1664],{"href":1663},"\u002Fexamples\u002Fcan-xcp-nucleo-maps","XCP on CAN on a NUCLEO-H723ZG"," — the same adapter with the XCP protocol",[1667,1668,1669],"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":476,"searchDepth":915,"depth":915,"links":1671},[1672,1673,1674,1675,1680,1681,1682],{"id":379,"depth":909,"text":380},{"id":503,"depth":909,"text":504},{"id":571,"depth":909,"text":572},{"id":657,"depth":909,"text":658,"children":1676},[1677,1678,1679],{"id":662,"depth":915,"text":663},{"id":725,"depth":915,"text":77},{"id":835,"depth":915,"text":112},{"id":841,"depth":909,"text":842},{"id":880,"depth":909,"text":881},{"id":1645,"depth":909,"text":1646},"An example of the Raw CAN Frames protocol — five random walks sent as raw CAN frames by a Raspberry Pi with a CAN HAT, read through a PEAK PCAN-USB, with offset and step written back to the bus.","md",{},{"title":353,"description":1683},"_pMly9HbbalLOqTxveExtlfqirKFobRyv9HzCg8ZqTY",[1689,1690],{"title":348,"path":349,"stem":350,"navTitle":351,"children":-1},{"title":358,"path":359,"stem":360,"navTitle":361,"children":-1},1791554568268]