前面我們通過控制LED燈和讀取按鈕狀態,簡單演示了樹莓派如何通過GPIO來與外部世界溝通。今天我們要用樹莓派模擬一個控制交通的紅綠燈,讓大家進一步學習如何通過程序和計算機的I/O來解決實際問題。
今天要做的紅綠燈是簡潔版,我們今后還會講它的進階版(高級版)。簡潔版的紅綠燈有一個開關控制按鈕和紅黃綠三色交通控制燈。當程序啟動時,只有黃燈處于閃爍狀態,提醒來往車輛注意其他路口的車輛,當第一次按下按鈕后,則進入紅綠燈交替開關的狀態,和大家日常在路口看到的類似,再次按下按鈕,則重新恢復到黃燈閃爍狀態。這是大部分路口自動控制紅綠燈的邏輯。(如果大家不明白紅綠燈相關的交規,可以咨詢父母或者上網搜索,這里不說了)。
需要的元器件
本次的紅綠燈需要如下的元器件
- 開關按鈕一個
- 跳線若干,元器件連接方式不同,需要的跳線數不同,約6-10個。
- 發光二極管(LED)三個,如果沒有紅黃綠三色,可以用同色LED,用LED位置表示紅黃綠。
- 1K歐姆的電阻三個
- 面包板(可選)
- 樹莓派GPIO擴展組件(可選)
紅綠燈電路
在前面控制發光二極管時,我們知道發光二極管需要連接一個1K歐姆的電阻來起到限制電流的保護作用。所以電路如下圖。

從電路可以看到,控制按鈕連接了GPIO17,紅色LED連接了GPIO26,黃色LED連接了GPIO5,綠色LED連接了GPIO27。
最終的元器件連接如下圖:

Python控制程序
在我們實際進行電路或程序設計時,一般都會采取循序漸進的方式,先從簡單的設計開始,然后一步一步加入更復雜的邏輯,直到最終實現我們需要的效果。這在電路或程序較復雜時尤其重要。
首先,我們需要確保電路連接都是正確的,有一個簡單的驗證方法,在前面的發光二極管控制一講也提到過,就是在發光二極管連接到GPIO之前,先直接連接GPIO的第一引腳,也就是3.3V的電源,此時LED會亮,則說明連接正確無誤。
其次,我們要確保各器件連接了正確的GPIO引腳,因為有些GPIO引腳緊挨著(如GPIO17,27,22),如果連接錯了,也是沒法成功控制電路的。按我的電路,先用下面的程序運行一下看,3個LED都應該亮1秒,滅1秒,同時按鈕按下超過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") #保持按鈕按下超過1秒,可以看到打印輸出
sleep(1)
#先讓LED亮1秒
red.off()
yellow.off()
green.off()
sleep(1)
#再讓LED滅1秒
接下來我們加入更多的邏輯。只讓黃燈閃爍,還是紅綠燈交替控制,需要有一個變量來進行判斷,因為非此即彼,所以可以把這個變量設置為布爾型(True或False),我們把它命名為kaiguan。代碼先改為如下:
from gpiozero import LED,Button
from time import sleep
kaiguan = False #控制變量默認設置為False,此時黃燈閃爍
red = LED(26) #紅燈鏈接了GPIO26
yellow= LED(5) #黃燈鏈接了GPIO5
green = LED(22) #綠燈連接了GPIO22
control = Button(17) #按鈕連接了GPIO17
while True:
if kaiguan == False: #當kaiguan變量為False時,黃燈閃爍
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)
運行上面的程序,可以看到黃燈閃爍,按按鈕沒有任何效果,因為else部分的代碼永遠執行不到。
接著我們加入按鈕是否按下的判斷邏輯,代碼改為:
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: #當kaiguan變量為False時,黃燈閃爍
yellow.on()
sleep(0.5)
yellow.off()
sleep(0.5)
else: #當kaiguan變量為True時,和原來邏輯一樣
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) #取反。
運行上面的程序,可以看到,一開始只有黃燈閃爍,當我們按下按鈕時(保持按下狀態直到看到Pressed被打印出來),會變成所有燈亮1秒滅1秒,再次按按鈕,又會變成黃燈閃爍,如此反復。
現在看來,我們需要修改else部分的邏輯,使它實現綠燈亮3秒,然后熄滅,同時黃燈亮1秒,然后熄滅,同時紅燈亮,3秒后紅燈熄滅,綠燈亮,如此反復。大家也可以按自己喜好調整紅綠燈的時間。最新的代碼如下:
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: #當kaiguan變量為False時,黃燈閃爍
yellow.on()
sleep(0.5)
yellow.off()
sleep(0.5)
else: #當kaiguan變量為True時
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)可以實現取反的效果,也就是當kaiguan現在是True時,運算后會被改為False,如果kaiguan現在是False,則會被改為True。
運行上面的代碼基本可以實現我們需要的邏輯,但是存在以下不足:
按鈕不是按下后就會觸發改變,而是需要多按一會,尤其是在紅綠燈交替亮滅時,需要多按一會,直到屏幕輸出Pressed后才會變化為黃燈閃爍。這是因為在紅綠燈交替亮滅時,約7秒的時間沒有檢測按鈕是否按下,只有這7秒的程序執行完畢后才能進入按鈕檢測部分的代碼,可以在紅燈亮了后再按,會減少按下的時間。
大家可以看看我的紅綠燈電路運行起來的樣子。
如何才能讓按鈕更靈敏,同時加入更高級的控制邏輯呢?下一次我們將在紅綠燈高階版進行介紹。
-
元器件
+關注
關注
113文章
5005瀏覽量
99705 -
led燈
+關注
關注
22文章
1606瀏覽量
111889 -
GPIO
+關注
關注
16文章
1329瀏覽量
56232 -
樹莓派
+關注
關注
122文章
2079瀏覽量
110474
發布評論請先 登錄
紅綠燈控制系統的LED城市路燈方案
交通紅綠燈
交通紅綠燈PLC控制系統編程方法與技巧
基于可編程控制的交通紅綠燈模擬系統設計
基于自定義時鐘脈沖的交通紅綠燈控制設計
將VR技術應用于交通紅綠燈中
基于8255A和8253芯片實現交通紅綠燈模擬系統的應用方案
用樹莓派控制交通紅綠燈(進階版)
用樹莓派控制交通紅綠燈(簡潔版)
評論