Complete guide for setting up OpenFlight on a Raspberry Pi 5 with the 7" touchscreen display.
Make sure you have all the hardware. See the Parts List for what to buy.
Required:
- Raspberry Pi 5 (4GB+ recommended)
- 7" Touchscreen Display
- MicroSD Card (32GB+)
- 27W USB-C Power Supply (official Pi 5 PSU recommended)
- OPS243-A Doppler Radar + USB cable
- SparkFun SEN-14262 sound detector (wired per the Sound Trigger Wiring Guide)
Optional:
- TI IWR6843LEVM + data cable — measured launch angle and experimental club path; see the IWR6843 Operator Guide
- Geekworm X1202 or X1206 UPS HAT — portable Pi 5 power using four separately purchased 18650 or 21700 cells; see the battery monitoring overview and Geekworm operator guide
- InnoMaker OV9281 global-shutter camera (~$30) — experimental vision work; see Camera and YOLO Experiments
Optional (deprecated):
- K-LD7 + FTDI adapter (×2) — for launch angle and club path (see Parts List). Deprecated — superseded by a more capable radar chip; don't buy for a new build. Supported for existing builds only.
Use Raspberry Pi Imager to flash Raspberry Pi OS (64-bit) to your SD card.
On the first boot, before cloning OpenFlight, you'll likely need a few dependencies to run the setup.sh script.
Run the following command:
sudo apt update && sudo apt install -y swig liblgpio-dev python3-devIf ./scripts/setup/setup.sh updates ~/.bashrc, you may need to run source ~/.bashrc (or open a new terminal) so your current shell picks up the new environment variables immediately without needing to reboot or re-login.
Plug in the OPS243-A (and the K-LD7 adapters if you have them), then:
cd ~
git clone https://github.com/jewbetcha/openflight.git
cd openflight
./scripts/setup/setup.shThe script installs everything, then walks you through the one-time hardware configuration with prompts:
- Dependencies — Python venv, packages, UI build, test run
- OPS243-A radar — saves rolling buffer mode to the radar's flash (you'll be asked to unplug/replug the radar once)
- K-LD7 radars (deprecated; if you have them) — identifies each radar by plugging them in one at a time, so OpenFlight always knows which is which
- Geekworm UPS (optional) — enables native X1202/X1206 battery and external-power telemetry, Pi power settings, and desktop battery support
- Auto-start on boot — optional systemd service
- Desktop shortcut — optional
- FlightWeb cloud sync — optional uploader and device linking
Every step can be skipped and the script is safe to re-run any time — it picks up where you left off.
./scripts/start-kiosk.sh # Default: rolling buffer + sound trigger
./scripts/start-kiosk.sh --mock # Mock mode (no hardware)Then open http://localhost:8080 or use the touchscreen.
For the current IWR6843 angle radar, use the measured startup command in the
IWR6843 Operator Guide. Existing K-LD7
builds use --kld7 --kld7-mount-tilt <measured-degrees>; see
Legacy K-LD7 Setup.
To send shots to GSPro, OpenGolfSim, or another supported sim, copy the example config and enable your simulator:
cp config/sim.example.json config/sim.json # then edit host/port + "enabled": trueSee Simulator Connectors for the full guide.
You don't need this section unless something went wrong or you prefer to do things by hand.
The OPS243-A needs a one-time configuration to enable rolling buffer mode with hardware sound triggering, saved to flash so it boots correctly every time.
Why? The OPS243-A has a firmware bug where the HOST_INT pin mode switches unexpectedly when entering rolling buffer mode at runtime. Saving to flash and power cycling bypasses this. Confirmed by OmniPreSense engineering.
Manual steps
# 1. Configure and save to flash
uv run python scripts/hardware-test/test_rolling_buffer_persist.py --setup
# 2. Power cycle the radar, wait 3 seconds, reconnect (see note below)
# 3. Verify — make a sound near the SEN-14262, you should see I/Q trigger data
uv run python scripts/hardware-test/test_rolling_buffer_persist.py --testHow you power cycle depends on how the OPS243 is connected:
| Connection | Power cycle by |
|---|---|
| USB | Unplugging the USB cable |
| Pi GPIO UART | Disconnecting 5V from OPS J3 pin 9 — not by rebooting the Pi, which does not necessarily drop the header rail |
If the OPS243 is on the GPIO UART, add --port /dev/ttyAMA0 to both commands
above.
The setup script does not configure the IWR6843 — it needs custom firmware flashed over the ROM bootloader, which requires physically moving a switch on the board. That is covered end to end in the IWR6843 Operator Guide.
Do it in this order, and confirm each step works before starting the next:
- Move the OPS243 to the Pi GPIO UART — migration guide. The Pi cannot power both radars over USB, so the OPS243 has to vacate the USB port. Validate the OPS on its own after rewiring, before the TI board is involved at all.
- Flash the IWR6843 — operator guide, Flash The IWR6843 Firmware. A
validated prebuilt image is in
firmware/releases/, so the TI toolchain is not required. You only need the firmware developer guide to build from source. - Mount, aim, and measure geometry — operator guide. The geometry values are passed on the command line and a wrong one silently biases the launch angle instead of erroring, so measure rather than estimate.
Re-flashing is only needed if the image in firmware/releases/ changes. A
software update alone does not require it — compare the release filename against
what you flashed.
Warning
A WiFi-equipped OPS243-A cannot use the GPIO UART. Its WiFi module already drives the radar processor's UART receive line, so the Pi cannot send it commands, and OpenFlight must be able to reconfigure and rearm the OPS after every capture. Use a separately powered USB hub for both radars instead (operator guide, Option B).
The optional UPS setup is automated and safe to rerun:
sudo ./scripts/battery/geekworm/setup.sh
sudo reboot
./scripts/battery/geekworm/setup.sh --verifyIt enables I2C, native Linux battery and charger devices, the Pi 5 EEPROM power settings required by Geekworm, and the Raspberry Pi taskbar compatibility package. It does not install automatic shutdown or charging-control services.
Cell type, board-revision power limits, physical installation, every system change, and troubleshooting are documented in the Geekworm X1202/X1206 Operator Guide.
Existing K-LD7 builds need stable /dev/kld7_vertical and
/dev/kld7_horizontal names because USB adapter numbers can swap after a
reboot. Run the device wizard, then follow the legacy guide:
./scripts/setup/setup_kld7_devices.sh
./scripts/setup/setup_kld7_devices.sh --showThe wizard also installs the required FTDI low-latency rule. See Legacy K-LD7 Setup for mounting and startup, and K-LD7 Troubleshooting for serial failures.
OpenFlight can display component progress immediately after a desktop launch without opening a terminal window. Install or refresh the user-local wrapper and desktop entry with:
cd ~/openflight
scripts/setup/install_desktop_launcher.shThe installer uses checkout-specific launcher and desktop filenames, preserving multiple OpenFlight installations on the same Pi. Machine-specific device paths and calibration remain outside Git. See the Startup Splash Screen guide for configuration, screenshots, error recovery, updating existing launchers, and rollback.
The setup script installs and enables a systemd service configured for your username and install path.
Manual steps and service management
# Install (adjust User= and paths in the file if your username isn't the default)
sudo cp ~/openflight/scripts/setup/openflight.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable openflight
sudo systemctl start openflightManagement:
sudo systemctl status openflight --no-pager # Check status
journalctl -u openflight -f # View logs
sudo systemctl stop openflight # Stop
sudo systemctl restart openflight # Restart
sudo systemctl disable openflight # Disable auto-startTo modify the service:
sudo nano /etc/systemd/system/openflight.service
sudo systemctl daemon-reload
sudo systemctl restart openflight./scripts/start-kiosk.sh # Default: rolling buffer + sound trigger
./scripts/start-kiosk.sh --mock # Mock mode (no hardware needed)Use the IWR6843 Operator Guide or Legacy K-LD7 Setup for angle-radar startup commands.
openflight-server # With radar
openflight-server --mock # No hardwareThen open http://localhost:8080.
DISPLAY=:0 ./scripts/start-kiosk.shOpenFlight can ship session logs to Grafana Cloud for long-term analysis.
sudo ./scripts/setup/setup_alloy.sh
sudo vim /etc/alloy/credentials.envSee observability.md for full setup and LogQL queries.
uv run python scripts/hardware-test/diagnose.py
# OPS243 connected through the Pi GPIO UART
uv run python scripts/hardware-test/diagnose.py --ops-port /dev/ttyAMA0See the Sound Trigger Wiring Guide — Troubleshooting.
# Check the device mapping
./scripts/setup/setup_kld7_devices.sh --show
# Test standalone
uv run python scripts/hardware-test/test_kld7.pyIf the mapping is missing or points at the wrong radar, re-run the wizard:
./scripts/setup/setup_kld7_devices.sh. Look for [KLD7] Connected on /dev/ttyUSB... in the server logs. See K-LD7 Troubleshooting
for "Wrong length reply" and other connection issues.
journalctl -u openflight --no-pager -n 50
# If service is masked
sudo systemctl unmask openflight
sudo cp ~/openflight/scripts/setup/openflight.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable openflightCheck for WebSocket instability:
journalctl -u openflight -fLook for "Client disconnected/connected" messages.
Use DISPLAY=:0 before commands that need the Pi's display.
./scripts/setup/setup.sh --deps-only # Dependencies only
./scripts/start-kiosk.sh --port 3000 # Custom web port
uv run python scripts/hardware-test/test_rolling_buffer_persist.py --test
uv run python scripts/hardware-test/test_sound_trigger_hardware.py
uv run pytest tests/ -v