This guide contains Amazon affiliate links. If you buy through them, DroneCoreGuide earns a small commission at no extra cost to you.
MAVLink is the language ArduPilot and PX4 speak. Once your Raspberry Pi can talk MAVLink to your flight controller, it can read telemetry, change modes and send movement commands: the foundation of every autonomous project.
Do this with props removed until the final step.
What you need
- A flight controller running ArduPilot (this guide) or PX4
- A Raspberry Pi 4 or 5 with Raspberry Pi OS
- Three jumper wires
- A separate 5 V regulator to power the Pi (shop regulators)
Step 1: Wire the serial connection
Connect a TELEM port on the flight controller to the Pi’s UART pins:
| Flight controller (TELEM2) | Raspberry Pi |
|---|---|
| TX | GPIO15 (RXD, pin 10) |
| RX | GPIO14 (TXD, pin 8) |
| GND | GND (pin 6) |
Don’t connect the FC’s 5 V to the Pi. Power the Pi from its own regulator and share only ground.
Step 2: Enable the Pi’s serial port
- Run
sudo raspi-config. - Under Interface Options, Serial Port: disable the login shell over serial, enable the serial hardware.
- Reboot. The port is usually
/dev/serial0.
Step 3: Configure ArduPilot
In Mission Planner or QGroundControl, set parameters for TELEM2 (SERIAL2 in ArduPilot):
SERIAL2_PROTOCOL = 2(MAVLink 2)SERIAL2_BAUD = 921(921600 baud)
Reboot the flight controller.
Step 4: Install a MAVLink library
python3 -m venv ~/drone && source ~/drone/bin/activate
pip install pymavlink
Step 5: Read telemetry
Save this as telemetry.py:
from pymavlink import mavutil
link = mavutil.mavlink_connection('/dev/serial0', baud=921600)
link.wait_heartbeat()
print("Connected to system", link.target_system)
while True:
msg = link.recv_match(type=['ATTITUDE', 'GLOBAL_POSITION_INT', 'SYS_STATUS'], blocking=True)
print(msg.get_type(), msg.to_dict())
Run it. You should see attitude, position and battery messages streaming. If nothing arrives, double-check TX/RX crossing, baud rate and the serial port settings.
Step 6: Change modes and send commands
With the connection working, you can switch modes, arm and send position or velocity targets in GUIDED mode. A simple example to change mode:
link.set_mode(link.mode_mapping()['GUIDED'])
For full missions and velocity control, many builders prefer MAVSDK (a higher-level API) or ROS 2 with MAVROS for bigger robotics projects.
Step 7: Test in simulation before real flight
Run the same script against ArduPilot SITL by changing the connection string to the simulator’s UDP address. Confirm every command does what you expect. See SITL and Gazebo.
Understanding MAVLink messages
A few messages you’ll use constantly:
| Message | Contains |
|---|---|
| HEARTBEAT | System type, mode and armed state |
| ATTITUDE | Roll, pitch and yaw angles and rates |
| GLOBAL_POSITION_INT | Latitude, longitude, altitude, velocity |
| SYS_STATUS | Battery voltage and system health |
| GPS_RAW_INT | GPS fix type and satellite count |
| STATUSTEXT | Text messages from the autopilot |
| SET_POSITION_TARGET_LOCAL_NED | Position or velocity commands in guided mode |
Requesting data at the right rate
Autopilots send some messages at default rates. You can request specific messages at higher rates using a SET_MESSAGE_INTERVAL command or by setting the stream rate parameters on the serial port. Don’t request everything at maximum rate: it wastes bandwidth and CPU on both sides.
Running your script automatically
Use a systemd service so your script starts at boot:
- Create a service file that runs your script inside its virtual environment.
- Enable it with
systemctl enable. - Check logs with
journalctlwhen debugging.
Debugging connection problems
- No heartbeat: check TX/RX crossing, ground, baud rate,
SERIAL2_PROTOCOLand that the Pi’s serial login shell is disabled. - Garbled data: baud rate mismatch.
- Works on the bench, fails in flight: check power to the Pi; voltage dips reboot it.
- Commands ignored: the drone must be in GUIDED mode, and often armed, for movement commands to take effect.
Safety rules for companion-computer control
- Keep a mode switch on your radio that overrides GUIDED mode, such as Loiter or Stabilize.
- Set failsafes in ArduPilot for radio loss and companion-computer loss.
- Limit speed and enable a geofence.
- First real tests: low altitude, open field, props on only when you’re ready.
Next: add object tracking.
Frequently Asked Questions
What is MAVLink?
A lightweight messaging protocol used by ArduPilot, PX4 and ground stations to exchange telemetry and commands.
Which port should I connect my Raspberry Pi to?
A TELEM port on the flight controller, such as TELEM2, configured for MAVLink 2 at 921600 baud.
Can I power the Raspberry Pi from the flight controller?
It’s not recommended. The Pi can draw more current than the FC’s regulator safely supplies. Use a separate 5 V regulator and share ground.
Should I use pymavlink or MAVSDK?
pymavlink is low-level and great for learning. MAVSDK offers a higher-level API that’s easier for missions and offboard control.