3、通信链路层:串口通信原理与配置、UDP/TCP网络通信、MAVLink over WiFi/4G/5G、链路质量评估与断线重连机制
地面站和无人机之间怎么说话?说白了,就是靠通信链路。我做了这么多年PX4地面站,见过太多因为链路问题炸机的案例。链路层要是没搞明白,上层协议写得再漂亮也是白搭。
这一章我们就把通信链路层彻底吃透。从最底层的串口,到网络层的UDP/TCP,再到承载MAVLink的各种无线介质,最后聊聊链路质量评估和断线重连——这些都是地面站系统的命脉。
3.1 串口通信原理与配置
串口是地面站和飞控之间最经典的连接方式。别看它老,稳定可靠是它的金字招牌。我记得2018年做第一个地面站原型时,就是用串口线连着Pixhawk调试,一跑就是十几个小时,从来没掉过链子。
3.1.1 串口参数匹配
串口通信的核心就四个参数:波特率、数据位、停止位、校验位。两边必须完全一致,否则收到的全是乱码。
| 参数 | PX4飞控默认值 | 地面站推荐值 | 说明 |
|---|---|---|---|
| 波特率 | 57600 / 115200 | 115200 | 速率越高,但抗干扰能力下降 |
| 数据位 | 8 | 8 | 标准值,不要改 |
| 停止位 | 1 | 1 | 2位停止位极少用 |
| 校验位 | 无 | 无 | MAVLink自带校验,串口层不需要 |
3.1.2 串口编程要点
在Linux上操作串口,我习惯用termios库。下面是一个配置串口的核心代码片段:
// 串口配置核心代码(C语言)
int setup_serial(const char* device, int baudrate) {
int fd = open(device, O_RDWR | O_NOCTTY);
if (fd < 0) return -1;
struct termios tty;
memset(&tty, 0, sizeof(tty));
// 获取当前配置
tcgetattr(fd, &tty);
// 设置波特率
cfsetospeed(&tty, baudrate);
cfsetispeed(&tty, baudrate);
// 8N1模式:8数据位,无校验,1停止位
tty.c_cflag &= ~PARENB; // 无校验
tty.c_cflag &= ~CSTOPB; // 1位停止位
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; // 8位数据
// 禁用硬件流控
tty.c_cflag &= ~CRTSCTS;
// 原始模式输入输出
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tty.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL);
tty.c_oflag &= ~OPOST;
// 设置读取超时
tty.c_cc[VMIN] = 0; // 非阻塞
tty.c_cc[VTIME] = 1; // 100ms超时
tcsetattr(fd, TCSANOW, &tty);
return fd;
}
3.2 UDP/TCP网络通信
当无人机飞远了,串口线就不现实了。这时候就得靠网络通信。UDP和TCP是地面站最常用的两种传输层协议。
3.2.1 UDP vs TCP 怎么选?
这个问题我每次培训都会被问到。直接上对比表:
| 特性 | UDP | TCP |
|---|---|---|
| 连接方式 | 无连接 | 面向连接 |
| 可靠性 | 不可靠,丢包不重传 | 可靠,丢包自动重传 |
| 延迟 | 低,实时性好 | 较高,重传导致延迟抖动 |
| 适用场景 | 实时遥测、视频流 | 参数上传、固件升级 |
| 地面站推荐 | 主链路(默认) | 备用链路或文件传输 |
我个人习惯:遥测数据走UDP,因为MAVLink协议本身就有丢包检测和重传机制,不需要TCP再包一层。但如果是上传飞控参数或刷固件,我会切到TCP——这些操作不容许丢任何一个字节。
3.2.2 地面站网络架构
地面站的网络通信通常采用客户端-服务器模式。飞控端(或数传电台)作为服务器,地面站作为客户端主动连接。
// UDP地面站客户端示例(Python)
import socket
import threading
class GCS_UDP_Client:
def __init__(self, remote_ip, remote_port, local_port=14550):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind(('0.0.0.0', local_port))
self.remote_addr = (remote_ip, remote_port)
self.running = True
def send(self, data):
self.sock.sendto(data, self.remote_addr)
def recv(self, bufsize=1024):
try:
data, addr = self.sock.recvfrom(bufsize)
return data
except:
return None
def start_recv_loop(self, callback):
def _loop():
while self.running:
data = self.recv()
if data:
callback(data)
threading.Thread(target=_loop, daemon=True).start()
3.3 MAVLink over WiFi/4G/5G
有了网络层,MAVLink就可以跑在各种无线介质上了。WiFi适合近距离,4G/5G适合超视距。我去年做了一个跨省无人机巡检项目,用的就是5G链路,延迟控制在30ms以内,效果相当不错。
3.3.1 各介质对比
| 介质 | 典型延迟 | 带宽 | 通信距离 | 典型场景 |
|---|---|---|---|---|
| WiFi(2.4G/5.8G) | 5-20ms | 高 | 100-500m | 近距离调试、编队飞行 |
| 4G LTE | 30-80ms | 中 | 不限(有信号) | 超视距巡检、物流配送 |
| 5G | 10-30ms | 高 | 不限(有信号) | 高清图传、远程操控 |
| 数传电台 | 10-50ms | 低 | 1-30km | 工业测绘、农业植保 |
3.3.2 4G/5G链路的关键配置
用4G/5G做MAVLink链路,有几个坑必须避开:
- NAT穿透: 运营商网络通常没有公网IP,需要搭建中继服务器或使用P2P打洞技术。我习惯用MQTT做中继,稳定且容易调试。
- 心跳保活: 运营商NAT会话有超时时间(通常30-300秒),必须定期发送心跳包维持连接。MAVLink的HEARTBEAT消息正好干这个用。
- 带宽控制: 4G上行带宽有限,不要一股脑把所有数据都往上推。我一般会把遥测数据降频,比如GPS位置降到5Hz,姿态数据降到10Hz。
3.4 链路质量评估与断线重连机制
链路质量评估,说白了就是实时监控通信链路好不好。断线重连,就是链路断了之后怎么自动恢复。这两个功能是地面站稳定运行的基石。
3.4.1 链路质量评估指标
我一般用以下几个指标来评估链路质量:
| 指标 | 计算方式 | 正常范围 | 告警阈值 |
|---|---|---|---|
| RSSI(信号强度) | 从数传模块读取 | -50 ~ -80 dBm | < -90 dBm |
| 丢包率 | 丢失包数 / 总包数 | < 5% | > 15% |
| 延迟 | 发送到接收的时间差 | < 100ms | > 500ms |
| 抖动 | 延迟的标准差 | < 30ms | > 100ms |
3.4.2 断线重连策略
断线重连不是简单的「断了就重连」。我总结了一套分级策略:
- 一级:链路劣化(丢包率 > 15%)
- 降低遥测数据频率
- 关闭非关键数据流(如日志上传)
- 提示操作员注意链路状态
- 二级:链路中断(连续3秒无数据)
- 启动快速重连:每秒尝试一次,持续10秒
- 切换备用链路(如果有)
- 记录断线时间戳
- 三级:长时间断线(超过30秒)
- 切换为重连策略:每5秒尝试一次
- 触发飞控端自动返航(RTL)
- 在地面站界面显示断线状态
// 断线重连逻辑伪代码
void connection_manager() {
while (running) {
if (check_link_alive()) {
// 链路正常,评估质量
evaluate_link_quality();
sleep(100ms);
} else {
// 链路中断,启动重连
int retry_count = 0;
while (retry_count < MAX_RETRY && !check_link_alive()) {
attempt_reconnect();
if (retry_count < 10) {
sleep(1s); // 快速重连
} else {
sleep(5s); // 慢速重连
}
retry_count++;
}
if (!check_link_alive()) {
trigger_rtl(); // 触发返航
}
}
}
}
3.4.3 链路状态可视化
地面站界面上,我习惯用颜色和图标直观展示链路状态:
- 绿色: 链路正常,丢包率 < 5%
- 黄色: 链路劣化,丢包率 5%-15%
- 红色: 链路差,丢包率 > 15%
- 灰色: 链路中断
同时显示RSSI数值和丢包率百分比,让操作员一目了然。