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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

树莓派综合项目2:智能小车(三)无线电遥控

發布時間:2024/3/26 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树莓派综合项目2:智能小车(三)无线电遥控 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、介紹

??閱讀本篇文章前建議先參考前期文章:
??樹莓派基礎實驗34:L298N模塊驅動直流電機實驗
??樹莓派綜合項目2:智能小車(一)四輪驅動
??樹莓派綜合項目2:智能小車(二)tkinter圖形界面控制
??《智能小車(一)四輪驅動》中,實現了代碼輸入對四個電機的簡單控制。《智能小車(二)tkinter圖形界面控制》中,實現了本地圖形界面控制小車的前進后退、轉向和原地轉圈。

??本實驗中將使用無線電遙控設備控制小車的前進后退、轉向和原地轉圈。使用傳統無線電通信設備通信仍然是非常重要的通信方式,比如無線電臺、對講機,航模、車模、船模遙控等等。與手機移動網絡、WIFI連接相比,無線電連接有它獨特的優勢,遙控距離遠,實時性好,操作靈活,不受網絡信號限制。

??其它基礎內容可以參考文集:樹莓派基礎實驗。

二、組件

★Raspberry Pi 3 B+全套*1

★睿思凱Frsky XM+ 迷你接收機*1

★電平反向器模塊*1

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

★L298N擴展板模塊*1

★智能小車底板模塊*1

★減速電機和車輪*4

★跳線若干

三、實驗原理

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


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

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

接收機輸出兩種信號,一種是模擬信號PWM,一種是SBUS數字信號。

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

S-BUS其實是一種串口通信協議,采用100000的波特率,數據位點8bits,停止位點2bits,偶效驗,即8E2的串口通信。使用樹莓派的串口GPIO(TXD/RXD)中的RXD端口接收接收機的SBUS輸出信號,解析出每路通道的控制信號,進而控制小車行進。

但是S-BUS采用的是反向電平傳輸,也就是說,在S-BUS的發送端高低電平是反向的,協議中的所有高電平都被轉換成低電平,協議中的所有低電平都被轉換成高電平。所以在S-BUS的接收端需要增加一個高低電平反向器來進行電平反轉。

關于解析無線電接收機PWM、SBUS信號的更詳細內容,請參考樹莓派基礎實驗39:解析無線電接收機PWM、SBUS信號。

四、實驗步驟

??第1步: 連接電路。在樹莓派綜合項目2:智能小車(一)四輪驅動中的接線基礎上,接入電平反向器、無線電接收機。

樹莓派(name)樹莓派(BOARD)L298N小車擴展板
GPIO.011ENA
GPIO.213IN1
GPIO.315IN2
GPIO.112ENB
GPIO.416IN3
GPIO.518IN4
GNDGND電池組供電負極

關于這里樹莓派GND、L298N小車擴展板的電池組供電負極相連,是特殊情況下的情況,經測試發現:
如果樹莓派用的是充電頭供電,而L298N擴展板用的是電池組供電,這兩個負極必須相連,否則馬達不動。
如果樹莓派用的是L298N擴展板接出來的5V供電,即兩者同一個電源,則這里不用連接。

L298N小車擴展板電池組樹莓派電壓表頭馬達
電池+(-)電池+(-)
5V供電電源接口
+(-)+(-)
T1(L后)+(-)
T2(L前)+(-)
T3(R前)+(-)
T4(R后)+(-)
樹莓派(name)樹莓派(BOARD)電平反向器無線電接收機
A6SBUS_OUT
RXD10B6
3.3V1VCC
0V9GND
5V2VCC
0V14GND

這里也要注意,由于樹莓派的GPIO只能接收3.3V的最高輸入,所以電平反相器的電源也只能使用3.3V,若反向后接收的信號需要是5V,則電平反相器的電源就使用5V。

這里我將18650電池組換成了航模使用的格氏ACE鋰電池(3S/11.1V/2200MAH/40C),電壓更高,能給樹莓派提供更穩定的電源,動力性也更好,效果非常不錯。

??第2步: 編寫電機的驅動程序,文件名為motor_4w.py。與樹莓派綜合項目2:智能小車(一)四輪驅動中的程序完全相同。

??該車的行進控制與履帶車的行進控制類似:

前進和后退很簡單,左右兩邊的方向都朝前或朝后,速度一致;
原地順時針旋轉時,左邊輪子前進,右邊輪子后退,速度一致;
原地逆時針旋轉時,左邊輪子后退,右邊輪子前進,速度一致;
偏左前進時,左右兩邊的方向都朝前,左輪速度比右輪速度慢一點;
偏右前進時,左右兩邊的方向都朝前,左輪速度比右輪速度快一點;
偏左后退時,左右兩邊的方向都朝后,左輪速度比右輪速度慢一點;
偏右后退時,左右兩邊的方向都朝后,左輪速度比右輪速度快一點;

motor_4w.py:

#!/usr/bin/env python #-*- coding: utf-8 -*- #本模塊只含SMPcar()一個類,用于樹莓派對電機信號的控制 #通過GPIO輸出信號,直接對某個電機的轉動方向、速度進行控制import RPi.GPIO as GPIOclass SMPcar():'''控制小車四輪動作的類'''ENA = 11 #使能信號A,左邊兩輪IN1 = 13 #信號輸入1IN2 = 15 #信號輸入2ENB = 12 #使能信號B,右邊兩輪IN3 = 16 #信號輸入3IN4 = 18 #信號輸入4GPIO.setwarnings(False) #關閉警告def setGPIO(self):'''初始化引腳'''GPIO.setmode(GPIO.BOARD)GPIO.setup(SMPcar.ENA, GPIO.OUT)GPIO.setup(SMPcar.IN1, GPIO.OUT)GPIO.setup(SMPcar.IN2, GPIO.OUT)GPIO.setup(SMPcar.ENB, GPIO.OUT)GPIO.setup(SMPcar.IN3, GPIO.OUT)GPIO.setup(SMPcar.IN4, GPIO.OUT)def pwm(self,pwm): '''初始化PWM(脈寬調制),返回PWM對象'''EN_pwm = GPIO.PWM(pwm, 500)EN_pwm.start(0)return EN_pwmdef changespeed(self,pwm,speed):'''通過改變占空比改變馬達轉速'''pwm.ChangeDutyCycle(speed)def clockwise(self,in1_pin,in2_pin):'''馬達順時針轉的信號'''GPIO.output(in1_pin, 1)GPIO.output(in2_pin, 0)def counter_clockwise(self,in1_pin,in2_pin):'''馬達逆時針轉的信號'''GPIO.output(in1_pin, 0)GPIO.output(in2_pin, 1)def stop_car(self,in1_pin,in2_pin):'''馬達制動的信號'''GPIO.output(in1_pin, 0)GPIO.output(in2_pin, 0)#使能信號為低電平,或者高電平(占空比設為100,IN1和IN2都為0或1時)馬達制動def destroy(self,A,B):'''結束程序時清空GPIO狀態'''A.stop()B.stop()GPIO.cleanup() # Release resourceif __name__ == '__main__': # 本模塊單獨測試時運行使用try:smpcar = SMPcar() #創建樹莓派小車對象smpcar.setGPIO() #初始化引腳ENA_pwm=smpcar.pwm(smpcar.ENA) #初始化使能信號PWM,A為左邊車輪ENB_pwm=smpcar.pwm(smpcar.ENB) #初始化使能信號PWM,B為右邊車輪while True:'''通過輸入的命令改變馬達轉動'''cmd = raw_input("Command, E.g. ff30ff30 :")direction = cmd[0] #只輸入字母b時,小車剎車A_direction = cmd[0:2] #字符串0/1兩位為控制A(左邊車輪)方向信號B_direction = cmd[4:6] #4/5位為控制B(右邊車輪)方向信號A_speed = cmd[2:4] #字符串2/3兩位為控制A(左邊車輪)速度信號B_speed = cmd[6:8] #字符串6/7兩位為控制B(右邊車輪)速度信號print (A_direction,B_direction,A_speed,B_speed) #測試用if A_direction == "ff": #控制A(左邊車輪)順時針信號smpcar.clockwise(smpcar.IN1,smpcar.IN2)if A_direction == "00": #控制A(左邊車輪)逆時針信號smpcar.counter_clockwise(smpcar.IN1,smpcar.IN2)if B_direction == "ff": #控制B(右邊車輪)順時針信號smpcar.clockwise(smpcar.IN3,smpcar.IN4)if B_direction == "00": #控制B(右邊車輪)逆時針信號smpcar.counter_clockwise(smpcar.IN3,smpcar.IN4)if direction == "b": #小車剎車,IN1和IN2都為0,馬達制動smpcar.stop_car(smpcar.IN1,smpcar.IN2)smpcar.stop_car(smpcar.IN3,smpcar.IN4)continue #跳出本次循環# 通過輸入的兩位數字設置占空比,改變馬達轉速smpcar.changespeed(ENA_pwm,int(A_speed))smpcar.changespeed(ENB_pwm,int(B_speed))except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.smpcar.destroy(ENA_pwm,ENB_pwm)finally:smpcar.destroy(ENA_pwm,ENB_pwm)

??第3步: 小車行進控制模塊,文件名為moving_control.py,設計小車的移動行為,方向控制分為:原地左轉彎、原地右轉彎、直線前進、直線后退、剎車,而向前左偏移開進或右偏移開進等,由左右兩邊不同的速度(油門)來控制。
moving_control.py:

#-*- coding: utf-8 -*- #本模塊只含MovingControl()一個類,針對遙控器的控制方式,設計小車的移動行為 #方向控制分為:原地左轉彎、原地右轉彎、直線前進、直線后退、剎車 #而向前左偏移開進或右偏移開進等,由左右兩邊不同的速度(油門)來控制class MovingControl():def __init__(self, smpcar,pwm1,pwm2):self.smpcar=smpcarself.ENA_pwm=pwm1self.ENB_pwm=pwm2self.rudder_value = 0self.acc_value = 0def accelerator(self,rate_left=1,rate_right=1):'''速度(油門)控制'''#rate_left為向左偏移行進時,降低左邊輪的速度#rate_right為向右偏移行進時,降低右邊輪的速度self.smpcar.changespeed(self.ENA_pwm,self.acc_value * rate_left)self.smpcar.changespeed(self.ENB_pwm,self.acc_value * rate_right)def leftTurn(self):'''原地左轉彎'''self.smpcar.counter_clockwise(self.smpcar.IN1,self.smpcar.IN2) #左邊車輪后退self.smpcar.clockwise(self.smpcar.IN3,self.smpcar.IN4) #右邊車輪前進def rightTurn(self):'''原地右轉彎'''self.smpcar.clockwise(self.smpcar.IN1,self.smpcar.IN2)self.smpcar.counter_clockwise(self.smpcar.IN3,self.smpcar.IN4)def forward(self):'''直線前進'''self.smpcar.clockwise(self.smpcar.IN1,self.smpcar.IN2)self.smpcar.clockwise(self.smpcar.IN3,self.smpcar.IN4)def reverse(self):'''直線后退'''self.smpcar.counter_clockwise(self.smpcar.IN1,self.smpcar.IN2)self.smpcar.counter_clockwise(self.smpcar.IN3,self.smpcar.IN4)def brake(self):'''剎車'''self.smpcar.stop_car(self.smpcar.IN1,self.smpcar.IN2)self.smpcar.stop_car(self.smpcar.IN3,self.smpcar.IN4)

??第4步: 編寫SBUS信號接收解析模塊,文件名為sbus_receiver_pi.py,與樹莓派基礎實驗39:解析無線電接收機PWM、SBUS信號中的Python2程序有所不同,下面的程序在Python3中運行,并標注了兩者的不同之處。
sbus_receiver_pi.py:

#!/usr/bin/env python #-*- coding: utf-8 -*- #本模塊只含SBUSReceiver()一個類,用于獲取和解析遙控器接收機的SBUS輸出信號 #并能返回每個通道的數值,遙控器的failsafe信號狀態,每次獲得數據幀的長度和這次數據的延遲時間#import array #python2運行時需要,array模塊是python中實現的一種高效的數組存儲類型 import serial #serial模塊封裝了對串行端口的訪問 #import binascii #python2運行時需要,binascii模塊包含很多在二進制和ASCII編碼的二進制表示轉換的方法 #import codecs #python2運行時需要,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,)# 常數#這里注意:Python2 與Python3 的編碼方式是不同的#self.START_BYTE = b'\x0f' #python2運行時用這句,起始字節為0x0f#self.END_BYTE = b'\x00' #python2運行時用這句,結束字節為0x00self.START_BYTE = 0x0f #python3運行時用這句,起始字節為0x0fself.END_BYTE = 0x00 #python3運行時用這句,結束字節為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的初始化數組;'''這里Python2與Python3存儲數據的編碼格式會不同'''self.sbusFrame = bytearray(25) # 單個SBUS數據幀,25個字節# 接收到的各頻道值,前面的Python2中使用了數組#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:初始化器,若數組為空,則省略初始化器# 接收到的各頻道值,Python3中這里也可以使用列表self.sbusChannels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]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) #Python2中要使用這句,轉換編碼格式return _from #Python3中要使用這句,即不用轉換編碼格式#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)用于展示得到最近這次數據的延遲

??第5步: 編寫樹莓派智能小車的主程序,文件名為smartcar.py,將這4個Python文件放入一個文件夾后,只運行本文件就可以了。
smartcar.py:

#!/usr/bin/env python #-*- coding: utf-8 -*- #本模塊為樹莓派小車的主程序 from motor_4w import SMPcar from sbus_receiver_pi import SBUSReceiver from moving_control import MovingControl import timetry:sbus_receiver = SBUSReceiver('/dev/ttyAMA0') #初始化實例smp_car = SMPcar() #初始化實例smp_car.setGPIO() #初始化引腳ENA_pwm = smp_car.pwm(smp_car.ENA) #初始化使能信號PWM,A為左邊車輪ENB_pwm = smp_car.pwm(smp_car.ENB) #初始化使能信號PWM,B為右邊車輪smartcar = MovingControl(smp_car,ENA_pwm,ENB_pwm) ##初始化實例acc_value_sbus = 172 #3通道,即油門的值,最低時為172while True:time.sleep(0.005)sbus_receiver.update() #獲取一個完整的幀數據aileron_value = sbus_receiver.get_rx_channel(0) #1通道為副翼通道,這里控制車原地轉向elevator_value = sbus_receiver.get_rx_channel(1)#2通道為升降舵通道,這里控制車前進后退smartcar.rudder_value = sbus_receiver.get_rx_channel(3)#4通道為方向舵通道,這里控制車左右偏移行進if sbus_receiver.get_rx_channel(2):acc_value_sbus = sbus_receiver.get_rx_channel(2) #3通道為油門通道,這里控制車速度#將172~1811的油門通道值轉換為0~100的占空比信號,smartcar.acc_value = int(100*(acc_value_sbus-172)/(1811-172))if 970 < smartcar.rudder_value < 1100: #沒有左右偏移時,中間值為992,但遙控器微調時會有上下浮動smartcar.accelerator()elif smartcar.rudder_value >=1100: #向右偏移行進時rate_right = (1811.0 - smartcar.rudder_value)/(1811-1100) #最大值一般為1811,這里使用浮點類型,所以一定要使用1811.0smartcar.accelerator(1,rate_right)elif smartcar.rudder_value <=970: #向左偏移行進時rate_left = (smartcar.rudder_value - 172.0)/(970-172) #最小值為172,這里使用浮點類型,所以一定要使用172.0smartcar.accelerator(rate_left,1)print(elevator_value,smartcar.acc_value,aileron_value,smartcar.rudder_value)#測試數據用if aileron_value >= 1100: #原地左轉彎smartcar.leftTurn()elif aileron_value <= 970: #原地右轉彎smartcar.rightTurn()else : smartcar.brake() #停車if elevator_value >=1100: #前進smartcar.forward()elif elevator_value <=970: #后退smartcar.reverse()#循環最后,這里不能再用停車了 except KeyboardInterrupt: smp_car.destroy(ENA_pwm,ENB_pwm) finally:smp_car.destroy(ENA_pwm,ENB_pwm)

操控演示視頻:
https://www.bilibili.com/video/BV1Q5411L75a/

最近太忙,這篇文章拖了很久才完成,當中克服了一個個不懂的技術難點和BUG,不過終于實現了遙控小車的想法,成功將無線電遙控和樹莓派結合起來。

辛苦是值得的,學到不少東西,后面將陸續把各種傳感器加入進來,實現智能化。

這個項目的代碼90%是我原創瞎寫的,有需要參考的同學可以下載:
樹莓派智能小車項目python源代碼下載

總結

以上是生活随笔為你收集整理的树莓派综合项目2:智能小车(三)无线电遥控的全部內容,希望文章能夠幫你解決所遇到的問題。

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