首頁>科技>

三實驗原理

HC-SR04超聲波感測器的Echo 返回的是 5v訊號,而樹莓派的 GPIO 接收超過 3.3v 的訊號可能會被燒燬,因此需要加一個分壓電路,這裡由於返回的脈衝時間非常短,我沒有加,能正常執行,但還是冒險了!

建議樹莓派實驗選用US-100超聲波感測器,使用3.3V電源時,輸出也是3.3V電源,更安全。某寶上20幾元,只比HC-SR04貴十幾元哈。

  關於超聲波感測器的基礎知識請參見樹莓派基礎實驗24:超聲波測距感測器實驗。

四、實驗步驟

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

樹莓派(name) 樹莓派(BOARD) L298N小車擴充套件板 GPIO.0 11 ENA GPIO.2 13 IN1 GPIO.3 15 IN2 GPIO.1 12 ENB GPIO.4 16 IN3 GPIO.5 18 IN4 GND GND 電池組供電負極

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

L298N小車擴充套件板 電池組 樹莓派 電壓表頭 馬達 電池+(-) 電池+(-) 5V供電 電源介面 +(-) +(-) T1(L後) +(-) T2(L前) +(-) T3(R前) +(-) T4(R後) +(-)

樹莓派(name) 樹莓派(BOARD) 電平反向器 無線電接收機 A6 SBUS_OUT RXD 10 B6 3.3V 1 VCC 0V 9 GND 5V 2 VCC 0V 14 GND

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

樹莓派(name) 樹莓派(BOARD) 超聲波模組 GPIO.6 22 Echo GPIO.7 7 Trig 5V 5V VCC GND GND GND

加裝超聲波模組小車電路圖:

加裝超聲波模組的小車:

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

  第2步: 編寫電機的驅動程式,檔名為motor_4w.py。與樹莓派綜合專案2:智慧小車(一)四輪驅動中的程式基本相同。

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

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

下面的部分程式在前面的文章中已有,這裡做了部分最佳化,本次實驗主要的超聲波模組程式,和主程式在最後面。

motor_4w.py:

#!/usr/bin/env python#-*- coding: utf-8 -*-#本模組只含Motor_4w()一個類,用於樹莓派對電機訊號的控制#透過GPIO輸出訊號,直接對某個電機的轉動方向、速度進行控制import RPi.GPIO as GPIOclass Motor_4w():    '''控制小車四輪動作的類'''    ENA = 11  #使能訊號A,左邊兩輪    IN1 = 13  #訊號輸入1    IN2 = 15  #訊號輸入2    ENB = 12  #使能訊號B,右邊兩輪    IN3 = 16  #訊號輸入3    IN4 = 18  #訊號輸入4    GPIO.setwarnings(False) #關閉警告    def setGPIO(self):        '''初始化引腳'''        GPIO.setmode(GPIO.BOARD)        GPIO.setup(Motor_4w.ENA, GPIO.OUT)        GPIO.setup(Motor_4w.IN1, GPIO.OUT)        GPIO.setup(Motor_4w.IN2, GPIO.OUT)        GPIO.setup(Motor_4w.ENB, GPIO.OUT)        GPIO.setup(Motor_4w.IN3, GPIO.OUT)        GPIO.setup(Motor_4w.IN4, GPIO.OUT)    def pwm(self,pwm):         '''初始化PWM(脈寬調製),返回PWM物件'''        EN_pwm = GPIO.PWM(pwm, 500)        EN_pwm.start(0)        return EN_pwm    def changespeed(self,pwm,speed):        '''透過改變佔空比改變馬達轉速'''        pwm.ChangeDutyCycle(speed)        #print('speed=',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:        motor_4w = Motor_4w() #建立樹莓派小車物件        motor_4w.setGPIO()  #初始化引腳        ENA_pwm=motor_4w.pwm(motor_4w.ENA) #初始化使能訊號PWM,A為左邊車輪        ENB_pwm=motor_4w.pwm(motor_4w.ENB) #初始化使能訊號PWM,B為右邊車輪        while True:            '''透過輸入的命令改變馬達轉動'''            cmd = 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(左邊車輪)順時針訊號                motor_4w.clockwise(motor_4w.IN1,motor_4w.IN2)            if A_direction == "00": #控制A(左邊車輪)逆時針訊號                motor_4w.counter_clockwise(motor_4w.IN1,motor_4w.IN2)            if B_direction == "ff": #控制B(右邊車輪)順時針訊號                motor_4w.clockwise(motor_4w.IN3,motor_4w.IN4)            if B_direction == "00": #控制B(右邊車輪)逆時針訊號                motor_4w.counter_clockwise(motor_4w.IN3,motor_4w.IN4)            if direction == "b": #小車剎車,IN1和IN2都為0,馬達制動                motor_4w.stop_car(motor_4w.IN1,motor_4w.IN2)                motor_4w.stop_car(motor_4w.IN3,motor_4w.IN4)                continue #跳出本次迴圈            # 透過輸入的兩位數字設定佔空比,改變馬達轉速            motor_4w.changespeed(ENA_pwm,int(A_speed))            motor_4w.changespeed(ENB_pwm,int(B_speed))    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.        motor_4w.destroy(ENA_pwm,ENB_pwm)    finally:        motor_4w.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=smpcar        self.ENA_pwm=pwm1        self.ENB_pwm=pwm2        self.rudder_value = 0        self.acc_value = 0    def 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)        #print('acc_value=',self.acc_value)    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 #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/ttyAMA0            baudrate = 100000,          #波特率為100k            parity=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執行時用這句,結束位元組為0x00        self.START_BYTE = 0x0f  #python3執行時用這句,起始位元組為0x0f        self.END_BYTE = 0x00    #python3執行時用這句,結束位元組為0x00        self.SBUS_FRAME_LEN = 25    #SBUS幀有25個位元組        self.SBUS_NUM_CHAN = 18     #18個通道        self.OUT_OF_SYNC_THD = 10        self.SBUS_NUM_CHANNELS = 18 #18個通道        self.SBUS_SIGNAL_OK = 0     #訊號正常為0        self.SBUS_SIGNAL_LOST = 1       #訊號丟失為1        self.SBUS_SIGNAL_FAILSAFE = 2   #輸出failsafe訊號時為2        # 堆疊變數初始化        self.isReady = True        self.lastFrameTime = 0        self.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])          # 接收到的各頻道值,Python3中這裡也可以使用列表        self.sbusChannels = [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_FAILSAFE    def get_rx_channels(self):        """        用於讀取最後的SBUS通道值        返回:由18個無符號短元素組成的陣列,包含16個標準通道值+ 2個數字(ch17和18)        """        return self.sbusChannels    def get_rx_channel(self, num_ch):        """        用於讀取最後的SBUS某一特定通道的值        num_ch: 要讀取的某個通道的通道序號        返回:某一通道的值        """        return self.sbusChannels[num_ch]    def get_failsafe_status(self):        """        用於獲取最後的FAILSAFE狀態        返回: FAILSAFE狀態值        """        return self.failSafeStatus    def 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] = 2047        else:            self.sbusChannels[16] = 0        #18頻道,第24位元組的低第二位,所以要右移一位        if (toInt(self.sbusFrame[23]) >> 1) & 0x0001 :            self.sbusChannels[17] = 2047        else:            self.sbusChannels[17] = 0        #幀丟失位為1時,第24位元組的低第三位,與0x04進行與運算        self.failSafeStatus = self.SBUS_SIGNAL_OK        if 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_FAILSAFE    def 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包到達,因此它已經被校驗過                        # 從臨時幀資料中取出剛驗證正確的一段正確幀資料                        lastUp<ickey>date = tempFrame[len(tempFrame)-end-self.SBUS_FRAME_LEN:len(tempFrame)-1-end]                        if not self.sbusFrame == lastUpdate: #相等即表示沒有操作,不用再次解碼                            self.sbusFrame = lastup(self):        GPIO.setmode(GPIO.BOARD)        GPIO.setup(Ultrasonic.TRIG, GPIO.OUT, initial = GPIO.LOW)        GPIO.setup(Ultrasonic.ECHO, GPIO.IN)    def distance(self):        GPIO.output(Ultrasonic.TRIG, 1)  #給Trig一個10US以上的高電平        time.sl<ickey>eep(0.00001)        GPIO.output(Ultrasonic.TRIG, 0)    #等待低電平結束,然後記錄時間        while GPIO.input(Ultrasonic.ECHO) == 0:  #捕捉 echo 端輸出上升沿            pass        time1 = time.time()      #等待高電平結束,然後記錄時間        while GPIO.input(Ultrasonic.ECHO) == 1:  #捕捉 echo 端輸出下降沿            pass        time2 = time.time()         during = time2 - time1       #ECHO高電平時刻時間減去低電平時刻時間,所得時間為超聲波傳播時間        return during * 340 / 2 * 100      #超聲波傳播速度為340m/s,最後單位米換算為釐米,所以乘以100    def destroy(self):        GPIO.cleanup()if __name__ == "__main__":    try:        ultr = Ultrasonic()        ultr.setup()        while True:            dis = ultr.distance()            print('distance= %f cm\n' %dis)            time.sl<ickey>eep(0.3)    except KeyboardInterrupt:        ultr.destroy()

  第6步: 編寫樹莓派智慧小車的主程式,檔名為smartcar.py,將這5個Python檔案放入一個資料夾後,只執行本檔案就可以了。  主程式中加入了ultra_control()超聲波控制函式,實現了距離小於50cm時,強制性降低油門值為35(即佔空比為35%),距離小於20cm時,自動剎車,並倒車0.5秒。smartcar.py:

#!/usr/bin/env python#-*- coding: utf-8 -*-#本模組為樹莓派小車的主程式,from motor_4w import Motor_4wfrom sbus_receiver_pi import SBUSReceiverfrom moving_control import MovingControlfrom ultrasonic import Ultrasonicimport timeacc_value_sbus_enable = 1 #使能是否執行SBUS油門訊號,為0時使遙控器油門訊號無效sbus_receiver = SBUSReceiver('/dev/ttyAMA0') #初始化SBUS訊號接收例項smp_car = Motor_4w() #初始化電機控制例項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)  #初始化車輛運動控制例項ultr = Ultrasonic() #初始化超聲波例項ultr.setup()        #初始化超聲波引腳def ultra_control():    '''超聲波感測器控制'''    global acc_value_sbus_enable    dis = ultr.distance()    print('distance= %.1f cm\n' %dis)    if dis < 50:    #當障礙距離小於50cm時,不執行SBUS油門訊號        if smartcar.acc_value > 35:        #當障礙距離小於50cm,且油門大於40時,油門設定為40,為防衝撞減速            smartcar.acc_value = 35             smartcar.accelerator() #調節油門    if dis < 20:    #如果測距小於20cm時,先停車再倒車0.5秒        smartcar.brake()        smartcar.reverse()        time.sl<ickey>eep(0.5)def sbus_control():    '''無線電控制'''    sbus_receiver.update() #獲取一個完整的幀資料    global acc_value_sbus_enable    aileron_value = sbus_receiver.get_rx_channel(0) #1通道為副翼通道,這裡控制車原地轉向    elevator_value = sbus_receiver.get_rx_channel(1)#2通道為升降舵通道,這裡控制車前進後退    rudder_value = sbus_receiver.get_rx_channel(3)#4通道為方向舵通道,這裡控制車左右偏移行進    if acc_value_sbus_enable == 1:    #使能SBUS訊號的油門控制            acc_value_sbus = 172  #3通道,即油門的值,最低時為172                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))        print('000.acc_value=',smartcar.acc_value) #檢測SBUS訊號的油門值    #print('subsu_acc_value_sbus_enable=',acc_value_sbus_enable) #測試資料用    ultra_control()        print('1111.acc_value=',smartcar.acc_value)  #檢測超聲波函式處理後的油門值    if 970 < rudder_value < 1100: #沒有左右偏移時,中間值為992,但遙控器微調時會有上下浮動        pass                    #沒有左右偏移時    elif rudder_value >=1100:      #向右偏移行進時        rate_right = (1811.0 - rudder_value)/(1811-1100)         #最大值一般為1811,這裡使用浮點型別,所以一定要使用1811.0        smartcar.accelerator(1,rate_right)    elif rudder_value <=970:       #向左偏移行進時        rate_left = (rudder_value - 172.0)/(970-172)          #最小值為172,這裡使用浮點型別,所以一定要使用172.0        smartcar.accelerator(rate_left,1)    print('elevator_value=%d,aileron_value=%d,rudder_value=%d'%(elevator_value,aileron_value,rudder_value))#測試資料用    if aileron_value >= 1100:  #原地左轉彎        smartcar.leftTurn()        smartcar.accelerator()    elif aileron_value <= 970: #原地右轉彎        smartcar.rightTurn()        smartcar.accelerator()    else :         smartcar.brake()       #停車    if elevator_value >=1100:  #前進        smartcar.forward()    elif elevator_value <=970: #後退        smartcar.reverse()        #迴圈最後,這裡不能再用停車了    try:        while True:        time.sl<ickey>eep(0.005)        sbus_control()except KeyboardInterrupt:      smp_car.destroy(ENA_pwm,ENB_pwm)finally:    smp_car.destroy(ENA_pwm,ENB_pwm)

樹莓派綜合專案2:智慧小車(四)超聲波避障程式碼和電路圖下載演示效果:

這裡將超聲波模組加入了進來,但只做了簡單應用,後面將把各種感測器加入進來後,會實現超聲波模組更復雜的應用。

19
最新評論
  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 小米獨佔驍龍888,僅僅因為銷量最高?10年前就埋下伏筆