一篇文章讲明白什么是mavlink(不玩飞控,但是想用mavlink协议)

本文介绍了Mavlink通信协议的基础概念,包括数据类型、帧结构、校验方法以及其在飞控中的应用。重点强调了Mavlink的广泛兼容性、社区支持和使用便利性,特别是在简化代码生成和单片机通信中的作用。
摘要由CSDN通过智能技术生成

什么是mavlink

什么是通信协议

如果你已经知道什么是通信协议可以直接跳到下一节

了解mavlink之前,我们要先了解什么是通信协议。通信协议是一种规定了数据传输格式、传输速率、错误检测和纠正等通信过程中所需的规则和约定的标准或约定。侠义的讲,只要你用串口了,就必定要用到通信协议,无论是调试,打印错误代码或者进行平衡车控制,大家都要约定好通信速率,数据是16进制还是ascii码。对于普通的调试打印大多数只是ascii(UTF-8等)码显示,这时候只要规定好通讯速率就好。

16进制还是ascii码

如果你调试的平衡车,这时候除了接收小车发送的状态信息,还是要给小车发送指令,这时候如果还是用ascii码就有点吃力了,一是同样的信息ascii码占的位数要比16进制多很多,例如给小车发送速度为100,如果是ascii码那么就是'1''0''0'共3个字节,而16进制只占1个字节0x64,对于单片机来说,带宽是非常小的,大多数串口速率为9.6kbps,高的为115.2kbps,对于单片机来说显然使用16进制是更好选择,二是单片机可以直接处理16进制,对于ascii码首先要转为16进制0x64才能处理,会额为增加单片机处理时间。

数据的解析,从帧开始

如何让单片机知道我发的是速度,而不是角度的。如果只发一个0x64对于单片机来说显然是不能分辨出是速度还是角度的,如果是ascii可以发送"LV:100 AV:10"来区分线速度和角度,这里LV(line velocity)和AV(angular velocity)可以作为区分。对于16进制我们同样要引入一个数据位来区分两者,称之为指令、命令或者功能位。例如0x01后面跟的是线速度,0x02后面跟得角速度,当然也可以定义0x03后面第一个字节是线速度,第二个字节是角速度。

发送0x01 0x64代表线速度设置100,

发送0x02 0x0A 代表角速度设置为10,

发送0x03 0x64 0x0A则代表同时设置线速度为100,角速度10.

这时候我们已经引入了两个核心的数据类型,指令和数据(负载、payload),有了这两个核心的类型,就够了吗。也够也不够,如果我收到的是0x01 0x02 0x04 怎么办,是线速度为2,还是角速度为4呢,这里帧的概念,帧是协议中的最小单位,0x01 0x64和0x02 0x0A都是一帧数据。那我们如何来区分帧呢,常用的有三种方式一种是基于时间的例如modbus就是利用3.5个字节进行断帧,stm32的uart也有空闲中断,都是利用时间进行断帧,即如果我长时间没有收到新的数据那么就认为一帧传输结束。如果先收到的0x01 0x02 过了一段时间收到0x04那么显然是线速度为2。这里有个弊端就是如果通信不稳定,特别是无线传输则有可能收到的是0x02 空闲 0x01 空闲 0x04空闲,那么这几个数据都会被抛弃。还有一种是靠帧头来做区分的,即我传输开始会先发一个固定的数据标识一帧的开始,通常使用的0xAA,0X55等。这时候协议就变成了

0xAA 0x01 0x64

0xAA 0x02 0x0A

还有一种是固定长度,即所有协议的长度都是固定的,这里不展开讲。

好了我们在指令、数据之外又引入了帧头,这样就可以了吗,对于一个可靠的协议来说还远远不够,一是我们选择帧头时尽管经量选择数据中不会出现的字节来做帧头,但显然这是不可靠的。这时候有的人会引入"帧尾",但是聪明如你显然也看出如果一个协议足够复杂,同样不够可靠的。那有没有办法来保证数据是正确的,常用的有两个分别是"长度"和"校验"。“校验”不但保证我这一帧断帧是正确的,还能保证数据是正确的,如果数据在传输过程中有干扰出现跳位,同样无法通过校验从而抛弃这一帧,常用校验有奇偶校验、和校验,CRC、哈希等。综合算力,校验结果长度,可靠性,这里选择CRC校验。什么是CRC校验?这里不展开讲,CRC为2字节以下用CRCH和CRCL代替不在计算具体CRC值。“长度”可以保证我们在解析的时候明确知道后面还有多少数据,对于长度不一且不依靠时间断帧的协议来说可以说是必须的。由于帧头、指令,校验是固定的长度,通常从"长度"字节只包含数据长度。这时候协议就变成了如下:

0xAA 0x01 0x01 0x64 CRCH CRCL

0xAA 0x02 0x01 0x0A CRCH CRCL

0xAA 0x03 0x02 0x64 0x0A CRCH CRCL

到现在为止我们可以说把一个通用协议有时候称之为“自由口”的所有关键数据类型都讲述完成,拿着这套协议架构,可以去自己定义任意一对一的通信了。

一对一?

为什么说是可以定义任意的一对一的协议,而不是任意协议?认为在协议中还有一类是一主多从,甚至多主多从的总线型协议,典型RS485就是总线型,多个设备公用同一个数据通道,一个节点(设备)发送到总线的数据,其他所有节点都可以接收到。那么这是时候如果收到一帧

0xAA 0x01 0x01 0x64 CRCH CRCL

就会很尴尬,这是谁发的,发给谁的,我该不该解析。这时候我们又引入ID的概念,通过不同的ID来区分消息是发送给谁的,有时候会有发送ID和接收ID。但是对于单片机来说通常一个ID就足够了。同时为了知道是否丢包了。通信质量怎么样,还会引入“序号(seq)”,序号每发送一帧自动加1,如果你收到序号1的帧之后收到序号4的帧,则表明中间序号为2,3的帧丢了。

这时候协议变成了

帧头(1byte)长度(1byte)序号(1byte)ID(1byte)命令(1byte)数据(Nbyte)校验(2byte)

对比mavlinkV1的协议帧,发现虽然我们没有讲mavlink,但是最后的协议与mavlinkV1已经非常相似了

STX帧头0xFE
LEN数据长度
SEQ序号
SYS IDID
COMP ID
MSG ID命令
PAYLOAD数据
CHECKSUMCRC校验

这里的COMP ID 指的是发送消息的组件 ID,用于区分系统中的组件(例如自动驾驶仪和摄像头)相当于SYS ID告诉是谁,COMP ID 告诉是具体哪部分。

放上mavlink V1的完整解释:

字节索引C版本内容说明
0uint8_t magic数据包启动标记0xFE特定于协议的启动(stx)标记,用于指示新数据包的开始。任何不识别协议版本的系统都将跳过数据包
1uint8_t len载荷长度0 - 255指示以下 payload 部分的长度 (为特定消息固定)
2uint8_t seq数据包序列号0 - 255用于检测数据包丢失。 组件为发送的每封消息递增值。
3uint8_t sysid系统 ID1 - 255发送消息的系统(vehicle)的 ID。用于区分网络上的系统。请注意,广播地址 0 可能不会在此字段中使用,因为它是无效的源地址。
4uint8_t compid组件ID1 - 255发送消息的组件 ID。用于区分系统中的组件(例如自动驾驶仪和摄像头)。在 MAV_COMPONENT 中使用适当的值。请注意,广播地址 MAV_COMP_ID_ALL 可能不会在此字段中使用,因为它是无效的源地址
5uint8_t msgid消息 ID0 - 255有效载荷中的 message type 的 id。 用于将数据解码出消息对象
n-byte payloaduint8_t payload[max 255]有效载荷有效载荷数据,消息内容取决于msgid
(n+6) to (n+7)uint16_t checksum校验和CRC-16/MCRF4XX计算,不包括magic字段,包括CRC_EXTERN

对于最新的mavlink V2

字节索引C版本内容说明
0uint8_t magic数据包启动标记0xFD特定于协议的启动(stx)标记,用于指示新数据包的开始。任何不识别协议版本的系统都将跳过数据包
1uint8_t len载荷长度0 - 255指示以下 payload 部分的长度 (为特定消息固定)
2uint8_t incompat_flags不兼容标志必须理解为 MAVLink 兼容性的标志 (如果不理解标志, 则实现丢弃数据包)
3uint8_t compat_flags兼容性标志如果不识别, 则可以忽略的标志 (即使不识别标志, 实现仍然可以处理数据包)
4uint8_t seq数据包序列号0 - 255用于检测数据包丢失。 组件为发送的每封消息递增值
5uint8_t sysid系统 ID1 - 255发送消息的系统(vehicle)的 ID。用于区分网络上的系统。请注意,广播地址 0 可能不会在此字段中使用,因为它是无效的源地址
6uint8_t compid组件ID1 - 255发送消息的组件 ID。用于区分系统中的组件(例如自动驾驶仪和摄像头)。在 MAV_COMPONENT 中使用适当的值。请注意,广播地址 MAV_COMP_ID_ALL 可能不会在此字段中使用,因为它是无效的源地址
7-9uint32_t msgid:24消息 ID (低、中、高字节)0 - 16777215有效载荷中的 message type 的 id。 用于将数据解码出消息对象
n-byte payloaduint8_t payload[max 255]有效载荷有效载荷数据,消息内容取决于msgid
(n+10) to (n+11)uint16_t checksum校验和CRC-16/MCRF4XX计算,不包括magic字段,包括CRC_EXTERN
(n+12) to (n+25)uint8_t signature[13]数据签名(可选)签名以确保链接是防篡改的

每个字段的具体内容参考https://www.cnblogs.com/hjx168/p/17706765.html写的非常详细。

mavlink 的消息类型

通过前面的讲述我们构建了一个和mavlink协议帧相似的协议,已经能够把收到的数据正确的解析出来。但是这还不够,因为目前为止我们还没有办法保证发送的端的数据正确的被发送。如果我们发送了一帧重要的数据,我怎么知道接收端也正确的接收到了呢,最好的办法就是接收端回复一帧数据,告诉我收到了。那么是不是所有的消息都要回复,其实不是的,在平衡车中,通常需要一直发送速度指令,即使速度没有发生变化,这样只要接收端一段时间内没有收到新指令应该自动停止运动,避免遥控器断开后发生危险。每个消息都会不是更好吗,主要是因为对于系统来说带宽是有限的,特别是单片机来系统,带宽可以说是很珍贵,能节省是最好的。

那么在mavlink中什么样的消息需要回复,什么样的不需要回复呢。在mavlink中消息可以分为几个主要类别,包括状态信息、命令、参数管理、任务管理等

  1. 状态消息
    • HEARTBEAT:提供系统的基本状态和类型信息。
    • SYS_STATUS:报告系统的当前状态,包括电池状态、处理器负载等。
    • GPS_RAW_INT:提供原始GPS数据。
  2. 命令消息
    • COMMAND_LONG:用于发送更复杂的命令到无人机,如更改飞行模式、控制舵机等。
    • COMMAND_ACK:响应COMMAND_LONG,表示命令接收和执行的状态。
  3. 参数消息
    • PARAM_REQUEST_READ:请求读取一个或多个参数。
    • PARAM_VALUE:返回请求的参数值。
    • PARAM_SET:设置一个参数的值。
    • PARAM_ACK_TRANSACTION:参数事务的响应。
  4. 任务管理消息
    • MISSION_ITEM:描述单个任务点。
    • MISSION_REQUEST:请求特定的任务信息。
    • MISSION_ACK:任务上传或下载的确认。
    • MISSION_CLEAR_ALL:清除所有任务项。
  5. 遥测数据消息
    • ATTITUDE:提供飞机的姿态数据,包括俯仰、横滚和偏航角度。
    • ALTITUDE:高度信息。
    • AIRSPEED_AUTOCAL:自动校准空速计的数据。
  6. 图像和视频消息
    • CAMERA_IMAGE_CAPTURED:摄像头捕捉到的图像数据。
    • VIDEO_STREAM_INFORMATION:视频流信息。
  7. 远程控制消息
    • RC_CHANNELS:遥控通道的实时值。
    • MANUAL_CONTROL:直接控制无人机的手动输入值。
  8. 扩展参数消息(MAVLink 2.0):
    • PARAM_EXT_VALUE:扩展参数的值。
    • PARAM_EXT_SET:设置扩展参数的值。
    • PARAM_EXT_ACK:确认扩展参数设置的响应。

这些消息类型的使用使得无人机系统的通信非常灵活和功能强大,允许进行详细的远程操作和监控。

在 MAVLink 协议中,不是所有消息都需要回复。一些消息需要接收方确认(ACK),通常是那些涉及到关键操作或参数设置的命令。以下是一些需要回复的消息类型和通常不需要回复的消息类型的例子:

需要回复的消息:

  1. COMMAND_LONG / COMMAND_INT

    • 需要 COMMAND_ACK 来确认命令是否被接受、正在执行或执行失败。
  2. PARAM_SET

    • 需要 PARAM_VALUE 或 PARAM_ACK_TRANSACTION 确认参数已被设置。
  3. MISSION_ITEM 和相关的任务管理消息:

    • 需要 MISSION_ACK 来确认任务点被接受或任务上传完成。
    • MISSION_REQUEST 在任务下载过程中发送,要求发送特定的任务项。
  4. PARAM_EXT_SET(扩展参数设置):

    • 需要 PARAM_EXT_ACK 来确认参数设置的状态。

通常不需要回复的消息:

  1. HEARTBEAT

    • 定期发送,用以表示设备状态和存在,通常不需要回复。
  2. SYS_STATUS

    • 提供系统状态信息,不需要回复。
  3. GPS_RAW_INTATTITUDE

    • 这些遥测数据消息通常是定期发送的状态更新,不需要回复。
  4. STATUSTEXT

    • 用于发送状态或错误文本信息,通常不需要回复。
  5. RC_CHANNELS

    • 发送遥控通道的当前值,通常用于监控而不需要回复。

回复消息的需求主要取决于消息的功能和在通信协议中的作用。关键的命令或参数设置需要确认以确保操作的正确执行,而常规的状态更新或数据流通常设计为不需要确认,以减少通信负载和简化处理过程。

当然如果是内部使用,可以根据自己需求来自定义哪些需要回复,哪些不需要回复。

MAVLINK复杂吗

说复杂也复杂,说简单也简单。

简单就是如果你不玩飞控,那么看到这就足够了,剩下的就是如何写xml,如何生成对应代码。

复杂就是mavlink在飞控领域制定了几百条(没细数)个通用MSG ID,很多都是晦涩难懂,如果想搞明白具体用了哪些,那么就复杂了。

为什么是mavlink而不是自由口

如果你是玩飞控,那么mavlink的最大好处广泛的兼容性和社区支持。

如果不玩飞控,只是想内部使用,那么优势吗?个人觉得此时最大的优势就是mavlink有多种现成的库和工具可以直接使用,大大减少了开发时间和成本。定义完成协议后,写一个xml文件,然后就可以自动生成对应的代码,而且可以支持多种编程语言。不用在自己写数据打包解包代码,缩短开发时间,提高程序可靠性。

如何使用mavlink生成的代码

简单来说,就是mavlink定义了一堆结构体,每个结构体都有对应的编码、解码函数。对于单片机来说,mavlink的xml生成都是.h的头文件,需要移植一个发送函数,数据接收也是固定套路,在官方例程中有。

今天太晚了,就写到这。如果你也感兴趣请点赞、收藏、加关注。

如果感兴趣的人多,后面会单独开一章讲解单片机如何使用mavlink生成的文件进行数据解析和发送。

  • 17
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MavLink协议的建立具有重要意义。MavLink是一种轻量级、高效且可扩展的通信协议,专门用于飞行控制系统与地面站或其他设备之间的通信。它被广泛应用于无人机系统,如无人机的飞行控制器与地面站之间的通信。 首先,MavLink协议的建立使得不同厂商开发的无人机系统能够实现互联互通。在无人机市场中,有许多不同厂商提供各种不同的飞控器系统和地面站软件。MavLink协议的出现消除了各个厂商之间不同通信协议的差异,从而实现了设备之间的无缝连接和信息交换。这样一来,飞行控制系统的开发商和地面站软件开发商可以更加专注于产品的独特特性和创新,而不必担心兼容性问题。 其次,MavLink协议的建立提供了一种统一的通信方式和数据格式,方便了数据的传输和解析。MavLink协议使用轻量级的二进制数据格式,可以有效地传输大量的实时数据,如传感器数据、飞行状态数据等。同时,MavLink的数据格式的设计也非常灵活,可以根据具体需求进行定制化。这样一来,飞行控制系统与地面站之间的数据交换更加高效和可靠。 此外,MavLink协议的建立还促进了无人机系统的开源和共享。MavLink是一个开放的协议,其源代码和文档都是公开的,可以随意使用和修改。这为开发者和爱好者提供了一个共同的平台,他们可以共同参与无人机系统的开发和改进,从而推动整个行业的发展。 总之,MavLink协议的建立为无人机系统的通信提供了一种标准化和统一的解决方案,促进了不同厂商设备之间的互联互通,提高了数据传输和解析的效率,促进了行业的开源和共享。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值