1常见模型控制信号
模型遥控器接收机输出的信号常见有三种:PWM、PPM、SBUS。
PWM信号优点是模型都有成熟的PWM控制的配套模块,如舵机、电调大部分都是PWM接口的,同样也存在很明显的缺点,第一是连线较多,每个通道至少需要1根线,第二是PWM信号是以高电平的时间作为控制信号,电平边沿容易受到干扰,造成错误的控制。
PPM可以理解成在一根线输出多组PWM信号,缺点显而易见和PWM信号一样,优点是少了不少线。
SBUS是两线制通信,需要信号线和地线即可,本质还是串口,此文重点介绍SBUS信号的电路、协议。
2 SBUS电路
SBUS电平本质是串口TTL电平,实质呢,电平和串口TTL是相反的,Futaba制定这个协议的时候有可能是为了规避专利,也有可能是为了装X……,给我们带来的问题就是需要电平转换电路,可以用2个电阻1个三极管实现,还用更简单的用1片74系列的单路反向芯片,本例中用的是三极管电阻方式,没有现成的板子临时搭个电路实验,本文以R9DS接收机、STM32F1XX测试,电路图、实物图如下:
电路原理图 电路实物 反向效果图
OK,电路问题解决了,下面开始读取数据
3 接收数据
Futaba官网说的很清楚:
The protocol is 25 Byte long and is send every 14ms (analog mode) or 7ms (highspeed mode).
One Byte = 1 startbit + 8 databit + 1 paritybit + 2 stopbit (8E2), baudrate = 100'000 bit/s
The highest bit is send first. The logic is inverted (Level High = 1)
翻译出来是这样的:一帧数据由25个字节构成,低速模式周期为14ms,高速模式周期为7ms,1个字节有1个起始位8个数据位1个校验位2个停止位构成,波特率为100K,高位在前低位在后,注意:电平是反的。
串口配置如下:
Uart_Init(COMM1,100000,USART_WordLength_8b, USART_Parity_Even);
串口接收中断:
void SBUS_RX_ISR(void)
{
INT8U res;
static INT8U Rx_Sta = 0;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
res =USART_ReceiveData(USART1);
SbusRxBuf[Rx_Sta++] = res;
}
else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{
USART_ReceiveData(USART1);
Rx_Sta = 0;
}
}
调试数据可以接收:
4数据解析
接收的数据和通道值是怎么个对应关系呢,Futaba官网接收如下:
[startbyte] [data1] [data2] .... [data22] [flags][endbyte]
startbyte = 11110000b (0xF0)
data 1-22 = [ch1, 11bit][ch2, 11bit] .... [ch16, 11bit] (ch# = 0 bis 2047)
channel 1 uses 8 bits from data1 and 3 bits from data2
channel 2 uses last 5 bits from data2 and 6 bits from data3
etc.
flags = bit7 = ch17 = digital channel (0x80)
bit6 = ch18 = digital channel (0x40)
bit5 = Frame lost, equivalent red LED on receiver (0x20)
bit4 = failsafe activated (0x10)
bit3 = n/a
bit2 = n/a
bit1 = n/a
bit0 = n/a
endbyte = 00000000b
一帧数据由1字节起始字节0xf0,22字节的通道数据,1字节标志位,1字节结束字节构成,总共25个字节,22个字节可以传输22*8/11=16通道数据,数据范围为0-2047。标志位的用R9DS没测试出Futaba协议中介绍的含义,有可能协议不兼容。
,遥控器关闭没信号时候,SbusRxBuf[24]接收数据位0xc0,,打开遥控器有信号时,SbusRxBuf[24]字节为0x00,可以用来做失控判断。
16通道数据解析如下:
void Sbus_Data_Count(INT8U *buf)
{
SbusCh[ 0] = ((INT16U)buf[ 1] >> 0 | ((INT16U)buf[ 2] << 8 )) & 0x07FF;
SbusCh[ 1] = ((INT16U)buf[ 2] >> 3 | ((INT16U)buf[ 3] << 5 )) & 0x07FF;
SbusCh[ 2] = ((INT16U)buf[ 3] >> 6 | ((INT16U)buf[ 4] << 2 ) | (INT16U)buf[ 5] << 10 ) & 0x07FF;
SbusCh[ 3] = ((INT16U)buf[ 5] >> 1 | ((INT16U)buf[ 6] << 7 )) & 0x07FF;
SbusCh[ 4] = ((INT16U)buf[ 6] >> 4 | ((INT16U)buf[ 7] << 4 )) & 0x07FF;
SbusCh[ 5] = ((INT16U)buf[ 7] >> 7 | ((INT16U)buf[ 8] << 1 ) | (INT16U)buf[9] << 9 ) & 0x07FF;
SbusCh[ 6] = ((INT16U)buf[9] >> 2 | ((INT16U)buf[10] << 6 )) & 0x07FF;
SbusCh[ 7] = ((INT16U)buf[10] >> 5 | ((INT16U)buf[11] << 3 )) & 0x07FF;
SbusCh[ 8] = ((INT16U)buf[12] << 0 | ((INT16U)buf[13] << 8 )) & 0x07FF;
SbusCh[ 9] = ((INT16U)buf[13] >> 3 | ((INT16U)buf[14] << 5 )) & 0x07FF;
SbusCh[10] = ((INT16U)buf[14] >> 6 | ((INT16U)buf[15] << 2 ) | (INT16U)buf[17] << 10 ) & 0x07FF;
SbusCh[11] = ((INT16U)buf[16] >> 1 | ((INT16U)buf[17] << 7 )) & 0x07FF;
SbusCh[12] = ((INT16U)buf[17] >> 4 | ((INT16U)buf[18] << 4 )) & 0x07FF;
SbusCh[13] = ((INT16U)buf[18] >> 7 | ((INT16U)buf[19] << 1 ) | (INT16U)buf[21] << 9 ) & 0x07FF;
SbusCh[14] = ((INT16U)buf[20] >> 2 | ((INT16U)buf[21] << 6 )) & 0x07FF;
SbusCh[15] = ((INT16U)buf[21] >> 5 | ((INT16U)buf[22] << 3 )) & 0x07FF;
yy = (INT16U)(0.6056*SbusCh[0]+895);
}
yy = (INT16U)(0.6056*SbusCh[0]+895);是y=ax+b的形式,实现SBUS数据与PWM脉宽的转换,转向系数a、b根据程序实际读到的数据和示波器读到的脉宽计算出来,就是个2点直线方程。
在10ms定时器中调用Sbus_Data_Count(SbusRxBuf);就可以计算出16个通道的数据,R9DS只能支持收到10个通道数据。