Skip to content
Judah Paul edited this page Jul 20, 2026 · 8 revisions

The reference build runs Canary Ground Control on a Raspberry Pi 4B mounted on a Holybro S500 V2 quadcopter, with the Pi wired to the flight controller over USB and online through a 4G modem on a public-IP SIM.

CanaryGC on the Holybro S500 V2

Components

Part Model Role
Companion computer Raspberry Pi 4B Runs the app and holds the link to the flight controller.
Airframe kit Holybro S500 V2 Development Kit 500mm quad: Pixhawk 6C flight controller, PM02 V3 power module, M10 GPS, SiK Telemetry Radio V3, 2216 920KV motors, BLHeli S 20A ESCs, 1045 props, ~915g.
Battery 4S 3000-5000mAh LiPo (XT60) Powers the airframe and, through the PM02, the Pi.
Camera Arducam OV5647 5MP 1080P day/night CSI camera on the Pi with automatic IR-cut for day and low-light video.
Modem Raspberry Pi 4G/LTE cellular modem kit Puts the Pi on the cellular network.
SIM Simbase public-IP SIM Gives the Pi a publicly reachable address.
FC link USB-A to USB-C cable Connects the Pi to the Pixhawk 6C USB-C port.

How it connects

The Pixhawk 6C plugs into the Pi over the USB-A to USB-C cable and enumerates as /dev/ttyACM0, a USB serial device carrying MAVLink. The production compose service maps that device into the app container, so the station talks to the autopilot with no extra radio. This Pixhawk runs on either PX4 or ArduPilot firmware, and the station flies the build on both.

The link also runs over the Pi's UART instead of USB. Wire TELEM2 to the Pi header with three pins, Pi TXD (GPIO14) to TELEM2 RX, Pi RXD (GPIO15) to TELEM2 TX, and ground to ground, with both sides on 3.3V logic. The JST-GH plug locks under vibration and the device path stays /dev/ttyAMA0 across FC reboots. The station scans the serial ports for MAVLink traffic and finds the UART on its own, and MAVLINK_SERIAL_PATH=/dev/ttyAMA0 with MAVLINK_BAUD=921600 in .env pins it. On ArduPilot set SERIAL2_PROTOCOL=2, SERIAL2_BAUD=921, and BRD_SER2_RTSCTS=0 for the two-wire hookup. On PX4 set MAV_1_CONFIG=TELEM2, MAV_1_MODE=Onboard, and SER_TEL2_BAUD=921600. Flashing from the Firmware tab stays on the USB port through FC_BOOTLOADER_PATH.

The Arducam sits on the Pi's CSI port and feeds the WebRTC live feed through MediaMTX. See Configuration for the camera-source options.

Betaflight stack

My Betaflight rig is an HGLRC XJB F428 flight controller talking to a Pi 4B, though I want to experiment with a CM5. Betaflight boards speak the MultiWii Serial Protocol (MSP) rather than MAVLink, so the app reaches them over MSP_SERIAL_PATH. See Firmware for board autodetect and flashing, and Configuration for the MSP link.

Reaching the drone over cellular

Most cellular carriers place a subscriber behind carrier-grade NAT (CG-NAT): the SIM shares one public address with many others and the carrier drops inbound connections, so a browser cannot open a session to the Pi. A public-IP SIM, such as the one from Simbase, assigns the Pi its own reachable address. With it, the station is a plain web page the operator opens from any browser over the cellular link, with no VPN or relay in between.

A public-IP data SIM handles that, and an eSIM data profile does the same thing without a physical SIM swap on a sealed airframe, as long as the plan hands the Pi a routable address. Any static-IP or public-IP data plan works, whatever provider covers the flight area.

Modems and companion boards

The reference build runs a Raspberry Pi 4B with a USB 4G modem, but the station just needs a Linux companion that talks to the flight controller over serial and reaches the network. A Waveshare SIM7600 or SIM8200 cellular HAT does the job on a Pi, and the same HAT drops onto a Compute Module 4 or Compute Module 5 carrier for a tighter build. Commercial kits like XBStation pair a companion and a 4G modem the same way, but they ship as a sealed appliance locked to their own firmware, so canarygc does not run on one. I have only tested SITL and the reference build running PX4 and ArduCopter, so treat the other modems and SIM options as a good bet but unproven.

Clone this wiki locally