日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

树莓派基础实验39:解析无线电接收机PWM、SBUS信号

發布時間:2024/3/26 编程问答 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树莓派基础实验39:解析无线电接收机PWM、SBUS信号 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、介紹

??雖然如今或者將來,5G網絡的建設帶來人工智能和工業自動化的全面升級,生產活動中勞動力的需求大大減少,大量的勞動力將向內容生產行業和服務行業轉移。教育、醫療、娛樂、公共管理等諸多領域,乃至整個社會都將迎來巨大變革。可參閱我的一篇讀書筆記5G社會:萬物互聯新時代。

??但是,使用傳統無線電通信設備通信仍然是非常重要的通信方式,比如無線電臺、對講機,航模、車模、船模遙控等等。與手機移動網絡、WIFI連接相比,無線電連接有它獨特的優勢。

??在樹莓派基礎實驗38:邏輯分析儀分析PWM、UART信號中使用邏輯分析儀,對樹莓派的PWM信號和UART信號進行分析,從中可以詳細了解邏輯分析儀分析的使用方法及PWM信號和UART信號。

??本實驗中將使用邏輯分析儀、樹莓派,對航模無線電接收機輸出的PWM信號、SBUS信號進行采集分析,以便樹莓派能夠接收無線電控制信號,進而可以開發基于無線電控制的樹莓派航模飛行控制系統、或者智能小車的無人駕駛系統。

二、組件

★Raspberry Pi 3 B+全套*1

★睿思凱Frsky X8R 接收機*1

★電平反向器模塊*1

★睿思凱Frsky Taranis X9D PLUS SE2019遙控器*1

★國產夢源DSLogic Plus邏輯分析儀*1

★面包板*1(可選)

★40P軟排線*1

★跳線若干

三、實驗原理

(一)航模無線電遙控系統

本實驗中使用的遙控系統可以自行選擇其它品牌的產品,如國產的天地飛還不錯。

航模的遙控器就是像電視機遙控器、空調遙控器一樣可以不用接觸到被控設備,而通過一個手持器件,使用無線電與被控設備進行通信,從而達到對設備的控制。

遙控器想到達到與無人機通信的功能需要有兩部分配合完成。即:發射器(遙控器)與接收機。遙控器上的控制桿轉為無線電波發送給接收機,而接收機通過接收無線電波,讀取遙控器上控制桿的讀數,并轉為數字信號發送到航模的控制器中。

目前用于無人機遙控器主流的無線電頻率是2.4G,這樣的無線電波的波長更長,可以通信的距離較遠,普通2.4G遙控器與接收機的通信距離在空曠的地方大概在1km以內。2.4GHz無線技術如今已經成為了無線產品的主流傳輸技術。所謂的2.4GHz所指的是一個工作頻段2400M-2483M范圍,這個頻段是全世界免申請使用。

常見的Wifi、藍牙、ZigBee都是使用的2.4G頻率段,只不過他們采用的協議不同,導致其傳輸速率不同,所以運用的范圍就不同。同樣是采用2.4G頻率作為載波,但不同的通訊協議衍生出的通訊方式會有著天壤之別;僅僅在傳輸數據量上,就有著從1M每秒到100M每秒的差別。

關于遙控器與無人機的通信協議也有很多種,常見的數據協議如下:
1.pwm:需要在接收機上接上全部pwm輸出通道,每一個通道就要接一組線,解析程序需要根據每一個通道的pwm高電平時長(即占空比)計算通道數值。

2.ppm:按固定周期發送所有通道pwm脈寬的數據格式,一組接線,一個周期內發送所有通道的pwm值,解析程序需要自行區分每一個通道的pwm時長。PPM的頻率通常是50Hz,周期長度20ms,每一個周期中可以存放最多10路PWM信號,每一路PWM的周期為2ms。

3.sbus:每11個bit位表示一個通道數值的協議,串口通信,但是sbus的接收機通常是反向電平,連接到航模時需要接電平反向器,大部分支持sbus的飛行控制板已經集成了反向器。

4.xbus:常規通信協議,支持18個通道,數據包較大,串口通信有兩種模式,可以在遙控器的配置選項中配置。接收機無需做特殊配置。

然后,就是電調通過接收接收機輸出的這些信號,來將輸入的電源轉為不同的電壓,并輸出到電機,從而達到使電機產生不同的轉速的目的。有刷電調可以改變電流方向,從而可以改變電機轉動方向。而無刷電調卻不能改變電機的轉動方向,但是可以將直流電轉為三相交流電,從而輸出到無刷電機上。

所謂電調就是電壓調節器,也可以通俗的說成是電機調節器,這里不做過多講解。

(二)接收機的PWM信號

PWM英文全稱為(Pulse-width modulation)。也稱占空比信號,它表示高電平時長占整個信號周期的比例。

PWM信號的頻率是通常是沒有規定的,可以是50hz、100hz、200hz或500hz等等。控制頻率越高,其周期越短,控制間隔也就越短,電調和電機響應速度也就越快。反之,控制頻率越低,其周期就越長,控制間隔就越長,電調和電機的響應速度就越慢。早期電調響應PWM信號的頻率是50hz,但隨著科技的發展和對控制流暢度的要求,現在多數電調都支持500hz以上的PWM信號,并且電調內部自帶濾波器,可以很好的響應并控制電機的轉動。

傳統的遙控器接收機是采用多路PWM的方式進行輸出的,遙控器中有多少個通道,接收機中就有多少路PWM輸出,睿思凱Frsky X8R接收機的1-8個PWM輸出通道,都是以PWM的形式輸出的,這就需要飛控能夠采集并解析這些PWM信號,并為飛控所用。

那么,睿思凱Frsky X8R接收機的PWM信號到底是怎樣的呢?我們使用邏輯分析儀看看吧,連接好遙控器、接收機、連接邏輯分析儀。

這里我只采集了1、3、5號通道的PWM信號。1號通道是右手油門搖桿左右晃動,會自動回中;3號通道是右手油門搖桿油門控制,由低到高表示油門由小到大,不會回中;5號通道是SA開關,有上中下3個檔位。

首先來看1號通道,當搖桿往左搖到底時,占空比約為5.5%,高電平時長為0.99ms,信號周期為18ms。

1號通道,當搖桿往右搖到底時,占空比約為11.2%,高電平時長為2.01ms,信號周期為18ms。

再看3號通道,當搖桿往下搖到底時,油門為0,占空比約為5.5%,高電平時長為0.99ms,信號周期為18ms。

3號通道,當搖桿往上搖到底時,油門為最大,占空比約為11.2%,高電平時長為2.01ms,信號周期為18ms。

那當他們居中時呢?占空比約為8.3%,高電平時長為1.50ms,信號周期還是為18ms。

5號通道為開關,上中下三檔,與1/3通道的高中低三檔時的數值一樣,占空比依次約為11.2%、8.3%、5.5%,高電平時長依次約為2ms、1.5ms、1ms,信號周期一直是穩定的18ms。


在采集接收機PWM信號時發現,當接收機剛通電時,接收機不輸出PWM信號,當遙控器連接成功接收機后,接收機就立馬輸出遙控器的即時狀態信號,所以請注意,連接之前請注意將油門調至0,否則如果電調沒有保護機制,螺旋槳會立馬飛起來。

無線電波在傳輸過程中可能受到干擾或是數據丟失等等問題,當接收機無法接收到發射器的數據時,通常會進入保護狀態,也就是仍舊向無人機發送控制信號,此時的信號就是接收機收到遙控器發射器最后一次的有效數據。這樣因為信號丟失而發送的保護數數據通常叫做failsafe數據。

如果遙控器沒有設置failsafe mode,X8R接收機默認HOLD模式,即保持斷聯之前的信號一直輸出;可以在遙控器上設置No pulses模式,指斷聯后接收機不輸出信號;可以在遙控器上設置Custom模式,定制斷聯后接收機要輸出的控制信號,比如降低油門到比較低的程度,以便飛機自動降落。

樹莓派輸出PWM信號很簡單,但是如果我們需要使用樹莓派來讀取接收機輸出的PWM信號值怎么辦呢?

我們以第一個通道的PWM為例,講述樹莓派對其處理的具體方法:
(1)檢測引腳由低點平變為高電平的時刻,并記錄當前時間t0,表示高電平開始;
(2)檢測引腳由高電平變為低點平的時刻,并記錄當前時間t1,表示高電平結束;
(3)繼續檢測引腳由低點平變為高電平的時刻,并記錄當前時間t2,表示一個PWM周期結束;
(4)計算高電平時長 = t1 - t0;
(5)計算整個PWM周期 = t2 - t0;
(6)計算PWM占空比 = 高電平時長 / PWM周期

每一個遙控器通道都需要一個PWM采集器進行采集,但是對于樹莓派來說不可能使用多個定時器來采集多個通道的PWM,這對于樹莓派的資源來說十分浪費,因此我優先采用的就是SBUS編碼,可以在一個管腳中傳輸多路控制信號。

(三)SBUS信號

1.介紹

S.BUS是FUTABA提出的舵機控制總線,全稱Serial Bus,別名S-BUS或SBUS,也稱 Futaba S.BUS。

S-BUS其實是一種串口通信協議,采用100000的波特率,數據位點8bits,停止位點2bits,偶效驗,即8E2的串口通信。但是S-BUS采用的是反向電平傳輸,也就是說,在S-BUS的發送端高低電平是反向的,協議中的所有高電平都被轉換成低電平,協議中的所有低電平都被轉換成高電平。所以在S-BUS的接收端需要增加一個高低電平反向器來進行電平反轉。

實際上,有的飛控板上已經集成了反向器,所以對于使用這種飛控的用戶來說,可以忽略掉S-BUS的反向機制,但是對于其它沒有集成S-BUS反向器的硬件平臺上,就需要使用者增加一個反向器來處理數據,否則將無法讀取協議數據。

另外,100000的波特率并不是標準的波特率,這在一些只支持標準波特率的系統上無法實現,我們可以通過對設備節點的配置實現波特率的設定。

通信接口:USART(TTL)

通信參數:1個起始位+8個數據位+偶校驗位+2個停止位,無控流,25個字節,波特率=100000bit/s,電平邏輯反轉。

X6R的SBUS通信速率:每6ms間隔發送數據,每數據幀時長為3ms。

數據幀格式:

需要注意的是S-BUS中用11bits來表示一個遙控器通道的數值,22個字節就可以表示16通道(8 × 22 = 11 ×16)。11個bit可以表示的數值范圍為0~2047。

每幀25個字節,排列如下:

[start byte] [data1] [data2] [data3] … [data22] [flag] [end byte]

簡單來說就是,通道1數據在前,通道16數據最后;每通道的數據,低位在前面的字節中,高位在后面的字節中;每8bit數據中,低位是上一通道的數據,高位是下一通道的數據。

start byte = 0x0F
CH1 = [data2]的低3位 + [data1]的8位
????(678?+?12345678 = 678,12345678)
CH2 = [data3]的低6位 + [data2]的高5位
????(345678?+?12345 = 345678,12345 )
CH3 = [data5]的低1位 + [data4]的8位 + [data3]的高2位
????(8 ? ?+? ?12345678 ?? +? ?12 = 8,12345678,12)
… …
flag(由高位到低位:N/A N/A N/A N/A 故障保護激活位 幀丟失位 數字通道CH18 數字通道CH17 )
end byte = 0x00

2.未做電平反向時的SBUS信號

可以看出字節數不對,只解析出23字節,起始字節不是正確的0x0F,而是0xF8,還有紅色的PE(Frame error)幀錯誤,即是亂碼。

3.電平反向后的SBUS信號

可以看出一幀數據為25字節,起始字節是正確的0x0F,結束字節為0x00。

再詳細分析起始字節,要搞清楚每個字節的含義,先弄清UART的數據通信的字節格式:

其中各位的意義如下:
起始位:先發出一個邏輯”0”信號,表示傳輸字符的開始。
數據位:可以是5~8位邏輯”0”或”1”。如ASCII碼(7位),擴展BCD碼(8位),小端傳輸。
校驗位:數據位加上這一位后,使得“1”的位數應為偶數(偶校驗)或奇數(奇校驗)
停止位:它是一個字符數據的結束標志。可以是1位、1.5位、2位的高電平。
空閑位:處于邏輯“1”狀態,表示當前線路上沒有資料傳送。
傳輸方向:即數據是從高位(MSB)開始傳輸還是從低位(LSB)開始傳輸,X8R是從低位開始傳輸的。

波特率:上圖中可以看出每位的時長是10us,意思就是每秒傳輸100000比特位數(bit),即波特率為100000。

起始位:先發出一個邏輯”0”的信號,即低電平,表示傳輸數據的開始。

數據位:SBUS信號明顯為8位。

校驗位:數據位加上這一位后,使得“1”的位數應為偶數(偶校驗)或奇數(奇校驗),以此來校驗數據傳送的正確性。SBUS為偶校驗,起始字節數據位中已有4個“1”,所以偶校驗位為0。

停止位:它是一幀數據的結束標志。可以是1bit、1.5bit、2bit的空閑電平。SBUS信號是2位停止位,即2位高電平。

空閑位:沒有數據傳輸時線路上的電平狀態。為邏輯1。

傳輸方向:uart傳輸數據的順序就是:剛開始傳輸一個起始位,接著傳輸數據位,接著傳輸校驗位(可不需要此位),最后傳輸停止位。這樣一幀的數據就傳輸完了。所以上圖中Bits顯示的11110000,是從左到右是由低到高位顯示的,其值實際上是B00001111=0x0F。

幀間隔:即傳送數據的幀與幀之間的間隔大小,這里的間隔為6ms,每幀的周期可以以位為計量也可以用時間,(起始1位+數據8位+校驗1位+中止2位=12位) x 25字節=300位,每位時長為10us x 300位=3000us=3ms。

每幀數據時長為2.990ms,有10us的誤差,應該是3ms:

4. 關閉遙控器后接收機的反應

為模擬接收機與遙控器失聯后的狀態,關閉遙控器的過程中,用邏輯分析儀分析了第24個字節的變化情況,在斷開連接的前900ms內,幀丟失位由0變為1,即第24個字節值為0x04。

之后,故障保護激活位由0變為1,幀丟失位仍為1,即第24個字節值為0x0C,此時如果設置了failsafe數據,接收機就按照failsafe數據輸出信號。

比如我設置的為No pulses(無脈沖),所有的通道值變為0。

四、實驗步驟

(一) 樹莓派解析接收機PWM信號

  • 連接線路。將接收機的1/3/5通道分別連接到樹莓派面包板上的G17、G18、G19上,接收機的電源+、-接5V和GND。
  • 樹莓派(name)T型轉接板(BCM)接收機
    GPIO.0G17Channel 1(SIG)
    GPIO.1G18Channel 3(SIG)
    GPIO.24G19Channel 5(SIG)
    5V5V+
    GNDGND-

    連線很簡單,電路圖就沒畫了,接收機上端接出的兩個黑色細長薄片是天線。

  • 編寫樹莓派解析PWM信號的程序。為了不至于結果刷新太快,為了便于觀察,我設置了每次采集信號0.5秒的延遲,在實際信號使用過程中,顯然是不用的。
  • #!/usr/bin/env pythonimport RPi.GPIO as GPIO import timechannel_1 = 17 #接收機1通道連接樹莓派G17針腳 channel_3 = 18 #接收機3通道連接樹莓派G18針腳 channel_5 = 19 #接收機5通道連接樹莓派G19針腳def setup():GPIO.setmode(GPIO.BCM)GPIO.setup(channel_1, GPIO.IN)GPIO.setup(channel_3, GPIO.IN)GPIO.setup(channel_5, GPIO.IN)def duty_cycle_collect(pin):#等待低電平結束,然后記錄時間while GPIO.input(pin) == 0: #捕捉信號端輸出上升沿passtime1 = time.time() #等待高電平結束,然后記錄時間while GPIO.input(pin) == 1: #捕捉信號端輸出下降沿passtime2 = time.time() #等待低電平結束,然后記錄時間while GPIO.input(pin) == 0: #捕捉信號端輸出上升沿passtime3 = time.time()period = time3 - time1high_time = time2 - time1low_time = time3 - time2duty_cycle = high_time * 100 / period#print periodreturn duty_cycle def loop():while True:#調用占空比采集函數duty_cycle_collect()獲得各通道的信號占空比duty_cycle_channel_1 = duty_cycle_collect(channel_1)print 'duty_cycle_channel_1 =',duty_cycle_channel_1 duty_cycle_channel_3 = duty_cycle_collect(channel_3)print 'duty_cycle_channel_3 =',duty_cycle_channel_3duty_cycle_channel_5 = duty_cycle_collect(channel_5)print 'duty_cycle_channel_5 =',duty_cycle_channel_5print '' time.sleep(0.5) #為了便于觀察結果設置了延遲def destroy():GPIO.cleanup()if __name__ == "__main__":setup()try:loop()except KeyboardInterrupt:destroy()
  • 測試成功獲取接收機PWM信號的占空比。1/5通道的遙控均在中位,所以占空比約為8.3%,與邏輯分析儀的結果一致;3通道是油門,由大到小滑動時,得到的占空比結果11.2%降至5.5%,與邏輯分析儀的結果一致。但是少數測量結果會有偏差,極少數情況偏差較大。
  • 當遙控器與接收機失聯時,我定制了failsafe數據,油門降低。3號通道的占空比在開始失聯的時候有抖動,約3秒鐘后穩定在設置的6.3%左右。
  • (二) 分析接收機SBUS信號

  • 連接電路。與樹莓派基礎實驗36:通用串口通信實驗一樣設置樹莓派的串口為通用串口,恢復硬件串口(/dev/ttyAMA0)與GPIO 14/15的映射關系,使得我們能夠通過GPIO使用高性能的硬件串口來連接我們的SBUS信號輸入。
  • T型轉接板(BCM)接收機電平反向模塊DSlogic邏輯分析儀
    -SBUSA6-
    --B6Channel 1(SIG)
    3.3V-3.3V-
    5V5V--
    GNDGNDGNDChannel 0(GND)

    電平反相模塊很便宜,某寶5元一個能買到6路的電平反相器。注意反向后的高電平是幾伏,反相器的VCC就接幾伏的電源,樹莓派GPIO接收3.3V高電平,不能接收5V高電平,所以這里電平反向模塊的VCC只能接3.3V電源。

  • 這里樹莓派要使用pyserial模塊編程接收SBUS信號,有關基礎可以參考樹莓派基礎實驗37:pyserial模塊通信實驗。下面的程序只能在Python2.7的環境下運行,Python3上會出現問題。如果有更快更好的代碼,請留言。
  • #!/usr/bin/env python #-*- coding: utf-8 -*-import array #array模塊是python中實現的一種高效的數組存儲類型 import serial #serial模塊封裝了對串行端口的訪問 import codecs #Python中專門用作編碼轉換的模塊 import timeclass SBUSReceiver():def __init__(self, _uart_port='/dev/ttyAMA0'):#初始化樹莓派串口參數self.ser = serial.Serial(port=_uart_port, #樹莓派的硬件串口/dev/ttyAMA0baudrate = 100000, #波特率為100kparity=serial.PARITY_EVEN, #偶校驗stopbits=serial.STOPBITS_TWO,#2個停止位bytesize=serial.EIGHTBITS, #8個數據位timeout = 0,)# 常數self.START_BYTE = b'\x0f' #起始字節為0x0fself.END_BYTE = b'\x00' #結束字節為0x00self.SBUS_FRAME_LEN = 25 #SBUS幀有25個字節self.SBUS_NUM_CHAN = 18 #18個通道self.OUT_OF_SYNC_THD = 10self.SBUS_NUM_CHANNELS = 18 #18個通道self.SBUS_SIGNAL_OK = 0 #信號正常為0self.SBUS_SIGNAL_LOST = 1 #信號丟失為1self.SBUS_SIGNAL_FAILSAFE = 2 #輸出failsafe信號時為2# 堆棧變量初始化self.isReady = Trueself.lastFrameTime = 0self.sbusBuff = bytearray(1) # 用于同步的單個字節#bytearray(n) 方法返回一個長度為n的初始化數組;self.sbusFrame = bytearray(25) # 單個SBUS數據幀,25個字節self.sbusChannels = array.array('H', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # 接收到的各頻道值#array.array(typecode,[initializer]) --typecode:元素類型代碼;initializer:初始化器,若數組為空,則省略初始化器self.failSafeStatus = self.SBUS_SIGNAL_FAILSAFEdef get_rx_channels(self):"""用于讀取最后的SBUS通道值返回:由18個無符號短元素組成的數組,包含16個標準通道值+ 2個數字(ch17和18)"""return self.sbusChannelsdef get_rx_channel(self, num_ch):"""用于讀取最后的SBUS某一特定通道的值num_ch: 要讀取的某個通道的通道序號返回:某一通道的值"""return self.sbusChannels[num_ch]def get_failsafe_status(self):"""用于獲取最后的FAILSAFE狀態返回: FAILSAFE狀態值"""return self.failSafeStatusdef decode_frame(self):"""對每幀數據進行解碼,每個通道的值在兩個或三個不同的字節之間,要讀取出來很麻煩不過futaba已經發布了下面的解碼代碼"""def toInt(_from):#encode() 方法以指定的編碼格式編碼字符串。#int() 函數用于將一個字符串或數字轉換為整型。return int(codecs.encode(_from, 'hex'), 16) #CH1 = [data2]的低3位 + [data1]的8位(678+12345678 = 678,12345678)self.sbusChannels[0] = ((toInt(self.sbusFrame[1]) |toInt(self.sbusFrame[2])<<8) & 0x07FF);#CH2 = [data3]的低6位 + [data2]的高5位(345678+12345 = 345678,12345 )self.sbusChannels[1] = ((toInt(self.sbusFrame[2])>>3 |toInt(self.sbusFrame[3])<<5) & 0x07FF);#CH3 = [data5]的低1位 + [data4]的8位 + [data3]的高2位(8+12345678+12 = 8,12345678,12)self.sbusChannels[2] = ((toInt(self.sbusFrame[3])>>6 |toInt(self.sbusFrame[4])<<2 |toInt(self.sbusFrame[5])<<10) & 0x07FF);self.sbusChannels[3] = ((toInt(self.sbusFrame[5])>>1 |toInt(self.sbusFrame[6])<<7) & 0x07FF);self.sbusChannels[4] = ((toInt(self.sbusFrame[6])>>4 |toInt(self.sbusFrame[7])<<4) & 0x07FF);self.sbusChannels[5] = ((toInt(self.sbusFrame[7])>>7 |toInt(self.sbusFrame[8])<<1 |toInt(self.sbusFrame[9])<<9) & 0x07FF);self.sbusChannels[6] = ((toInt(self.sbusFrame[9])>>2 |toInt(self.sbusFrame[10])<<6) & 0x07FF);self.sbusChannels[7] = ((toInt(self.sbusFrame[10])>>5 |toInt(self.sbusFrame[11])<<3) & 0x07FF);self.sbusChannels[8] = ((toInt(self.sbusFrame[12]) |toInt(self.sbusFrame[13])<<8) & 0x07FF);self.sbusChannels[9] = ((toInt(self.sbusFrame[13])>>3 |toInt(self.sbusFrame[14])<<5) & 0x07FF);self.sbusChannels[10] = ((toInt(self.sbusFrame[14])>>6 |toInt(self.sbusFrame[15])<<2|toInt(self.sbusFrame[16])<<10) & 0x07FF);self.sbusChannels[11] = ((toInt(self.sbusFrame[16])>>1 |toInt(self.sbusFrame[17])<<7) & 0x07FF);self.sbusChannels[12] = ((toInt(self.sbusFrame[17])>>4 |toInt(self.sbusFrame[18])<<4) & 0x07FF);self.sbusChannels[13] = ((toInt(self.sbusFrame[18])>>7 |toInt(self.sbusFrame[19])<<1|toInt(self.sbusFrame[20])<<9) & 0x07FF);self.sbusChannels[14] = ((toInt(self.sbusFrame[20])>>2 |toInt(self.sbusFrame[21])<<6) & 0x07FF);self.sbusChannels[15] = ((toInt(self.sbusFrame[21])>>5 |toInt(self.sbusFrame[22])<<3) & 0x07FF);#17頻道,第24字節的最低一位if toInt(self.sbusFrame[23]) & 0x0001 :self.sbusChannels[16] = 2047else:self.sbusChannels[16] = 0#18頻道,第24字節的低第二位,所以要右移一位if (toInt(self.sbusFrame[23]) >> 1) & 0x0001 :self.sbusChannels[17] = 2047else:self.sbusChannels[17] = 0#幀丟失位為1時,第24字節的低第三位,與0x04進行與運算self.failSafeStatus = self.SBUS_SIGNAL_OKif toInt(self.sbusFrame[23]) & (1 << 2):self.failSafeStatus = self.SBUS_SIGNAL_LOST#故障保護激活位為1時,第24字節的低第四位,與0x08進行與運算 if toInt(self.sbusFrame[23]) & (1 << 3):self.failSafeStatus = self.SBUS_SIGNAL_FAILSAFEdef update(self):"""我們需要至少2幀大小,以確保找到一個完整的幀所以我們取出所有的緩存(清空它),讀取全部數據,直到捕獲新的數據首先找到END BYTE并向后查找SBUS_FRAME_LEN,看看它是否是START BYTE"""#我們是否有足夠的數據在緩沖區和有沒有線程在后臺?if self.ser.inWaiting() >= self.SBUS_FRAME_LEN*2 and self.isReady: #inWaiting()返回接收緩存中的字節數self.isReady = False #表明有線程在運行,isReady = False# 讀取所有臨時幀數據tempFrame = self.ser.read(self.ser.inWaiting())# 在緩沖區幀的每個字符中,我們尋找結束字節for end in range(0, self.SBUS_FRAME_LEN):#尋找結束字節,從后向前查找if tempFrame[len(tempFrame)-1-end] == self.END_BYTE :#從最后的命中點減去SBUS_FRAME_LEN尋找起始字節if tempFrame[len(tempFrame)-end-self.SBUS_FRAME_LEN] == self.START_BYTE :# 如果相等,則幀數據正確,數據以8E2包到達,因此它已經被校驗過# 從臨時幀數據中取出剛驗證正確的一段正確幀數據lastUpdate = tempFrame[len(tempFrame)-end-self.SBUS_FRAME_LEN:len(tempFrame)-1-end]if not self.sbusFrame == lastUpdate: #相等即表示沒有操作,不用再次解碼self.sbusFrame = lastUpdateself.decode_frame() #調用解碼函數self.lastFrameTime = time.time() # 跟蹤最近的更新時間self.isReady = Truebreakif __name__ == '__main__':sbus = SBUSReceiver('/dev/ttyAMA0')while True:time.sleep(0.005)# X8R的SBUS信號是間隔6ms發送一次,一次持續發送3ms;# 不要調用sbus.update()太快,如果sbus.ser.inWaiting()>50,且增長很多,可以調用sbus.update()快點,即time.sleep()延遲短點;# 如果sbus.ser.inWaiting()<50,可以調用sbus.update()慢點,即time.sleep()延遲長點;sbus.update()#在您的代碼中,您可以調用sbus.get_rx_channels()來獲取所有數據,或者調用sbus.get_rx_channels()[n]來獲取第n個通道的值;#或get_rx_channel(self, num_ch)來獲得第num_ch個通道的值;print sbus.get_failsafe_status(), sbus.get_rx_channels(), str(sbus.ser.inWaiting()).zfill(4) , (time.time()-sbus.lastFrameTime)#str() 函數將對象轉化為適于人閱讀的形式,將指定的值轉換為字符串。#zfill() 方法返回指定長度的字符串,原字符串右對齊,前面填充0。#(time.time()-sbus.lastFrameTime)用于展示得到最近這次數據的延遲
  • 運行程序后,依次打印出了failsafe狀態值、所有通道的10進制數組、讀取緩存中的字節數、當次數據更新的延遲時間。控制遙控器搖桿晃動,能夠及時得到該通道的數值變化。

  • 從實驗數據中可以看出,三個檔位的通道的下檔值為172,中間檔位時值為992,上檔位時值為1811;2個檔位的下檔值為172,上檔值為1811,搖桿在中間位置時值為992,向其它方向搖動時,數值向172或1811變化。

  • 使用上面的數值,通過函數轉換,就可以輸出相應通道的PWM控制信號,或者其它開關控制信號了!為什么不直接使用PWM輸出呢?因為這樣可以通過無線電遠距離控制樹莓派了,再通過樹莓派編程,控制其他設備,比如樹莓派無人機或者樹莓派智能小車,特別是在沒有移動網絡信號的時候。

  • 遙控器的數字通道17/18沒有搞明白怎么用,所以這里沒有能夠測試,有知道的同學可以留言。

    總結

    以上是生活随笔為你收集整理的树莓派基础实验39:解析无线电接收机PWM、SBUS信号的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。