The Drone Integration Handbook

Free. Open. No login required.

A practical reference for anyone integrating, operating, or troubleshooting multi-platform drone systems. Not a product manual. Not a sales pitch. A handbook you keep open on your bench. Covers RF communications, flight controller firmware, field diagnostics, fleet operations, and the real-world problems that don't show up in manufacturer documentation.

CC BY-SA 4.0 · v1.0 · Source on GitHub

Part 1 — RF Fundamentals

1The Five Link Types 2Frequency Bands & Regulatory Reality 3Antennas for People Who Aren't RF Engineers 4Link Budgets Without the Math

Part 2 — Flight Controller Firmware

5The Four Firmwares 6MSP Protocol 7MAVLink Protocol 8UART Layout and Why It Matters

Part 3 — Field Operations

9Pre-Flight Checklist That Actually Works 10Blackbox Logs 11PID Tuning for People Who Fly 12When Things Go Wrong

Part 4 — Integration

13Adding a Companion Computer 14Mesh Radios for Multi-Vehicle 15TAK Integration

Chapter 1: The Five Link Types

Every drone in the air right now is using between one and five simultaneous radio links. Most operators can name two. This chapter covers all five.


The Problem Nobody Talks About

A racing quad has two links — RC control and video. Simple. But the moment you add GPS return-to-home, you've added a third (telemetry). Add a companion computer with a mesh radio and you're at four. Add a payload camera with its own downlink and you're at five.

Each link has its own frequency, its own protocol, its own antenna, its own failure mode, and its own opinion about which direction the drone should go. When they disagree, things get interesting.

Understanding the five link types is the foundation of everything else in this handbook. If you don't know what's talking on your drone, you can't diagnose why it stopped talking.


What it does: Carries stick commands from the pilot to the flight controller. The link that keeps a human in the loop.

Protocols: ELRS (ExpressLRS), CRSF (TBS Crossfire), GHST (IRC Ghost), SBUS (FrSky), IBUS (FlySky), PPM (legacy).

Frequencies: - 2.4 GHz — most common (ELRS 2.4, CRSF, Ghost, FrSky ACCST) - 900/868 MHz — long range (ELRS 900, Crossfire, FrSky R9) - Sub-GHz proprietary — tactical (IRONghost dual-band)

What you need to know: - This is the only link where latency matters in milliseconds. ELRS at 500 Hz has ~2 ms latency. SBUS is ~6 ms. At 250 Hz freestyle, you won't feel the difference. In a racing final, you might. - Loss of this link triggers failsafe. Every FC firmware handles failsafe differently. Know yours before you need it. - ELRS and Crossfire use serial protocols (CRSF wire format) that carry bidirectional telemetry inside the RC link. This blurs the line between Link 1 and Link 2 — your RC receiver is also a telemetry radio. This is efficient but means RC loss also kills your telemetry.

Common problems: - RC and video on the same frequency band (both 2.4 GHz) causing desense. Solution: different bands, or physical antenna separation. - Wrong UART baud rate in FC configurator — CRSF wants 420000, not 115200. - ELRS binding phrase mismatch after firmware update.


What it does: Bidirectional data link between the drone and a ground station. Carries flight data down (position, battery, attitude) and commands up (waypoints, parameter changes, mode switches).

Protocols: MAVLink v2 (ArduPilot, PX4), MSP (Betaflight, iNav), LTM (Lightweight Telemetry), FrSky S.Port/F.Port.

Transport options: - Embedded in RC link — CRSF/ELRS carry MAVLink or custom telemetry inside the control channel. No separate radio needed. - Dedicated telemetry radio — SiK (3DR), RFD900x, MicroHard P900. Separate frequency, separate antenna, separate failure mode. - WiFi — ESP32 bridge, companion computer WiFi, mesh radio backhaul. - Cellular — LTE modems for beyond-visual-line-of-sight (BVLOS).

What you need to know: - MAVLink is the lingua franca for autonomous platforms. If you're running ArduPilot or PX4, everything speaks MAVLink. If you're running Betaflight, everything speaks MSP. If you're running a mixed fleet, you need both. - Telemetry bandwidth matters more than telemetry latency. You don't need millisecond position updates on the ground — 1-10 Hz is fine. But you do need all the data fields to arrive intact. - Dedicated telemetry radios (RFD900x, SiK) are point-to-point. They don't scale to multiple drones without a mesh layer on top.

Common problems: - MAVLink stream rate misconfigured — too high floods the link, too low makes the GCS look frozen. Start with SR0_POSITION=2, SR0_EXTRA1=4, adjust from there. - SiK radio firmware mismatch between air and ground units. - UART conflict — telemetry and GPS both assigned to the same UART.


What it does: Sends camera feed from the drone to the pilot's goggles or ground station monitor. The link that lets you see.

Technologies: - Analog 5.8 GHz — lowest latency (~1 ms glass-to-glass), degrades gracefully (static, then snow, then nothing). Still dominant in FPV racing and tactical ops where latency kills. - DJI digital — DJI O3, O4, Vista, Air Unit. Low latency (~20-28 ms), good image quality, locked ecosystem. No third-party interop. - HDZero — digital, ultra-low latency (~15 ms), open ecosystem, lower resolution than DJI. Popular with racers going digital. - OpenHD / WFB-ng / OpenIPC — open-source digital video over commodity WiFi hardware (RTL8812AU/EU). Higher latency (~80-120 ms), fully open, hackable, configurable. The platform for custom builds. - Walksnail (Avatar) — Caddx/Walksnail digital system. Competes with DJI on image quality, runs on Artosyn AR8030 chip.

What you need to know: - Video is almost always 5.8 GHz. This means it's on the same band as 5 GHz WiFi, some mesh radios, and the 5.8 GHz ISM band that everyone assumes is uncontested. In practice, 5.8 GHz is crowded. - Analog video uses 40 channels across 5.8 GHz. At a race event with 8 pilots, frequency management is a real operational problem. At a tactical deployment with multiple teams, it's a coordination requirement. - Digital video links (DJI, HDZero) are frequency-hopping or wideband. They're harder to interfere with but also harder to coordinate. You can't just "pick a channel" the way you can with analog. - The RTL8812AU chip that OpenHD/WFB-ng depends on has been discontinued by Realtek. The RTL8812EU replacement does NOT support monitor mode in the same way. This is slowly killing the open-source digital FPV ecosystem. OpenIPC is moving to other solutions.

Common problems: - 5.8 GHz video transmitter (VTX) too close to 2.4 GHz RC antenna causes receiver desense. Minimum 10 cm separation, more is better. - VTX power set too high for proximity flying — at 800 mW you're heating the VTX and potentially interfering with your own RC. 25-200 mW is enough for most LOS operations. - Wrong VTX table in Betaflight — mismatched power levels, missing channels, or wrong band assignments.


What it does: Carries data from a mission payload — mapping camera, multispectral sensor, LiDAR, SAR, SIGINT receiver, delivery mechanism confirmation. Distinct from the FPV video feed (Link 3).

Technologies: - Ethernet (wired, on companion computer) - USB (camera to companion) - WiFi (payload-specific AP) - Dedicated RF downlink (separate frequency, separate antenna) - Store-and-forward (record on board, download after landing)

What you need to know: - Most consumer and racing drones don't have Link 4. It shows up on commercial mapping drones, agricultural platforms, and defense ISR platforms. - Payload data is usually high bandwidth and tolerant of latency. A mapping camera generates gigabytes per flight — you're not streaming that in real time. You're storing it and downloading after landing. - When payload data IS streamed (tactical video from a gimbal camera, SAR data, EW sensor output), it competes for bandwidth with telemetry and video. This is where mesh radios with QoS become important — prioritize C2 over payload, always. - The companion computer is the integration point. Payload connects to companion via USB/Ethernet/GPIO. Companion decides what goes down the RF link and what gets stored.

Common problems: - Payload drawing too much power from the FC's 5V/12V rail. Payload should have its own BEC or regulated supply. - USB bandwidth contention between payload camera and companion computer's other USB devices. - Payload data timestamps not synchronized with flight controller timestamps. Use GPS time or NTP on the companion for correlation.


What it does: Drone-to-drone communication for fleet operations. Position sharing, intent coordination, task allocation, sensor data relay. The link that turns individuals into a team.

Technologies: - ESP-NOW — Espressif peer-to-peer, 2.4 GHz, ~250 byte packets, no infrastructure needed. Good for ground operations (Tooth mesh, pre-flight sync). Not suitable for in-flight swarm at range. - WiFi mesh (batman-adv / 802.11s) — Linux-based mesh networking. Doodle Labs, Silvus, and Persistent Systems all use this under the hood (yes, your $5,000 Silvus StreamCaster is running OpenWRT with batman-adv). Range 1-50 km depending on radio and power. - MANET (Mobile Ad-hoc Network) — military-grade mesh with frequency hopping, anti-jam, encryption. Persistent Systems MPU5, Silvus at higher tiers, Harris/L3Harris. $10,000-50,000 per node. - MAVLink over mesh — any of the above carrying MAVLink messages between platforms. Each drone gets a unique system ID (1-254). Standard MAVLink messages (GLOBAL_POSITION_INT, HEARTBEAT) become the swarm awareness layer.

What you need to know: - Most drones don't have Link 5. It's the last link to be added and the first to be cut when budget or weight is tight. - Mesh radios that claim "50 km range" are telling you the radio range, not the mesh range. Mesh adds overhead. Real throughput across 3 hops is typically 30-50% of single-hop throughput. - The dirty secret of tactical mesh: Doodle Labs is OpenWRT on Atheros/Qualcomm WiFi silicon running batman-adv. Silvus is similar with their own MAC layer. Persistent Systems MPU5 is the most custom but still builds on standard radio architectures. They're not magic. They're well-engineered WiFi radios in ruggedized enclosures with good antenna design and custom firmware. - Mesh network planning is its own discipline. Node placement, antenna orientation, channel assignment, traffic prioritization — these matter more than the radio's datasheet specs.

Common problems: - Mesh radio on 2.4 GHz interfering with 2.4 GHz RC link. Solution: different bands (mesh on 900 MHz or 5 GHz). - batman-adv OGM (Originator Message) interval too high, causing stale routing. Default 1 second is fine for slow-moving platforms. Fast-moving drones may need 250 ms. - IP address conflicts in the mesh. Use a consistent addressing scheme: 10.0.0.{system_id} with system_id matching MAVLink ID.


How They Interact

The five links are not independent. They share spectrum, share power, share the FC's limited UARTs, and share the operator's limited attention.

Frequency Deconfliction

Link Common Frequency Conflict With
RC (Link 1) 2.4 GHz WiFi mesh, BLE, companion WiFi
RC (Link 1) 900 MHz Telemetry radio, mesh radio
Telemetry (Link 2) 900 MHz Long-range RC, mesh radio
Video (Link 3) 5.8 GHz 5 GHz WiFi, mesh radio, payload WiFi
Payload (Link 4) varies depends on payload type
Mesh (Link 5) 2.4/5/900 MHz everything else

The rule: no two links on the same band within the same airframe unless they're designed to coexist. ELRS 2.4 GHz and an ESP32 WiFi AP on the same drone will fight. ELRS 900 MHz and an RFD900x telemetry radio will fight. Plan your frequency layout before you build.

UART Allocation

A typical F405 flight controller has 3-6 UARTs. They get consumed fast:

UART Typical Assignment
UART1 RC receiver (CRSF/ELRS/SBUS)
UART2 GPS
UART3 Telemetry radio or MSP bridge
UART4 ESC telemetry (if DShot + telemetry)
UART5 Companion computer (MAVLink or MSP)
UART6 (you're out of UARTs)

Running out of UARTs is one of the most common integration problems on F4-class FCs. Solutions: use soft serial (limited baud rate), upgrade to an H7 FC (more UARTs), or use a companion computer to multiplex multiple data streams over a single UART.

Power Budget

Every link has a radio that draws power. Every radio has an amplifier that draws more power. On a 5-inch FPV quad with a 1300 mAh 6S battery, your total electronics budget (FC + ESCs + radio + VTX + GPS + receiver) is typically 2-5W continuous. Adding a mesh radio at 1-2W is significant. Adding a companion computer at 3-10W changes your flight time.

Know your power budget before you add links.


The Operator's Decision

Not every drone needs all five links. Most don't. The right number of links depends on the mission:

Mission Links Needed
FPV racing 2 (RC + video)
Freestyle / cinematic 2-3 (RC + video + optional telemetry)
Mapping / survey 3-4 (RC + telemetry + video + payload)
Tactical ISR 4-5 (all five)
Swarm operations 5 (all five, mesh is mandatory)
Autonomous delivery 3 (telemetry + video + optional mesh)

More links = more complexity = more things to break = more things to diagnose. Add links because the mission requires them, not because the hardware supports them.


Next


Every link you add is a complication. Know what it costs before you add it.

Chapter 2: Frequency Bands and Regulatory Reality

The regulations tell you what you're allowed to do. The physics tell you what will actually work. They don't always agree.


The Bands That Matter

Drone operations live in a handful of frequency bands. Here's where everything sits and why.

900 MHz (902–928 MHz in the US, 868 MHz in EU)

What lives here: Long-range RC links (ELRS 900, TBS Crossfire), telemetry radios (RFD900x, SiK, MicroHard P900), some mesh radios, LoRa, and a surprising amount of industrial IoT.

Why it matters: Sub-GHz propagation is king. 900 MHz bends around obstacles, penetrates foliage, and reaches farther per milliwatt than any other band you'll use. A 100 mW ELRS 900 link will outrange a 1 W 2.4 GHz link in most real-world environments.

Regulatory: - US: ISM 902–928 MHz, up to 1 W conducted + antenna gain (FCC Part 15.247) - EU: 868 MHz band, 25 mW ERP with duty cycle limits (ETSI EN 300 220) - The EU/US split is the single biggest cross-border problem in drone operations. 900 MHz hardware built for the US market doesn't work in Europe, and vice versa. ELRS handles this with region-specific firmware builds. Many other systems don't.

What the regulations don't tell you: The 900 MHz ISM band is shared with utility meters (smart grid AMI), industrial SCADA, agricultural sensors, and LoRaWAN gateways. In urban environments, the noise floor at 900 MHz can be 20+ dB higher than rural. Your range will be shorter in the city.


2.4 GHz (2400–2483.5 MHz)

What lives here: Most RC links (ELRS 2.4, Ghost, ACCST, IBUS), WiFi (802.11b/g/n/ax), Bluetooth, ZigBee, microwave ovens, baby monitors, wireless cameras, mesh radios, and roughly half of all wireless devices ever manufactured.

Why it matters: 2.4 GHz is the default for everything. It's globally harmonized (same band everywhere), license-free, and supported by every chip on the market. If you don't know what frequency to use, you use 2.4 GHz. So does everyone else.

Regulatory: - Global ISM band, generally 100 mW–1 W EIRP depending on jurisdiction - FCC: up to 1 W conducted, 4 W EIRP with directional antennas (Part 15.247) - EU: 100 mW EIRP (ETSI EN 300 328) - Japan: 10 mW/MHz (effectively limits wideband signals)

What the regulations don't tell you: 2.4 GHz is a war zone. At any given moment at a race event, fly-in, or urban deployment site, you're sharing spectrum with: - Every phone's WiFi and Bluetooth - Every laptop's WiFi - Every smart home device - Other pilots' RC links - Nearby mesh radios - The microwave in the food truck

The saving grace is that modern protocols (ELRS, Ghost, CRSF) use frequency hopping, which spreads the signal across the entire band and makes them resilient to narrowband interference. But when the entire band is congested, even FHSS degrades.

The 2.4 GHz deconfliction problem: If your RC link is 2.4 GHz AND your mesh radio is 2.4 GHz AND your companion computer's WiFi is 2.4 GHz, you have three transmitters on the same band in the same airframe. Even with different channels and different protocols, the front-end receivers will desense each other. The fix is simple: put at least one of them on a different band.


5.8 GHz (5725–5875 MHz)

What lives here: Analog FPV video, digital FPV video (DJI, HDZero, Walksnail), 5 GHz WiFi (802.11a/n/ac/ax), some mesh radios, radar, and weather services.

Why it matters: 5.8 GHz is the FPV video band. Virtually every drone with a camera transmits video on 5.8 GHz. The band has enough bandwidth for analog and digital video, and the higher frequency means smaller antennas.

Regulatory: - ISM 5.725–5.875 GHz in most jurisdictions - FCC: 1 W conducted (Part 15.247) - EU: 25 mW EIRP (yes, really — ETSI EN 300 440). Most VTX modules shipped into the EU are technically non-compliant at any setting above 25 mW. - The broader 5 GHz UNII bands (5.15–5.35, 5.47–5.725 GHz) are used by WiFi but have DFS (Dynamic Frequency Selection) requirements due to radar coexistence. DFS can force your radio to change channels mid-flight. Not ideal.

What the regulations don't tell you: - 5.8 GHz has significantly higher path loss than 2.4 GHz. In free space, 5.8 GHz loses ~7.7 dB more than 2.4 GHz at the same distance. In practice this means roughly half the range per milliwatt. You compensate with power and antenna gain. - 5.8 GHz does not penetrate foliage, buildings, or terrain well. If you fly behind a tree, your video will break before your RC link does (assuming RC is on 2.4 GHz or 900 MHz). - At FPV race events, analog 5.8 GHz channel management is critical. 40 channels sounds like a lot until 8 pilots are in the air and their harmonics are stepping on each other. Digital systems (DJI, HDZero) are wideband and harder to deconflict — they don't fit neatly into the 40-channel system.


Sub-GHz Below 900 (433, 315, 169 MHz)

What lives here: LoRa long-range, some RC systems (FrSky R9 at 433 MHz in some regions), key fobs, garage door openers, tire pressure monitors, and very long-range telemetry.

Why it matters: Lower frequency = better propagation = longer range. 433 MHz LoRa links can reach 10+ km with tiny antennas and milliwatts of power. But bandwidth is measured in kilobits, not megabits.

Regulatory: - 433 MHz ISM: 10 mW in EU, not ISM in the US (amateur band, requires ham license for non-ISM use) - 315 MHz: US ISM for low-power devices - 169 MHz: EU smart meter band, very restricted

When you'd use it: Very long-range telemetry (LoRa), sub-floor FHSS detection (listening, not transmitting), or interoperability with existing infrastructure on these bands.


Military and Licensed Bands

L-band (1–2 GHz): Some tactical mesh radios (Doodle Labs HelixL+S). Military satellite. GPS (L1 at 1575.42 MHz, L2 at 1227.60 MHz). No ISM access — requires licensing or government authorization.

S-band (2–4 GHz): Overlaps 2.4 GHz ISM. Some military radar. Weather radar. Tactical links.

C-band (4–8 GHz): Doodle Labs C-Band radios, satellite downlinks, some military comms. Requires licensing in most jurisdictions.

You don't need to operate on these bands unless you're working with military or government platforms. But you do need to know they exist because: (a) military radar on S-band and C-band can overwhelm your receivers, and (b) GPS signals on L-band can be jammed or spoofed, affecting your drone's navigation.


The Gap Between Rules and Reality

What Operators Actually Do

The regulatory framework assumes static, ground-based transmitters in controlled environments. Drone operations are none of those things.

In practice: - FPV pilots routinely fly 600–800 mW VTX power despite EU limits of 25 mW - Long-range operators use 900 MHz at full power in countries where the band allocation is ambiguous - "1 W EIRP" limits are rarely enforced at hobby flying fields - Military operators have blanket spectrum authority in their operational areas and don't worry about ISM band rules

This handbook doesn't tell you to break the rules. It tells you the rules exist, what they are, and acknowledges that the enforcement reality differs from the regulatory text. Know your jurisdiction's rules. Make your own informed decisions.

Frequency Coordination at Events

At any gathering of more than 4-5 pilots:

  1. Assign video channels before anyone powers up. Analog 5.8 GHz has 40 channels across 6 bands (A, B, E, F, R, L). Use non-adjacent channels. Band F (Fatshark / IRC) and Band R (RaceBand) are the most common for events.

  2. Separate RC bands. If half the pilots are on 2.4 GHz ELRS and half are on 900 MHz Crossfire, that's actually ideal — no RC interference between the two groups.

  3. Power down when not flying. A VTX broadcasting 800 mW on the ground creates more interference than one in the air at 200m, because ground-level signals have direct paths to every other receiver in the pit area.

  4. Know your VTX table. Betaflight's VTX table maps power levels and channels for your specific VTX hardware. Verify it matches reality — misconfigured VTX tables can put you on the wrong channel or the wrong power level.

Frequency Coordination for Fleet Operations

At a commercial or tactical deployment with multiple drones:

  1. Map all five links for each platform. Build a frequency plan before the operation, not during it.

  2. Separate bands where possible. RC on 900, telemetry on 2.4, video on 5.8, mesh on a different 5 GHz channel. The more band separation, the less self-interference.

  3. Document what's transmitting. If you're operating near other teams, other companies, or military assets, knowing exactly what frequencies you're using — and at what power — prevents problems and demonstrates professionalism.

  4. Plan for interference. If your operation is near an airport, military base, or large venue (stadiums use a LOT of 2.4 and 5 GHz), your range predictions from a clean test site are optimistic. Budget a 50% range reduction in congested spectrum environments.


Quick Reference: Band Comparison

Band Range (per mW) Penetration Bandwidth Congestion Typical Use
433 MHz Excellent Best Very low Low LoRa telemetry
900 MHz Very good Good Low-medium Medium Long-range RC, telemetry
2.4 GHz Good Fair High Severe RC, WiFi, mesh, BLE
5.8 GHz Fair Poor Very high High FPV video, WiFi

The universal trade-off: lower frequency = longer range and better penetration but less bandwidth. Higher frequency = more bandwidth but shorter range and worse penetration. Everything in RF engineering is a version of this trade-off.


Next


The spectrum is a shared resource. Know what you're transmitting, where, and at what power. The drone next to you is sharing the same resource.

Chapter 3: Antennas for People Who Aren't RF Engineers

The antenna is the most important and least understood component on your drone. A $200 radio with a bad antenna loses to a $30 radio with a good one.


The One Rule

Match your antenna to your link.

That's it. Everything else in this chapter is explaining what that means and how to do it.


What an Antenna Does

An antenna converts electrical signal into radio waves (transmit) and radio waves back into electrical signal (receive). It doesn't amplify — it shapes. An antenna with "5 dBi gain" isn't creating energy. It's focusing the energy that's already there into a narrower pattern, the same way a flashlight focuses light from a bulb into a beam.

More gain = narrower beam = longer range in one direction, shorter range in every other direction.

This is the fundamental trade-off in antenna selection. There is no antenna that's better in all directions. There are only antennas that trade coverage pattern for range.


Antenna Types You'll Actually Use

Dipole / Whip

What it is: A straight stick. The stock antenna on most receivers, telemetry radios, and mesh radios.

Pattern: Donut-shaped. Good coverage in all horizontal directions, weak directly above and below the antenna axis.

Gain: 2–5 dBi

When to use it: Default choice for anything where you don't know which direction the other radio will be. RC receivers, telemetry, mesh nodes on drones that fly in all orientations.

Orientation matters: A vertical dipole radiates horizontally. A horizontal dipole radiates vertically. On a drone, the receiver antenna should point down or sideways — NOT parallel to the frame. Two antennas at 90 degrees to each other (antenna diversity) covers all orientations.


Patch Antenna

What it is: A flat rectangle. Common on GPS modules, some directional links, and video receivers.

Pattern: Directional — strong in front, weak behind. Like holding up a book and only hearing what's in front of it.

Gain: 6–14 dBi depending on size

When to use it: On the ground station pointing at the drone. GPS antennas (patch facing sky). Video receiver antennas in goggles (facing forward). NOT on the drone itself unless you know exactly where the ground station will be.

The goggle antenna mistake: Many pilots fly with stock goggle antennas (usually small omnis) and wonder why they get video breakup at 500m. Replacing one goggle antenna with a directional patch that points toward the flying area can double or triple video range with no change to the drone.


Helical Antenna

What it is: A coil of wire. Comes in two types: normal-mode (small, used as compact omni) and axial-mode (larger, highly directional, used for long range).

Pattern: Axial-mode helix is a focused beam — high gain, narrow coverage. Normal-mode is similar to a dipole.

Gain: 8–15+ dBi (axial mode)

When to use it: Ground-station tracking antenna for long-range operations. Paired with an antenna tracker that points it at the drone. Not practical on the drone itself (too large, too directional).


Pagoda / Lollipop / Stubby

What it is: Compact circular-polarized antenna. The standard FPV video antenna on both the drone and the goggles.

Pattern: Roughly omnidirectional with circular polarization.

Gain: 1–3 dBi

When to use it: 5.8 GHz FPV video. Both the VTX antenna on the drone and the receiver antenna on the goggles should be circular polarized and the same handedness (both RHCP or both LHCP). Mixing handedness costs you ~3 dB (half your signal).

Why circular polarization for video: When a linearly polarized signal bounces off a surface (multipath), its polarization can rotate. If your receive antenna is linear and the signal arrives at the wrong angle, you lose it. Circular polarization doesn't have this problem — it receives equally regardless of rotation. The trade-off is ~3 dB less gain than an equivalent linear antenna.


PCB / Ceramic Chip Antenna

What it is: A tiny antenna printed on the circuit board or bonded as a ceramic chip. Found inside ESP32 modules, Bluetooth devices, GPS modules, and small receivers.

Pattern: Roughly omnidirectional but with significant nulls depending on PCB ground plane and nearby components.

Gain: -2 to 2 dBi (often negative gain compared to an ideal isotropic radiator)

When to use it: When size and cost matter more than range. The ESP32-C6 on a Tooth uses its built-in PCB antenna for mesh communication at short range. For anything beyond 100m, use an external antenna via the U.FL/IPEX connector if available.


Polarization

Radio waves vibrate in a specific orientation. If the transmit antenna sends vertically polarized waves and the receive antenna is oriented horizontally, you lose ~20 dB of signal. That's the difference between a clear link and no link.

The rules: - Linear antennas (dipole, whip): orient both the same way. Both vertical, or both horizontal. On a drone that changes orientation constantly, this is hard — which is why diversity (two antennas at 90 degrees) helps. - Circular polarized antennas (pagoda, lollipop): match handedness. Both RHCP or both LHCP. Don't mix. - Cross-polarization loss: linear TX → circular RX (or vice versa) costs ~3 dB. Not ideal but survivable.


Connectors

The small connectors used in drone antennas are fragile. Know them.

Connector Size Common Use Durability
SMA Medium VTX, telemetry radio, ground station Good — threaded, secure
RP-SMA Medium Same as SMA, reversed polarity Good — check male/female
U.FL / IPEX Tiny On-board connections, GPS, receiver Fragile — 30 mate cycles rated
MMCX Small Some receivers, compact VTX Fair — snap-on, better than U.FL

The U.FL problem: U.FL (also called IPEX or MHF) connectors are rated for about 30 connect/disconnect cycles. After that, the spring contact weakens and the connection becomes intermittent. Every time you unplug and replug a U.FL antenna, you're using one of those 30 cycles. On a racing drone that gets rebuilt weekly, this matters.

Fix: Don't disconnect U.FL antennas unless you have to. Route the antenna wire so it stays connected during maintenance. If a U.FL connection becomes intermittent (video cuts out when you flex the cable), replace the pigtail — the connector is worn out.


Antenna Placement on a Drone

Where you put the antenna matters as much as which antenna you choose.

Do

Don't


Range Estimation (Quick and Dirty)

You don't need to calculate a full link budget to estimate range. Here's the shortcut.

Start with the manufacturer's claimed range. Divide by 3. That's your real-world range with obstacles, interference, and non-ideal antenna placement.

If you're doing better than 1/3 of claimed range, your setup is good. If you're doing worse, check antenna orientation, connections, and interference from other on-board transmitters.

If you need more range: 1. Better antenna on the ground station (cheapest improvement) 2. Higher VTX/radio power (easy but wastes battery) 3. Better antenna on the drone (limited by weight/size) 4. Lower frequency band (900 MHz instead of 2.4 GHz) 5. Higher gain directional antenna with tracker (most effective, most complex)

The order above is also the order of cost-effectiveness. A $15 directional antenna on your goggles does more for range than a $50 amplifier on the drone.


The Antenna You Already Have

Before buying new antennas, check the ones you have:


Next


The best antenna is the one that's pointed the right way, connected properly, and on the correct frequency. Everything else is optimization.

Chapter 4: Link Budgets Without the Math

A link budget tells you whether your radio link will work at a given distance. You don't need a calculator. You need to understand three numbers and three things that kill them.


The Three Numbers

Every radio link has three numbers that determine whether it works:

1. Transmit Power (How loud you're shouting)

Measured in milliwatts (mW) or dBm. More power = more range, up to a point.

Power dBm Typical Use
10 mW 10 dBm Bluetooth, low-power telemetry
25 mW 14 dBm EU legal VTX limit, ELRS minimum
100 mW 20 dBm Standard FPV, ELRS default
250 mW 24 dBm Long-range FPV
500 mW 27 dBm Extended range
1000 mW (1W) 30 dBm FCC limit for most ISM, long-range telemetry

The key insight: Doubling your power only gets you ~40% more range (because radio signal falls off with the square of distance). Going from 100 mW to 200 mW doesn't double your range — it adds about 40%. Going from 100 mW to 1000 mW (10x power) roughly triples your range. Power is an expensive way to buy range.

2. Receiver Sensitivity (How well you can hear a whisper)

Measured in dBm (negative numbers — more negative = more sensitive). This is how faint a signal the receiver can still decode.

Sensitivity Typical Device
-90 dBm Basic WiFi receiver
-105 dBm Good telemetry radio (SiK)
-112 dBm ELRS 2.4 GHz at 50 Hz
-117 dBm ELRS 900 MHz at 25 Hz
-130 dBm LoRa at lowest data rate
-148 dBm Wio-SX1262 (absolute best available)

The key insight: Receiver sensitivity improves when you lower the data rate. ELRS at 500 Hz (fast, for racing) has worse sensitivity than ELRS at 50 Hz (slow, for long range). This is why long-range modes exist — they trade update rate for range.

Link margin = (transmit power + antenna gains) - (path loss) - (receiver sensitivity)

If the margin is positive, the link works. If it's negative, it doesn't. The bigger the positive margin, the more resilient the link is to fading, interference, and obstacles.

Comfortable margins: - 10 dB: Works in clean conditions, fragile in the real world - 20 dB: Handles moderate interference and some obstacles - 30 dB+: Robust link, will survive urban environments and bad days


1. Distance (Path Loss)

Radio signals get weaker with distance. In free space (no obstacles), the signal drops by 6 dB every time you double the distance. That means at twice the distance, you have one quarter the signal power.

Free-space path loss at common frequencies:

Distance 900 MHz 2.4 GHz 5.8 GHz
100 m -51 dB -60 dB -68 dB
500 m -65 dB -74 dB -82 dB
1 km -71 dB -80 dB -88 dB
5 km -85 dB -94 dB -102 dB
10 km -91 dB -100 dB -108 dB

Read this table like this: at 1 km on 2.4 GHz, the signal is 80 dB weaker than when it left the transmitter. If you started with 20 dBm (100 mW) transmit power and 0 dBi antennas, the signal arriving at the receiver is 20 - 80 = -60 dBm. If your receiver sensitivity is -112 dBm, your margin is 52 dB. Plenty.

At 10 km, the same setup gives you 20 - 100 = -80 dBm arriving signal. Margin is 32 dB. Still fine in free space.

But you're not in free space.

2. Obstacles (The Real Range Killer)

Free-space path loss is the theoretical minimum. Everything else makes it worse:

Obstacle Additional Loss
Light foliage (few trees) 3–10 dB
Dense forest 15–30 dB
Single brick wall 10–15 dB
Concrete building 20–40 dB
Metal structure 30–50+ dB
Hill / terrain (no line of sight) 20–60+ dB
Rain (heavy, 5.8 GHz) 1–3 dB per km
Humidity (negligible below 10 GHz) < 1 dB per km

The single biggest factor in real-world range is line of sight. If you can see the other antenna, the link probably works. If you can't, it might not. Every obstacle between the two antennas subtracts from your margin.

This is why 900 MHz outperforms 2.4 GHz in obstructed environments — lower frequencies diffract around obstacles better. A 900 MHz signal bends around a tree that a 5.8 GHz signal bounces off of.

3. Interference (The Urban Tax)

Every other radio on your frequency subtracts from your link margin by raising the noise floor. In a clean rural environment, the noise floor might be -110 dBm. In a city, it could be -90 dBm. That's 20 dB of margin you just lost to other people's WiFi.

Environment Noise Floor (2.4 GHz) Impact
Rural, no buildings -105 to -110 dBm Minimal — close to theoretical range
Suburban -95 to -100 dBm 10–15 dB lost to ambient noise
Urban -85 to -95 dBm 15–25 dB lost
Stadium / convention -75 to -85 dBm 25–35 dB lost — significant range reduction
Race event (many pilots) -80 to -90 dBm 20–30 dB lost on shared frequencies

The fix isn't more power (that raises the noise floor for everyone). The fix is: - Different frequency band (if possible) - More directional antennas (which reject interference from the sides) - Lower data rate (which improves receiver sensitivity) - Better antenna placement (which avoids self-interference)


The No-Math Range Estimate

You don't need to calculate path loss. Use this:

Step 1: Find the manufacturer's claimed range for your radio link.

Step 2: Apply the environment factor:

Environment Multiply By
Open field, clear day, nobody else around 0.7
Suburban, some trees, moderate interference 0.4
Urban, buildings, heavy interference 0.2
Indoor or dense urban canyon 0.1

Step 3: That's your expected range.

Example: ELRS 900 MHz at 100 mW claims 30 km range. - Open field: 30 × 0.7 = 21 km. Reasonable. - Suburban: 30 × 0.4 = 12 km. Realistic. - Urban: 30 × 0.2 = 6 km. About right. - These are LOS (line of sight) estimates. Flying behind a hill or building cuts range further.


How Antennas Change the Budget

Antenna gain is free range. A 6 dBi antenna on the ground station adds 6 dB of margin, which effectively doubles your range compared to a 0 dBi antenna, without increasing power or changing anything on the drone.

Both ends count. If you add 3 dBi on the drone antenna AND 3 dBi on the ground station antenna, you get 6 dB total improvement. But adding gain on the ground station is usually easier (no weight constraint, can use larger antennas, can use a tracker).

The practical limit: On the drone, you're limited to small, lightweight, roughly omnidirectional antennas (2–5 dBi). On the ground, you can use a directional patch (8–14 dBi) or helical (10–16 dBi) on a tracker. The ground antenna is where you get the most range improvement per dollar.


FPV Racing Quad (Short Range)

RC Link (ELRS 2.4 GHz, 250 mW, 500 Hz):
  TX power:            24 dBm
  TX antenna:          2 dBi (dipole on drone)
  RX antenna:          2 dBi (dipole on TX)
  Path loss at 500m:  -74 dB
  Arriving signal:     24 + 2 + 2 - 74 = -46 dBm
  RX sensitivity:     -108 dBm (ELRS 500 Hz)
  Margin:              62 dB  ← massive, no problems

Racing at 500m with ELRS has 62 dB of margin. You could fly behind buildings and through moderate obstacles and still be fine. RC is not your range bottleneck.

Video Link (Analog 5.8 GHz, 400 mW):
  TX power:            26 dBm
  TX antenna:          2 dBi (pagoda)
  RX antenna:          2 dBi (pagoda on goggles)
  Path loss at 500m:  -82 dB
  Arriving signal:     26 + 2 + 2 - 82 = -52 dBm
  RX sensitivity:     -85 dBm (analog threshold for usable image)
  Margin:              33 dB  ← healthy

At 500m, analog video has 33 dB of margin. At 2 km it drops to about 21 dB. At 5 km, about 7 dB — you'll see static. Video is always the range bottleneck on an FPV quad, not RC.

Long-Range Survey (5 km)

Telemetry (RFD900x, 1W, 900 MHz):
  TX power:            30 dBm
  TX antenna:          3 dBi (dipole on drone)
  RX antenna:          6 dBi (directional on GCS)
  Path loss at 5 km:  -85 dB
  Arriving signal:     30 + 3 + 6 - 85 = -46 dBm
  RX sensitivity:     -121 dBm (SiK at 64 kbps)
  Margin:              75 dB  ← enormous

RFD900x at 5 km in open terrain has 75 dB of margin. Even in heavy suburban with 25 dB noise floor elevation and 15 dB of foliage, you still have 35 dB of margin. This is why RFD900x is the standard for long-range telemetry.


Quick Reference: What Uses Your Margin

Factor Typical Impact
Double the distance -6 dB
Light foliage in path -5 to -10 dB
One building wall -10 to -15 dB
Urban noise floor (2.4 GHz) -15 to -25 dB
Cross-polarized antennas -20 dB
Antenna connector loss (each) -0.5 to -1 dB
Coax cable loss (per meter) -0.5 to -2 dB (frequency dependent)
Add 6 dBi ground station antenna +6 dB
Switch from 2.4 to 900 MHz +8 dB at same distance
Lower ELRS packet rate by half +3 dB sensitivity

Next


Range is not a single number. It depends on what's between you and the drone. The link budget tells you how much you can afford to lose before the link breaks.

Chapter 5: The Four Firmwares

There are four flight controller firmware ecosystems that matter. Each one is the right choice for somebody and the wrong choice for somebody else. This chapter helps you figure out which.


The Landscape

Firmware Protocol Built For License
Betaflight MSP v2 FPV racing, freestyle, acro GPL-3.0
iNav MSP v2 GPS navigation, fixed-wing, VTOL GPL-3.0
ArduPilot MAVLink v2 Autonomous missions, survey, commercial GPL-3.0
PX4 MAVLink v2 Research, defense, companion compute BSD-3

All four are open-source. All four run on STM32 flight controllers. All four are actively developed. None of them are going away.


Betaflight

What it does well: Rate-mode acrobatic flight. Sub-millisecond gyro loop. The tightest, most responsive flight controller stack for manual piloting. If you're flying FPV by hand and you want the sticks to feel like an extension of your body, Betaflight.

What it doesn't do: Autonomous anything. No waypoint missions, no GPS hold (angle mode with GPS rescue is a failsafe, not a flight mode), no companion computer integration beyond MSP bridge, no offboard control. Betaflight assumes a human is flying at all times.

Protocol: MSP v2. Binary request/response over serial. Simple, fast, well-documented. Every message has a function code and a payload. Read PID values, write PID values, download blackbox, read sensor state. No streaming — you ask, it answers.

Configuration: Betaflight Configurator (Chrome app) or CLI. The CLI is powerful — diff all gives you a complete delta from defaults, dump all gives you everything. Most experienced operators work in CLI.

Typical platforms: 5-inch freestyle quads, 3-inch cinewhoops, racing drones, micro quads, FPV wings (with limitations).

Community: Massive. Largest FPV firmware community. Fast development cycle. Frequent releases. Sometimes too frequent — breaking changes between minor versions are common.

When to choose it: Your primary control input is a human with a transmitter. You need the best possible manual flight feel. You don't need autonomous modes, waypoints, or programmatic control.


iNav

What it does well: GPS navigation on everything. Multi-rotor, fixed-wing, VTOL, rovers, boats. If it moves and you want it to follow waypoints or hold position, iNav probably supports it. iNav is what Betaflight would be if Betaflight cared about navigation.

What it doesn't do: It doesn't have ArduPilot's depth of autonomous mission planning or PX4's companion computer integration. It's a step up from Betaflight toward autonomy, but it's not a full autopilot stack.

Protocol: MSP v2 with extensions. Same wire format as Betaflight, but with additional messages for navigation, waypoints, and mission planning. iNav also supports MSP2_COMMON_SETTING for named parameter access — cleaner than Betaflight's CLI-only approach for many settings.

Configuration: iNav Configurator (forked from Betaflight Configurator, same Chrome app pattern). CLI is similar but not identical to Betaflight — don't assume commands transfer 1:1.

Typical platforms: Long-range FPV with GPS return, survey wings, fixed-wing platforms, VTOL (tiltrotor, tailsitter), autonomous boats, GPS-guided multicopters.

Community: Smaller than Betaflight, deeply knowledgeable. Fixed-wing and VTOL support is stronger than any other open-source option except ArduPilot.

When to choose it: You need GPS navigation and you're coming from the FPV world. You want something more capable than Betaflight but less complex than ArduPilot. You're building a fixed-wing or VTOL and don't want to learn the ArduPilot parameter universe.


ArduPilot

What it does well: Everything. Multi-rotor, fixed-wing, helicopter, rover, submarine, boat, antenna tracker, blimp. ArduPilot is the Swiss Army knife of autopilots. It has more flight modes, more parameters, more sensor support, and more mission planning capability than any other open-source firmware.

What it doesn't do well: Simple. ArduPilot has ~1,200 parameters. The learning curve is real. The documentation is extensive but assumes you know what you're looking for. If you just want to fly a 5-inch quad freestyle, ArduPilot is overkill.

Protocol: MAVLink v2. Binary message protocol with system/component addressing. Every device on the network has a system ID (1-254) and component ID (1-254). Messages are published, not requested — you tell the FC what stream rates you want and it sends them continuously. Bidirectional: commands go up, telemetry comes down.

Configuration: Mission Planner (Windows), QGroundControl (cross-platform), MAVProxy (command-line). Parameter tree is deep — learning which parameters matter for your platform takes time. The ArduPilot wiki is your primary reference.

Typical platforms: Commercial survey drones, delivery platforms, research vehicles, defense platforms, agricultural sprayers, any platform that needs full autonomous mission capability.

Community: Large, technical, welcoming. Strong contributor base. Excellent wiki. Monthly developer calls. The go-to choice for academic and government research.

When to choose it: You need real autonomous capability. Waypoint missions, sensor integration, companion computer support, multiple flight modes, or you're building something that isn't a standard multicopter. ArduPilot probably already supports your platform.


PX4

What it does well: Companion computer integration, research workflows, defense applications. PX4 was designed from the ground up for programmatic control. The uORB publish/subscribe internal bus, the uXRCE-DDS bridge to ROS2, and the clean offboard control API make it the natural choice when a computer is flying the drone and a human is supervising.

What it doesn't do well: Community hand-holding. PX4's documentation assumes a higher baseline than ArduPilot's. The parameter set (~900 parameters) is smaller than ArduPilot's but the naming convention is less intuitive. Hardware support is narrower — PX4 cares less about supporting every FC board and more about supporting the ones that matter for its target users.

Protocol: MAVLink v2 (same as ArduPilot, different dialect extensions). Additionally supports uXRCE-DDS for high-bandwidth sensor telemetry to companion computers, replacing the older microRTPS bridge.

Configuration: QGroundControl (primary), PX4 CLI via MAVLink shell. No equivalent to ArduPilot's Mission Planner.

Typical platforms: Research drones, defense autonomous systems, companion-compute-heavy platforms, anything running ROS2, platforms that need VTOL transition.

Community: Smaller than ArduPilot, more academic/defense-focused. Strong institutional backing (Dronecode Foundation, Auterion). Development is faster on core features, slower on edge-case platform support.

When to choose it: You're integrating with ROS2 or a companion computer. You need offboard control APIs. You're building for defense or research. You want a clean software architecture that's designed for programmatic control first and manual control second.


Cross-Firmware Reality

The Split

The FPV world runs Betaflight and iNav. MSP protocol. Configurator apps. CLI dumps. Rate mode. Manual piloting with optional GPS backup.

The autonomous world runs ArduPilot and PX4. MAVLink protocol. GCS applications. Parameter trees. Mission planning. The human supervises, the computer flies.

These two worlds are converging. Betaflight quads are getting GPS rescue and companion computers. ArduPilot platforms are getting acro mode and FPV video. But the protocol split (MSP vs. MAVLink) remains the fundamental divide.

Any tool that wants to work across the whole spectrum — which is what Wingman does — needs to speak both languages fluently.

Switching Firmware

Changing firmware on an existing platform is possible but not trivial. The major challenges:


Quick Reference

Feature Betaflight iNav ArduPilot PX4
Manual acro flight Best Good Good Good
GPS hold / RTH Basic rescue Good Best Good
Waypoint missions No Yes Best Yes
Fixed-wing Limited Good Best Good
VTOL No Yes Yes Yes
Companion computer MSP bridge MSP bridge MAVLink + DroneKit MAVLink + uXRCE-DDS + ROS2
Offboard control No Limited Yes (Guided mode) Yes (Offboard mode)
Parameters ~100 (CLI) ~200 (CLI/MSP2) ~1200 (MAVLink) ~900 (MAVLink)
Configuration tool BF Configurator iNav Configurator Mission Planner / QGC QGC
Blackbox logging Flash / SD Flash / SD SD (DataFlash) SD (ULog)
Community size Largest Medium Large Medium
Release cadence ~3-4 months ~6 months Monthly point releases ~6 months

Next


No religious wars. Use what works for your mission. Switch when the mission changes.

Chapter 6: MSP Protocol — The Betaflight/iNav Language

MSP is a question-and-answer protocol. You ask the FC a question (send a request with a function code). It answers (sends a response with the data). No streaming, no subscriptions, no surprises.


What MSP Is

MSP (MultiWii Serial Protocol) is the serial communication protocol used by Betaflight and iNav. It's been around since the MultiWii days and has evolved through several versions. The current version is MSP v2, which supports 16-bit function codes and CRC8 checksums.

MSP is simple by design. It runs over any serial connection (UART, USB, TCP, Bluetooth) at any baud rate. There are no connection handshakes, no sessions, no state. Send a request, get a response.


Packet Format

MSP v2 Request (outgoing)

Byte:  0     1     2     3     4-5       6     7-8       9..N     N+1
       $     X     <     flag  func_id   0x00  payload   payload  crc8
       0x24  0x58  0x3C  0x00  [16-bit]  0x00  size[16]  [data]   [crc]
Field Size Value Description
Header 3 bytes $X< MSP v2 request marker
Flag 1 byte 0x00 Reserved
Function ID 2 bytes Little-endian Which data you're requesting
Payload size 2 bytes Little-endian 0 for most requests
Payload variable Data (for SET commands)
CRC8 1 byte DVB-S2 CRC Over flag + func_id + size + payload

MSP v2 Response (incoming)

Byte:  0     1     2     3     4-5       6-7       8..N     N+1
       $     X     >     flag  func_id   size      payload  crc8
       0x24  0x58  0x3E  0x00  [16-bit]  [16-bit]  [data]   [crc]

Same structure but with > (0x3E) instead of < (0x3C).


The Messages That Matter

Identity

Function ID Direction Returns
MSP_FC_VARIANT 0x02 Read 4-byte ASCII: "BTFL" or "INAV"
MSP_FC_VERSION 0x03 Read 3 bytes: major, minor, patch
MSP_BOARD_INFO 0x04 Read Board identifier, manufacturer, board name

These are the first messages to send on any new connection. They tell you what firmware is running, what version, and what hardware it's running on.

Auto-detect pattern: Send MSP_FC_VARIANT. If you get "BTFL", it's Betaflight. If "INAV", it's iNav. If no response within 2 seconds, it's not an MSP firmware (try MAVLink).

PID Tuning

Function ID Direction Payload
MSP_PID 0x70 Read 9 bytes: [Roll P, Roll I, Roll D, Pitch P, Pitch I, Pitch D, Yaw P, Yaw I, Yaw D]
MSP_SET_PID 0xCA Write Same 9 bytes

Each value is 0-255. The FC interprets these differently by firmware version (scaling factors change between BF 4.3 and 4.4, for example). Always record the firmware version alongside PID values.

Rates

Function ID Direction Payload
MSP_RC_TUNING 0x6B Read Rate values (format depends on rate type)
MSP_SET_RC_TUNING 0xCC Write Same format

Rate payload format depends on the configured rate type (Betaflight rates, Actual rates, KISS rates, Quick rates). Read rates_type from the RC tuning response to know how to interpret the values.

Filters

Function ID Direction Payload
MSP_FILTER_CONFIG 0x5E Read Gyro lowpass, D-term lowpass, notch filters, dynamic notch settings
MSP_SET_FILTER_CONFIG 0xC9 Write Same format

Battery

Function ID Direction Payload
MSP_BATTERY_STATE 0x82 Read Cell count, capacity, voltage (mV), current (cA), mAh consumed
MSP_ANALOG 0x6E Read Voltage, power (mAh), RSSI, current

Blackbox

Function ID Direction Payload
MSP_BLACKBOX_CONFIG 0x5C Read Device (flash/SD), rate, conditions
MSP_DATAFLASH_SUMMARY 0x70 Read Total size, used size, ready flag
MSP_DATAFLASH_READ 0x71 Read Address + data chunk (~4 KB)
MSP_DATAFLASH_ERASE 0x72 Write Erases all flash (10-30 sec)

Blackbox download is the most bandwidth-intensive MSP operation. At 115200 baud, downloading 2 MB of flash takes ~3 minutes. At 921600 baud (via ESP32 bridge), it takes ~20 seconds.

Motor Control

Function ID Direction Payload
MSP_MOTOR 0x68 Read 8x uint16: motor values (1000-2000 or DShot)
MSP_SET_MOTOR 0xD6 Write Same format — TEST MODE ONLY

MSP_SET_MOTOR bypasses the PID controller and directly sets motor outputs. Props must be removed when using this. This is for motor direction testing, not flight.

EEPROM

Function ID Direction Description
MSP_EEPROM_WRITE 0xF9 Write Saves current settings to EEPROM

Always send MSP_EEPROM_WRITE after SET commands. Without it, your changes are lost on the next reboot.


Write Safety Pattern

Never write to an FC without this sequence:

  1. Read the current value (snapshot before)
  2. Show the diff to the operator (before vs after)
  3. Get approval (operator confirms)
  4. Write the new value via MSP_SET_*
  5. Read back to verify the FC accepted it
  6. Compare read-back to what you wrote
  7. EEPROM write after all changes in the batch
  8. Log every change with timestamp, old value, new value

Step 5 is critical. Some FC firmware versions silently clamp values to valid ranges. If you write P=200 and read back P=150, the FC clamped it. Your operator needs to know.


Practical Tips

Baud rate: MSP works at any baud rate, but the FC UART must be configured to match. Betaflight defaults MSP-configured UARTs to 115200. You can change this in the Ports tab. For blackbox download speed, 921600 is recommended.

Timeout: If you send a request and don't get a response within 100 ms, the FC didn't understand it (wrong function code, wrong firmware version, or the UART isn't configured for MSP). Retry once, then try a different approach.

Versioning: MSP function codes and payload formats change between firmware versions. A message that works on BF 4.4 may not exist on BF 4.2. Always detect the firmware version (MSP_FC_VERSION) before sending version-specific messages.

Multiple MSP ports: An FC can have multiple UARTs configured for MSP simultaneously. This is useful for connecting both a configurator and a companion computer. Each port operates independently.

MSP over WiFi: The ESP32 bridge (Tooth, SpeedyBee adapter) wraps MSP in TCP. The byte stream is identical to serial — the same parser works on both USB and TCP transport. The only difference is the connection setup.


Next


MSP is simple. That's its strength. Ask a question, get an answer. No handshakes, no state, no negotiation. The protocol stays out of the way so you can focus on the data.

Chapter 7: MAVLink Protocol — The ArduPilot/PX4 Language

MAVLink is a publish-subscribe protocol. You tell the FC what streams you want, and it sends them continuously. You send commands when you need something done. Both directions flow at the same time.


MAVLink (Micro Air Vehicle Link) is the communication protocol used by ArduPilot, PX4, and their ecosystems. It's been the standard for autonomous drone communication since ~2009.

Unlike MSP (request-response), MAVLink is a streaming protocol. The FC continuously publishes telemetry at configured rates, and the GCS/companion sends commands as needed. Both directions are independent — you can receive telemetry while sending a command.

MAVLink v2 is the current version. v1 is deprecated but still supported for backward compatibility. Always use v2 for new development.


Byte:  0     1     2     3     4       5       6       7-9       10..N    N+1..N+2
       0xFD  len   seq   sys   comp    msg_id  msg_id  msg_id    payload  crc16
       magic             id    id      [24-bit LE]               [data]   [checksum]
Field Size Description
Magic 1 0xFD (v2) or 0xFE (v1)
Payload length 1 0-255 bytes
Incompatible flags 1 Feature flags (signing, etc.)
Compatible flags 1 Backward-compatible flags
Sequence 1 Incrementing counter per link
System ID 1 Which vehicle (1-254)
Component ID 1 Which subsystem (1=autopilot, 191=companion)
Message ID 3 24-bit, little-endian
Payload variable Message-specific data
Checksum 2 CRC-16/MCRF4XX with seed byte

System and Component IDs

Every device on a MAVLink network has a system ID and component ID.

System ID: Identifies the vehicle. Drone 1 = system 1, Drone 2 = system 2. GCS is typically system 255. In a swarm, each drone must have a unique system ID.

Component ID: Identifies a subsystem within the vehicle. - 1 = Autopilot (the FC) - 100 = Camera - 154 = Gimbal - 191 = Companion computer (Wingman uses this) - 250 = GCS

Why this matters: When you connect to a mesh with 10 drones, you'll receive MAVLink messages from all of them. The system ID tells you which drone sent each message. If two drones have the same system ID, you can't tell them apart. This is one of the most common mistakes in multi-vehicle setups.

Setting the system ID: - ArduPilot: SYSID_THISMAV parameter - PX4: MAV_SYS_ID parameter


The Messages That Matter

HEARTBEAT (msg_id = 0) — The Keepalive

Every MAVLink device sends HEARTBEAT at 1 Hz. It's how devices discover each other and know the connection is alive.

Fields:
  type          = vehicle type (2=quadrotor, 1=fixed wing, etc.)
  autopilot     = firmware (3=ArduPilot, 12=PX4)
  base_mode     = armed/disarmed flag (bit 7)
  custom_mode   = current flight mode (firmware-specific number)
  system_status = boot/calibrating/active/critical/emergency

Auto-detect pattern: Send a HEARTBEAT with system ID 255 (GCS). Wait for a response. Read the autopilot field: 3 = ArduPilot, 12 = PX4. This is the equivalent of MSP_FC_VARIANT for the MAVLink world.

No heartbeat = dead link. If you stop receiving heartbeats from a drone for > 5 seconds, the link is lost. ATAK and QGC both use this to mark connections as stale.


Parameter Protocol

MAVLink parameters are named floating-point values. ArduPilot has ~1,200. PX4 has ~900.

Message Direction Description
PARAM_REQUEST_LIST GCS → FC "Send me all parameters"
PARAM_VALUE FC → GCS One parameter: name, value, type, index, count
PARAM_SET GCS → FC "Set this parameter to this value"

Full parameter pull: 1. Send PARAM_REQUEST_LIST 2. FC streams PARAM_VALUE messages (one per parameter) 3. Track received indices — if any are missing after the stream ends, request them individually with PARAM_REQUEST_READ

A full pull of ~1,200 ArduPilot parameters at 115200 baud takes 5-15 seconds depending on link quality.

Writing a parameter: 1. Send PARAM_SET with param_id (name) and param_value 2. FC responds with PARAM_VALUE confirming the new value 3. If the confirmed value differs from what you sent, the FC rejected or clamped the value

Parameters persist across reboots (stored in EEPROM/flash). No separate save command needed, unlike MSP's MSP_EEPROM_WRITE.


Telemetry Streams

Request telemetry streams by sending REQUEST_DATA_STREAM or SET_MESSAGE_INTERVAL.

Key telemetry messages:

Message ID Rate Content
GLOBAL_POSITION_INT 33 2-10 Hz Lat, lon, alt, heading, velocities
ATTITUDE 30 10-50 Hz Roll, pitch, yaw (radians)
VFR_HUD 74 2-10 Hz Airspeed, groundspeed, heading, throttle, alt, climb
SYS_STATUS 1 1-2 Hz Sensor health, battery voltage, current, remaining %
BATTERY_STATUS 147 1 Hz Per-cell voltage, current, mAh consumed, temperature
GPS_RAW_INT 24 2-5 Hz GPS fix type, satellites, HDOP, raw position
RC_CHANNELS 65 5-10 Hz All RC channel values (for monitoring stick input)

Setting stream rates (ArduPilot):

SR0_POSITION=2      # GLOBAL_POSITION_INT at 2 Hz
SR0_EXTRA1=4         # ATTITUDE at 4 Hz
SR0_EXTRA2=2         # VFR_HUD at 2 Hz
SR0_RAW_SENS=1       # RAW sensor data at 1 Hz
SR0_RC_CHAN=5         # RC channels at 5 Hz

SR0_* parameters control stream rates for serial port 0 (usually TELEM1). Replace 0 with the port number for other connections.

Setting stream rates (PX4): PX4 uses SET_MESSAGE_INTERVAL command to set per-message rates.


Commands

MAVLink commands are sent via COMMAND_LONG or COMMAND_INT and acknowledged via COMMAND_ACK.

Command ID Description
MAV_CMD_COMPONENT_ARM_DISARM 400 Arm or disarm
MAV_CMD_DO_SET_MODE 176 Change flight mode
MAV_CMD_NAV_TAKEOFF 22 Takeoff to specified altitude
MAV_CMD_NAV_LAND 21 Land at current position
MAV_CMD_NAV_RETURN_TO_LAUNCH 20 Return to home
MAV_CMD_DO_REBOOT 246 Reboot FC

Arm command:

COMMAND_LONG:
  target_system = 1    (drone's system ID)
  command = 400         (ARM_DISARM)
  param1 = 1.0          (1=arm, 0=disarm)
  param2 = 0.0          (0=normal, 21196=force arm — dangerous)

Wait for COMMAND_ACK. Result 0 = accepted. Result 4 = denied (pre-arm checks failed). Result 5 = in progress.


Mission Protocol

Upload waypoint missions to the FC:

  1. Send MISSION_COUNT (number of waypoints)
  2. FC requests each with MISSION_REQUEST_INT
  3. Send each MISSION_ITEM_INT
  4. FC confirms with MISSION_ACK

Download existing mission: 1. Send MISSION_REQUEST_LIST 2. FC sends MISSION_COUNT 3. Request each with MISSION_REQUEST_INT 4. FC sends each MISSION_ITEM_INT


Offboard Control (PX4)

PX4's offboard mode lets the companion computer directly command position, velocity, or attitude setpoints:

SET_POSITION_TARGET_LOCAL_NED:
  x, y, z = position in local NED frame (meters)
  vx, vy, vz = velocity (m/s)
  type_mask = which fields are valid

Requirements for offboard mode: 1. Companion must stream setpoints at > 2 Hz (PX4 requires continuous updates or it exits offboard mode) 2. RC switch must be set to offboard mode 3. Vehicle must be armed

This is the control path for Wingman L3 (Delegate) autonomous operations on PX4.


Both speak MAVLink v2, but they differ in important ways:

Feature ArduPilot PX4
Flight mode numbers ArduPilot-specific (0=Stabilize, 3=Auto, 6=RTL) PX4-specific (different numbers for same concepts)
Parameter names ATC_RAT_RLL_P style MC_ROLLRATE_P style
Stream rate config SR0_* parameters SET_MESSAGE_INTERVAL command
Offboard control Guided mode + SET_POSITION_TARGET Offboard mode + SET_POSITION_TARGET
Sensor data High-bandwidth DDS bridge uXRCE-DDS to ROS2
Mission dialect Standard + ArduPilot extensions Standard (fewer extensions)

Implication for tools: Any tool that works across both ArduPilot and PX4 (QGroundControl, MAVSDK, Wingman) must handle these differences. The MAVLink wire format is identical — the interpretation of mode numbers, parameter names, and command behaviors differs.


Practical Tips

Always send heartbeats. Your GCS or companion must send HEARTBEAT at 1 Hz to the FC. If the FC doesn't receive GCS heartbeats, it may trigger GCS failsafe (ArduPilot: FS_GCS_ENABLE).

Monitor packet loss. MAVLink packets have a sequence number. If you see gaps in the sequence, you're losing packets. At > 5% loss, the link is degraded. At > 20%, it's unreliable for commands.

Don't flood the link. Sending commands faster than the FC can process them causes buffer overflow and dropped messages. One command at a time, wait for COMMAND_ACK before sending the next.

Use MAVSDK or pymavlink, not raw parsing. MAVLink has 300+ message types with varying payload formats. Writing a parser from scratch is an error-prone waste of time. MAVSDK (for control) and pymavlink (for analysis) handle the parsing.

Test with SITL. Both ArduPilot and PX4 have Software-In-The-Loop simulators that emulate a real FC over a simulated MAVLink link. Test your companion software against SITL before connecting to real hardware.


Next


MAVLink is a conversation. The FC talks continuously. You listen and speak when you have something to say. The protocol handles the rest.

Chapter 8: UART Layout and Why It Matters

You will run out of UARTs before you run out of ideas. Planning the layout before you build saves hours of rewiring later.


What a UART Is

A UART (Universal Asynchronous Receiver/Transmitter) is a serial port. Two wires: TX (transmit) and RX (receive). Every device that talks to the flight controller — RC receiver, GPS, telemetry radio, companion computer, ESC telemetry, Bluetooth module, mesh radio — needs a UART.

The flight controller has a fixed number of UARTs. Once they're allocated, they're gone. Adding another device means either freeing a UART or getting a different FC.


How Many UARTs You Actually Get

MCU Typical FC Hardware UARTs Usable UARTs Notes
STM32F405 Most 30x30 FCs 6 3–5 UART1 often hardwired to USB/VCP
STM32F722 Budget FCs 4 3 Fewer UARTs, fewer features
STM32F745/F765 Mid-range 8 5–6 More headroom
STM32H743/H750 Premium FCs 8+ 6–8 Best for complex builds
RP2040 Pico-based FCs 2 2 Very limited
ESP32-C6 Tooth/Seed 2 1–2 One for FC bridge, one for debug

"Usable" is lower than "hardware" because: - One UART is typically dedicated to USB (VCP/CDC) for configurator access - Some UARTs share pins with SPI (used for gyro, OSD, flash) and can't be used - Some UARTs have inverted-only pads on the PCB (for SBUS) and can't be repurposed without hardware modification

Check your FC's documentation for which UARTs are actually available on pads. The schematic may show 6 UARTs, but if only 4 have TX/RX pads on the board, you have 4 usable UARTs.


The Standard Allocation

For a typical FPV quad with GPS and telemetry:

UART Assignment Protocol Baud Rate
UART1 RC Receiver CRSF (ELRS/Crossfire/Ghost) 420000
UART2 GPS NMEA or UBX 38400 or 115200
UART3 Telemetry / MSP Bridge MSP, MAVLink, or SmartPort 115200
UART4 ESC Telemetry BLHeli/AM32 telemetry 115200

That uses 4 of your ~5 usable UARTs and you haven't added a companion computer, mesh radio, or Bluetooth module yet.


What Eats UARTs

Every peripheral that communicates over serial needs its own UART. Here's the complete list of things that might want one:

Device Protocol Required? Notes
RC Receiver CRSF/SBUS/IBUS Yes Non-negotiable. No UART = no control.
GPS NMEA/UBX For navigation Required for RTH, GPS modes, position logging
Telemetry radio MSP/MAVLink/LTM For GCS link Can share with RC if receiver supports it (CRSF telemetry)
ESC Telemetry Serial telemetry For RPM filter Only needed if using bidirectional DShot or ESC temp monitoring
OSD (analog) MSP DisplayPort For on-screen display Only if using DJI OSD or analog OSD with MSP
Companion computer MAVLink/MSP For AI/autonomy The big UART consumer — wants high baud rate
Bluetooth module SPP/BLE For wireless config Can use MSP-over-BT instead of USB
Mesh radio Serial/Ethernet For swarm If the mesh radio uses serial (some use Ethernet instead)
LED controller Serial LED For prop LEDs Rarely needs a full UART — can use soft serial
Rangefinder Serial For altitude hold Some rangefinders use I2C instead (saves a UART)
Optical flow Serial/I2C For position hold Prefer I2C version to save UARTs

Strategies When You Run Out

1. CRSF Telemetry Passthrough

If your RC receiver uses CRSF protocol (ELRS, Crossfire, Ghost), it already has a bidirectional link to the transmitter. You can send telemetry data (battery, GPS, attitude) through the RC link instead of using a separate telemetry radio.

Saves: 1 UART (the one that would have gone to a telemetry radio)

Trade-off: Telemetry bandwidth is limited to what CRSF can carry (basic flight data, not full MAVLink). If you need full MAVLink telemetry (parameter editing, mission upload), you still need a separate radio.

2. Soft Serial

Betaflight and iNav support "soft serial" — bit-banging a UART on any GPIO pin. It works for low-baud-rate devices.

Saves: 1 hardware UART

Trade-off: Limited to ~19200 baud reliably. Not suitable for CRSF (420000), GPS at high rate, or MAVLink. Good for: SmartPort telemetry, serial LED, low-rate telemetry.

3. Companion Computer as Hub

Instead of connecting multiple devices to the FC, connect them to a companion computer and use one UART between the companion and FC.

Before (4 UARTs on FC):
  FC UART1 ← RC receiver
  FC UART2 ← GPS
  FC UART3 ← Telemetry radio
  FC UART4 ← Mesh radio

After (2 UARTs on FC):
  FC UART1 ← RC receiver
  FC UART2 ← Companion computer (MAVLink)

  Companion ← GPS (USB)
  Companion ← Telemetry radio (USB or Ethernet)
  Companion ← Mesh radio (Ethernet)

Saves: 2+ UARTs on the FC

Trade-off: Adds weight, power consumption, and complexity. The companion computer becomes a single point of failure for everything except manual RC control.

4. I2C Instead of Serial

Some peripherals (compass, barometer, rangefinder, optical flow) are available in both serial and I2C versions. I2C uses a shared bus — multiple devices on the same two wires (SDA, SCL).

Saves: 1 UART per device moved to I2C

Trade-off: I2C is slower than serial and can have bus contention issues with multiple devices. But for low-bandwidth sensors, it's fine.

5. DMA and UART Sharing (Advanced)

On STM32H7 FCs, DMA (Direct Memory Access) allows the CPU to handle UART traffic more efficiently. Some advanced configurations use UART inversion and protocol detection to share a single UART between two devices that take turns.

This is fragile, FC-specific, and not recommended unless you know exactly what you're doing.


The UART Planning Template

Before building, fill this out:

Platform: _______________
FC: _______________
MCU: _______________
Available UARTs: _______________

| UART | Device | Protocol | Baud Rate | Required? |
|------|--------|----------|-----------|-----------|
| 1    |        |          |           |           |
| 2    |        |          |           |           |
| 3    |        |          |           |           |
| 4    |        |          |           |           |
| 5    |        |          |           |           |
| 6    |        |          |           |           |

Devices that didn't get a UART:
  _______________ → moved to I2C / soft serial / companion / dropped

UARTs remaining after allocation: ___

If you fill this out and you're already at zero remaining UARTs before adding the companion computer you wanted, you need a different FC or a companion-as-hub architecture.


Platform-Specific UART Maps

Typical F405 (4 usable UARTs)

UART1 → USB VCP (configurator) — not available for peripherals
UART2 → RC Receiver (CRSF @ 420000)
UART3 → GPS (UBX @ 115200)
UART4 → Available
UART5 → Available
UART6 → ESC Telemetry (if DShot bidirectional)

Two free UARTs (4 and 5) for telemetry radio, companion, mesh, or Bluetooth.

Orqa H7 QuadCore (6+ usable UARTs)

USART1 → USB VCP
USART2 → Available
USART3 → RC (GHST/IRONghost @ 420000)
UART4  → Available
USART6 → MAVLink telemetry (ATAK/TAK @ 115200)
UART7  → GPS (UBX @ 115200)
UART8  → ESC telemetry

Three free UARTs (2, 4, plus potential soft serial). The H7's extra UARTs are why it supports more complex integrations than F4.

PX4 on Pixhawk 6X

TELEM1 → MAVLink GCS (115200 or 57600)
TELEM2 → MAVLink companion computer (921600)
GPS 1  → GPS (auto-detect)
GPS 2  → Second GPS or compass
RC IN  → RC receiver (SBUS/CRSF)
DEBUG  → Console / NSH shell

PX4 labels its ports by function rather than UART number. The mapping to hardware UARTs is in the board configuration.


Common Mistakes

1. Wrong baud rate. CRSF is 420000. Many people set 115200 because that's the "default" they're used to. The receiver will not connect. Always check the protocol's required baud rate.

2. TX/RX swap. FC TX connects to device RX, and vice versa. This is wrong more often than any other wiring mistake. If a serial device doesn't respond, swap TX and RX as the first diagnostic step.

3. Voltage mismatch. Most FCs output 3.3V serial. Most peripherals accept 3.3V. But some older devices are 5V serial and can damage 3.3V inputs. Check before connecting.

4. Two devices on one UART. You can't connect a GPS and a telemetry radio to the same UART and expect both to work. Serial is point-to-point. Use a companion computer or multiplexer if you need to share.

5. Forgetting the configurator UART. If you reassign the USB/VCP UART to a peripheral, you may lose the ability to connect Betaflight Configurator. Always keep at least one path to the configurator available (USB or MSP-over-other-UART).


Next


Plan your UARTs before you solder. Desoldering a GPS module because you need that UART for a companion computer is not how you want to spend a Saturday.

Chapter 9: Pre-Flight Checklist That Actually Works

The manufacturer's checklist is marketing. This one catches the problems that actually ground you.


The 60-Second Field Check

This is the minimum check before every flight. Takes 60 seconds once you've done it a few times. Skipping it takes longer when you have to walk 500 meters to recover a crashed drone.

Visual (15 seconds)

  1. Props: All four present, correct rotation, no nicks, nuts tight. Spin each by hand — should rotate freely with no catch.

  2. Frame: No cracks on arms. No loose standoffs. Antenna mounts intact. Nothing rattling when you shake it.

  3. Battery: Strapped tight. Will not shift under acceleration. Balance lead tucked, not dangling near props.

  4. Antenna position: RC antenna elements deployed (not folded under the frame). VTX antenna pointed up/back, not blocked by battery. GPS antenna has clear sky view.

Power-On (30 seconds)

  1. Voltage check: Battery voltage matches expected full charge. 4S = 16.4–16.8V. 6S = 24.6–25.2V. If significantly low, the battery wasn't fully charged or a cell is bad. Don't fly it.

  2. Gyro cal: Wait for the FC to finish gyro calibration (usually 1-2 seconds after power on). Don't move the quad during this time. On Betaflight the OSD shows "CALIBRATING" then clears.

  3. RC link: Confirm connected. Move sticks — verify response on OSD or in the video feed (stick position overlay if enabled). Check that arming switch is in disarmed position.

  4. GPS (if equipped): Check satellite count. Wait for 3D fix. Most firmwares show sat count on OSD. Minimum 8 sats for any GPS-dependent mode. More is better. If you need GPS return-to-home, confirm the home point is set (some firmwares set home on arm, others on first GPS lock).

  5. Video feed: Confirm you see a live image in your goggles or monitor. Correct channel. No interference patterns. If analog, check that nobody else is on your channel.

Arm Check (15 seconds)

  1. Clear the area. Nobody within 3 meters of the drone. Nothing the drone could hit if it does something unexpected on arm.

  2. Arm. Motors should spin at idle (or not, if "Motor Stop" is enabled). Listen for any unusual sounds — grinding, clicking, uneven RPM.

  3. Control check (optional but recommended on new builds): With the drone on the ground, briefly blip throttle and check that it tries to lift evenly. Tilt the quad by hand — motors should speed up on the low side to self-level (in angle/level mode) or resist the tilt (in acro/rate mode).

Go fly.


The Deep Check (Pre-Session or New Build)

Do this once per session (before the first flight of the day) or after any change to the build (new props, firmware update, parameter change, crash repair).

Electrical

Mechanical

Software


Post-Flight Check

After each flight, before the next:

  1. Battery voltage: Check remaining voltage. If below 3.5V/cell under resting conditions, you pushed too hard. Adjust your timer.

  2. Temperature sweep: Touch each motor, each ESC, the FC, the VTX. Anything unusually hot compared to normal? Investigate before flying again.

  3. Visual scan: Any new damage? Props nicked? Antenna bent? Camera mount shifted?

  4. Log pull (if analyzing this session): Pull blackbox now. Flash will be overwritten by the next flight.


Post-Session

After the last flight of the day:

  1. Storage charge batteries. LiPo storage voltage is 3.8V/cell (22.8V for 6S). Do not leave batteries at full charge or fully depleted. Storage charge the same day.

  2. Clean the quad. Grass, dirt, and moisture accelerate corrosion on exposed electronics. Compressed air for motor bells.

  3. Note anything that needs attention. A prop you noticed was slightly nicked. A motor that felt warm. A GPS that took too long to lock. Write it down or you'll forget by next session.


The Checks That Catch Real Problems

In order of how often they prevent incidents:

  1. Props — wrong rotation, damaged, or loose. The most common cause of unexpected behavior on arm or immediately after takeoff.

  2. Battery strap — a battery that shifts forward on a punch-out changes the CG and the drone flips. Cinch it tight.

  3. RC link — flying on a dead receiver because you forgot to check the link. Especially after changing receiver firmware or binding phrase.

  4. Failsafe — having the wrong failsafe behavior configured. "Drop" is almost never what you want. Test it before you need it.

  5. GPS home point — flying 2 km out, triggering RTH, and having the drone return to a GPS position from three flights ago because you didn't wait for a fresh fix.

  6. Antenna — a U.FL connector that popped off a receiver during a battery change. Video or RC works at 5 meters, fails at 50.


The One Check Nobody Does (But Should)

Turn off your transmitter with the drone armed on the ground.

This tests your failsafe. Every time you change firmware, change receivers, or change failsafe settings, do this test. It takes 10 seconds and it's the only way to know what will actually happen when you lose signal in the air.

If the motors keep spinning at the last throttle position: your failsafe is misconfigured and your drone will fly away on signal loss. Fix it before flying.


Next


The checklist is boring. Walking half a kilometer to pick up a crashed drone because you didn't check the prop nuts is also boring, and takes longer.

Chapter 10: Blackbox Logs — What They Tell You

The blackbox doesn't lie. Your memory does. Pull the log.


What Gets Logged

A blackbox log records everything the flight controller knows at high sample rate (typically 1–4 kHz on Betaflight, 100–400 Hz on ArduPilot/PX4). This includes:

Data What It Tells You
Gyroscope (roll, pitch, yaw rate) How the drone is actually rotating — the ground truth
Accelerometer Attitude estimation, vibration level
Motor outputs (1–8) What the FC commanded each motor to do
RC commands What the pilot actually asked for
PID terms (P, I, D per axis) How the PID controller responded to error
Setpoint What the FC was trying to achieve
Battery voltage Voltage under load, sag profile
Battery current (if sensor) Power consumption, mAh tracking
GPS position/speed (if equipped) Flight path, speed, altitude
Filter state Pre/post filter gyro (Betaflight debug modes)

How to Pull Logs

Betaflight (Flash-Based)

Betaflight stores blackbox data on the FC's on-board flash chip (typically 2–16 MB) or an SD card.

Via Configurator: 1. Connect USB 2. Blackbox tab → Download Flash → Save .bbl file

Via MSP (what Wingman does): 1. MSP_DATAFLASH_SUMMARY → get used bytes 2. MSP_DATAFLASH_READ in 4 KB chunks → stream raw data 3. Save as .bbl file

Important: Flash fills up. If it's full, new flights overwrite old ones. After a session where you need the data, pull logs before the next flight. Or switch to SD card logging if your FC supports it.

ArduPilot (SD Card)

ArduPilot writes .bin DataFlash logs to the SD card.

Via Mission Planner: DataFlash Logs → Download Via MAVLink: LOG_REQUEST_LIST → LOG_REQUEST_DATA → stream Via SD card: Pull the card, copy .bin files directly

PX4 (SD Card)

PX4 writes .ulg (ULog) files to the SD card.

Via QGroundControl: Analyze → Log Download Via SD card: Pull the card, copy .ulg files


Reading the Traces

The Gyro Trace Is Everything

The gyroscope trace is the single most important data in a blackbox log. It shows the actual angular rate of the drone on each axis, sampled at 1–4 kHz. Everything else is derived from or compared against the gyro.

A clean gyro trace looks like smooth curves that follow the stick inputs. When you push the stick right, the roll gyro shows a clean step to the commanded rate, holds, then returns to zero when you release.

A noisy gyro trace looks like the clean curve with fuzz, spikes, or oscillation layered on top. The noise is real — the drone is actually vibrating. The question is where the vibration comes from and whether it matters.

The Five Patterns That Indicate Real Problems

Pattern 1: High-frequency noise on all axes, increasing with throttle.

What it looks like: Fuzz on the gyro trace that gets worse as you increase throttle. Consistent across roll, pitch, and yaw.

What it means: Mechanical vibration from the motors/props is reaching the FC. The motors are the only thing on the drone whose vibration scales with throttle.

What to check: Prop balance, motor bearings, FC soft mount, frame arm tightness. If the noise is broadband (not at a specific frequency), it's probably multiple sources. Fix the biggest one first — usually props.


Pattern 2: Oscillation at a specific frequency, visible as regular waves.

What it looks like: A sine wave overlaid on the gyro trace. Consistent frequency regardless of stick input. May be present on one axis more than others.

What it means: Resonance. Something on the frame has a natural frequency that's being excited by the motors. The FC's filters are either not catching it or are making it worse.

What to check: Look at the frequency (use the Betaflight Blackbox Explorer's spectrum analyzer). Common resonances: - 80–150 Hz: Frame flex (arms, standoffs) - 150–300 Hz: Prop/motor mechanical resonance - 300–600 Hz: Gyro noise floor (filter issue, not mechanical)

If the dynamic notch filter is enabled, check if it's tracking this frequency. If not, adjust the notch range.


Pattern 3: D-term noise spikes, especially on yaw.

What it looks like: The D-term trace (visible in debug mode) is noisy or spiky, even when the gyro trace looks relatively clean. Yaw axis is typically worst.

What it means: The D-term is the derivative of gyro error. It amplifies high-frequency noise by design — that's how it reacts quickly to changes. If the gyro has even small amounts of high-frequency content, D amplifies it into large motor corrections.

What to check: Lower D-term gain (try -20%). If that helps significantly, the issue is D sensitivity to noise, not mechanical. Also check: D-term lowpass filter cutoff (lowering it reduces D noise at the cost of slower D response), dynamic notch filter (should be catching the frequencies that D is reacting to).


Pattern 4: Motor output asymmetry — one motor consistently higher.

What it looks like: In the motor output traces, one motor is always running at higher output than the others. The difference is consistent across throttle levels.

What it means: The FC is compensating for something that makes the drone want to rotate toward the weak motor's side. Possible causes: - Motor or ESC weaker on one side (dying motor, marginal ESC) - Center of gravity offset (battery mounted off-center) - Bent motor mount changing thrust angle - Damaged prop generating less thrust

What to check: Swap the suspect motor to a different arm. If the asymmetry follows the motor, it's the motor. If it stays on the same arm, it's the mount or frame. If it moves to the diagonal, it's CG.

Rule of thumb: Up to 5% asymmetry is normal. 5–10% is worth investigating. Above 10% is a problem that will get worse.


Pattern 5: Voltage sag correlating with performance loss.

What it looks like: Battery voltage drops sharply during aggressive maneuvers. At the same time, motor outputs hit 100% (full throttle commanded but can't produce it), and the gyro shows the drone not achieving the commanded rate.

What it means: The battery can't deliver enough current. The voltage sags, the ESCs can't spin the motors fast enough, and the drone loses authority. This is a power system problem, not a tuning problem.

What to check: Battery internal resistance (measure with a charger that shows IR per cell). IR above 15 mΩ/cell means the pack is aging. Voltage sag below 3.3V/cell under load is concerning. Below 3.0V/cell is damaging the battery.

Don't tune around bad batteries. If the battery is sagging, no amount of PID tuning will fix the performance loss. Replace the battery.


Blackbox Analysis Workflow

Step 1: Pull the log. Immediately after the flight you want to analyze. Don't fly again first.

Step 2: Open in the right tool. - Betaflight: Betaflight Blackbox Explorer - ArduPilot: Mission Planner → DataFlash Log tab, or UAV Log Viewer - PX4: Flight Review or PlotJuggler

Step 3: Look at the gyro first. Always. Before looking at PIDs, motor outputs, or anything else. The gyro tells you what actually happened. Everything else tells you what the FC tried to do about it.

Step 4: Compare setpoint to gyro. The setpoint is what the FC was trying to achieve. The gyro is what actually happened. The gap between them is the error. A well-tuned drone tracks setpoint closely. A poorly tuned one lags, overshoots, or oscillates around it.

Step 5: Check motor outputs. Are they even? Are any hitting 100%? Are there sudden spikes? Motor output tells you how hard the FC is working to maintain control.

Step 6: Check battery voltage. Does it hold steady or sag under load? Voltage sag during aggressive maneuvers is normal. Voltage sag during hover is a problem.

Step 7: If you found a problem, change ONE thing. Fly again. Pull another log. Compare. This is how tuning works — iterative, data-driven, one variable at a time.


What Logs Don't Tell You


Next


The log is the flight's memory. It remembers what you don't. Pull it. Read it. Trust it over your recollection.

Chapter 11: PID Tuning for People Who Fly, Not Simulate

PID tuning is not magic. P reacts to error. I removes steady error. D resists change. That's it. The rest is learning what each one feels like through the sticks.


What P, I, and D Actually Do

P (Proportional) — The Reaction

P pushes back proportional to how far off the drone is from where it should be. Big error = big correction. Small error = small correction.

Too high: The drone overshoots its target and corrects back, creating fast oscillation. Feels like the quad is vibrating or buzzing, especially visible on a punch-out or sharp turn.

Too low: The drone feels mushy, soft, unresponsive. It drifts through commands instead of snapping to them. Slow to respond to stick input.

What to listen for: P oscillation is fast — 10-50 Hz range. It sounds like a buzz or rattle. If you hear a high-pitched buzzing that increases when you do aggressive maneuvers, P is too high.


I (Integral) — The Memory

I accumulates error over time. If the drone is consistently a little off in one direction (wind pushing it, CG offset, motor imbalance), I builds up a correction to counter it.

Too high: The drone feels "stuck" or slow to change direction. Overshoot on sustained moves. After a long turn, it keeps turning briefly after you release the stick. In extreme cases, I windup causes the drone to suddenly lurch as the accumulated correction releases.

Too low: The drone drifts. In a hover, it doesn't hold position well. In forward flight, wind pushes it off course and it doesn't correct. The quad won't hold a steady rate in a turn.

What to feel for: I issues are slow. If the drone seems to "remember" what it was doing and resists changing, I is too high. If it can't hold a line in wind, I is too low.

For most operators: Leave I at the default. It's the least sensitive of the three terms and the default is usually close enough. Only touch I if you have specific drift or windup problems.


D (Derivative) — The Brake

D resists change. It's proportional to how fast the error is changing, not how big it is. D slows down both the drone's response AND oscillation.

Too high: Motors run hot. D amplifies noise (see Chapter 10, Pattern 3). The drone feels "dampened" — controlled but lacking snap. In extreme cases, motors make a grinding sound from rapid micro-corrections driven by noise.

Too low: The drone overshoots on quick maneuvers. Feels bouncy at the end of rolls and flips. P oscillation becomes harder to control because D isn't there to brake it.

What to listen for: D noise is a constant, low-level motor buzz that's present even in smooth flight. It gets worse with throttle because motor vibration (which D amplifies) increases with RPM.

The D dilemma: You need enough D to control overshoot but not so much that it amplifies noise. This is the core tension in PID tuning and why filters exist — filters clean the gyro signal so D can do its job without reacting to noise.


The Field Tuning Workflow

This workflow assumes you're starting from a reasonable default (Betaflight defaults are a good starting point for most 5-inch builds). If you're building from scratch on unusual hardware, start with community presets for your motor/frame size.

Step 0: Mechanical First

Before touching PIDs, confirm: - Props are balanced and undamaged - Motors spin freely with no grit or catch - FC is soft-mounted properly - Frame has no loose screws or cracked arms - Battery is secured and not shifting in flight

If any of these are wrong, no amount of PID tuning will fix it. See Chapter 12 (Troubleshooting), Step 2.

Step 1: Fly the Default

Fly a representative flight — hover, forward flight, some rolls and flips, a punch-out, some turns. Pay attention to: - Does it feel mushy or sharp? (P) - Does it hold a line in wind? (I) - Does it bounce at the end of maneuvers? (D) - Is there any buzzing or vibration? (P too high or D noise)

Pull a blackbox log.

Step 2: Adjust P

P is where most of the feel comes from. Adjust P first.

Adjust roll and pitch P together unless you have a reason not to (asymmetric frame, different prop spacing). Yaw P is usually set independently and is less sensitive.

Step 3: Adjust D

Once P feels right, check D:

D and P interact — raising P often requires raising D to maintain damping. If you raised P in Step 2, you may need more D.

Step 4: Leave I Alone (Usually)

I is rarely the problem for freestyle and racing. If the default works, keep it.

Step 5: Check Filters

If you can't get P and D where you want them because noise starts before you reach the desired gain, the issue is filters, not PIDs.

The filter-PID relationship: Filters remove noise so PIDs can run higher without reacting to it. A well-filtered build can run higher P and D, which means sharper and more responsive flight. A poorly filtered build (or a build with mechanical vibration issues) must run lower PIDs to compensate.

Step 6: Fly, Log, Compare, Repeat

After each change: 1. Fly a representative flight (same maneuvers as before) 2. Pull blackbox 3. Compare gyro traces to the previous flight 4. Did it get better or worse? If better, keep the change. If worse, revert.

One change at a time. If you change P, D, and filters simultaneously, you won't know what helped and what hurt.


Rates vs. PIDs

Rates and PIDs are different things. People confuse them constantly.

Rates control how fast the drone rotates per degree of stick deflection. Higher rates = faster rotation at full stick. Rates affect how the drone FEELS to fly but they don't affect stability.

PIDs control how well the drone FOLLOWS the rate command. Higher P = more aggressively follows the command. Higher D = more damped following.

If the drone feels slow: it might be rates (increase max rate), not PIDs.

If the drone feels floaty: it might be PIDs (increase P), not rates.

If the drone rotates at the right speed but wobbles while doing it: that's PIDs.


Tuning for Different Flight Styles

Freestyle

Racing

Cinematic / Smooth

Long-Range / GPS Cruise


When to Stop Tuning

The tune is "good enough" when: - No audible buzz or vibration in normal flight - The drone responds to stick inputs without delay or overshoot - Blackbox gyro traces are clean (no sustained oscillation) - Motors are warm after flight, not hot (hot = D noise or P oscillation making the ESCs work too hard) - You stop noticing the quad and start noticing the flying

Most pilots overtune. The difference between a "good" tune and a "perfect" tune is 2-3% performance improvement that you'll never notice in real flying. Get it to "no oscillation, responsive, motors not hot" and go fly.


Next


The best tune is the one that lets you forget about the quad and focus on the flying. If you're thinking about PIDs in the air, you're not done tuning. If you're not thinking about PIDs in the air, you probably are.

Chapter 12: When Things Go Wrong

This is the chapter you read at the field with a broken drone in your hands. Start with the symptom. Follow the tree.


How to Use This Chapter

Find your symptom in the list below. Follow the diagnostic steps in order. Each step either solves the problem or narrows it down. Don't skip steps — the obvious cause is often not the actual cause.


Symptom: Won't Arm

The FC refuses to arm. This is the most common field problem and the one with the most possible causes.

Step 1: Read the arming flags. - Betaflight: CLI → status → look for arming disable flags - iNav: CLI → status → same - ArduPilot: GCS → Messages tab → pre-arm check failures - PX4: QGC → Vehicle Setup → Summary → pre-arm checks

Step 2: Common arming flags and fixes.

Flag Meaning Fix
RXLOSS / No RC FC not receiving RC signal Check UART assignment, baud rate, protocol selection. Verify receiver is powered and bound.
ACC not cal Accelerometer not calibrated Calibrate accel (level the quad, run cal in configurator)
ANGLE Quad not level enough Place on level surface. If on uneven ground, raise arm angle limit temporarily.
THROTTLE Throttle not at minimum Move throttle stick fully down. Check endpoint calibration.
CLI CLI is open Close the CLI connection
MSP MSP connection active preventing arm Some configurator connections block arming. Disconnect.
LOAD CPU overloaded Reduce gyro/PID loop frequency or disable unnecessary features
RPMFILTER RPM filter configured but no signal Check ESC telemetry UART or disable RPM filter
GPS FIX Requires GPS fix before arm (nav modes) Wait for GPS lock or disable GPS pre-arm requirement

Step 3: If no flags show but still won't arm. - Check switch assignment. Arm switch might be on a channel that isn't configured or is inverted. - Check throttle endpoints. Some FCs require throttle below 1050 µs. - Power cycle everything. Receiver, FC, ESCs. In that order.


Symptom: Oscillation / Vibration in Flight

The quad shakes, wobbles, or makes a buzzing sound in flight. Could be mechanical or electronic.

Step 1: Determine if it's always present or speed-dependent. - Always present (even at hover): likely filter or PID issue - Only at high throttle: likely mechanical — prop balance, motor bearing, loose standoff - Only after a crash: prop damage, bent motor shaft, cracked frame arm

Step 2: Check mechanical first. Always. Before touching PIDs. - Spin each motor by hand. Feel for grit, catch, or uneven resistance. One bad bearing can cause the whole quad to oscillate. - Check props for damage. Even a tiny nick changes balance. Replace suspect props — they're the cheapest component. - Check motor mounting screws. Loose motor = oscillation source. - Press on each arm. Flex = vibration transmission path. Carbon fiber arms don't flex. Cheap 3D-printed arms do. - Check FC mounting. Soft mount grommets should be intact and the FC should not contact the frame directly.

Step 3: Pull a blackbox log. If mechanical checks pass: - Look at gyro traces. Clean gyro = clean flight. Noisy gyro = something is shaking the FC. - Compare pre-filter and post-filter gyro. If pre-filter is noisy but post-filter is clean, your filters are working hard. Consider addressing the source instead of filtering harder. - Look for a specific frequency peak. A resonance at a consistent frequency often indicates a specific mechanical source: - Prop-speed frequency: prop balance issue - Frame resonance (usually 100-300 Hz): frame flex - Motor bearing: broadband noise that increases with throttle

Step 4: If it's a filter/PID issue: - Lower D-term first. D is the most noise-sensitive PID term. Drop D by 20% and fly again. - Check dynamic notch filter. If not enabled, enable it. If enabled, check that it's tracking the right frequency range. - Lower gyro lowpass filter cutoff. Default is usually fine, but noisy builds may need 150 Hz instead of 200 Hz. - As a last resort, lower P-term. But if you need to drop P significantly to stop oscillation, the problem is mechanical, not tuning.


Symptom: Flyaway / Unexpected Movement

The drone moves in a direction the pilot didn't command.

Step 1: Did it respond to stick input during the event? - Yes, but drifted: likely sensor issue (compass interference, GPS glitch, accelerometer drift) - No response to sticks at all: likely failsafe triggered, mode switch, or loss of RC link

Step 2: Check flight mode. Did the mode change unexpectedly? - A mode switch bumped during handling can change from acro to angle to GPS hold, causing unexpected behavior. - ArduPilot/PX4: check mode channel (usually CH5) assignment and thresholds. - Betaflight: check mode tab for overlapping ranges on the aux channels.

Step 3: Check compass and GPS. For GPS-assist modes: - Compass interference from power wires is the #1 cause of GPS-mode flyaways. The compass reads the magnetic field from the battery leads as a heading change and "corrects" by turning. - Fix: move the compass (external GPS/compass module) as far from power wires as possible. Use a GPS mast. - Check for GPS glitch in the log. A sudden position jump causes the FC to "correct" toward the wrong position.

Step 4: After landing, pull logs immediately. Don't fly again until you understand what happened. Logs will show stick inputs, actual motor outputs, sensor readings, and mode changes. The cause is almost always visible in the data.


Symptom: Video Loss / Breakup

FPV video feed drops, goes to static, shows artifacts, or freezes.

Step 1: Analog or digital?

Analog 5.8 GHz: - Gradual static/snow = range limit or obstruction. Normal degradation. - Sudden black screen = VTX failure, antenna disconnect, or power loss to VTX. - Rolling lines or interference pattern = self-interference from another transmitter on the same airframe (RC, mesh radio). - Check antenna connector. IPEX/U.FL connectors are fragile. A crash can unseat them without visible damage. Reseat and check. - Check VTX power. Is it set to the right level? Too low = no range. Too high = overheating (some VTXs thermal throttle or shut down).

Digital (DJI, HDZero, Walksnail): - Frozen frame = link degradation. Digital doesn't gracefully degrade like analog — it works perfectly until it doesn't, then freezes. - Gray screen / "No Signal" = complete link loss. - Latency spike = the link is fighting to maintain connection. Reduce range or increase power. - Check firmware versions. DJI goggles and air unit firmware must match. Mismatched firmware can cause connection failures.

Step 2: Is it consistent or intermittent? - Consistent at a specific distance/direction = range or obstruction. Normal. Adjust flight pattern or antenna. - Intermittent at close range = self-interference, loose antenna, or power supply issue. Check that VTX is getting clean power (no voltage sag from motor current). - Only happens at high throttle = voltage sag pulling VTX supply below minimum. Add a capacitor on the VTX power input or use a dedicated BEC.


Symptom: Motor Desync / Stuttering

One or more motors stutters, stops momentarily, or makes grinding sounds.

Step 1: Is it one motor or all? - One motor: likely ESC or motor issue (bearing, winding, timing) - All motors: likely FC signal issue (DShot errors, wiring)

Step 2: Swap the suspect ESC and motor. If the problem follows: - The motor: bad bearing or winding - The ESC: bad ESC - Neither (stays on the same arm): wiring issue on that arm

Step 3: Check motor timing. In BLHeli_S/BLHeli_32/AM32: - Stock timing is usually fine. If someone has adjusted it, try resetting to default. - High timing + high KV + low battery voltage = desync recipe.

Step 4: Check DShot settings. - Bidirectional DShot (for RPM filter) can cause desyncs on some ESC/motor combinations. Try disabling it to test. - DShot300 is more reliable than DShot600 on longer signal wires. If wires from FC to ESC are >10 cm, try DShot300.


Symptom: Failsafe Triggered in Flight

The drone enters failsafe (lands, returns home, or drops) unexpectedly.

Step 1: Determine which failsafe. - RC failsafe (lost RC link): check RC RSSI in the log. Was signal actually lost or did the FC misinterpret a signal issue? - Battery failsafe: check voltage in the log. Did voltage sag below threshold under load? - GPS failsafe (geofence, GPS loss): check GPS data in log. - GCS failsafe (ArduPilot/PX4): lost MAVLink heartbeat from GCS.

Step 2: RC failsafe diagnosis. - Check RSSI history in the log. A gradual decline to zero = range. A sudden drop = obstruction, interference, or antenna issue. - Check failsafe settings. Betaflight: failsafe_procedure. ArduPilot: FS_THR_ENABLE + FS_THR_VALUE. PX4: COM_RC_LOSS_T. - Is failsafe set to the right response? "Drop" is rarely what you want. "Land" or "RTH" are usually better. But RTH requires GPS — if GPS isn't locked, RTH failsafe may not work. - Check RC receiver failsafe behavior. Some receivers output "no pulses" on signal loss (correct). Others output last-known values (dangerous — FC doesn't know signal is lost). Others output a pre-set failsafe position. Verify your receiver's behavior.

Step 3: Battery failsafe diagnosis. - Voltage sag under load can briefly dip below the failsafe threshold even when the battery has plenty of capacity. - Fix: lower the failsafe voltage threshold, or use mAh-consumed instead of voltage as the trigger (more reliable). - Check battery internal resistance. An aging battery sags more under load. If your pack used to fly 5 minutes and now triggers failsafe at 3 minutes, the battery is dying.


Symptom: GPS Glitch / Toilet Bowl / Position Drift

In GPS-assist modes, the drone circles, drifts, or jumps to a wrong position.

Step 1: Check satellite count. Below 8-10 satellites, GPS position accuracy degrades significantly. Don't use GPS modes with < 8 sats.

Step 2: Check HDOP. Horizontal Dilution of Precision. Below 1.5 is good. Above 2.5 is unreliable. Above 4.0, don't trust GPS position at all.

Step 3: Toilet bowl = compass problem. The classic circular drift pattern means the compass heading is wrong, so the FC "corrects" in the wrong direction, overshoots, corrects again, and orbits. - Calibrate compass away from metal, cars, buildings. - Move external compass away from power wires and motors. - Check compass orientation matches FC configuration. - If using internal compass on an FC near ESCs: disable it and use external compass only.

Step 4: Position jumps = multipath or interference. - Near buildings, GPS signals bounce off walls, creating phantom positions. This is normal in urban environments. No fix except dual-band GPS (L1+L5) which is more resistant to multipath. - Near military installations or during exercises, GPS can be jammed or spoofed. If GPS suddenly shows you 50 km away, that's not a hardware problem.


The Universal Diagnostic Rule

When something breaks:

  1. Don't change multiple things at once. Change one thing, test, observe. If you change PID, filter, and rates all at once, you won't know what fixed (or broke) it.

  2. Pull logs before flying again. The data is in there. Every time you fly without understanding why it broke, you're gambling.

  3. Trust the instruments, not your memory. "I think it was oscillating on roll" is less useful than "gyro roll axis shows 200 Hz peak at 40% throttle." Log it. Read it. Then fix it.

  4. The simplest explanation is usually right. Loose prop nut causes more crashes than firmware bugs. Check the physical hardware first.


Next


Something broke. That's normal. The question is whether you understand why, or whether you're about to break it again.

Chapter 13: Adding a Companion Computer

A flight controller flies the drone. A companion computer thinks about why it's flying. They're different jobs on different hardware connected by a serial cable.


When You Need One

You don't need a companion computer to fly a drone. You need one when:

If all you need is fly-to-waypoint with GPS, the FC handles that natively on ArduPilot and PX4. Don't add complexity you don't need.


The Hardware Options

Platform CPU RAM GPU / Accelerator Weight Power Price Best For
Raspberry Pi 5 Cortex-A76 4-core 4-8 GB None (VideoCore for display) 50g 5-10W $60-80 General companion, MAVProxy, basic CV
Pi Zero 2W Cortex-A53 4-core 512 MB None 10g 1-3W $15 Lightweight telemetry, data logging, RF detect
Jetson Orin Nano Cortex-A78AE 6-core 8 GB 1024 CUDA + 32 Tensor 60g (module) 7-15W $250-500 ML inference, real-time CV, object detection
Jetson Orin NX Cortex-A78AE 8-core 8-16 GB 1024 CUDA + 32 Tensor 60g (module) 10-25W $400-900 Heavy ML, multiple camera streams
ModalAI VOXL 2 QRB5165 8 GB Hexagon DSP + GPU 16g 4-8W $400 Integrated flight platform, PX4 native
Radxa Zero 3W RK3566 4-core 2 GB Mali-G52 10g 2-4W $25 Budget Linux companion, WiFi scanning

What Matters Most

Weight: On a 5-inch quad, every gram counts. A Pi 5 at 50g (plus carrier board, cables, heatsink) adds 80-100g total. That's a significant percentage of all-up weight. A Pi Zero 2W at 10g is much more practical for small platforms.

Power: A companion drawing 10W from a 1300 mAh 6S battery is consuming roughly 30% of your total energy budget. Flight time drops proportionally. Budget the power before choosing the hardware.

I/O: The companion needs to connect to the FC (UART or USB), to the network (WiFi, Ethernet for mesh radio, USB for cellular), and to sensors (USB cameras, CSI cameras, SPI/I2C sensors). Count your I/O requirements before selecting hardware.


Connecting to the Flight Controller

The Physical Connection

The companion talks to the FC over serial (UART) or USB. Serial is preferred for reliability — USB adds a hub, OTG logic, and enumeration that can fail.

Companion TX  →  FC UART RX
Companion RX  →  FC UART TX
Companion GND →  FC GND

Baud rate: 921600 for high-bandwidth MAVLink. 115200 for MSP. Match both ends.

Level shifting: Pi GPIO is 3.3V. Most FCs are 3.3V. Compatible without level shifting. If your FC has 5V serial outputs (rare), use a level shifter or resistor divider.

The Protocol

ArduPilot / PX4: MAVLink v2. The companion runs mavproxy, MAVSDK, DroneKit, or a custom MAVLink parser. The FC streams telemetry to the companion and accepts commands from it.

# ArduPilot: connect via MAVSDK (Python)
from mavsdk import System
drone = System()
await drone.connect(system_address="serial:///dev/ttyAMA0:921600")
# PX4: connect via MAVSDK (same API, different autopilot behavior)
drone = System()
await drone.connect(system_address="serial:///dev/ttyAMA0:921600")

Betaflight / iNav: MSP over serial. The companion sends MSP requests and receives MSP responses. No streaming — poll-based.

# MSP: manual serial (simplified)
import serial
ser = serial.Serial('/dev/ttyAMA0', 115200)
# Send MSP_IDENT request
ser.write(bytes([0x24, 0x4D, 0x3C, 0x00, 0x64, 0x64]))
response = ser.read(32)

PX4 Dual-Channel

PX4 supports two simultaneous communication channels:

  1. MAVLink (UART) — commands, parameters, mission, C2
  2. uXRCE-DDS (UART or UDP) — high-bandwidth sensor telemetry, ROS2 topics

The dual-channel architecture lets you separate control traffic (low bandwidth, high priority) from data traffic (high bandwidth, lower priority). The companion runs a Micro-XRCE-DDS agent that bridges PX4's internal uORB topics to ROS2 topics on the companion.

This replaces the older microRTPS bridge. If you see references to microRTPS in older documentation, use uXRCE-DDS instead.


Software Stack

MAVProxy (Simplest)

MAVProxy is a command-line MAVLink proxy. It connects to the FC, parses MAVLink, and forwards it to multiple destinations (GCS, scripts, log files).

# Basic: FC on serial, forward to GCS on mesh radio
mavproxy.py \
  --master=/dev/ttyAMA0,921600 \
  --out=udp:10.0.0.255:14550

MAVProxy can run scripts (modules) that react to MAVLink messages. It's the fastest path from "I have a companion computer" to "I have telemetry flowing to a mesh radio."

MAVSDK (Programmatic Control)

MAVSDK is a library (Python, C++, Swift, Rust) for programmatic drone control over MAVLink. It abstracts MAVLink messages into clean API calls.

# Take off, fly to a point, land
await drone.action.arm()
await drone.action.takeoff()
await drone.action.goto_location(lat, lon, alt, yaw)
await drone.action.land()

MAVSDK is the recommended path for PX4. For ArduPilot, both MAVSDK and DroneKit work (DroneKit is older, more ArduPilot-specific).

ROS2 (Full Robotics Stack)

ROS2 (Robot Operating System 2) is the standard middleware for robotics. It provides publish/subscribe messaging, service calls, parameter management, and a massive ecosystem of packages for navigation, perception, planning, and control.

PX4 integrates with ROS2 via uXRCE-DDS. ArduPilot has a ROS2 interface via mavros2.

When to use ROS2: When you need sensor fusion (multiple cameras, LiDAR, IMU), SLAM (Simultaneous Localization and Mapping), path planning with obstacle avoidance, or integration with existing robotics software. ROS2 is heavyweight — it's the right choice for research and complex autonomy, overkill for "relay telemetry to a mesh radio."


Power and Cooling

Power Distribution

The companion needs clean, stable power. Noise from ESCs and motors on the main power bus will crash a Pi faster than any software bug.

Recommended: Dedicated BEC (Battery Eliminator Circuit) from the main battery to the companion. 5V, rated for the companion's peak current draw (2A minimum for Pi 5, 500mA for Pi Zero 2W).

Do not: - Power the companion from the FC's 5V rail (not enough current for most companions, and FC brownout risk) - Share a BEC with servos or LEDs (current spikes from servos cause voltage drops that crash the companion) - Use a USB cable to power the companion from the FC (USB host mode, OTG, and power delivery vary wildly between platforms)

Cooling

Most companions need cooling at sustained load. A Pi 5 at full CPU load will thermal throttle within minutes without airflow.

On a drone, the props create significant airflow. Mount the companion where prop wash hits the heatsink. In a sealed enclosure, this doesn't help — add a small thermal pad to conduct heat to the frame (carbon fiber is a reasonable heat spreader).

The VOXL 2 is designed for drones and handles thermal management internally. The Jetson Orin modules require active cooling (fan) for sustained ML inference.


The UART Budget Impact

Adding a companion computer consumes at least one FC UART. If you're using the companion-as-hub architecture (see Chapter 8), it may be the only non-RC UART you need — GPS, mesh radio, and telemetry radio connect to the companion instead of the FC.

Before (consuming 4 FC UARTs):
  FC ← RC receiver (UART1)
  FC ← GPS (UART2)
  FC ← Telemetry radio (UART3)
  FC ← Mesh radio (UART4)

After (consuming 2 FC UARTs):
  FC ← RC receiver (UART1)
  FC ← Companion MAVLink (UART2)
  Companion ← GPS (USB)
  Companion ← Telemetry radio (Ethernet)
  Companion ← Mesh radio (Ethernet)
  Companion ← Camera (USB/CSI)

This is one of the strongest practical reasons to add a companion even if you don't need AI or computer vision: it solves the UART shortage on F4-class FCs.


What to Start With

If you've never used a companion computer on a drone:

  1. Start with a Pi Zero 2W ($15, 10g, 2W). Wire it to the FC UART, install MAVProxy, forward telemetry to your laptop over WiFi. This proves the concept without the weight or power penalty.

  2. Graduate to a Pi 5 when you need more compute — running CV models, processing sensor data, or hosting a Wingman agent.

  3. Move to Jetson or VOXL 2 when you need real-time ML inference with multiple camera streams. This is where object detection, visual SLAM, and neural network planning live.

The hardware changes. The MAVLink connection pattern stays the same. Learn it once on a Pi Zero and it works the same on a Jetson.


Next


The flight controller flies. The companion thinks. Don't make the flight controller think. Don't make the companion fly.

Chapter 14: Mesh Radios for Multi-Vehicle Operations

The expensive tactical mesh radio in your kit bag is running the same open-source software as a $15 router. Knowing this changes how you think about mesh networking.


What Mesh Radios Actually Are

A mesh radio is a WiFi radio in a ruggedized enclosure with custom firmware that routes traffic between nodes without infrastructure. No access point, no router, no internet connection. Nodes find each other, establish links, and route packets through intermediate nodes to reach destinations.

That's it. Everything else is implementation detail.

The Software Stack (What They Won't Tell You in the Datasheet)

Vendor Operating System Mesh Protocol Radio Hardware
Doodle Labs OpenWRT (Linux) batman-adv (layer 2 mesh) Qualcomm/Atheros WiFi
Silvus Custom Linux Custom MAC + TDMA Custom MIMO radio
Persistent Systems Custom Linux Wave Relay (proprietary) Custom wideband
Rajant Custom Linux InstaMesh (proprietary) Dual-radio Atheros

Doodle Labs is the most transparent about this — their radios run OpenWRT, and if you SSH into one (which you can), you'll see batman-adv kernel modules, standard Linux networking, and iptables rules. The "mesh intelligence" that costs $3,000 per radio is largely batman-adv with custom antenna design and RF front-end optimization.

This isn't a criticism. Antenna design, RF front-end engineering, thermal management, and ruggedization are real engineering. The software is well-integrated and tuned. But understanding that the foundation is open-source Linux networking demystifies mesh radios and helps you troubleshoot them.


The Major Players

Doodle Labs

What they sell: Compact mesh radios from 200 MHz to 6 GHz. The Mini series (Mini900, Mini2400, etc.) are small enough to mount on a drone. The MR series are larger with better RF performance. The Helix series covers L/S/C bands for defense.

What's good: - Open platform (OpenWRT) — you can SSH in and configure anything - Small form factor (Mini series fits on a 5-inch quad) - Wide frequency range across the product line - batman-adv mesh is well-understood and debuggable - Active development, responsive technical support

What's not: - batman-adv mesh has convergence delays when topology changes (a drone moving fast can outrun the routing table) - Power consumption is significant (2-5W depending on model) - At the low end (Mini series), RF performance is limited by the tiny antenna and low TX power

Typical use: Commercial drone fleets, tactical ISR, research platforms, any application where you want mesh but also want to understand and customize the network.

Silvus Technologies

What they sell: StreamCaster mesh radios. Higher-end than Doodle Labs, with custom MIMO radio hardware and their own MAC-layer protocol. The SC4200/4400 series are the workhorses.

What's good: - Custom MIMO gives better spectral efficiency than commodity WiFi - TDMA-based MAC layer provides deterministic latency - High throughput (up to 100 Mbps per radio) - Strong defense/government customer base - Good video streaming support (multicast-aware mesh)

What's not: - Closed platform — you can't SSH in and debug the way you can with Doodle Labs - Expensive ($5,000-15,000 per node) - Configuration is through their web GUI, which is functional but not scriptable - Larger and heavier than Doodle Labs Mini series

Typical use: Defense ISR, government operations, commercial applications where budget supports the higher cost.

Persistent Systems

What they sell: MPU5 (manpack), Wave Relay ecosystem. The most mature tactical mesh network product. Used extensively by US SOF and allied forces.

What's good: - Wave Relay protocol is the most resilient mesh available — handles high mobility, rapid topology changes, and contested spectrum better than batman-adv - Proven in combat - Ecosystem includes vehicle mounts, body-worn units, drone-specific form factors - Integrated MANET management tools

What's not: - Most expensive option ($10,000-50,000 per node) - Heaviest option (MPU5 is not going on a 5-inch quad) - Closed ecosystem — Wave Relay doesn't interoperate with batman-adv or other mesh protocols - Long procurement cycles for military variants

Typical use: Military operations, high-end defense ISR, applications where proven combat performance justifies the cost.

Rajant

What they sell: BreadCrumb mesh radios. Dual-radio architecture (each node has two radios on different bands for simultaneous transmit and receive on different frequencies).

What's good: - Dual-radio avoids the half-duplex penalty of single-radio mesh - InstaMesh protocol handles mobility well - Good industrial track record (mining, oil & gas)

What's not: - Larger form factor than Doodle Labs - Less drone-specific than Silvus or Persistent

Typical use: Industrial applications, infrastructure monitoring, some defense applications.


Mesh Networking Fundamentals

How batman-adv Works (And Why It Matters)

batman-adv (Better Approach To Mobile Ad-hoc Networking - advanced) is a Linux kernel module that implements layer-2 mesh routing. It's what Doodle Labs and many other mesh products use underneath.

Key concepts: - Each node broadcasts OGMs (Originator Messages) periodically. These propagate through the mesh, allowing every node to learn the best path to every other node. - OGM interval (default 1 second) controls how fast the mesh adapts to topology changes. Lower = faster adaptation but more overhead. - TQ (Transmit Quality) is batman-adv's link quality metric. It's calculated from OGM reception rates. Higher = better link. - Routing is hop-by-hop. Each node only needs to know the next hop toward the destination, not the full path.

Why this matters for drones: Drones move fast. A mesh network optimized for static nodes (cell towers, sensor posts) may not adapt fast enough for a drone moving at 20+ m/s. If the OGM interval is 1 second and the drone has moved 20 meters since the last OGM, the routing table may be stale. Solutions: - Lower OGM interval (250-500 ms for fast-moving nodes) - Accept that mesh routing will lag position by 0.5-1 second - Use direct unicast for time-critical messages when nodes are within direct radio range (bypass mesh routing)

Throughput vs. Hops

Every hop in a mesh network costs throughput. A single-hop link at 50 Mbps becomes roughly: - 2 hops: ~25 Mbps - 3 hops: ~17 Mbps - 4 hops: ~12 Mbps

This is because traditional mesh radios are half-duplex — they can't transmit and receive at the same time on the same channel. Each hop requires the intermediate node to receive, then retransmit. Rajant's dual-radio approach mitigates this by receiving on one radio while transmitting on the other.

For drone operations: Keep the mesh shallow. 2-3 hops maximum for real-time data (telemetry, commands). Store-and-forward is acceptable for non-real-time data (sensor logs, blackbox files).

Channel Planning

Mesh radios on the same channel form a shared collision domain. More nodes = more contention = less per-node throughput.

Rules of thumb: - Up to 5 nodes on one channel works well - 5-15 nodes: consider splitting into two channels with a gateway node bridging them - 15+ nodes: you need a proper network plan with multiple channels and deliberate topology

For drone swarms, the practical limit is usually 8-12 platforms on a single mesh channel before throughput degrades noticeably. This aligns with typical tactical swarm sizes.


Practical Setup: Doodle Labs on a Drone

This section covers the most common drone mesh setup — a Doodle Labs Mini radio on a multi-rotor.

Physical Installation

Network Configuration

The companion computer (or FC with Ethernet) sends MAVLink over UDP to the mesh radio. The mesh radio delivers it to the GCS.

FC (UART) → Companion (mavproxy) → UDP → Mesh Radio → [mesh] → GCS

MAVProxy configuration on the companion:

mavproxy.py --master=/dev/ttyS1,921600 --out=udp:10.0.0.255:14550

On the GCS, QGroundControl or Mission Planner listens on UDP 14550 for incoming MAVLink from any mesh node.

Critical: Set the MAVLink system ID on each drone to a unique value. If two drones both use system ID 1, the GCS can't distinguish them. PX4: MAV_SYS_ID parameter. ArduPilot: SYSID_THISMAV parameter.


When Mesh Isn't The Answer

Mesh networking adds weight, power consumption, complexity, and a new failure mode to every platform. Before adding a mesh radio, ask:

Mesh is the right answer when you need multiple platforms sharing data simultaneously, beyond point-to-point range, with dynamic topology. For everything else, simpler is better.


Next


A $5,000 mesh radio is a $15 router with a great antenna and a ruggedized case. Respect the engineering. But don't be intimidated by it.

Chapter 15: TAK Integration

TAK is where your drone shows up on the map next to everyone else's position. Getting there doesn't require a defense contractor. It requires one UDP packet.


What TAK Is

TAK (Team Awareness Kit) is a situational awareness platform used by the US military, law enforcement, fire services, and increasingly by civilian teams. It shows positions, tracks, sensor data, and messages on a shared map.

The ecosystem: - ATAK — Android TAK (phone/tablet) - WinTAK — Windows version (laptop) - iTAK — iOS version - TAK Server — centralized server for team data sharing - WebTAK — browser-based viewer

TAK speaks one protocol: Cursor-on-Target (CoT). Everything that appears on the map is a CoT event — an XML message with a type, position, and metadata. If your drone can send a CoT event, it appears on TAK.


Cursor-on-Target (CoT) Basics

A CoT event is an XML message. Here's the minimum viable drone position report:

<?xml version="1.0" encoding="UTF-8"?>
<event version="2.0"
       uid="drone-01"
       type="a-f-A-M-H-Q"
       how="m-g"
       time="2026-03-16T18:30:00Z"
       start="2026-03-16T18:30:00Z"
       stale="2026-03-16T18:30:30Z">
  <point lat="44.9778" lon="-93.2650" hae="300"
         ce="10" le="15"/>
</event>

That's it. Send this over UDP to port 4242 on a TAK Server or directly to ATAK devices on the local network, and your drone appears on the map.

The Fields That Matter

uid: Unique identifier for your drone. Once set, every update with the same uid moves the same icon on the map. Use something stable — wingman-{tooth-id} or drone-{serial}.

type: The CoT type code determines the icon and classification. It follows the 2525C symbology standard:

Type Code Meaning Icon
a-f-A-M-H-Q Friendly, Air, Military, Rotary Wing Blue helicopter
a-f-A-M-F-Q Friendly, Air, Military, Fixed Wing Blue airplane
a-f-G Friendly, Ground Blue ground vehicle
a-n-A-M-H-Q Neutral, Air, Rotary Wing Green helicopter
a-h-A-M-H-Q Hostile, Air, Rotary Wing Red helicopter
a-h-G-E-V-A Hostile, Ground, Equipment, Vehicle Red vehicle (used for RF detections)

The first character after a- is the affiliation: f = friendly, n = neutral, h = hostile, u = unknown.

how: How the position was determined. m-g = machine GPS, h-e = human entry, h-g-i-g-o = GPS from another source.

time/start/stale: When the event was generated, when it starts being valid, and when it becomes stale (should be removed from the map if not refreshed). Set stale to 30-60 seconds for a moving drone so the icon disappears if the drone stops reporting.

point: Latitude, longitude, height above ellipsoid (meters), circular error (meters), linear error (meters).


Adding Detail

Telemetry in CoT

CoT supports a <detail> element for additional data. TAK clients display this in the info popup when you tap the icon:

<event ...>
  <point lat="44.9778" lon="-93.2650" hae="300" ce="10" le="15"/>
  <detail>
    <remarks>Battery: 14.8V (76%) | Alt: 300m AGL | Speed: 12 m/s</remarks>
    <track course="045" speed="12"/>
    <contact callsign="WINGMAN-01"/>
    <__group name="Blue" role="Team Member"/>
  </detail>
</event>

track: Course (degrees true) and speed (m/s). Allows TAK to show heading arrows and predict future position.

contact: The callsign displayed on the map next to the icon.

__group: Team assignment and role. Determines icon color in some TAK configurations.

remarks: Free-text field. Put your telemetry summary here. ATAK shows it in the detail popup.

Sensor Point of Interest

When your drone detects something (RF emission, visual target, anomaly), send a separate CoT event for the detection:

<event uid="detect-001"
       type="a-h-G-E-V-A"
       how="m-g" ...>
  <point lat="44.9790" lon="-93.2640" hae="0" ce="50" le="50"/>
  <detail>
    <remarks>RF Detection: DoodleLabs MR900 | RSSI: -72 dBm | Bearing: 045</remarks>
    <contact callsign="RF-DETECT-001"/>
  </detail>
</event>

This places a hostile marker on the map at the estimated position of the detection. The NeedleNThread tactical RF detector uses exactly this pattern to push detections to TAK.


Transport: Getting CoT to TAK

Direct UDP (Simplest)

Send CoT XML as a UDP packet to ATAK devices on the local network. Default port: 4242.

import socket

cot_xml = '''<?xml version="1.0" encoding="UTF-8"?>
<event version="2.0" uid="drone-01" type="a-f-A-M-H-Q"
       how="m-g" time="{time}" start="{time}" stale="{stale}">
  <point lat="{lat}" lon="{lon}" hae="{alt}" ce="10" le="15"/>
  <detail>
    <contact callsign="WINGMAN-01"/>
    <track course="{heading}" speed="{speed}"/>
  </detail>
</event>'''

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(cot_xml.encode(), ('239.2.3.1', 6969))  # multicast
# or
sock.sendto(cot_xml.encode(), ('192.168.1.100', 4242))  # unicast to ATAK device

Multicast (239.2.3.1:6969) reaches all ATAK devices on the local network without knowing their IPs. Requires a network that supports multicast (WiFi works, some mesh radios don't forward multicast by default).

Unicast to a specific IP is more reliable but requires knowing the ATAK device's address.

Via TAK Server

A TAK Server centralizes all CoT traffic. Devices connect to the server (TCP, TLS, or WebSocket) and the server distributes events to all connected clients.

The drone (or its companion computer) connects to the TAK Server and sends CoT events. All ATAK/WinTAK clients connected to the same server see the drone.

FreeTAKServer is an open-source TAK Server that runs on a Pi, laptop, or cloud VM. It handles basic CoT routing without the complexity of the official TAK Server.

pip install FreeTAKServer
python -m FreeTAKServer.controllers.services.FTS

Via Mesh Radio

If the drone has a mesh radio (Chapter 14), CoT can travel over the mesh. The companion computer sends CoT to the mesh radio's IP, and the mesh radio delivers it to the GCS or TAK Server on the other end.

Drone: FC → Companion → CoT UDP → Mesh Radio → [mesh] → GCS/TAK Server

This is the standard architecture for tactical drone operations. The mesh radio carries both MAVLink (for flight control) and CoT (for situational awareness) on the same link, typically on different UDP ports.


Integration Points

From the Flight Controller

The FC has the position, altitude, heading, speed, and battery data. This needs to get from the FC to the TAK sender:

ArduPilot/PX4: MAVLink messages on the companion → parse GLOBAL_POSITION_INT, VFR_HUD, BATTERY_STATUS → format as CoT → send.

Betaflight/iNav: MSP on the companion → parse MSP_RAW_GPS, MSP_ATTITUDE, MSP_ANALOG → format as CoT → send. Or use the ELRS/CRSF telemetry downlink on the transmitter side → forward to ATAK on the GCS phone.

From Sensors

Payload sensors (cameras, RF detectors, environmental) generate their own CoT events through the companion computer. Each detection gets its own uid and type code.

From the Wingman Ecosystem

The Wingman architecture naturally generates TAK-compatible data: - Tooth mesh: Fleet position sharing maps directly to CoT events - Seed detections: Acoustic, RF, and PIR detections become CoT hostile/unknown markers - Wingman Command: The Command layer IS the TAK integration point for the full ecosystem — it translates Wingman mesh data into the CoT format that existing TAK infrastructure consumes


Practical Tips

1. Keep CoT events small. TAK clients handle thousands of events. Your drone doesn't need to send a novel — position, callsign, basic telemetry in remarks. The detail popup in ATAK has limited space.

2. Update rate: 1 Hz is enough. TAK is situational awareness, not flight control. Sending position once per second is plenty. Faster than that wastes bandwidth and doesn't improve the map display.

3. Use meaningful callsigns. "WINGMAN-01" is useful on a shared map. "drone-abc123def" is not. Callsigns should be short, unique, and recognizable.

4. Set stale time appropriately. 30 seconds for a moving drone. If the drone stops sending CoT (crash, link loss, battery dead), the icon disappears from the map after the stale time. This is correct behavior — a stale position is worse than no position.

5. Test with ATAK first. Install ATAK on an Android phone, connect to the same network as your CoT sender, and verify the icon appears. Don't integrate with a TAK Server until direct UDP works.

6. CoT type codes matter. Using the wrong type code means your drone shows up as a ground vehicle, or a hostile, or a waypoint. Get the type code right for your affiliation and platform type.


Next


TAK is a shared map. Your drone belongs on it. One UDP packet puts it there. Everything else is refinement.