4、关键消息定义:COMMAND_INT、COMMAND_LONG、PROTOCOL_VERSION

好,咱们进入第四章。这一章我打算聊聊三个在电调校准里绕不开的消息——COMMAND_INT、COMMAND_LONG 和 PROTOCOL_VERSION。你可能会问,为什么要把它们放在一起讲?

说白了,这三个东西决定了你的地面站和飞控之间能不能「好好说话」。我在做第一个飞控项目时,就因为在协议版本上踩了坑,导致电调死活不响应校准指令。后来才发现,是版本号没对齐。

嗯,咱们一个一个来看。

4.1 COMMAND_LONG:最常用的指令载体

COMMAND_LONG 是 MAVLink 里最通用的指令消息。它的编号是 #76。我个人习惯把它叫做「万能指令包」。

它的结构很简单,但很实用:

uint16_t command    // 指令编号,比如 MAV_CMD_DO_SET_MOTOR
uint8_t confirmation // 确认标志,0表示无需确认
uint8_t target_system // 目标系统ID
uint8_t target_component // 目标组件ID
float param1..param7  // 7个参数,每个都是32位浮点

为什么是7个参数?你想想看,一个电调校准指令,可能需要设置油门行程、校准模式、超时时间……7个参数基本够用。我在实际项目中,最多用到过5个参数,剩下的都填0。

我的习惯:发送 COMMAND_LONG 时,confirmation 字段第一次填0,如果没收到 ACK,重试时填1。这样飞控可以区分是首次发送还是重发,避免重复执行。

4.2 COMMAND_INT:带坐标的指令

COMMAND_INT(#75)和 COMMAND_LONG 很像,但有一个关键区别——它的参数用整数表示坐标。

看它的结构:

uint16_t command
uint8_t target_system
uint8_t target_component
uint8_t frame      // 坐标系,比如 MAV_FRAME_GLOBAL
uint16_t current   // 当前航点标记
uint16_t autocontinue // 自动继续标记
float param1..param3  // 前3个参数是浮点
int32_t x, y, z       // 坐标参数,用整数表示
float param4..param7  // 后4个参数是浮点

你可能会问:「电调校准用得到坐标吗?」

嗯,一般情况下用不到。但如果你在做无人机编队校准,或者需要根据GPS位置动态调整电调参数,COMMAND_INT 就派上用场了。我记得有一次做多机协同测试,需要每架飞机在不同位置执行不同的校准流程,就是用 COMMAND_INT 把位置信息带进去的。

注意:COMMAND_INT 的 x/y/z 是 int32_t,单位取决于 frame 字段。如果是经纬度,单位是 1e7 度。我曾经见过有人直接把经纬度当整数发过去,结果飞机以为自己在南极。

4.3 PROTOCOL_VERSION:握手的暗号

PROTOCOL_VERSION 不是一条独立的消息,而是 MAVLink 协议握手阶段的一个关键字段。它通常出现在 HEARTBEAT 消息里,或者作为 AUTOPILOT_VERSION 的一部分。

它的作用很简单:告诉对方「我用的是哪个版本的协议」。

MAVLink 目前有两个主流版本:

版本 特点 适用场景
MAVLink 1.0 8字节 payload 头,消息ID 8位 老旧设备、资源受限的飞控
MAVLink 2.0 12字节 payload 头,消息ID 24位,支持签名 现代飞控、需要安全通信的场景

我个人建议,新项目直接用 MAVLink 2.0。为什么?因为它的消息ID范围更大,不容易冲突。而且支持签名,可以防止有人伪造指令。我曾经在开源飞控上遇到过有人通过地面站发送伪造的校准指令,差点把电调烧了。后来升级到 MAVLink 2.0 并启用签名,这个问题就解决了。

关键点:电调校准过程中,地面站和飞控必须使用相同的协议版本。如果版本不匹配,飞控会直接丢弃指令。我建议在握手阶段就检查 PROTOCOL_VERSION,不匹配就报错,别等到校准开始了才发现。

4.4 三者的关系

为了让你更直观地理解这三个消息的关系,我画了一张图:

COMMAND_INT、COMMAND_LONG、PROTOCOL_VERSION 关系图 地面站 (GCS) 飞控 (FC) PROTOCOL_VERSION 握手 COMMAND_LONG (通用指令) COMMAND_INT (带坐标指令) 电调 (ESC) 说明: 1. 先通过 PROTOCOL_VERSION 握手确认版本 2. 再通过 COMMAND_LONG 或 COMMAND_INT 发送校准指令

从这张图你可以看到,整个流程分三步:

  1. 握手阶段:地面站和飞控交换 PROTOCOL_VERSION,确认双方使用同一版本的协议。
  2. 指令发送:地面站根据需求选择 COMMAND_LONG 或 COMMAND_INT,发送校准指令。
  3. 指令执行:飞控解析指令,转发给电调执行。
避坑指南:我曾经在调试时发现,地面站发送了 COMMAND_LONG,但飞控就是不响应。查了半天,发现是 PROTOCOL_VERSION 不匹配——地面站用的是 MAVLink 2.0,飞控固件只支持 MAVLink 1.0。所以,我建议你在握手阶段就打印版本号,确认一致后再往下走。

4.5 实际应用中的选择

那么,在实际的电调校准中,到底该用哪个?

我的建议是:

  • 普通校准:用 COMMAND_LONG。它简单、通用,7个参数足够覆盖大多数场景。
  • 带位置信息的校准:用 COMMAND_INT。比如你需要根据飞机当前位置动态调整校准参数。
  • 协议版本:优先用 MAVLink 2.0。如果遇到老旧设备,再降级到 1.0。

嗯,这一章的内容就到这里。记住,这三个消息是电调校准的「基础设施」,搞懂了它们,后面的流程就顺了。