Software
Two-Brain UAV: The Pixhawk 6C and Raspberry Pi 5 Software Architecture
We didn't try to cram it onto one board. Two separate processors, a MAVLink bridge between them, and two weeks of SITL testing before we ever took it to the field. Here's how the architecture came together.
At first we wanted to try fitting everything onto a single board. We reviewed the Raspberry Pi 4 + Navio2 combination. Two weeks later we gave up on it. The reason: the PID loop needs a deterministic response time, image processing doesn't have one. Race the two workloads against each other and both suffer. We ended up moving to two separate pieces of hardware.
Division of labor
- Pixhawk 6C: reading sensor data, sending PWM to the motors, staying stable in the air. That's it.
- Raspberry Pi 5 (8 GB): image processing + decision-making.
- Bridge between the two boards: the MAVLink protocol over FTDI USB-TTL.
We deliberately keep the Pixhawk 'dumb'. Decisions live on the Pi, only commands live on the Pixhawk. That split makes it much easier to isolate which side crashed. Once during an autonomous test the UAV just kept circling in the air; three minutes later we figured out that the OpenCV script on the Pi had thrown an exception, but the Pixhawk was faithfully holding the last 'turn right' command it had received. We treat this as expected behavior in the architecture, not a bug. Once we added a watchdog on the Pi side, the problem never came back.
ArduPilot, PID, and a carbon-fiber detail
We chose ArduPilot as our flight stack for its open-source structure. We also evaluated PX4; ArduPilot has more documentation and there's support in the Turkish community too. The carbon-fiber airframe's dynamics are different from a plastic one; we had to spend two days tuning the P, I, D values in Stabilize mode. We turned on AutoTune, but the values it suggested were too aggressive for us, so we brought them down manually.
The Pi side: DroneKit and PyMAVLink
The Python code running on the Pi 5 converts the target coordinates OpenCV finds into an error vector. That vector becomes a velocity_target command in Guided mode via DroneKit. PyMAVLink is lower-level; for some commands it gives us more control. We use both together. With 8 GB of RAM and an active cooler, the whole loop completes in around 200 ms.
SITL: two weeks before the field
UAV hardware is expensive; we wanted to bring crash risk down to zero. We ran every autonomous mission and target-detection algorithm under SITL (Software In The Loop) first. SITL simulates the real Pixhawk firmware on a virtual vehicle. In our first SITL run the 'land' command touched down 4 meters off target. The cause: the y-axis hadn't been flipped in the coordinate transform. If we'd found that in the field, we'd probably have ended up replacing propellers.
- MAVLink channel
- TELEM2
- Telemetry
- 915 MHz
- Radio control
- 2.4 GHz
- Motor response time
- 0.0059 s
Ground station
We use Mission Planner in the field, both for live position and battery tracking and for quickly revising PID parameters. Every flight gets logged on a laptop; back home we go through the log files and check whether there's any gap between the decision that came from the Pi and the Pixhawk's actual response. Because we use a Holybro 3DR 100 mW 915 MHz telemetry radio, we haven't run into interference with the 2.4 GHz radio control.
Send us your questions or collaboration ideas about this post.
Get in Touch →