极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 28326|回复: 0

Arduino解析FUTABA-S.BUS总线

[复制链接]
发表于 2021-6-30 11:02:43 | 显示全部楼层 |阅读模式
本帖最后由 gangguo 于 2021-6-30 11:05 编辑

S.BUS是FUTABA(模型遥控器知名品牌)特有的一个接收机串行总线输出,通过这根总线,可以获得遥控器上所有通道的数据。目前很多模型及无人机电子设备都支持S.BUS总线的接入,如:V-BAR陀螺仪、Pixhawk飞控等。使用S.BUS总线获取通道数据,效率是比较高的,而且非常节省硬件资源-只需要“一根线”即可获取所有通道的数据。
在本次试验中,使用的遥控器为FUTABA T10CHG,接收机使用的穿越机专用神器:FM800PRO微型总线输出接收机,Arduino板使用的MEGA2560板。


在解析数据前,先说说S.BUS总线的一些特性。经过资料查阅得到:S.BUS总线使用的是TTL电平的反向电平,即标准TTL中的1取反为0,而0则取反为1,串口波特率为100000,数据位为8位,2个停止位,偶校验。因此,这里需要制作一个电平反向电路,电平反向电路在百度上可以找到大神们的无私共享,这里直接给出原理图,图中使用的三极管型号为:SS8050。

下图为制作好的电平反向电路模块,这个模块在上面原理图的基础上做了一点小小的改进:增加了一个5V的VCC贯通输入和输出端,图中的3.3V上拉则从5V的VCC上经过电阻分压获得,这样的方便之处在于方便用Arduino板对模块接收机供电,也可以接收机对模块及Arduino板供电。

获得正确的电平后,接下来看看S.BUS的数据帧结构。S.BUS一帧数据的长度为25个字节,其中第“0”个字节为帧头:0x0f;第24个字节为帧尾:0x00;从第1个字节到第22个字节为1-16号比例通道的数据字节;第23字节中,第7位为数字开关通道17通道,第6位为数字开关通道18通道,第5位为帧状态标志为(判断是否丢帧),用于控制接收机上的LED的状态,第4位为失控保护激活标志位,此位为1时,表示接收机进入失控保护状态,本次试验所用的接收机对于第23字节为做出处理,但使用福睿斯接收机时可以正确判断失控保护。
(注:数字字节帧的排位从0开始,第0个实质上是指第一个字节)

接下来看1-16比例通道的数据解算,每个通道用11位(bit)二进制数表示,通道数据的值为:0-2048:
1通道(AILE):第2字节的低3位(11位数据的高3位)+第1字节(11位数据的低8位);
2通道(ELEV):第3字节的低6位(11位数据的高6位)+第2字节的高5位(11位数据的低5位);
3通道(THRO):第5字节的最低1位(11位数据的最高1位)+第4字节(11位数据的中间8位)+第3字节的最高2位(11位数据的最低2位);
4通道(RUDD):第6字节的低4位(11位数据的高4位)+第5字节的高7位(11位数据的低7位);
这里的文字叙述比较繁琐,下面直接给出通道解算的代码:

简要说明:sbusData[]用于存放从串口读取的原始数据,channels[]用于存放解算完成的通道数据,其中channels[0]代表1通道AILE。

下面来看看如何进行帧同步,即寻找帧头。本次试验用Arduino mega2560的串口1来接收SBUS数据,再由串口0将通道数据发送到串口监视器。接收串口数据代码:

简要说明:sbus_flag用于判断是否读取到了帧头,开始时sbus_flag为0,此时还未同步到帧头,程序会一直停留在寻找帧头的位置,不断地从串口缓冲区中读取字节数据,读取一次判断一次,当寻找到帧头0x0f时,sbus_flag置1,跳出帧头寻找,进入后续的帧读取,当sbusData更新完毕后,sbus_flag重新置0,准备进入下一轮的读取。下图为串口监视器显示1-12比例通道+原始数据第23字节(本次试验用的遥控器只有10个通道)的状态:

从上图可以看到,摇杆在中位时,解算出来的通道数据为1024左右,以一通道AILE为例:中杆时为1024,左右满行程的值分别为1686和366,此时的遥控器AILE行程设置(END POINT)为左右100%。至此,SBUS总线数据成功解析,通过试验验证了FUTABA T10CHG确实有10个通道,而且10个通道均为标准PWM(舵机)输出;其中1-8通道可设置为比例通道,即可跟随摇杆、旋钮或3端开关;而9,10通道只能作为开关通道,即只能用两段开关控制PWM的最大值和最小值,但行程可调。
下面是完整测试代码:
  1. #include <Timer.h>
  2. Timer t;

  3. int16_t channels[16];
  4. uint8_t sbusData[25];
  5. char sbus_flag=0;

  6. void setup()
  7. {
  8.   Serial.begin(115200);
  9.   Serial1.begin(100000);
  10.   t.every(10,channels_updata);
  11.   t.every(20,dete_print);

  12. }


  13. void serialEvent1(void)
  14. {
  15.   if(Serial1.available()>=25)
  16.   {
  17.     while(sbus_flag==0)
  18.     {
  19.       sbusData[0]=Serial1.read();
  20.       if(sbusData[0]==0x0f)
  21.       {sbus_flag=1;}
  22.     }
  23.     if(sbus_flag==1)
  24.     {
  25.        for(int i=1;i<25;i++)
  26.        {sbusData[i]=Serial1.read();}
  27.        sbus_flag=0;
  28.       }
  29.     }
  30.   }

  31.   

  32. void channels_updata(void)
  33. {
  34.    if(sbusData[0]==0x0f&&sbusData[24]==0x00)
  35.   {
  36.   channels[0]  = ((sbusData[1]|sbusData[2]<< 8) & 0x07FF);
  37.   channels[1]  = ((sbusData[2]>>3|sbusData[3]<<5) & 0x07FF);
  38.   channels[2]  = ((sbusData[3]>>6|sbusData[4]<<2|sbusData[5]<<10) & 0x07FF);
  39.   channels[3]  = ((sbusData[5]>>1|sbusData[6]<<7) & 0x07FF);
  40.   channels[4]  = ((sbusData[6]>>4|sbusData[7]<<4) & 0x07FF);
  41.   channels[5]  = ((sbusData[7]>>7|sbusData[8]<<1|sbusData[9]<<9) & 0x07FF);
  42.   channels[6]  = ((sbusData[9]>>2|sbusData[10]<<6) & 0x07FF);
  43.   channels[7]  = ((sbusData[10]>>5|sbusData[11]<<3) & 0x07FF);
  44.   channels[8]  = ((sbusData[12]|sbusData[13]<< 8) & 0x07FF);
  45.   channels[9]  = ((sbusData[13]>>3|sbusData[14]<<5) & 0x07FF);
  46.   channels[10] = ((sbusData[14]>>6|sbusData[15]<<2|sbusData[16]<<10) & 0x07FF);
  47.   channels[11] = ((sbusData[16]>>1|sbusData[17]<<7) & 0x07FF);
  48.   channels[12] = ((sbusData[17]>>4|sbusData[18]<<4) & 0x07FF);
  49.   channels[13] = ((sbusData[18]>>7|sbusData[19]<<1|sbusData[20]<<9) & 0x07FF);
  50.   channels[14] = ((sbusData[20]>>2|sbusData[21]<<6) & 0x07FF);
  51.   channels[15] = ((sbusData[21]>>5|sbusData[22]<<3) & 0x07FF);
  52.   }
  53. }





  54. void dete_print()
  55. {
  56.    Serial.print(channels[0]);
  57.    Serial.print("  ");
  58.    Serial.print(channels[1]);
  59.    Serial.print("  ");
  60.    Serial.print(channels[2]);
  61.    Serial.print("  ");
  62.    Serial.print(channels[3]);
  63.    Serial.print("  ");
  64.    Serial.print(channels[4]);
  65.    Serial.print("  ");
  66.    Serial.print(channels[5]);
  67.    Serial.print("  ");
  68.    Serial.print(channels[6]);
  69.    Serial.print("  ");
  70.    Serial.print(channels[7]);
  71.     Serial.print("  ");
  72.    Serial.print(channels[8]);
  73.     Serial.print("  ");
  74.    Serial.print(channels[9]);
  75.     Serial.print("  ");
  76.    Serial.print(channels[10]);
  77.     Serial.print("  ");
  78.    Serial.print(channels[11]);
  79.     Serial.print("  ");
  80.    Serial.println(sbusData[23],BIN);
  81.    
  82.   
  83.   }


  84. void loop()
  85. {

  86.   t.update();

  87. }
复制代码



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-19 04:02 , Processed in 0.044837 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表