MAVLink Flow Control & Throttling
Executive Summary
ArduPilot uses a "Pull-Based" flow control system. Instead of blindly pushing messages into a buffer and hoping for the best, the scheduler explicitly queries the hardware: "Do you have space for 40 bytes?". If the answer is No, the message is skipped for this cycle. This prevents internal buffer overflows but can result in "gappy" telemetry if the link bandwidth is saturated.
Theory & Concepts
1. Backpressure (The Clogged Pipe)
Imagine a funnel. You can pour water in faster than it drains out, but only until the funnel is full.
- The Funnel: The TX Buffer (RAM).
- The Drain: The Serial Baud Rate (Radio Speed).
- The Pour: MAVLink Scheduler.
- Backpressure: When the funnel is full, the water (data) spills over. ArduPilot checks the funnel level before pouring. If it's full, it holds the cup.
2. CTS/RTS (Hardware Flow Control)
- CTS (Clear To Send): A wire from the Radio to the Flight Controller.
- Low: "I'm ready!"
- High: "Stop! My buffer is full!"
- Mechanism: If the radio is transmitting a slow packet over the air, it pulls CTS High. The Flight Controller's UART driver sees this and stops pushing bits out of its internal buffer.
Architecture (The Engineer's View)
1. The Gatekeeper: comm_get_txspace
Before any message is generated, the macro HAVE_PAYLOAD_SPACE(chan, id) is called.
- It calls
comm_get_txspace(chan). - It queries the HAL UART Driver for
write_space(). - Result: This returns the number of bytes free in the hardware ring buffer.
2. The Decision Logic
Inside do_try_send_message():
- Check Space: Calculate the packet size. If
Free_Space < Packet_Size, ABORT. - Abort Behavior:
- The function returns
false. - The
last_sent_mstimestamp is NOT updated. - Consequence: The scheduler moves on to the next task. In the next main loop (e.g., 2.5ms later), it will see this message is still "overdue" and try again.
- Effect: Messages simply "slide" in time until bandwidth opens up. They are not dropped in the traditional networking sense (packet loss), but they are delayed (latency).
- The function returns
3. Hardware Flow Control (RTS/CTS)
If your telemetry radio supports hardware flow control (RTS/CTS pins):
- Radio Buffer Full: The radio pulls the CTS pin high.
- UART Driver: The HAL driver detects this and stops shifting bytes out of its ring buffer.
- Ring Buffer Fills: The internal buffer fills up.
- Back Pressure:
comm_get_txspacestarts returning 0. - Scheduler Pauses: ArduPilot stops generating MAVLink packets entirely until the radio clears its throat.
Common Issues & Troubleshooting
"Telemetry stops when I download parameters"
- Cause: Parameter packets are large and sent as fast as possible. They fill the buffer instantly.
- Mechanism: The scheduler sees
txspace == 0for lower-priority telemetry messages (like Attitude) and skips them. - Fix: Use
MAV_CMD_SET_MESSAGE_INTERVALto increase priority of critical streams, or use a faster link (USB/Wifi).
"ELRS / Crossfire Telemetry is slow"
- Cause: These links have extremely small buffers (often just a few packets).
- Mechanism: The link throttles heavily. ArduPilot's 50Hz streams saturate the link immediately, causing massive "sliding" delays.
- Fix: Reduce
SRx_rates to match the actual throughput of the link (e.g., 2Hz or 4Hz).
Source Code Reference
- Space Check:
comm_get_txspace() - Send Loop:
GCS_MAVLINK::do_try_send_message()