一、介紹
??樹莓派的小項(xiàng)目中,我首選了智能小車這個(gè)項(xiàng)目作為我探索的第一個(gè)目標(biāo),因?yàn)楹秃芏嘈∨笥岩粯?,對遙控小汽車有種喜歡,特別是有過小時(shí)候欲求而不得的經(jīng)歷的大人們哈。
??其實(shí)也還有現(xiàn)實(shí)因素考慮,智能小車是地上跑的,比天上飛的水下潛的操作方便、簡單、便宜,所需要的元素和技術(shù)也比較全面,市場上現(xiàn)有的硬件也很多,資料也較多,作為新手村入場很不錯(cuò)!
??然則事實(shí)很打臉,這哪是1級的新手村啊,起碼是10級的副本地圖,沒人帶的話,結(jié)果可想而知。

??2018年6月8日購買的,今天才正式開玩,中間雖說很多事情耽誤了但也拖得夠久的了,主要是送的視頻資料講解內(nèi)容很淺顯,對編程的解釋不夠細(xì),而且只有C++的源碼,雖然本人有過開發(fā)C++的淺薄經(jīng)驗(yàn),但自我鑒定級別很低?,F(xiàn)在有個(gè)這么好學(xué)好用的Python,不想去倒騰C++了,可那時(shí)Python也不會??!那先運(yùn)行商家的C++吧,組裝好車后編譯半天,車不動啊,咨詢淘寶店家,不搭理你!現(xiàn)在發(fā)現(xiàn)可能是樹莓派的GND和拓展板的GND沒連接的緣故。
??后來一想,還是回新手村老實(shí)升級吧!
??于是入手了幾本樹莓派開發(fā)的書和Python入門書,學(xué)了一段時(shí)間后發(fā)現(xiàn),霧里探花,總不得勁,不真實(shí)!

??這種實(shí)踐類課程還是得做實(shí)驗(yàn)才最有效,淘寶上選了一套樹莓派傳感器套餐,每種傳感器一個(gè)實(shí)驗(yàn),從原理到接線,再到編程,簡單但清晰明了,一個(gè)個(gè)實(shí)驗(yàn)下來,收獲滿滿。
??學(xué)到現(xiàn)在,估計(jì)10多級了,離開新手村再去當(dāng)初那個(gè)副本瞧瞧,我覺得用Python,用自己的思想,重寫智能小車的所有功能,不是夢想,而是現(xiàn)實(shí)了!有挑戰(zhàn),但很上癮哦(′-ω-`)!

??下面是大部分的零配件,可以自行選購,價(jià)格都不貴哈,總共就幾百塊:



??一個(gè)項(xiàng)目初看時(shí)很大很難,但分解成若干個(gè)小部分后就簡單了。大家可以選購套餐,整體便宜,也可以用到什么買什么,不浪費(fèi)?;A(chǔ)實(shí)驗(yàn)打牢地基后,復(fù)雜應(yīng)用也沒多復(fù)雜了,這里我像搭積木一樣,一個(gè)功能一個(gè)功能的實(shí)現(xiàn)智能小車的構(gòu)建,首先本章實(shí)現(xiàn)對四個(gè)輪子的初步控制。
??如果對電機(jī)驅(qū)動模塊一點(diǎn)都不清楚的,建議先看另外一篇基礎(chǔ)文章,請參考樹莓派基礎(chǔ)實(shí)驗(yàn)34:L298N模塊驅(qū)動直流電機(jī)實(shí)驗(yàn)。
??以后也是,復(fù)雜內(nèi)容的基礎(chǔ)版本會在文集:樹莓派基礎(chǔ)實(shí)驗(yàn)當(dāng)中講解。
二、組件
★Raspberry Pi 3主板*1
★樹莓派電源*1
★40P軟排線*1
★L(fēng)298N擴(kuò)展板模塊*1
★智能小車底板模塊*1
★減速電機(jī)和車輪*4
★面包板*1
★跳線若干
三、實(shí)驗(yàn)原理




(一)車身及小零件
車身及零件可以自己DIY,但我覺得重點(diǎn)在后面編程當(dāng)中,淘寶上買一個(gè)直接用更好,好的車身底盤可以匹配好多種板子,螺絲孔也很多,方便美觀。
(二)L298N驅(qū)動擴(kuò)展板
L298N是ST公司生產(chǎn)的一種高電壓、大電流電機(jī)驅(qū)動芯片。該芯片采用15腳封裝,主要特點(diǎn)是:工作電壓高,最高工作電壓可達(dá)46V;輸出電流大,瞬間峰值電流可達(dá)3A,持續(xù)工作電流為2A;額定功率25W。
內(nèi)含兩個(gè)H橋的高電壓大電流全橋式驅(qū)動器,可以用來驅(qū)動直流電動機(jī)和步進(jìn)電動機(jī)、繼電器線圈等感性負(fù)載;采用標(biāo)準(zhǔn)邏輯電平信號控制;具有兩個(gè)使能控制端,在不受輸入信號影響的情況下允許或禁止器件工作有一個(gè)邏輯電源輸入端,使內(nèi)部邏輯電路部分在低電壓下工作;可以外接檢測電阻,將變化量反饋給控制電路。
使用L298N芯片驅(qū)動電機(jī),該芯片可以驅(qū)動一臺兩相步進(jìn)電機(jī)或四相步進(jìn)電機(jī),也可以驅(qū)動兩臺直流電機(jī),并聯(lián)時(shí)可以驅(qū)動四臺電機(jī)。
L298N特點(diǎn):
? 1、具有信號指示。
? 2、轉(zhuǎn)速可調(diào)
? 3、抗干擾能力強(qiáng)
? 4、具有過電壓和過電流保護(hù)
? 5、可單獨(dú)控制兩臺直流電機(jī)
? 6、可單獨(dú)控制一臺步進(jìn)電機(jī)
? 7、PWM脈寬平滑調(diào)速
? 8、可實(shí)現(xiàn)正反轉(zhuǎn)
直流電機(jī)的控制實(shí)例:
使用直流/步進(jìn)兩用驅(qū)動器可以驅(qū)動兩臺直流電機(jī)。分別為M1和M2。引腳A,B可用于輸入PWM脈寬調(diào)制信號對電機(jī)進(jìn)行調(diào)速控制。(如果無須調(diào)速可將兩引腳接5V,使電機(jī)工作在最高速狀態(tài),既將短接帽短接)
實(shí)現(xiàn)電機(jī)正反轉(zhuǎn)就更容易了,輸入信號端IN1接高電平,輸入端IN2接低電平,電機(jī)M1正轉(zhuǎn)。(如果信號端IN1接低電平, IN2接高電平,電機(jī)M1反轉(zhuǎn)。)控制另一臺電機(jī)是同樣的方式,輸入信號端IN3接高電平,輸入端IN4接低電平,電機(jī)M2正轉(zhuǎn)。(反之則反轉(zhuǎn)),PWM信號端A控制M1調(diào)速,PWM信號端B控制M2調(diào)速。

這里的L298N驅(qū)動擴(kuò)展板實(shí)際上在L298N的基礎(chǔ)上擴(kuò)展了很多其它傳感器,是一個(gè)多功能的智能小車擴(kuò)展板。

本章只實(shí)驗(yàn)?zāi)芊癯晒︱?qū)動四輪旋轉(zhuǎn),其它的接口和功能以后的章節(jié)再使用。
關(guān)于L298N驅(qū)動電機(jī)的更基礎(chǔ)、更詳細(xì)的內(nèi)容,請參考樹莓派基礎(chǔ)實(shí)驗(yàn)34:L298N模塊驅(qū)動直流電機(jī)實(shí)驗(yàn)。
四、實(shí)驗(yàn)步驟
??第1步: 連接電路。
| 樹莓派(name) | 樹莓派(BOARD) | L298N小車擴(kuò)展板 |
|---|---|---|
| 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 | 電池組供電負(fù)極 |
關(guān)于這里樹莓派GND、L298N小車擴(kuò)展板的電池組供電負(fù)極相連,是特殊情況下的情況,經(jīng)測試發(fā)現(xiàn):
如果樹莓派用的是充電頭供電,而L298N擴(kuò)展板用的是電池組供電,這兩個(gè)負(fù)極必須相連,否則馬達(dá)不動。
如果樹莓派用的是L298N擴(kuò)展板接出來的5V供電,即兩者同一個(gè)電源,則這里不用連接。
| L298N小車擴(kuò)展板 | 電池組 | 樹莓派 | 電壓表頭 | 馬達(dá) |
|---|---|---|---|---|
| 電池+(-) | 電池+(-) | |||
| 5V供電 | 電源接口 | |||
| +(-) | +(-) | |||
| T1(L后) | +(-) | |||
| T2(L前) | +(-) | |||
| T3(R前) | +(-) | |||
| T4(R后) | +(-) |
剛開始時(shí)使用了面包板接線,GPIO使用的BCM模式,后來為了方便路面移動測試,讓樹莓派使用了多功能L298N智能小車擴(kuò)展板上的5V供電,并且GPIO改用了BOARD模式。




??第2步: 編寫程序。本次編程創(chuàng)建了一個(gè)樹莓派小車的類,便于后期多模塊編程調(diào)用。關(guān)于L298N模塊更基礎(chǔ)的編程內(nèi)容可以參考樹莓派基礎(chǔ)實(shí)驗(yàn)34:L298N模塊驅(qū)動直流電機(jī)實(shí)驗(yàn)。這里與基礎(chǔ)實(shí)驗(yàn)不同的是要控制4個(gè)電機(jī),而L298N模塊只能驅(qū)動2路直流電機(jī),所以小車?yán)锏淖筮厓蓚€(gè)車輪是并聯(lián)的,由1路同時(shí)控制,右邊亦然。
??所以該車的行進(jìn)控制與履帶車的行進(jìn)控制類似:
前進(jìn)和后退很簡單,左右兩邊的方向都朝前或朝后,速度一致;
原地順時(shí)針旋轉(zhuǎn)時(shí),左邊輪子前進(jìn),右邊輪子后退,速度一致;
原地逆時(shí)針旋轉(zhuǎn)時(shí),左邊輪子后退,右邊輪子前進(jìn),速度一致;
偏左前進(jìn)時(shí),左右兩邊的方向都朝前,左輪速度比右輪速度慢一點(diǎn);
偏右前進(jìn)時(shí),左右兩邊的方向都朝前,左輪速度比右輪速度快一點(diǎn);
偏左后退時(shí),左右兩邊的方向都朝后,左輪速度比右輪速度慢一點(diǎn);
偏右后退時(shí),左右兩邊的方向都朝后,左輪速度比右輪速度快一點(diǎn);
#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
class SMPcar:
'''控制小車四輪動作的類'''
ENA = 11 #使能信號A,左邊兩輪
IN1 = 13 #信號輸入1
IN2 = 15 #信號輸入2
ENB = 12 #使能信號B,右邊兩輪
IN3 = 16 #信號輸入3
IN4 = 18 #信號輸入4
GPIO.setwarnings(False) #關(guān)閉警告
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(脈寬調(diào)制),返回PWM對象'''
EN_pwm = GPIO.PWM(pwm, 500)
EN_pwm.start(0)
return EN_pwm
def changespeed(self,pwm,speed):
'''通過脈寬調(diào)制改變占空比改變馬達(dá)轉(zhuǎn)速'''
pwm.ChangeDutyCycle(speed)
def clockwise(self,in1_pin,in2_pin):
'''馬達(dá)順時(shí)針轉(zhuǎn)的信號
若電機(jī)旋轉(zhuǎn)方向不正確,交換電機(jī)的正負(fù)極'''
GPIO.output(in1_pin, 1)
GPIO.output(in2_pin, 0)
def counter_clockwise(self,in1_pin,in2_pin):
'''馬達(dá)逆時(shí)針轉(zhuǎn)的信號'''
GPIO.output(in1_pin, 0)
GPIO.output(in2_pin, 1)
def stop_car(self,in1_pin,in2_pin):
'''馬達(dá)制動的信號
使能信號為低電平,或者高電平(占空比設(shè)為100,
IN1和IN2都為0或1時(shí))馬達(dá)制動'''
GPIO.output(in1_pin, 0)
GPIO.output(in2_pin, 0)
def destroy(self,A,B):
'''結(jié)束程序時(shí)清空GPIO狀態(tài),
若不清空狀態(tài),再次運(yùn)行時(shí)會有警告'''
A.stop()
B.stop()
GPIO.cleanup() # Release resource
if __name__ == '__main__': # Program start from here
try:
smpcar = SMPcar() #創(chuàng)建樹莓派小車對象
smpcar.setGPIO() #初始化引腳
ENA_pwm=smpcar.pwm(smpcar.ENA) #初始化使能信號PWM,ENA為左邊車輪
ENB_pwm=smpcar.pwm(smpcar.ENB) #初始化使能信號PWM,ENB為右邊車輪
while True:
'''通過輸入的命令改變馬達(dá)轉(zhuǎn)動
這里是考慮到后期,遠(yuǎn)程控制也是發(fā)送控制代碼實(shí)現(xiàn)控制,
這里采用這種方式也很方便'''
cmd = input("Command, E.g. ff30ff30 :")
direction = cmd[0] #只輸入字母b時(shí),小車剎車
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(左邊車輪)順時(shí)針信號
smpcar.clockwise(smpcar.IN1,smpcar.IN2)
if A_direction == "00": #控制A(左邊車輪)逆時(shí)針信號
smpcar.counter_clockwise(smpcar.IN1,smpcar.IN2)
if B_direction == "ff": #控制B(右邊車輪)順時(shí)針信號
smpcar.clockwise(smpcar.IN3,smpcar.IN4)
if B_direction == "00": #控制B(右邊車輪)逆時(shí)針信號
smpcar.counter_clockwise(smpcar.IN3,smpcar.IN4)
if direction == "b": #小車剎車,IN1和IN2都為0,馬達(dá)制動
smpcar.stop_car(smpcar.IN1,smpcar.IN2)
smpcar.stop_car(smpcar.IN3,smpcar.IN4)
continue #跳出本次循環(huán)
# 通過輸入的兩位數(shù)字設(shè)置占空比,改變馬達(dá)轉(zhuǎn)速
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)
下一章會實(shí)現(xiàn)本地的圖形界面控制。
??實(shí)驗(yàn)結(jié)果示例:

這個(gè)項(xiàng)目的代碼90%是我原創(chuàng)瞎寫的,有需要參考的同學(xué)可以下載:
樹莓派智能小車項(xiàng)目python源代碼下載
