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個通道數據。