feat(ops243): add internal hardware trigger - #221
JPMarhefka wants to merge 9 commits into
Conversation
Updated the Raspberry Pi retest checklist to clarify merging requirements and added a note about regression testing the sound trigger.
There was a problem hiding this comment.
Pull request overview
Adds an opt-in OPS243 internal hardware-trigger strategy for rolling-buffer capture, threading new configuration flags through the kiosk script and server so installations without the external sound-trigger module can still capture I/Q history (while keeping sound-trigger as the default).
Changes:
- Add OPS243 driver support for configuring, waiting on, parsing, and re-arming the internal speed-trigger rolling-buffer dump (firmware-gated to v1.3.1).
- Extend server/kiosk CLI plumbing with
--trigger hardwareplus hardware-mode defaults/overrides (threshold, magnitude, pre-trigger split) and corresponding validation. - Add focused tests and documentation for the new trigger mode and its operational constraints.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_start_kiosk.py | Verifies kiosk CLI forwarding behavior for hardware trigger defaults and overrides. |
| tests/test_server.py | Adds server CLI parsing/forwarding tests for hardware trigger mode and its constraints. |
| tests/test_rolling_buffer.py | Registers/validates the new trigger strategy and adds behavior tests for accept/reject/re-arm flows. |
| tests/test_ops243.py | Adds focused OPS243 command-ordering, validation, re-arm, and recovery tests for internal triggering. |
| src/openflight/server.py | Adds hardware trigger CLI flags/validation and threads trigger kwargs into monitor startup. |
| src/openflight/rolling_buffer/trigger.py | Implements HardwareTriggeredCapture strategy around board-managed trigger + host-side validation + re-arm. |
| src/openflight/rolling_buffer/monitor.py | Configures OPS243 internal trigger on connect when trigger_type == "hardware". |
| src/openflight/rolling_buffer/init.py | Exposes HardwareTriggeredCapture from the rolling_buffer package. |
| src/openflight/ops243.py | Implements firmware validation, internal-trigger configuration, re-arm, and UART recovery behavior. |
| scripts/start-kiosk.sh | Adds kiosk flag parsing and forwarding for hardware-trigger-specific settings. |
| README.md | Documents the new opt-in hardware trigger mode and links to the new guide. |
| docs/rolling_buffer_spin_detection.md | Clarifies the default sound-trigger pipeline and references the new hardware trigger option. |
| docs/hardware-trigger.md | New guide describing command ordering, defaults, and retest expectations for internal triggering. |
| docs/CHANGELOG.md | Adds an Unreleased changelog entry describing the new hardware trigger mode and constraints. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
This is great, and much needed. However we are waiting on Omnipresence for a way to update OPS radars to this version that doesn't require their extra device. Will ping them again to see if this is a realistic ask. |
|
So do we have the hex file to flash with the new firmware? |
Send an email to Rob at customerservice@omnipresense.com. He will be able to get you the file once it's public and help you find the correct model SEGGER. |
|
Review note: Correcting my earlier version of this comment: I claimed boards reporting 1.5.2 would be blocked today. AN-010 rev AE Table 9 shows the OPS243-A line runs 1.2.3 → 1.3.1, with the |
|
Docs suggestion for
The J2 JTAG header physical is: When shopping for cables for your SEGGER programmer. Also worth a warning: AN-013 says never press Erase — it wipes factory settings and persistent memory, which is where Not blocking; the code change is unaffected. |
Possible cheap path. The OPS243's I/O is 3.3 V (this repo already wires Pi GPIO straight to J3 with no level shifter), and the XMC4500/4700 speaks SWD, which OpenOCD supports via its in-tree Caveats: XMCFlasher won't drive a CMSIS-DAP probe, so this is OpenOCD-only and off the vendor-supported path. Unverified on this board: BMI/boot-mode handling (J-Link does it automatically) and whether the part is read-protected. J2 is a keyed fine-pitch header, so it needs a proper cable — worth asking OmniPreSense for the pinout. Vendor-blessed alternative: the SEGGER J-Link EDU Mini, which AN-013 links directly (adafruit.com/product/3571, $75.95). Worth 30 minutes on a spare board. I wouldn't try it on the only radar in a build. |
Email sent! |
|
Instructions on how to apply the firmware update: |
…hain to the DS3502 PR open-flight#221 adds an opt-in OPS243 internal hardware trigger (firmware v1.3.1) that needs no SEN-14262, so call it out in the Sound Trigger section as an optional path that is not merged yet, and say under the Cost Summary that the Sound Trigger line drops out on that path. Totals are unchanged. Document that the Qwiic-to-Dupont cable's chain can continue from the LIS3DH's second STEMMA QT socket further down to the DS3502 digital potentiometer, and give the DS3502 row that wiring plan plus the note that it is moot if the sound trigger goes away. Claude-Session: https://claude.ai/code/session_01Y55yaLV4h2SVf5EVHN7Yz8 Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
…hain to the DS3502 PR open-flight#221 adds an opt-in OPS243 internal hardware trigger (firmware v1.3.1) that needs no SEN-14262, so call it out in the Sound Trigger section as an optional path that is not merged yet, and say under the Cost Summary that the Sound Trigger line drops out on that path. Totals are unchanged. Document that the Qwiic-to-Dupont cable's chain can continue from the LIS3DH's second STEMMA QT socket further down to the DS3502 digital potentiometer, and give the DS3502 row that wiring plan plus the note that it is moot if the sound trigger goes away. Claude-Session: https://claude.ai/code/session_01Y55yaLV4h2SVf5EVHN7Yz8 Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
|
New information from Sandy on the OPS team in the discord server:
JedS — 20:39
So we would need this code to gate to >1.3.2 and hoepfully we will be able to point people to update it - also we need to update the AN-XXX documents included in our repo when the new ones are released and point people in the direction on how to update their boards. |
|
@JPMarhefka Also was succesfull upgrading mine to 1.3.2 - I got an SEGGER jlink EDU mini and for that the Jlink driver install process need to be run as adminstrator and the legacy jlink usb driver need to be ticked when installing that. Other than that it went well and verified with Putty. |
Put the deprecated K-LD7 parts and wiring and the filament-estimate paragraph in collapsible details blocks. Remove the DS3502 digital potentiometer, its Qwiic-to-Qwiic cable, its two cable-length rows and the chain sentence in the Qwiic-to-Dupont row: the internal trigger in PR open-flight#221 makes a software gain trim on the sound detector moot. Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
Add the 200 mm Raspberry Pi display cable (SC1131) the Touch Display 2 needs in the openflight-enclosure v3 case, where the Pi and UPS mount to the shell rather than the screen and the ~100 mm ribbon in the box does not reach (openflight-enclosure#11). Document power input on the v3 case: the shell has no USB-C opening, so a USB-C supply is captive and a detachable supply is the DC route. Add the no-solder parts for it (a pre-wired 5.5 x 2.1 mm panel jack, Tensility 10-03609 on Mouser or Amazon DC-099 kits; two Wago 221-412 for the XH header option; the Adafruit 369 screw-terminal plug for the barrel option into the X1202's own jack, with the plug dimensions), fed at 12 V because the XH input is rated for about 3 A. Note that 5 A USB-C pass-throughs are hard to find. Give every Mouser ProductDetail link the ?qs= token from the shared Mouser project, which is the form Mouser still resolves, add Amazon options beside them, and move the Qwiic-to-Dupont row to the SparkFun CAB-17261 the project carries. Move every measured distance out of the product rows into the collapsible cable-lengths section and replace the v2 table with runs measured on the v3 STEP, including the display and camera ribbons, Ethernet, both DC jack options and both button-hole options. Record that both rear holes in the v3 shell are 12.5 mm, so the 16 mm Adafruit 1445 needs the CAD hole opened or a 12 mm button. Replace the v2 insert and screw table with a link to the enclosure repository's Required hardware page, re-base the filament estimate on the v3 print set from the STL mesh volumes (~750 g PETG, ~$17) inside a collapsible block, and fold the deprecated K-LD7 section into one too. Drop the DS3502 potentiometer and its cable, since the internal trigger in PR open-flight#221 makes a software gain trim moot; drop the IARC case and the X1206 input-range comparison; correct the internal-trigger firmware to OPS243-A 1.3.2. Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
Add the 200 mm Raspberry Pi display cable (SC1131) the Touch Display 2 needs in the openflight-enclosure v3 case, where the Pi and UPS mount to the shell rather than the screen and the ~100 mm ribbon in the box does not reach (openflight-enclosure#11). Document power input on the v3 case: the shell has no USB-C opening, so a USB-C supply is captive and a detachable supply is the DC route. Add the no-solder parts for it (a pre-wired 5.5 x 2.1 mm panel jack, Tensility 10-03609 on Mouser or Amazon DC-099 kits; two Wago 221-412 for the XH header option; the Adafruit 369 screw-terminal plug for the barrel option into the X1202's own jack, with the plug dimensions), fed at 12 V because the XH input is rated for about 3 A. Note that 5 A USB-C pass-throughs are hard to find. Give every Mouser ProductDetail link the ?qs= token from the shared Mouser project, which is the form Mouser still resolves, add Amazon options beside them, and move the Qwiic-to-Dupont row to the SparkFun CAB-17261 the project carries. Move every measured distance out of the product rows into the collapsible cable-lengths section and replace the v2 table with runs measured on the v3 STEP, including the display and camera ribbons, Ethernet, both DC jack options and both button-hole options. Record that both rear holes in the v3 shell are 12.5 mm, so the 16 mm Adafruit 1445 needs the CAD hole opened or a 12 mm button. Replace the v2 insert and screw table with a link to the enclosure repository's Required hardware page, re-base the filament estimate on the v3 print set from the STL mesh volumes (~750 g PETG, ~$17) inside a collapsible block, and fold the deprecated K-LD7 section into one too. Explain the PR open-flight#221 internal-trigger path next to the sound trigger: the OPS243-A fires the capture itself on firmware 1.3.2, every unit can be brought to that release, sensors shipping since September 2026 arrive with it, and older ones are flashed over the J2 JTAG header with a SEGGER J-Link and Infineon's XMCFlasher per AN-013 with the hex from OmniPreSense support. Add the J-Link EDU Mini row (about $76) so the cost of that choice sits next to the $18 detector. Drop the DS3502 potentiometer and its cable, since the internal trigger in PR open-flight#221 makes a software gain trim moot; drop the IARC case, the X1206 input-range comparison and the cost-summary paragraph that itemised the complete-build line; correct the internal-trigger firmware to OPS243-A 1.3.2. Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
Spell out, next to the sound trigger, what the PR #221 internal trigger changes and what it costs: the OPS243-A fires the rolling-buffer capture itself on firmware 1.3.2, every OPS243-A can be brought to that release, sensors shipping since OmniPreSense's September 2026 note arrive with it, and older units are flashed over the J2 JTAG header with a SEGGER J-Link and Infineon's XMCFlasher following AN-013, with the hex requested from OmniPreSense support. Add a J-Link EDU Mini row (about $76, tokenised Mouser link from the shared project, Amazon and Adafruit alternatives) so that cost sits next to the $18 detector, and say the same in the Cost Summary. Drop the Cost Summary paragraph that itemised the complete-build line; the table already carries it. Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
docs(parts): explain the PR #221 internal-trigger firmware path
|
Will also add that I needed to fiddel with XMCflasher as the application is designed before javaFX was remove from the JDK - got it working with OpenJDK 27 + JavaFX 27 on windows 11 with the following: **Flashing the OPS243 on Windows: two blockers that hit before XMCFlasher even opens**
I got the SEGGER + XMCFlasher path working on Windows 11 (JDK 27, J-Link V9.78). Neither blocker is an OPS243 problem, but both cost time, so noting them here for whoever writes the firmware-update doc. 1. XMCFlasher does not start on any Java newer than 8XMCFlasher start /b javaw -jar %~dp0\xmcflasher.jar --guiJavaFX stopped shipping inside the JDK at Java 11, so on any current JDK it dies before showing a window: Installing a JavaFX SDK and setting javaw --module-path "<javafx-sdk>\lib" --add-modules javafx.controls,javafx.fxml ^
--enable-native-access=javafx.graphics,ALL-UNNAMED ^
-jar "<install-dir>\XMCFlasher.jar" --guiVerified working with OpenJDK 21 + JavaFX 21.0.7 and OpenJDK 27 + JavaFX 27. The app only uses Why
|
I'm working on fixing the hardware trigger with the current OpenFlight codebase and OPS 1.3.2. There was a slight regression, but it should be finished soon. Thanks for putting together the docs for this! |





What does this PR do?
Adds an opt-in OPS243 internal hardware-trigger capture strategy for rolling-buffer mode.
--trigger hardwarewith hardware-mode defaults of a 25 mph outbound threshold,SM25,S#6, and 30 ksps.GC.--sound-pre-triggerbehavior.Why was this required?
The existing rolling-buffer path depends on the external SEN-14262 sound-trigger edge. The OPS243 can perform the speed-trigger decision internally, allowing installations with the internal trigger wiring to capture the rolling I/Q history without requiring the sound-trigger module.
This is opt-in so existing installations continue to use sound mode unchanged. Hardware mode is intentionally limited to the OPS243 trigger path; unrelated experimental analysis, replay, board-diagnostic, clock, and UI work is not included.
Automated tests
PYTHONPATH=src uv run --no-sync pytest tests/ -q: 1,352 passed, 8 skipped, 17 warningsuv run --no-sync ruff check src/openflight/: passeduv run --no-sync pylint src/openflight/ --fail-under=9: passed, 9.72/10cd ui && npm run build: passedcd ui && npm run lint: passedThe focused tests cover command ordering, firmware and parameter validation, dump-boundary filtering, dump parsing, re-arm behavior and recovery, accepted/rejected captures, strategy selection, and CLI forwarding.
Manual (human) testing
Hardware testing was performed with an OPS243 running firmware v1.3.1.
SM25setting.S#6produced the best ball/club parsing compared withS#4andS#8.Initial with ball.jsonlsession recorded 18 hardware-trigger shot outputs with zero logged errors.swing_only_no_ball.jsonlsession recorded 4 accepted no-ball outputs with zero logged errors, documenting the limitation above.hit-0005andhit-0006produced usable ball/club outputs. The rail-adjacent energy in the I/Q view was the club passing close to the sensor and did not prevent useful output parsing.Checklist