一天精通无人中级篇:遥控器协议 S-BUS

2018 年 12 月 20 日 无人机

今天我们来一起学习遥控器常见通讯协议S-BUS的解析方法。S-BUS其实是一种串口通信协议,采用100000的波特率,数据位点8bits,停止位点2bits,偶效验,即8E2的串口通信。但是S-BUS采用的是反向电平传输,也就是说,在S-BUS的发送端高低电平是反向的,协议中的所有高电平都被转换成低电平,协议中的所有低电平都被转换成高电平。所以在S-BUS的接收端需要增加一个高低电平反向器来进行电平反转,如下图:

实际上,我们使用的Pixhawk飞控板上已经集成了这个反向器,所以对于使用Pixhawk的用户来说,可以忽略掉S-BUS的反向机制,但是对于其它没有集成S-BUS反向器的硬件平台上,就需要使用者增加一个反向器来处理数据,否则将无法读取协议数据。

另外,100000的波特率并不是标准的波特率,这在一些只支持标准波特率的系统上无法实现,好在Nuttx支持自定义的波特率,我们可以通过对设备节点的配置实现波特率的设定。在Pixhawk IO上,S-BUS总线的设备节点为/dev/ttyS2,于是我们可以编写一个程序对这个串口节点的波特率进行配置:

void sbus_config(void){
    int sbus_fd = open("/dev/ttyS2", O_RDWR | O_NONBLOCK);
    if (sbus_fd < 0)
    {
        return;
    }
    struct termios t;       
    //设置100000波特率
    tcgetattr(sbus_fd, &t);
    cfsetspeed(&t, 100000);
    t.c_cflag |= (CSTOPB | PARENB);
    tcsetattr(sbus_fd, TCSANOW, &t);}

设置好波特率就可以对标准文件设备进行读取了,也就是通过read()函数来读取串口当中的数据。S-BUS协议在传输过程中还有两种不同的传输模式:

  1. 高速模式:数据发送周期为4ms,发送频率为250Hz;

  2. 低速模式:数据发送周期为14ms,发送频率为71.4Hz。

S-BUS协议数据格式如下:

需要注意的是S-BUS中用11bits来表示一个遥控器通道的数值,22个字节就可以表示16通道(8 × 22 = 11 ×16)。11个bit可以表示的数值范围为0~2047。例如:我们的遥控器前4个通道数值分别为200、300、400和500,其它通道都为0。它们的二进制数据分别为:

200: 000 1100 1000
300: 001 0010 1100
400: 001 1001 0000
500: 001 1111 0100
其它通道都为:0

S-BUS的16个遥控器通道,每一个通道用11个bit表示,那么这16个通道的二进制数值拼接起来则为:

0001 1001 0000 0100 1011 0000 1100 1000 0001 1111 0100
[0F] 19 04 B0 C8 1F 40 …… 00 [00]

实际上遥控器发送每一个通道的数值在200~1800之间,用来表示遥控器通道的所有数值。但是PX4飞控程序中有效的通道值范围通常是1000~2000,所以就需要将原始数值进行一次转换。接下来我们就来编写S-BUS协议解析的驱动程序:

#define SIZE_BUFF   (100)//S-BUS协议中遥控器通道数值范围#define SBUS_RANGE_MIN 200.0f#define SBUS_RANGE_MAX 1800.0f//PX4中使用的遥控器通道数值范围#define SBUS_TARGET_MIN 1000.0f#define SBUS_TARGET_MAX 2000.0f//数值放大因子#define SBUS_SCALE_FACTOR ((SBUS_TARGET_MAX - SBUS_TARGET_MIN) / (SBUS_RANGE_MAX - SBUS_RANGE_MIN))//数值放大偏移量#define SBUS_SCALE_OFFSET (int)(SBUS_TARGET_MIN - (SBUS_SCALE_FACTOR * SBUS_RANGE_MIN + 0.5f))//S-BUS解析函数int sbus_read_parse(int _fd, uint16_t *val){
    //读取遥控器通道数据
    uint8_t _buf[SIZE_BUFF];
    int len = read(_fd, _buf, SIZE_BUFF);
    if (len < 0)
    {
        return -1;
    }

    //略过协议包头、包尾、长度判断过程

    //按11bits解析遥控器通道
    val[0] = ((buff[ind + 1] | buff[ind + 2] << 8) & 0x07FF);
    val[1] = ((buff[ind + 2] >> 3 | buff[ind + 3] << 5) & 0x07FF);
    val[2] = ((buff[ind + 3] >> 6 | buff[ind + 4] << 2 | buff[ind + 5] << 10) & 0x07FF);
    val[3] = ((buff[ind + 5] >> 1 | buff[ind + 6] << 7) & 0x07FF);
    val[4] = ((buff[ind + 6] >> 4 | buff[ind + 7] << 4) & 0x07FF);
    val[5] = ((buff[ind + 7] >> 7 | buff[ind + 8] << 1 | buff[ind + 9] << 9) & 0x07FF);
    val[6] = ((buff[ind + 9] >> 2 | buff[ind + 10] << 6) & 0x07FF);
    val[7] = ((buff[ind + 10] >> 5 | buff[ind + 11] << 3) & 0x07FF);
    val[8] = ((buff[ind + 12] | buff[ind + 13] << 8) & 0x07FF);
    val[9] = ((buff[ind + 13] >> 3 | buff[ind + 14] << 5) & 0x07FF);
    val[10] = ((buff[ind + 14] >> 6 | buff[ind + 15] << 2 | buff[ind + 16] << 10) & 0x07FF);
    val[11] = ((buff[ind + 16] >> 1 | buff[ind + 17] << 7) & 0x07FF);
    val[12] = ((buff[ind + 17] >> 4 | buff[ind + 18] << 4) & 0x07FF);
    val[13] = ((buff[ind + 18] >> 7 | buff[ind + 19] << 1 | buff[ind + 20] << 9) & 0x07FF);
    val[14] = ((buff[ind + 20] >> 2 | buff[ind + 21] << 6) & 0x07FF);
    val[15] = ((buff[ind + 21] >> 5 | buff[ind + 22] << 3) & 0x07FF);

    //将原始数值转换到PX4所使用的范围
    for (int i = 0; i < 16; i++)
    {
        val[i] = (uint16_t)(val[i] * SBUS_SCALE_FACTOR + .5f) + SBUS_SCALE_OFFSET;
    }

    return 0;}

当然,我们需要在驱动程序中启动一个线程来读取并解析S-BUS协议,此进程将使用循环的方式调用int sbus_read_parse(int _fd, uint16_t *val)函数,之后将val数组中的内容使用input_rc.msg消息发布到uORB总线上为其它进程所使用。


点击下面链接 查看历史文章

无人机自动避障技术盘点

GeForce独立显卡,无人机地面站的当仁之选:X500

八一八:这世界上本来就没有什么“弱肉强食”

三防便携式加固计算机X500的独门绝技:扩展坞

中国的无人机采购和开发计划

效率提升300%!全新无人机勘测系统入市


登录查看更多
51

相关内容

【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
【实用书】Python技术手册,第三版767页pdf
专知会员服务
234+阅读 · 2020年5月21日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
161+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【干货书】数值计算C编程,319页pdf,Numerical C
专知会员服务
67+阅读 · 2020年4月7日
【图神经网络(GNN)结构化数据分析】
专知会员服务
115+阅读 · 2020年3月22日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
携程用ClickHouse轻松玩转每天十亿级数据更新
DBAplus社群
11+阅读 · 2019年8月6日
被动DNS,一个被忽视的安全利器
运维帮
11+阅读 · 2019年3月8日
介绍WAF以及过滤机制
黑白之道
22+阅读 · 2019年2月5日
教你实现超流行的骨架屏预加载动态效果
IMWeb前端社区
73+阅读 · 2018年11月27日
已删除
AI科技评论
4+阅读 · 2018年8月12日
Python | 爬爬爬:爬百度云,爬百度贴吧,爬爱奇艺
计算机与网络安全
3+阅读 · 2018年3月30日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Arxiv
24+阅读 · 2020年3月11日
Arxiv
35+阅读 · 2019年11月7日
Arxiv
4+阅读 · 2018年5月24日
Arxiv
8+阅读 · 2018年4月8日
Arxiv
3+阅读 · 2018年3月13日
VIP会员
相关VIP内容
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
【实用书】Python技术手册,第三版767页pdf
专知会员服务
234+阅读 · 2020年5月21日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
161+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【干货书】数值计算C编程,319页pdf,Numerical C
专知会员服务
67+阅读 · 2020年4月7日
【图神经网络(GNN)结构化数据分析】
专知会员服务
115+阅读 · 2020年3月22日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
相关资讯
后渗透利用msf关闭防火墙
黑白之道
8+阅读 · 2019年8月24日
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
携程用ClickHouse轻松玩转每天十亿级数据更新
DBAplus社群
11+阅读 · 2019年8月6日
被动DNS,一个被忽视的安全利器
运维帮
11+阅读 · 2019年3月8日
介绍WAF以及过滤机制
黑白之道
22+阅读 · 2019年2月5日
教你实现超流行的骨架屏预加载动态效果
IMWeb前端社区
73+阅读 · 2018年11月27日
已删除
AI科技评论
4+阅读 · 2018年8月12日
Python | 爬爬爬:爬百度云,爬百度贴吧,爬爱奇艺
计算机与网络安全
3+阅读 · 2018年3月30日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Top
微信扫码咨询专知VIP会员