前面我們通過(guò)控制LED燈和讀取按鈕狀態(tài),簡(jiǎn)單演示了樹莓派如何通過(guò)GPIO來(lái)與外部世界溝通。今天我們要用樹莓派模擬一個(gè)控制交通的紅綠燈,讓大家進(jìn)一步學(xué)習(xí)如何通過(guò)程序和計(jì)算機(jī)的I/O來(lái)解決實(shí)際問(wèn)題。
今天要做的紅綠燈是簡(jiǎn)潔版,我們今后還會(huì)講它的進(jìn)階版(高級(jí)版)。簡(jiǎn)潔版的紅綠燈有一個(gè)開關(guān)控制按鈕和紅黃綠三色交通控制燈。當(dāng)程序啟動(dòng)時(shí),只有黃燈處于閃爍狀態(tài),提醒來(lái)往車輛注意其他路口的車輛,當(dāng)?shù)谝淮伟聪掳粹o后,則進(jìn)入紅綠燈交替開關(guān)的狀態(tài),和大家日常在路口看到的類似,再次按下按鈕,則重新恢復(fù)到黃燈閃爍狀態(tài)。這是大部分路口自動(dòng)控制紅綠燈的邏輯。(如果大家不明白紅綠燈相關(guān)的交規(guī),可以咨詢父母或者上網(wǎng)搜索,這里不說(shuō)了)。
需要的元器件
本次的紅綠燈需要如下的元器件
- 開關(guān)按鈕一個(gè)
- 跳線若干,元器件連接方式不同,需要的跳線數(shù)不同,約6-10個(gè)。
- 發(fā)光二極管(LED)三個(gè),如果沒有紅黃綠三色,可以用同色LED,用LED位置表示紅黃綠。
- 1K歐姆的電阻三個(gè)
- 面包板(可選)
- 樹莓派GPIO擴(kuò)展組件(可選)
紅綠燈電路
在前面控制發(fā)光二極管時(shí),我們知道發(fā)光二極管需要連接一個(gè)1K歐姆的電阻來(lái)起到限制電流的保護(hù)作用。所以電路如下圖。
從電路可以看到,控制按鈕連接了GPIO17,紅色LED連接了GPIO26,黃色LED連接了GPIO5,綠色LED連接了GPIO27。
最終的元器件連接如下圖:
Python控制程序
在我們實(shí)際進(jìn)行電路或程序設(shè)計(jì)時(shí),一般都會(huì)采取循序漸進(jìn)的方式,先從簡(jiǎn)單的設(shè)計(jì)開始,然后一步一步加入更復(fù)雜的邏輯,直到最終實(shí)現(xiàn)我們需要的效果。這在電路或程序較復(fù)雜時(shí)尤其重要。
首先,我們需要確保電路連接都是正確的,有一個(gè)簡(jiǎn)單的驗(yàn)證方法,在前面的發(fā)光二極管控制一講也提到過(guò),就是在發(fā)光二極管連接到GPIO之前,先直接連接GPIO的第一引腳,也就是3.3V的電源,此時(shí)LED會(huì)亮,則說(shuō)明連接正確無(wú)誤。
其次,我們要確保各器件連接了正確的GPIO引腳,因?yàn)橛行〨PIO引腳緊挨著(如GPIO17,27,22),如果連接錯(cuò)了,也是沒法成功控制電路的。按我的電路,先用下面的程序運(yùn)行一下看,3個(gè)LED都應(yīng)該亮1秒,滅1秒,同時(shí)按鈕按下超過(guò)1秒,可以看到打印輸出Pressed。
from gpiozero import LED
from time import sleep
red = LED(26) #紅燈鏈接了GPIO26
yellow= LED(5) #黃燈鏈接了GPIO5
green = LED(22) #綠燈連接了GPIO22
control = Button(17) #按鈕連接了GPIO17
while True:
red.on()
yellow.on()
green.on()
if control.is_pressed:
print("Pressed") #保持按鈕按下超過(guò)1秒,可以看到打印輸出
sleep(1)
#先讓LED亮1秒
red.off()
yellow.off()
green.off()
sleep(1)
#再讓LED滅1秒
接下來(lái)我們加入更多的邏輯。只讓黃燈閃爍,還是紅綠燈交替控制,需要有一個(gè)變量來(lái)進(jìn)行判斷,因?yàn)榉谴思幢?,所以可以把這個(gè)變量設(shè)置為布爾型(True或False),我們把它命名為kaiguan。代碼先改為如下:
from gpiozero import LED,Button
from time import sleep
kaiguan = False #控制變量默認(rèn)設(shè)置為False,此時(shí)黃燈閃爍
red = LED(26) #紅燈鏈接了GPIO26
yellow= LED(5) #黃燈鏈接了GPIO5
green = LED(22) #綠燈連接了GPIO22
control = Button(17) #按鈕連接了GPIO17
while True:
if kaiguan == False: #當(dāng)kaiguan變量為False時(shí),黃燈閃爍
yellow.on()
sleep(0.5)
yellow.off()
sleep(0.5)
else:
red.on()
yellow.on()
green.on()
if control.is_pressed:
print("Pressed")
sleep(1)
red.off()
yellow.off()
green.off()
sleep(1)
運(yùn)行上面的程序,可以看到黃燈閃爍,按按鈕沒有任何效果,因?yàn)閑lse部分的代碼永遠(yuǎn)執(zhí)行不到。
接著我們加入按鈕是否按下的判斷邏輯,代碼改為:
from gpiozero import LED,Button
from time import sleep
kaiguan = False
red = LED(26) #紅燈鏈接了GPIO26
yellow= LED(5) #黃燈鏈接了GPIO5
green = LED(22) #綠燈連接了GPIO22
control = Button(17) #按鈕連接了GPIO17
while True:
if kaiguan == False: #當(dāng)kaiguan變量為False時(shí),黃燈閃爍
yellow.on()
sleep(0.5)
yellow.off()
sleep(0.5)
else: #當(dāng)kaiguan變量為True時(shí),和原來(lái)邏輯一樣
red.on()
yellow.on()
green.on()
sleep(1)
red.off()
yellow.off()
green.off()
sleep(1)
if control.is_pressed: #判斷按鈕是否被按下
print("Pressed")
kaiguan = bool(1-kaiguan) #取反。
運(yùn)行上面的程序,可以看到,一開始只有黃燈閃爍,當(dāng)我們按下按鈕時(shí)(保持按下狀態(tài)直到看到Pressed被打印出來(lái)),會(huì)變成所有燈亮1秒滅1秒,再次按按鈕,又會(huì)變成黃燈閃爍,如此反復(fù)。
現(xiàn)在看來(lái),我們需要修改else部分的邏輯,使它實(shí)現(xiàn)綠燈亮3秒,然后熄滅,同時(shí)黃燈亮1秒,然后熄滅,同時(shí)紅燈亮,3秒后紅燈熄滅,綠燈亮,如此反復(fù)。大家也可以按自己喜好調(diào)整紅綠燈的時(shí)間。最新的代碼如下:
from gpiozero import LED,Button
from time import sleep
kaiguan = False
red = LED(26) #紅燈鏈接了GPIO26
yellow= LED(5) #黃燈鏈接了GPIO5
green = LED(22) #綠燈連接了GPIO22
control = Button(17) #按鈕連接了GPIO17
while True:
if kaiguan == False: #當(dāng)kaiguan變量為False時(shí),黃燈閃爍
yellow.on()
sleep(0.5)
yellow.off()
sleep(0.5)
else: #當(dāng)kaiguan變量為True時(shí)
green.on()
sleep(3) #綠燈亮3秒
green.off()
yellow.on() #黃燈亮1秒
sleep(1)
yellow.off()
red.on() #紅燈亮3秒
sleep(3)
red.off()
if control.is_pressed: ##判斷按鈕是否被按下
print("Pressed")
kaiguan = bool(1-kaiguan)
上面代碼中 bool(1-kaiguan)可以實(shí)現(xiàn)取反的效果,也就是當(dāng)kaiguan現(xiàn)在是True時(shí),運(yùn)算后會(huì)被改為False,如果kaiguan現(xiàn)在是False,則會(huì)被改為True。
運(yùn)行上面的代碼基本可以實(shí)現(xiàn)我們需要的邏輯,但是存在以下不足:
按鈕不是按下后就會(huì)觸發(fā)改變,而是需要多按一會(huì),尤其是在紅綠燈交替亮滅時(shí),需要多按一會(huì),直到屏幕輸出Pressed后才會(huì)變化為黃燈閃爍。這是因?yàn)樵诩t綠燈交替亮滅時(shí),約7秒的時(shí)間沒有檢測(cè)按鈕是否按下,只有這7秒的程序執(zhí)行完畢后才能進(jìn)入按鈕檢測(cè)部分的代碼,可以在紅燈亮了后再按,會(huì)減少按下的時(shí)間。
大家可以看看我的紅綠燈電路運(yùn)行起來(lái)的樣子。
如何才能讓按鈕更靈敏,同時(shí)加入更高級(jí)的控制邏輯呢?下一次我們將在紅綠燈高階版進(jìn)行介紹。
-
元器件
+關(guān)注
關(guān)注
112文章
4716瀏覽量
92329 -
led燈
+關(guān)注
關(guān)注
22文章
1592瀏覽量
108006 -
GPIO
+關(guān)注
關(guān)注
16文章
1204瀏覽量
52104 -
樹莓派
+關(guān)注
關(guān)注
116文章
1707瀏覽量
105648
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論