一、介紹
??閱讀本篇文章前建議先參考前期文章:
??樹(shù)莓派基礎(chǔ)實(shí)驗(yàn)34:L298N模塊驅(qū)動(dòng)直流電機(jī)實(shí)驗(yàn),學(xué)習(xí)了單個(gè)電機(jī)的簡(jiǎn)單驅(qū)動(dòng)。
??樹(shù)莓派綜合項(xiàng)目2:智能小車(chē)(一)四輪驅(qū)動(dòng),實(shí)現(xiàn)了代碼輸入對(duì)四個(gè)電機(jī)的簡(jiǎn)單控制。
??樹(shù)莓派綜合項(xiàng)目2:智能小車(chē)(二)tkinter圖形界面控制,實(shí)現(xiàn)了本地圖形界面控制小車(chē)的前進(jìn)后退、轉(zhuǎn)向和原地轉(zhuǎn)圈。
??樹(shù)莓派綜合項(xiàng)目2:智能小車(chē)(三)無(wú)線(xiàn)電遙控,實(shí)現(xiàn)了無(wú)線(xiàn)電遙控設(shè)備控制小車(chē)的前進(jìn)后退、轉(zhuǎn)向和原地轉(zhuǎn)圈。
??樹(shù)莓派綜合項(xiàng)目2:智能小車(chē)(四)超聲波避障,實(shí)現(xiàn)了超聲波傳感器實(shí)時(shí)感知小車(chē)前方障礙物的距離,當(dāng)距離近于某個(gè)閾值時(shí),小車(chē)自動(dòng)減速,再低于某個(gè)閾值時(shí)自動(dòng)剎車(chē),然后倒車(chē)至安全距離。
??本實(shí)驗(yàn)中將使用HJ-IR2紅外光電傳感器,探測(cè)到物體即輸出脈沖,輸入到樹(shù)莓派中處理,再對(duì)電機(jī)驅(qū)動(dòng)模塊進(jìn)行控制,實(shí)現(xiàn)壁障的功能,這樣的避障小車(chē)又稱(chēng)為簡(jiǎn)單的避障機(jī)器人。
??其它基礎(chǔ)內(nèi)容可以參考文集:樹(shù)莓派基礎(chǔ)實(shí)驗(yàn)。
二、組件
★Raspberry Pi 3 B+全套*1
★睿思凱Frsky XM+ 迷你接收機(jī)*1
★電平反向器模塊*1
★睿思凱Frsky Taranis X9D PLUS SE2019遙控器*1
★L(fēng)298N擴(kuò)展板模塊*1
★智能小車(chē)底板模塊*1
★減速電機(jī)和車(chē)輪*4
★HC-SR04超聲波模塊*1
★HJ-IR2紅外光電傳感器*2
★跳線(xiàn)若干
三、實(shí)驗(yàn)原理

??本實(shí)驗(yàn)原理和超聲波避障相似,紅外傳感器就是一個(gè)紅外對(duì)射開(kāi)關(guān),通電狀態(tài)下,紅外發(fā)射頭發(fā)射紅外信號(hào),經(jīng)過(guò)目標(biāo)反射后接收頭接收此信號(hào),并輸出一個(gè)低電平信號(hào),樹(shù)莓派采集這個(gè)低電平信號(hào)后采取相應(yīng)措施避障。


??若沒(méi)有被任何一個(gè)探頭檢測(cè)到障礙物,小車(chē)直行;左邊探頭檢測(cè)到障礙物時(shí)小車(chē)向右轉(zhuǎn),右邊探頭檢測(cè)到障礙物時(shí)小車(chē)向左轉(zhuǎn)。
??關(guān)于紅外傳感器的基礎(chǔ)知識(shí)請(qǐng)參見(jiàn)樹(shù)莓派基礎(chǔ)實(shí)驗(yàn)28:紅外避障傳感器實(shí)驗(yàn)。
四、實(shí)驗(yàn)步驟
??第1步: 連接電路。這里對(duì)紅外避障外的連線(xiàn)方法不在累述,請(qǐng)參考樹(shù)莓派綜合項(xiàng)目2:智能小車(chē)(四)超聲波避障。
| 樹(shù)莓派(name) | 樹(shù)莓派(BOARD) | 紅外探測(cè)模塊 |
|---|---|---|
| GPIO.21 | 29 | 左側(cè)紅外輸出 |
| GPIO.22 | 31 | 右側(cè)紅外輸出 |
| 5V | 5V | 兩個(gè)模塊的VCC |
| GND | GND | 兩個(gè)模塊的GND |

??第2步: motor_4w.py,moving_control.py,sbus_receiver_pi.py,ultrasonic.py文件的編碼這里不再累述,參考樹(shù)莓派綜合項(xiàng)目2:智能小車(chē)(四)超聲波避障。
??第3步:編寫(xiě)紅外探測(cè)模塊,文件名為infrared.py,與樹(shù)莓派基礎(chǔ)實(shí)驗(yàn)28:紅外避障傳感器實(shí)驗(yàn)中的Python程序基本相同,只是設(shè)置了類(lèi),重構(gòu)了程序。
infrared.py:
#!/usr/bin/env python3
#-*- coding: utf-8 -*-
#本模塊只含Infrared()一個(gè)類(lèi),用于紅外避障模塊測(cè)出是否有障礙物
#有障礙物時(shí)返回值0,無(wú)障礙物時(shí)返回值1
import RPi.GPIO as GPIO
import time
class Infrared():
InfraredPinLeft = 29 #左側(cè)模塊的輸出連接樹(shù)莓派29號(hào)針腳
InfraredPinRight = 31
def setup(self):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(Infrared.InfraredPinLeft, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(Infrared.InfraredPinRight, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def infra_detect(self):
infra_left_value = 1
infra_right_value = 1
if (0 == GPIO.input(Infrared.InfraredPinLeft)): #當(dāng)檢測(cè)到障礙物時(shí),輸出低電平信號(hào)
infra_left_value = 0
if (0 == GPIO.input(Infrared.InfraredPinRight)): #當(dāng)檢測(cè)到障礙物時(shí),輸出低電平信號(hào)
infra_right_value = 0
return infra_left_value,infra_right_value
def destroy(self):
GPIO.cleanup()
if __name__ == "__main__":
try:
infrared = Infrared()
infrared.setup()
while True:
infra_left_value,infra_right_value = infrared.infra_detect()
print('infra_left_value=%d infra_right_value=%d'%(infra_left_value,infra_right_value) )
time.sleep(0.1)
except KeyboardInterrupt:
infrared.destroy()
??第4步: 編寫(xiě)樹(shù)莓派智能小車(chē)的主程序,文件名為smartcar.py,將這5個(gè)Python文件放入一個(gè)文件夾后,只運(yùn)行本文件就可以了。
??主程序中加入了infra_control()紅外避障函數(shù),實(shí)現(xiàn)了沒(méi)有障礙物時(shí)小車(chē)直行;左邊探頭檢測(cè)到障礙物時(shí)小車(chē)向右轉(zhuǎn),右邊探頭檢測(cè)到障礙物時(shí)小車(chē)向左轉(zhuǎn)。
smartcar.py:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
#本模塊為樹(shù)莓派小車(chē)的主程序,
from motor_4w import Motor_4w
from sbus_receiver_pi import SBUSReceiver
from moving_control import MovingControl
from ultrasonic import Ultrasonic
from infrared import Infrared
import time
acc_value_sbus_enable = 1 #使能是否執(zhí)行SBUS油門(mén)信號(hào),為0時(shí)使遙控器油門(mén)信號(hào)無(wú)效
sbus_receiver = SBUSReceiver('/dev/ttyAMA0') #初始化SBUS信號(hào)接收實(shí)例
smp_car = Motor_4w() #初始化電機(jī)控制實(shí)例
smp_car.setGPIO() #初始化引腳
ENA_pwm = smp_car.pwm(smp_car.ENA) #初始化使能信號(hào)PWM,A為左邊車(chē)輪
ENB_pwm = smp_car.pwm(smp_car.ENB) #初始化使能信號(hào)PWM,B為右邊車(chē)輪
smartcar = MovingControl(smp_car,ENA_pwm,ENB_pwm) #初始化車(chē)輛運(yùn)動(dòng)控制實(shí)例
ultr = Ultrasonic() #初始化超聲波實(shí)例
ultr.setup() #初始化超聲波引腳
infrared = Infrared() #初始化紅外避障實(shí)例
infrared.setup() #初始化紅外避障引腳
def ultra_control():
'''超聲波傳感器控制'''
global acc_value_sbus_enable
dis = ultr.distance()
print('distance= %.1f cm\n' %dis)
if dis < 50:
#當(dāng)障礙距離小于50cm時(shí),不執(zhí)行SBUS油門(mén)信號(hào)
if smartcar.acc_value > 40:
#當(dāng)障礙距離小于50cm,且油門(mén)大于40時(shí),油門(mén)設(shè)定為40,為防沖撞減速
smartcar.acc_value = 40
smartcar.accelerator() #調(diào)節(jié)油門(mén)
if dis < 10:
#如果測(cè)距小于10cm時(shí),先停車(chē)再倒車(chē)0.3秒
smartcar.brake()
smartcar.reverse()
time.sleep(0.3)
def infra_control():
'''紅外避障傳感器控制'''
infra_left_value = 1 #值默認(rèn)為1時(shí),表示無(wú)障礙物
infra_right_value = 1
infra_left_value,infra_right_value = infrared.infra_detect()
if infra_left_value == 0: #值為0時(shí),表示左側(cè)檢測(cè)到障礙物
#smartcar.acc_value=80
smartcar.accelerator(1,0) #控制小車(chē)向右偏轉(zhuǎn)
time.sleep(0.5) #向右偏轉(zhuǎn)行進(jìn)0.5秒
if infra_right_value == 0:
#smartcar.acc_value=80
smartcar.accelerator(0,1)
time.sleep(0.5)
print('infra_left_value=%d infra_right_value=%d'%(infra_left_value,infra_right_value) )
def sbus_control():
'''無(wú)線(xiàn)電控制'''
sbus_receiver.update() #獲取一個(gè)完整的幀數(shù)據(jù)
global acc_value_sbus_enable
aileron_value = sbus_receiver.get_rx_channel(0) #1通道為副翼通道,這里控制車(chē)原地轉(zhuǎn)向
elevator_value = sbus_receiver.get_rx_channel(1)#2通道為升降舵通道,這里控制車(chē)前進(jìn)后退
rudder_value = sbus_receiver.get_rx_channel(3)#4通道為方向舵通道,這里控制車(chē)左右偏移行進(jìn)
if acc_value_sbus_enable == 1:
#使能SBUS信號(hào)的油門(mén)控制
acc_value_sbus = 172 #3通道,即油門(mén)的值,最低時(shí)為172
if sbus_receiver.get_rx_channel(2):
acc_value_sbus = sbus_receiver.get_rx_channel(2) #3通道為油門(mén)通道,這里控制車(chē)速度
#將172~1811的油門(mén)通道值轉(zhuǎn)換為0~100的占空比信號(hào),
smartcar.acc_value = int(100*(acc_value_sbus-172)/(1811-172))
print('original.acc_value=',smartcar.acc_value) #檢測(cè)SBUS信號(hào)的油門(mén)值
ultra_control() #超聲波避障
infra_control() #紅外避障
print('disposed.acc_value=',smartcar.acc_value) #檢測(cè)超聲波函數(shù)處理后的油門(mén)值
if 970 < rudder_value < 1100: #沒(méi)有左右偏移時(shí),中間值為992,但遙控器微調(diào)時(shí)會(huì)有上下浮動(dòng)
pass #沒(méi)有左右偏移時(shí)
elif rudder_value >=1100: #向右偏移行進(jìn)時(shí)
rate_right = (1811.0 - rudder_value)/(1811-1100)
#最大值一般為1811,這里使用浮點(diǎn)類(lèi)型,所以一定要使用1811.0
smartcar.accelerator(1,rate_right)
elif rudder_value <=970: #向左偏移行進(jìn)時(shí)
rate_left = (rudder_value - 172.0)/(970-172)
#最小值為172,這里使用浮點(diǎn)類(lèi)型,所以一定要使用172.0
smartcar.accelerator(rate_left,1)
print('elevator_value=%d,aileron_value=%d,rudder_value=%d'%(elevator_value,aileron_value,rudder_value))#測(cè)試數(shù)據(jù)用
if aileron_value >= 1100: #原地左轉(zhuǎn)彎
smartcar.leftTurn()
smartcar.accelerator()
elif aileron_value <= 970: #原地右轉(zhuǎn)彎
smartcar.rightTurn()
smartcar.accelerator()
else :
smartcar.brake() #停車(chē)
if elevator_value >=1100: #前進(jìn)
smartcar.forward()
elif elevator_value <=970: #后退
smartcar.reverse()
#循環(huán)最后,這里不能再用停車(chē)了
try:
while True:
time.sleep(0.01)
sbus_control()
except KeyboardInterrupt:
smp_car.destroy(ENA_pwm,ENB_pwm)
finally:
smp_car.destroy(ENA_pwm,ENB_pwm)
這個(gè)項(xiàng)目的代碼90%是我原創(chuàng)瞎寫(xiě)的,有需要參考的同學(xué)可以下載:
樹(shù)莓派智能小車(chē)項(xiàng)目python源代碼下載
