
1. 无人机通信协议全景1.1 三个关键词MAVLink、PPM、SBUS 到底在无人机里扮演什么角色刚开始玩无人机的时候最容易懵的事情不是怎么飞而是看不懂飞控背后的那堆线。一堆杜邦线、排针、接收机、数传模块每个接口旁边还标着看不懂的英文缩写RX、TX、SBUS、PPM、TELEM...如果你把某个插头插错位置飞控可能毫无反应甚至直接冒烟。这其实就是通信协议的锅。无人机内部各个模块之间要说话PPM、SBUS、MAVLink 就是它们各自的语言体系。PPM 和 SBUS 负责把遥控器的手柄操作转成飞控能读懂的通道数据MAVLink 则负责飞控和地面站、机载电脑之间传递状态信息和任务指令。要真正理解无人机这三条协议绕不开。先抛结论PPM 和 SBUS 都属于遥控链路层面的输入协议解决的是遥控器怎么把操作意图传给飞控MAVLink 属于遥测和任务链路层面的通信协议解决的是飞控怎么把状态告诉地面站、地面站怎么把航点下发到飞控。两者层级不同但经常出现在同一台无人机上所以大家容易混在一起。这篇文章就把它们逐个拆开讲清楚。1.2 遥控链路与数传链路两条逻辑线不要混在深入协议之前先理清一条逻辑线一架无人机里数据的流动路径其实可以分为两条主流。第一条是遥控链路从遥控器发射机到接收机再到飞控。你要打杆、切模式、解锁、返航这些操作都走这条路。PPM 和 SBUS 就是这条路线上飞控和接收机之间的通信方式。老式遥控器还经常用 PWM一根信号线对应一个通道通道多了就得拉一捆线PPM 和 SBUS 则用一根信号线传所有通道。第二条是数传链路从飞控到地面站软件Mission Planner、QGroundControl 等或者机载电脑树莓派、NVIDIA Jetson 之类。你在地面站上看到的高度、速度、电池电压、卫星数都是通过这条路传上来的你在电脑上规划一系列航点也需要走这条路下发。MAVLink 就是这条链路上最常见的语言。这两条线有时候会交汇比如某些接收机支持遥测回传能把接收信号强度通过遥控链路反向发回遥控器再比如 ArduPilot 允许你把遥控通道值记录进日志方便回放分析。但概念上先把这两条逻辑分开后面看协议就不会乱。2. MAVLink 深度解析2.1 MAVLink 的诞生与设计思路MAVLink 全称 Micro Air Vehicle Link最早由 Lorenz Meier 在 2009 年为了 PX4 项目设计。后来 ArduPilot 也开始采用逐渐成了开源飞控领域的事实标准。为什么要专门设计一个协议而不是直接用现成的 TCP/IP 或者简单的串口字符串因为无人机通信有自己独特的约束带宽有限、链路可能丢包、消息要求低延迟、还要支持不同厂商设备互操作。MAVLink 的设计目标就是轻量、可靠、可扩展。MAVLink 有两种主要版本MAVLink 1 和 MAVLink 2。MAVLink 2 在 1 的基础上增加了消息签名、扩展帧头、更大的载荷上限是目前推荐使用的版本。ArduPilot 从 4.x 系列开始全面支持 MAVLink 2默认也是按 MAVLink 2 输出。MAVLink 的本质是一种二进制串行协议数据按固定格式打包成帧通过串口、UDP、TCP 等载体传输。它不关心底层物理链路是 USB 线、数传电台还是局域网只要你有一个能传字节的通道就能跑 MAVLink。2.2 MAVLink 消息帧结构与解析流程MAVLink 的帧结构有点像快递包裹每一层都有固定字段收件人拿到包裹先验视再拆包。一个标准的 MAVLink 2 帧长这样帧起始标志STX固定值 0xFD表示这是 MAVLink 2 消息。MAVLink 1 是 0xFE看到第一个字节基本就能区分版本。帧长度LEN表示后面载荷区域的字节数。不兼容标志INC_FLAGS和兼容标志CMP_FLAGS用来做签名、扩展等特性开关。序列号SEQ消息序号用于检测丢包。系统 IDSYS ID区分同一链路上的不同飞行器或地面站。组件 IDCOMP ID区分同一系统内的不同组件比如飞控是 1摄像头是 100。消息 IDMSG ID告诉接收方这条消息是心跳、姿态、航点还是别的什么。载荷PAYLOAD实际的消息内容比如姿态消息里就是横滚角、俯仰角、偏航角。校验和CRC从协议里提取出来的 16 位 CRC用于完整性校验。签名SIGNATURE可选字段MAVLink 2 里如果开启签名会额外多出 13 个字节防止消息被伪造或篡改。解析流程其实不复杂。接收端拿到串口字节流后先等一个 0xFD然后读取长度字段再按长度读完整的帧最后做 CRC 校验。校验通过就把载荷交给对应的消息解析器。很多刚开始接触的人看到 CRC 会问串口通信本身有奇偶校验为什么还要在协议层再算一次因为串口校验只保证字节在物理传输过程中没有被干扰不能保证发端和收端使用的是同一套帧格式。MAVLink 的 CRC 里还混入了消息的指纹信息如果收发两端的消息定义不一致CRC 就对不上就能及时发现问题。这个设计在飞控固件升级后特别有用端和端定义不匹配时会立刻体现出来。2.3 常用 MAVLink 消息盘点MAVLink 目前定义了上百种消息日常开发真正高频用到的其实就那么几个。HEARTBEAT心跳是所有 MAVLink 系统的基础。飞控会定时默认 1 秒向外广播心跳消息告诉地面站我还在线我的类型是 ArduPilot当前飞行模式是什么。地面站如果连续一段时间没收到心跳就会提示连接断开。GPS_RAW_INTGPS 原始信息携带经纬度、海拔、地面速度、卫星数、定位类型。地面站画地图轨迹靠的就是它。ATTITUDE姿态携带四元数和欧拉角。如果你看地面站的姿态仪表盘在动那就是 ATTITUDE 消息在工作。GLOBAL_POSITION_INT 是经过滤波后的全局位置估计包含经纬度、相对高度、绝对高度和三维速度。相比 GPS_RAW_INT这个值更平滑更适合任务逻辑使用。SYS_STATUS系统状态包含电池电压、电流、剩余电量、传感器健康位。很多地面站的电池显示就依赖这条消息。任务相关的消息有 MISSION_ITEM_INT、MISSION_COUNT、MISSION_REQUEST_INT 等。地面站下发航点的时候会先发一个 MISSION_COUNT 告诉飞控下面要传多少个航点然后飞控逐个发送 MISSION_ITEM_INT 请求地面站再逐条把航点发过去。整个过程有一个明确的握手流程保证每个航点都送达传完后还要 MISSION_ACK 确认。高频发送的消息一般有速率控制。ArduPilot 里 SR0_EXTRA、SR1_POSITION 等参数就是干这个的。合理设置消息传输速率能有效避免链路带宽被无用的消息占满。2.4 MAVLink 的应用场景和哪种场景不该用MAVLink 最常见的应用是飞控与地面站之间的通信但它的应用边界远不止于此。机载电脑通过串口或 USB 连接飞控用 MAVLink 读取实时状态、发送指令这是无人机自动驾驶最常见的架构。开源生态里非常成熟的 MAVSDK 就是面向机载电脑的 MAVLink 开发库支持 Python、C、Swift 等多种语言。编队飞行也是 MAVLink 的重要场景。多台无人机通过数传组网共享位置和速度信息配合规划算法实现编队。MAVLink 默认的广播模式天然支持这种拓扑同一链路上一台飞控广播的消息其他飞控也都能收到。不过 MAVLink 并非万能。它的设计目标是飞行控制相关的高频小数据包不适合传大文件。很多新手尝试用 MAVLink 传图片结果发现带宽几乎被榨干还耽误正常遥测这就是用错了场景。图像和视频应该走独立链路比如 WiFi 图传或者 HDMI 采集卡MAVLink 只负责元数据和指令。3. PPM 工作原理与适用场景3.1 PPM 信号到底是怎么编码的PPM 全称 Pulse Position Modulation脉冲位置调制。它的核心思想是把所有通道的油门、方向、开关状态按顺序塞进一个固定周期的信号里用高电平保持的时间长度来表示每个通道的数值。具体来说一个完整的 PPM 帧大约 20 到 25 毫秒帧的起始由一个比较宽的同步脉冲标记出来。同步脉冲之后是一连串窄脉冲两个窄脉冲之间的时间间隔代表一个通道的值。每个通道值范围通常是 1000 到 2000 微秒对应 PWM 输入的最小到最大。如果某个通道值是 1500 微秒就说明这个通道处于中立位置。举个例子8 通道的 PPM 信号大概是这样的结构同步脉冲约 300 微秒高电平通道 0 的间隔时间比如 1200 微秒窄脉冲约 300 微秒高电平通道 1 的间隔时间比如 1500 微秒窄脉冲依次类推直到第 8 个通道帧之间的空白时间填充到 20 毫秒周期接收机输出的 PPM 信号本质上是把原本独立的 PWM 通道信号串行化。原来 8 通道需要 8 根信号线现在只需要 1 根信号线代价是对时序的要求更高。任何一段电平跳变抖动都可能被解码器解读成错误的通道值。很多飞控的输入端有 PPM 编码器电路直接把接收机输出的 PPM 信号解码成各通道的 PWM 值。Pixhawk 系列飞控通常要求把接收机信号线接到 RC_IN 接口。ArduPilot 在参数里设置 RC_PROTOCOLS 为 0 时会同时自动检测 PPM 和 SBUS 输入。3.2 用示波器看一段真实 PPM 信号如果你手头有示波器或者逻辑分析仪强烈建议实际抓一段 PPM 信号看看。我最初就是用逻辑分析仪看了 PPM 波形之后才对脉冲位置调制有了直观的理解。把接收机的 PPM 输出接上逻辑分析仪设置采样率不低于 1 MHz手动拨动遥控器油门杆你能看到清晰的波形一个宽的同步脉冲后面跟着一串均匀分布的窄脉冲。通道值变化时对应的间隔会变大或变小。整个过程肉眼很难看出差异必须借助处理器的时间捕获功能测量。在代码层面PPM 解码通常用输入捕获中断。MCU 捕获到每次上升沿或下降沿的时间戳时间差就是电平持续时间再根据帧周期和通道间隔来划分通道。如果你要自己写 PPM 解码器重点关注的不是高电平本身而是两个上升沿之间的时间间隔。这是新手最容易搞反的地方以为通道值等于脉冲宽度其实是等于脉冲间隔。3.3 PPM 的局限性延迟、精度和协议天花板PPM 最大的问题是精度和延迟。精度方面PPM 的一个通道间隔通常解析到 1 微秒量级这在 1000 到 2000 微秒的量程里理论精度大约千分之一。实际中因为帧周期固定通道间隔受到上一通道和下一通道抖动的影响精度会更差一些。对于油门、方向这类通道这个精度完全够用但如果你用遥控通道去做云台微调或者特殊控制模式精度不足的问题会暴露出来。延迟方面因为所有通道是串行传输的最后一个通道必须等前面所有通道都说完之后才能轮到自己。8 通道 PPM 信号最后一个通道的更新周期约等于一个完整帧周期也就是 20 毫秒左右。相比之下SBUS 全通道串行传输的帧周期是 14 毫秒延迟更小。还有一个天花板PPM 的通道数上限受帧周期限制。标准 20 毫秒周期最多塞 8 到 10 个通道。如果你要 12 通道甚至 16 通道遥控PPM 就撑不住了。这也解释了为什么现代遥控协议逐渐往 SBUS、CRSF 这类数字协议迁移。顺便说一句PPM 是模拟时代的产物但它并没有完全退役。很多入门级接收机和开源飞控仍然支持 PPM 输入因为简单、稳定、兼容性好。对于只飞 4 通道、6 通道固定翼或多旋翼的玩家PPM 依然是够用的方案。3.4 PPM 适合用在什么场景基于上面的特性PPM 的适用场景比较明确。一是入门级搭建。新手第一次焊飞控、接接收机的时候PPM 接线最简单通常只要一根信号线加一根地线接收机只要有 PPM 输出就够。出错概率低排查也直观。二是备用通道少的小型机架。比如 250 级别以下的穿越机如果你不需要太多通道用 PPM 可以减少一根线机身更清爽。三是对延迟不敏感的飞行器。慢速固定翼、FPV 巡航、测绘无人机对打杆延迟的敏感度远低于穿越机。这种场景下 PPM 的延迟感知并不明显。如果你的目标是高速穿越机或竞速机建议跳过 PPM直接上 SBUS 或 CRSF。延迟和帧率差距在高速飞行中会直接影响手感。4. SBUS 深度解析4.1 SBUS 的信号格式与数据帧结构SBUS 是由 Futaba 推出的一种串行总线协议如今已经被大量第三方接收机、飞控、舵机支持成了遥控链路里事实上的数字标准。SBUS 底层走的是 UART 串口波特率固定 1000008 位数据位、偶校验、2 位停止位。注意这个波特率不是常规的 9600、115200而是 100000这导致它不能直接接到普通串口工具上解析需要专门的硬件或软件适配。SBUS 数据帧长度固定 25 字节其中 22 字节是通道数据每 11 位一个通道一共 16 个通道。11 位的分辨率意味着通道值范围是 0 到 2047比 PPM 的精度高了不少。实际飞控通常会把 0 到 2047 映射成 1000 到 2000 的 PWM 值范围通道 1 到 16 的数据按小端字节序连续存放。除了通道数据SBUS 帧里还包含标志位和尾字节。标志位用于指示信号丢失、舵机帧失败等状态尾字节固定是 0x00。帧之间有一个明显的空闲间隔接收端根据这个间隔来同步帧边界。SBUS 信号还有一个坑逻辑电平是反相的。Futaba 在设计时把信号发出来的时候就是反相的很多飞控的 SBUS 输入接口内部有反相电路但如果你买的是那种廉价接收机转接板可能需要自己加一级反相器。这一点我在后面的常见问题里再详细展开。4.2 用数据视角看 SBUS 与 PPM 的差异如果只看最终效果SBUS 和 PPM 都是把遥控器通道数据传给飞控但数据组织方式截然不同。PPM 是模拟时序信号每个通道的数值体现在脉冲间隔里解码需要精确的定时测量SBUS 是数字信号每个通道的数值体现在二进制数据里解码只需要正确读取字节然后拼位。打个比方PPM 像摩尔斯电码靠长短间隔表达信息SBUS 像普通文本文件按格式读取即可。数据率方面SBUS 的 16 通道同时传输帧周期 14 毫秒实际约 7 毫秒高电平 7 毫秒低电平最大 14 毫秒对应约 70 Hz 的刷新率。这比 20 毫秒周期的 PPM 有优势而且通道数更多、分辨率更高所以现代高端遥控器普遍支持 SBUS 输出。ArduPilot 里对 SBUS 的处理是把串口接收到的字节流按 SBUS 帧结构解析然后再转成 RC 通道值。如果你接的是 SBUS 信号注意接收机接飞控的线要接到 RC_IN而不是普通串口。很多飞控的 SBUS 输入口和 PPM 输入口是同一个物理接口固件自动识别协议类型但硬件上需要有反相电路。4.3 SBUS 的优势和局限优势第一条就是通道数和精度。16 通道对绝大多数无人机绰绰有余11 位分辨率也能满足精细操作需求。优势第二条是延迟更低。数字协议不需要像 PPM 那样等待帧周期全部走完数据打包后一次性传输处理效率更高。对于穿越机选手来说SBUS 比 PPM 延迟低是一种可感知的改善。局限方面SBUS 最大的问题是兼容性。它毕竟是 Futaba 制定的私有协议虽然被广泛支持但在细节上各厂商实现并不完全一致。部分廉价接收机输出的 SBUS 信号时序不稳定偶发丢帧部分飞控对 SBUS 的反相处理不够好导致信号无法识别。另一个局限是 SBUS 能传输的信息种类有限。它只是单向遥控通道数据不支持回传。如果你需要接收机把 RSSI接收信号强度等参数回传给飞控甚至地面站得找支持相应回传协议的接收机或者另外走一条遥测链路。这一点和 MAVLink 的丰富消息体系形成鲜明对比。4.4 SBUS 的适用场景SBUS 几乎覆盖了 PPM 的全部场景而且更优秀。所以如果条件允许建议优先用 SBUS。穿越机和竞速机是 SBUS 的最大受益者。低延迟、高刷新率让打杆反馈更跟手这也是穿越机玩家普遍追求数字协议的原因。大型多旋翼和固定翼也是 SBUS 的主场。你可能有 8 通道甚至 12 通道的需求比如控制起落架、云台、投掷器、相机触发等SBUS 可以轻松满足。还有一个实用场景是飞控调参。当你需要在地面站里观察遥控器各通道的输入是否正常时SBUS 提供更准确的数值映射后的通道值稳定很少出现 PPM 那种跳变。5. 三者对比怎么选怎么用5.1 一张表看懂 MAVLink、PPM、SBUS对比维度MAVLinkPPMSBUS通信层级遥测/任务链路遥控输入链路遥控输入链路信号类型二进制串行数据包模拟时序脉冲数字串行数据传输内容状态、指令、航点、参数等1-10 通道的遥控值1-16 通道的遥控值典型波特率/帧率57600/115200 等取决于链路每帧 20-25ms每帧 14ms100000 波特率通道分辨率不适用消息字段约 1us 间隔11 位0-2047是否需要专门硬件串口/TTL/数传模块输入捕获引脚UART 反相电路双向通信支持飞控与地面站双向不支持单向不支持单向可扩展性消息可以自定义受帧长限制固定结构不可扩展适用场景地面站交互、自动驾驶、编队入门机、低通道数穿越机、多通道高端机这张表建议大家存下来。选型的时候先问一句这条链路上要传什么如果是遥控操作指令在 PPM 和 SBUS 之间二选一如果是飞控与电脑之间的状态和任务那考虑 MAVLink。5.2 从硬件层面看信号线应该怎么接硬件接线是新手最容易困惑的地方。PPM 接收机通常有 CH1 到 CH8 的引脚其中 CH1 或标注为 PPM 的输出引脚输出合并后的 PPM 信号。把该引脚接到飞控的 RC IN 信号脚即可。SBUS 接收机一般有一个专门的 SBUS 引脚如果没有有的接收机允许你在编程设置里把某个通道改成 SBUS 输出。把 SBUS 引脚接到飞控的 SBUS/RX 输入脚注意部分飞控还需要一根反向信号线。很多现代飞控都集成了 SBUS 反相电路直接接就行老飞控或者自制的转接板上可能需要三极管反相电路。MAVLink 走的是数传串口。Pixhawk 系列飞控上有 TELEM1、TELEM2 接口每一个都是四针TX、RX、VCC、GND。接数传模块时飞控的 TX 接数传的 RX飞控的 RX 接数传的 TXVCC 和 GND 对应接好。如果你用的是机载电脑可以直接用 USB 线连飞控的 USB 口或者通过 UART 转接板连接。5.3 从软件层面看三种协议的配合一台完成了的无人机软件层面往往是三种协议同时在工作。飞控启动后接收机通过 PPM 或 SBUS 输入遥控信号经过协处理器或主控解码后映射到 RC 通道值RC Channel。ArduPilot 把通道 1-4 默认映射为 Roll、Pitch、Throttle、Yaw通道 5 以上是模式开关和辅助开关。地面上你在 Mission Planner 的 RC 界面看到的值就是经过映射后的结果。与此同时飞控通过 MAVLink 持续向外广播心跳和状态消息。地面站收到后把飞控模式和传感器状态显示在界面里。你在地面站上点写航点地面站就把航点数据用 MAVLink 消息发送给飞控飞控存储到参数和任务列表里。飞行时飞控根据 MAVLink 下发的任务和当前姿态解算控制输出同时继续通过遥控链路接收手动打杆指令。三者的配合核心是遥控链路和数传链路是独立的两套通路飞控是它们的交汇点。如果你想做更高级的开发比如在机载电脑上写 Python 脚本控制飞行实际上是在和 MAVLink 打交道而不是直接干涉 PPM/SBUS。6. 实战用 Python 通过 MAVLink 给 ArduPilot 发航点6.1 环境准备与连接方式这一节我们进入实操。假设你手里有一台 ArduPilot 飞控Pixhawk 系列或同类目标是通过 USB 或数传连接电脑用 Python 代码向飞控下发一组航点。推荐用 pymavlink 这个 Python 库。它是 MAVLink 官方生态的 Python 实现安装很简单pip install pymavlink连接方式有两种。USB 直连时Linux 下一般识别为 /dev/ttyACM0Windows 下是 COM3 之类数传模块连接时通常是一个串口设备。确定设备路径后用 pymavlink 建立连接from pymavlink import mavutil # USB 直连时波特率通常 115200数传则按数传模块的波特率设置 master mavutil.mavlink_connection(/dev/ttyACM0, baud115200) # 等待飞控心跳确认通信链路正常 master.wait_heartbeat() print(收到心跳飞控在线)如果这一步卡住了先检查设备路径是否正确、串口是否被占用、波特率是否匹配。常见的坑是插着 Mission Planner 占用了串口导致 Python 无法打开。6.2 发送航点的完整代码ArduPilot 的航点上传遵循一个明确的消息握手流程先发 MISSION_COUNT 声明航点数量然后逐个处理飞控返回的 MISSION_REQUEST_INT 请求每个请求对应一个航点索引我们用 MISSION_ITEM_INT 把对应航点发送过去最后飞控返回 MISSION_ACK。下面是一份可以直接跑通的示例代码往飞控上传两个航点import time from pymavlink import mavutil master mavutil.mavlink_connection(/dev/ttyACM0, baud115200) master.wait_heartbeat() # 清除当前任务避免旧航点干扰 master.mav.mission_clear_all_send(master.target_system, master.target_component) # 等待清除确认 ack master.recv_match(type[MISSION_ACK], blockingTrue) print(f清除任务结果: {ack}) # 定义航点列表(纬度, 经度, 相对高度) waypoints [ (31.123456, 121.654321, 20.0), (31.123457, 121.654322, 25.0), ] # 发送航点数量 master.mav.mission_count_send(master.target_system, master.target_component, len(waypoints), 0) # 逐个响应飞控的请求 sent 0 while sent len(waypoints): msg master.recv_match(type[MISSION_REQUEST_INT, MISSION_REQUEST], blockingTrue) seq msg.seq lat, lon, alt waypoints[seq] master.mav.mission_item_int_send( master.target_system, master.target_component, seq, # 航点序号 mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT, # 坐标系全局相对高度 mavutil.mavlink.MAV_CMD_NAV_WAYPOINT, # 命令类型普通航点 0, 0, # 是否继续自动航点、是否从当前点开始 0, 0, 0, # 参数1-3停留时间、半径、通过半径 int(lat * 1e7), # 纬度单位 1e-7 度 int(lon * 1e7), # 经度 float(alt), # 高度 0, 0, # 相机相关参数不需要就置 0 mavutil.mavlink.MAVLINK_TYPE_MISSION_ITEM_INT ) sent 1 # 等待最终确认 ack master.recv_match(type[MISSION_ACK], blockingTrue) print(f航点上传结果: {ack})这段代码有几点需要解释。纬度、经度用 int 类型单位是 1e-7 度所以要把浮点数乘以 1e7 再取整。如果你直接填浮点数飞控会解析错误。坐标系用了 MAV_FRAME_GLOBAL_RELATIVE_ALT意思是经纬度取全局真实坐标高度取相对于起飞点的海拔。这是大多数无人机任务的默认选择因为不需要知道绝对海拔也不用担心气压计漂移。参数 1、2、3 的含义随命令类型变化。对 NAV_WAYPOINT 来说参数 1 是停留时间秒参数 2 是到达半径米参数 3 是通过半径米。常用的设置是参数 2 设为 0.2 到 0.5 米表示飞机到距离航点中心这么多米就算到达。航点上传成功后你可以用下面代码切到 AUTO 模式让飞控执行任务# 切换飞行模式 mode_id master.mode_mapping().get(AUTO) if mode_id is None: print(未知模式) else: master.set_mode_apm(mode_id)注意 ArduPilot 默认要求解锁后才能自动起飞执行任务。如果你只是测试航点上传不需要解锁上传成功后在地面站里也能看到任务列表被更新。6.3 自定义 MAVLink 消息的实现思路热词里提到MAVLink 自定义消息这里展开讲一下。MAVLink 2 之所以比 MAVLink 1 强大除了签名和扩展性之外一个关键点是支持在 XML 中定义自己的消息然后生成对应的编解码代码。pymavlink 支持自定义消息。步骤是在某个目录里新建一个 XML 文件比如 my_messages.xml里面用 MAVLink 的 XML 语法定义消息名、ID、字段。用 mavgen.py 脚本生成 Python 代码。把生成的代码放进项目里import 后就能使用自定义消息。例如定义一个简单的调试消息mavlink messages message id150 nameMY_DEBUG descriptionCustom debug message/description field typefloat namevalueA float value/field field typeuint16_t nameindexIndex number/field /message /messages /mavlink生成代码后发送方调用 my_debug_send 发送接收方在 mavlink 回调里捕获 MY_DEBUG 消息即可。不过要提醒一句自定义消息只适合两端都是你控制的设备。如果一端是标准地面站或标准 MAVLink 库对方不会解析你的自定义消息可能会报警或忽略。实际项目中我一般建议优先用标准消息里已有的字段或者用 DEBUG_VECT、STATUSTEXT 这类通用消息来传递调试信息。只有确实没有标准方案时才考虑自定义消息。7. 常见问题与排查技巧7.1 遥控器没反应飞控收不到通道输入这是新手最高频的问题。接好线、通电、对频成功但打杆没反应。排查顺序建议按下面来打开 Mission Planner 的 Radio Calibration 页面观察通道值是否随打杆变化。如果通道值不动说明接收机和飞控之间的链路没通。确认接线是否正确。很多飞控的 RC_IN 接口是有方向性的信号线、电源线、地线的引脚定义别接反。如果信号线接了但没反应检查接收机是否真的输出了 PPM 或 SBUS。有的接收机出厂默认 PWM 输出需要进接收机设置里改协议。检查飞控的 RC_PROTOCOLS 参数。ArduPilot 里 RC_PROTOCOLS0 表示自动检测有些自定义固件里默认值可能不同需要改成 0 或指定协议。确认固件版本。老版本固件对 SBUS 反相的支持可能不完善更新固件后重试。7.2 SBUS 信号接反或接收失效SBUS 最经典的坑就是反相。我把話放这里几乎每个从 PPM 转 SBUS 的玩家都踩过这个坑。当你把 SBUS 接收机接到飞控发现飞控死活不识别通道值时第一反应应该是检查信号反相。最简单的方法是用逻辑分析仪抓一下 SBUS 引脚的电平。正常 SBUS 信号在空闲时是低电平如果抓到的空闲电平是高电平说明信号是反相的。解决方式有三种购买支持自动反相的接收机或飞控。现在主流的 Pixhawk 飞控大多内置反相电路不需要额外处理。自己做一个反相电路。用一个 NPN 三极管就能实现网上有现成电路图。用飞控内部参数处理。部分飞控固件里的 RC_PROTOCOLS 或 SERIAL_OPTIONS 参数有Signal Inverted选项调节后可能解决。另外注意有些飞控的 SBUS 输入引脚和 UART 引脚复用如果你在参数里把对应的串口设为其他功能SBUS 输入可能会失效。7.3 MAVLink 通信丢包或连不上地面站MAVLink 连接不上的原因五花八门最常见的有三个。串口被占用。Mission Planner 或其他地面站程序占用着串口你再开 Python 或者第二个地面站肯定连不上。解决办法是关闭其他程序或者用不同的 USB 口。波特率不匹配。飞控端 TELEM1 默认波特率一般是 57600USB 口默认 115200。如果你用数传模块连接数传模块空中波特率为 57600地面端也要配成 57600。曾经有个朋友把数传模块的地面端波特率设置成 115200连接上但数据全是乱码排查了好久才发现是波特率问题。线路接触不良或数传模块供电不足。数传模块虽然有 VCC 和 GND 接线但个别质量差的 USB 转串口线供电能力弱导致数传模块无线重连。这种问题表现很诡异心跳偶尔能收到但很快断开。建议用独立供电的 USB Hub或者换一根质量好的数据线。7.4 协议转换模块怎么选硬件的世界里还有一种常见需求是把一种协议转成另一种。比如某些飞控只有 PPM 输入而你的遥控器接收机只支持 SBUS 输出或者你想用地面站通过 MAVLink 控制一个只支持模拟遥控输入的飞控。如果只是 PPM 和 SBUS 互转市面上有专门的小模块比如PPM to SBUS 转换器或者SBUS to PPM 转换器。选这种模块时要看清楚输入输出逻辑电平是否匹配、是否支持反相、通道数上限是多少。便宜的模块可能只转了信号没有做反相处理接上去还是不行。如果是 MAVLink 和其他协议的转换就有意思了。很多开源项目比如 MAVProxy、QGroundControl 本身就支持多种 MAVLink 传输端点用一根 USB 线连接飞控和电脑不需要额外模块。如果你需要在物理层把 MAVLink 转成串口透传基本就是一个 UART 转 TTL 模块没有协议上的魔法。8. 最后分享几个实操心得写到这里我把这几年和这三类协议打交道的体会一并说透希望能帮你少走弯路。第一个心得信号完整性的优先级远高于协议本身。不管是 PPM、SBUS 还是 MAVLink信号线一定要用短线、屏蔽线或者双绞线并且避开电调和大电流线。无人机上电调产生的电磁干扰非常强我曾经在一个四轴上把接收机信号线和电调线平行走结果 SBUS 信号在地上站上表现为间歇性丢通道重新布线后才恢复正常。别小看这种问题排查起来非常费时间。第二个心得动手前先做地面测试。拿到一套新飞控、新接收机不要直接上桨先接好所有线进入 Mission Planner 或 QGroundControl 检查通道映射、模式切换是否正常再用文字指令或者模拟器验证 MAVLink 通信。我见过不少飞友在装好机后首次试飞因为通道方向反了直接翻机。地面测试花 10 分钟能避免炸机的损失。第三个心得尽量用较新版本的 MAVLink 和固件。ArduPilot 从 4.1 开始默认使用 MAVLink 2对自定义消息、签名、扩展字段的支持都更好。如果你还在用老固件建议升级到 4.1 以上很多莫名其妙的兼容性问题会在升级后消失。第四个心得对数传链路带宽做一点规划。MAVLink 默认的 SRx 参数设置的是每秒发送几条消息如果你同时连接地面站和机载电脑两个消费端会共享链路带宽。有时候地面站显示卡顿不是硬件问题而是因为 SR0_EXTRA 里配置了太多不必要的高频消息。按需关闭一些消息你会发现链路稳定很多。第五个心得不要把 SBUS 和 CRSF 搞混。同样是数字串行协议SBUS 是 100000 波特率、偶校验、2 停止位、11 位通道CRSF 是 420000 波特率、8N1、每个通道 16 位还支持双向通信。穿越机圈子里现在 CRSF 越来越流行因为它延迟更低还能回传遥控器和接收机状态。如果你买的是 ExpressLRS 接收机默认输出通常是 CRSF不是 SBUS。接错后飞控不识别是玩穿越机最容易犯的错之一。如果你能把 MAVLink、PPM、SBUS 这三条线彻底理解透无人机在你的眼里就不再是一堆线和参数而是一套可以灵活组合、按需定制的完整系统。希望这篇长文能帮你把最基础、也最关键的一环打结实。