4. 连接飞控:通过串口连接Pixhawk、读取心跳包、验证连接状态
好,咱们进入实战环节的第一个硬骨头——把地面站和飞控真正连起来。
很多初学者觉得这步很简单,插上线就行。嗯,我当年也这么想。结果第一次调参时,地面站死活连不上,折腾了整整一个下午。后来发现,就是波特率没对上。
所以这一章,咱们把串口连接的每个细节都掰开揉碎。你跟着走一遍,以后遇到类似问题,心里就有底了。
4.1 串口通信基础
Pixhawk 和地面站之间,说白了就是通过串口在聊天。一个发,一个收,约定好说话的速度和格式。
| 参数 | Pixhawk 默认值 | 说明 |
|---|---|---|
| 波特率 | 115200 | 每秒传输的比特数,越高越快 |
| 数据位 | 8 | 每个字节用8位表示 |
| 停止位 | 1 | 字节结束的标志位 |
| 校验位 | 无 | 不启用奇偶校验 |
你可能会问:为什么是 115200?其实早期飞控用 57600 甚至 38400 都有。115200 是后来统一的标准,兼顾了速度和稳定性。我在一个项目中试过 921600,结果线稍微长一点就丢包,得不偿失。
4.2 硬件连接与端口识别
先把 Pixhawk 用 USB 线连到电脑。这时候别急着写代码,先确认系统认没认到设备。
Windows 用户:打开设备管理器,看「端口 (COM 和 LPT)」下面有没有出现类似 USB Serial Device (COM3) 的条目。如果没有,检查驱动或换根线。
Linux / macOS 用户:终端里敲 ls /dev/tty*,找类似 /dev/ttyACM0 或 /dev/ttyUSB0 的设备。Pixhawk 通常是 ACM 开头。
4.3 Python 串口编程实战
Python 里操作串口,最常用的库是 pyserial。先装好它:
pip install pyserial
然后,咱们写一个最基础的连接脚本:
import serial
import time
# 配置串口参数
ser = serial.Serial(
port='/dev/ttyACM0', # Windows 下改成 'COM3'
baudrate=115200,
bytesize=8,
parity='N',
stopbits=1,
timeout=2 # 读取超时2秒
)
print(f"已连接到 {ser.portstr}")
# 持续读取数据
try:
while True:
if ser.in_waiting > 0:
data = ser.read(ser.in_waiting)
print(data.hex())
time.sleep(0.01)
except KeyboardInterrupt:
ser.close()
print("连接已关闭")
跑一下这个脚本,你会看到一串串十六进制数据刷出来。别慌,这就是飞控在不停往外吐的数据流。
Permission denied,说明当前用户没有串口权限。执行 sudo usermod -a -G dialout $USER 然后注销重登,或者临时用 sudo python 跑脚本。
4.4 解读心跳包
飞控发出来的数据里,有一种特殊的报文叫「心跳包」。它的作用是告诉地面站:我还活着,系统状态正常。
MAVLink 协议里,心跳包的 ID 是 0(也就是 HEARTBEAT)。它的结构长这样:
| 字段 | 字节偏移 | 说明 |
|---|---|---|
| STX(起始标志) | 0 | 0xFD(MAVLink 2)或 0xFE(MAVLink 1) |
| LEN(长度) | 1 | 有效载荷长度 |
| SEQ(序列号) | 2 | 报文序号,用于检测丢包 |
| SYS ID(系统ID) | 3 | 飞控的编号,通常为1 |
| COMP ID(组件ID) | 4 | 组件编号,飞控通常为1 |
| MSG ID(消息ID) | 5-7 | 0 表示心跳包 |
| 有效载荷 | 8+ | 包含系统状态、模式等信息 |
咱们不需要手动解析每个字节。用 pymavlink 库,几行代码就能搞定:
pip install pymavlink
from pymavlink import mavutil
# 创建连接
master = mavutil.mavlink_connection('/dev/ttyACM0', baud=115200)
# 等待第一个心跳包
print("等待飞控心跳...")
master.wait_heartbeat()
print(f"收到心跳!系统ID: {master.target_system}, 组件ID: {master.target_component}")
# 持续接收并打印心跳
while True:
msg = master.recv_match(type='HEARTBEAT', blocking=True)
if msg:
print(f"模式: {mavutil.mode_string_v10(msg)}, 状态: {msg.system_status}")
跑起来之后,你会看到类似这样的输出:
等待飞控心跳...
收到心跳!系统ID: 1, 组件ID: 1
模式: STABILIZE, 状态: 3
模式: STABILIZE, 状态: 3
模式: ALT_HOLD, 状态: 3
看到没?飞控每隔几秒就会发一次心跳。如果超过 3 秒没收到,那就要检查连接了。
- 连续收到 3 个以上心跳包,且序列号递增
- 系统状态值在 0-6 之间(0=未初始化,3=活跃,6=紧急)
- 模式字符串能正确解析
4.5 常见问题与避坑
我在项目里遇到过不少连接问题,挑几个典型的说说:
- 端口被占用:有时候 Mission Planner 或 QGroundControl 没关干净,串口就被占用了。关掉所有地面站软件再试。
- 波特率不匹配:有些飞控固件默认是 57600。如果 115200 连不上,试试 57600 或 38400。
- USB 线质量差:这个坑我踩过好几次。劣质 USB 线只能充电,不能传数据。换根好线立马解决。
- 驱动问题:Windows 下 Pixhawk 需要装驱动。去官网下载「Zadig」工具,把设备驱动换成 WinUSB 或 libusb。
4.6 知识体系总览
下面这张图,把本章的核心逻辑串起来了:
从硬件连接开始,到端口识别、串口配置,再到数据读取和心跳解析,最后验证状态——每一步都环环相扣。任何一个环节出问题,地面站都连不上飞控。
4.7 本章小结
到这,你应该能独立完成飞控的串口连接了。总结几个关键点:
- 串口参数必须和飞控固件一致,尤其是波特率
- 心跳包是验证连接的黄金标准,学会用 pymavlink 解析它
- 遇到问题先从硬件排查:线、端口、驱动