0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

用樹莓派控制交通紅綠燈(進(jìn)階版)

CHANBAEK ? 來源:和娃一起玩樹莓派 ? 作者:老孟K ? 2023-07-02 15:10 ? 次閱讀

哇奧,今天才發(fā)現(xiàn)上一次建造的紅綠燈居然不對,綠燈一般在下方,當(dāng)紅燈變綠燈時(shí)黃燈閃爍,我做的是綠燈變紅燈時(shí)黃燈閃爍!。這在我們開發(fā)時(shí)也會(huì)碰到,就像找bug一樣,對于發(fā)現(xiàn)的問題要及時(shí)修正。在修正問題之前,我們還是先看看如何讓紅綠燈更快的響應(yīng)按鈕操作,然后修正紅綠燈問題。

要想更快的響應(yīng)按鈕,則需要找出原因,上一講提到因?yàn)槌绦蜻\(yùn)行時(shí)沒有及時(shí)檢測按鈕是不是被按下了,那么我們第一反應(yīng)可能是在程序中加上更多的檢測語句,但這樣程序?qū)⒆兊锰貏e臃腫,也不容易被別人理解。其實(shí),計(jì)算機(jī)設(shè)計(jì)者早就考慮到了這個(gè)問題,他們利用一個(gè)叫做“中斷”的概念來對需要及時(shí)響應(yīng)的事情進(jìn)行處理。

什么是中斷

中斷是指計(jì)算機(jī)運(yùn)行過程中,出現(xiàn)某些需要及時(shí)處理時(shí),計(jì)算機(jī)能自動(dòng)暫停正在運(yùn)行的程序并轉(zhuǎn)入處理新情況的程序,處理完畢后又返回原被暫停的程序繼續(xù)運(yùn)行。中斷發(fā)生時(shí)運(yùn)行的程序叫做中斷程序。

在我們的紅綠燈程序中,當(dāng)按鈕被按下時(shí),我們希望計(jì)算機(jī)可以把它作為一個(gè)中斷,然后運(yùn)行中斷程序,及時(shí)修改運(yùn)行狀態(tài)。

研究gpiozero的文檔,我們發(fā)現(xiàn)Button類有一個(gè)when_pressed的方法,說明如下

圖片

意思是說當(dāng)按鈕按下時(shí)將調(diào)用一個(gè)函數(shù)(function)。那么什么是函數(shù)呢?

函數(shù)是什么

函數(shù)是可以完成某些任務(wù)的代碼塊,而且這些代碼塊可以被重復(fù)使用,就像我們玩具里的積木塊一樣。在python中,用def來定義或者說創(chuàng)建函數(shù),其語法如下

def 函數(shù)名(參數(shù)):     #注意最后的冒號
   函數(shù)代碼(完成工作需要的代碼)
   return 返回值      #不是必須的,當(dāng)需要向調(diào)用函數(shù)的程序返回?cái)?shù)值或?qū)ο髸r(shí)使用

函數(shù)是編程語言非常重要的一部分內(nèi)容,參數(shù)有形參和實(shí)參,參數(shù)也可以是多個(gè),返回值可以是各種數(shù)據(jù)類型,有了函數(shù)后,變量也就分為全局 變量和局部變量了,這些內(nèi)容我們會(huì)逐步涉及到。今天我們先從最簡單的無參數(shù)函數(shù)開始,顧名思義,這樣的函數(shù)沒有參數(shù)。

創(chuàng)建參數(shù)

回過頭來看我們的紅綠燈程序,只閃爍黃燈還是正常工作取決于其中的一個(gè)變量kaiguan。

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)    #綠燈亮3green.off()
        yellow.on()  #黃燈亮1sleep(1)
        yellow.off()
        red.on()     #紅燈亮3sleep(3)
        red.off()
    if control.is_pressed:  ##判斷按鈕是否被按下
            print("Pressed")
            kaiguan = bool(1-kaiguan)

所以,利用中斷,我們的需要在按鈕按下時(shí)及時(shí)改變kaiguan這個(gè)變量的數(shù)值,然后在程序中及時(shí)判斷這個(gè)值是否已經(jīng)變化了,從而作出正確的邏輯控制。

現(xiàn)在我們創(chuàng)建一個(gè)叫做changeKaiguan的函數(shù):

def changeKaiguan():   #創(chuàng)建無參數(shù)函數(shù):修改kaiguan變量,從而控制紅綠燈
    print("Pressed")
    global kaiguan       #kaiguan是全局變量,在主程序中已經(jīng)聲明
    kaiguan = bool(1 - kaiguan)    #取反操作
    print(kaiguan)                #打印kaiguan的數(shù)值,True或False

因?yàn)閗aiguan變量是在主函數(shù)聲明的,函數(shù)如果要使用它,需要用global關(guān)鍵字,表示它是一個(gè)全局變量 。

當(dāng)控制按鈕按下時(shí),調(diào)用changeKaiguan函數(shù),通過如下代碼實(shí)現(xiàn):

control.when_pressed = changeKaiguan  #按下按鈕時(shí)調(diào)用changeKaiguan函數(shù)

注意: 這一個(gè)語句應(yīng)該在changeKaiguan函數(shù)創(chuàng)建之后才行,否則就會(huì)報(bào)變量沒有定義的錯(cuò)誤。

驗(yàn)證中斷程序

通過上面的代碼,我們創(chuàng)建了一個(gè)中斷函數(shù),當(dāng)按鈕按下時(shí),每次都調(diào)用changeKaiguan函數(shù)。讓我們來測試一下,完整代碼如下:

from gpiozero import LED,Button


from time import sleep


kaiguan = False   


green = LED(26)  #green燈鏈接了GPIO26
yellow= LED(5)   #黃燈鏈接了GPIO5
red = LED(22)  #red燈連接了GPIO22
control = Button(17) #按鈕連接了GPIO17




def changeKaiguan():   #創(chuàng)建無參數(shù)函數(shù):修改kaiguan變量,從而控制紅綠燈
    print("Pressed")
    global kaiguan       #kaiguan是全局變量,在主程序中已經(jīng)聲明
    kaiguan = bool(1 - kaiguan)    #取反操作
    print(kaiguan)                #打印kaiguan的數(shù)值,True或False


control.when_pressed = changeKaiguan  #按鈕按下時(shí)調(diào)用changeKaiguan函數(shù)


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í),
        red.on()   
        sleep(3)    #綠燈亮3秒
        red.off()
        yellow.on()  #黃燈亮1秒
        sleep(1)
        yellow.off()
        green.on()     #紅燈亮3秒 
        sleep(3)
        green.off()

運(yùn)行上面的程序,可以發(fā)現(xiàn),無論程序運(yùn)行在那個(gè)階段,當(dāng)按下按鈕時(shí),都可以馬上在Shell界面看到打印“Pressed"以及最新的kaiguan參數(shù)數(shù)值。

圖片

我們發(fā)現(xiàn)每次按鈕按下,都馬上進(jìn)入了中斷程序changeKaiguan,在程序中修改了kaiguan變量的值并打印了出來,當(dāng)前程序運(yùn)行在sleep還是其他語句都沒有影響。

進(jìn)階版紅綠燈程序

現(xiàn)在,是時(shí)候完成我們的進(jìn)階版程序,讓紅綠燈可以在按鈕按下后及時(shí)切換工作狀態(tài)。在此之前,我們需要調(diào)整紅綠燈連接線,把紅燈和綠燈互換位置,同時(shí)修改程序。最新的電路圖:

圖片

電路實(shí)物照片:

圖片

要修改程序,需要考慮在什么時(shí)候探測kaiguan變量值,然后作出邏輯調(diào)整,原程序紅綠燈正常工作時(shí)不能及時(shí)探測kaiguan變量才造成對按鈕的反應(yīng)遲鈍,所以需要修改這部分代碼,為了保證控制操作的完整性,我們不能在某個(gè)燈還亮著時(shí)進(jìn)行切換,需要在燈滅后進(jìn)行,所以修改如下:

from gpiozero import LED,Button


from time import sleep


kaiguan = False   


green = LED(26)  #green燈鏈接了GPIO26
yellow= LED(5)   #黃燈鏈接了GPIO5
red = LED(22)  #red燈連接了GPIO22
control = Button(17) #按鈕連接了GPIO17




def changeKaiguan():
    print("Pressed")

    global kaiguan
    kaiguan = bool(1 - kaiguan)
    print(kaiguan)



control.when_pressed = changeKaiguan


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í),
        red.on()   
        sleep(3)    #綠燈亮3秒
        red.off()
        if kaiguan == False: #判斷kaiguan是否已經(jīng)變?yōu)镕alse,如果是,則跳出當(dāng)前操作,繼續(xù)下一個(gè)循環(huán)
            continue     #跳過下面的代碼,開始下一個(gè)循環(huán)
        yellow.on()  #黃燈亮1秒
        sleep(1)
        yellow.off()
        if kaiguan == False: #判斷kaiguan是否已經(jīng)變?yōu)镕alse,如果是,則跳出當(dāng)前操作,繼續(xù)下一個(gè)循環(huán)
            continue
        green.on()     #紅燈亮3秒 
        sleep(3)
        green.off()

運(yùn)行程序,看看是不是按我們期望的正常運(yùn)作了呢?

是的,現(xiàn)在只要我們按下按鈕,程序都可以及時(shí)切換,即使在紅燈或綠燈亮?xí)r按下按鈕,當(dāng)燈滅時(shí)也會(huì)判斷出kaiguan值變?yōu)镕alse,從而中止當(dāng)前循環(huán),進(jìn)入下一個(gè)循環(huán)中。如此,進(jìn)階版的紅綠燈大功告成!

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 計(jì)算機(jī)
    +關(guān)注

    關(guān)注

    19

    文章

    7295

    瀏覽量

    87532
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    894

    瀏覽量

    41322
  • python
    +關(guān)注

    關(guān)注

    54

    文章

    4759

    瀏覽量

    84294
  • 紅綠燈
    +關(guān)注

    關(guān)注

    2

    文章

    34

    瀏覽量

    11933
  • 樹莓派
    +關(guān)注

    關(guān)注

    116

    文章

    1684

    瀏覽量

    105397
收藏 人收藏

    評論

    相關(guān)推薦

    紅綠燈控制系統(tǒng)的LED城市路燈方案

    將LED路燈裝置與交通紅綠燈控制系統(tǒng)結(jié)合在一起,利用每一路段紅綠燈的轉(zhuǎn)換實(shí)現(xiàn)對下一路段燈光強(qiáng)弱的控制。將當(dāng)前市場上 LED 集燈板上的LED燈分為兩組,在滿足不同時(shí)段照明要求前
    發(fā)表于 10-17 14:44 ?3804次閱讀

    PLC實(shí)現(xiàn)交通紅綠燈控制方法及原理

    PLC實(shí)現(xiàn)交通紅綠燈控制電路熟悉PLC編程原理及方法。掌握定時(shí)器使用方法。
    發(fā)表于 03-19 15:15

    交通紅綠燈帶仿真和程序

    交通紅綠燈帶仿真和程序
    發(fā)表于 03-29 10:53

    交通紅綠燈

    本帖最后由 samuergao 于 2014-7-3 14:13 編輯 交通燈,并顯示當(dāng)前時(shí)間和倒計(jì)時(shí),包含了單條路遇到人行道的紅綠燈,還有十字路口的紅綠燈,大家?guī)涂纯从械母倪M(jìn)沒有。
    發(fā)表于 07-03 12:12

    如何去實(shí)現(xiàn)一種交通紅綠燈設(shè)計(jì)

    1、功能描述觀察十字路口紅綠燈工作流程,設(shè)計(jì)交通燈。1、初始時(shí):南北向、東西向直行左轉(zhuǎn)均為紅燈2、南北向直行:①南北向直行綠燈亮,延時(shí)若干秒②啟動(dòng)南北向左轉(zhuǎn)數(shù)碼管顯示:倒計(jì)時(shí)6秒;同時(shí)南北向直行
    發(fā)表于 11-09 09:21

    基于單片機(jī)的交通紅綠燈控制系統(tǒng)的設(shè)計(jì)

    前一段時(shí)間,做了一個(gè)關(guān)于基于單片機(jī)的交通紅綠燈控制系統(tǒng)的設(shè)計(jì)
    發(fā)表于 11-10 06:34

    交通紅綠燈PLC控制系統(tǒng)編程方法與技巧

    本文介紹了交通紅綠燈基本控制形式,針對帶綠閃的紅綠燈和帶數(shù)顯的紅綠控制和實(shí)現(xiàn)方法,詳細(xì)論述了相應(yīng)的編程方法和技巧。實(shí)驗(yàn)證明編制的程序運(yùn)行可靠
    發(fā)表于 08-14 10:31 ?152次下載

    基于可編程控制交通紅綠燈模擬系統(tǒng)設(shè)計(jì)

    本文在綜合分析了8255A 及8253 芯片的特點(diǎn)之后,運(yùn)用二者的特性,進(jìn)行了交通紅綠燈模擬系統(tǒng)設(shè)計(jì),在詳細(xì)闡述了設(shè)計(jì)思想及電路設(shè)計(jì)方案之后,對該系統(tǒng)的有效性測試表明了該交通紅
    發(fā)表于 05-18 11:03 ?199次下載
    基于可編程<b class='flag-5'>控制</b>的<b class='flag-5'>交通紅綠燈</b>模擬系統(tǒng)設(shè)計(jì)

    基于自定義時(shí)鐘脈沖的交通紅綠燈控制設(shè)計(jì)

    以三菱FX2N型PLC作為控制核心元件,闡明交通紅綠燈控制設(shè)計(jì)思路和控制方案。以PLC定時(shí)器構(gòu)成的自定義時(shí)鐘脈沖程序段作為程序基本單元設(shè)計(jì)的交通紅
    發(fā)表于 06-19 11:42 ?6335次閱讀
    基于自定義時(shí)鐘脈沖的<b class='flag-5'>交通紅綠燈</b><b class='flag-5'>控制</b>設(shè)計(jì)

    EDA設(shè)計(jì)應(yīng)用之紅綠燈交通控制器設(shè)計(jì)

    紅綠燈交通控制器EDA設(shè)計(jì)
    發(fā)表于 01-22 16:28 ?51次下載

    將VR技術(shù)應(yīng)用于交通紅綠燈

    大家都知道,不管是行人還是汽車,在過路口的時(shí)候,一般都會(huì)有紅綠燈的存在,如果沒有紅綠燈的話,那整個(gè)交通都會(huì)混亂,交通事故絕對是層出不窮,而且堵車也會(huì)堵得水泄不通,所以
    發(fā)表于 12-22 09:38 ?3854次閱讀

    使用樹莓控制紅綠燈的源代碼免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用樹莓控制紅綠燈的源代碼免費(fèi)下載。
    發(fā)表于 10-28 17:11 ?10次下載
    使用<b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>控制</b><b class='flag-5'>紅綠燈</b>的源代碼免費(fèi)下載

    基于8255A和8253芯片實(shí)現(xiàn)交通紅綠燈模擬系統(tǒng)的應(yīng)用方案

    本文在綜合分析了8255A 及8253 芯片的特點(diǎn)之后,運(yùn)用二者的特性,進(jìn)行了交通紅綠燈模擬系統(tǒng)設(shè)計(jì),在詳細(xì)闡述了設(shè)計(jì)思想及電路設(shè)計(jì)方案之后,對該系統(tǒng)的有效性測試表明了該交通紅綠燈模擬系統(tǒng)具有較為
    的頭像 發(fā)表于 03-23 14:47 ?5170次閱讀

    中文編程鴻蒙Hi3861開發(fā)基礎(chǔ)案例之-03交通紅綠燈

    中文編程鴻蒙Hi3861開發(fā)模擬交通紅綠燈亮與滅控制
    的頭像 發(fā)表于 05-11 11:27 ?1919次閱讀
    中文編程鴻蒙Hi3861開發(fā)基礎(chǔ)案例之-03<b class='flag-5'>交通紅綠燈</b>

    樹莓控制交通紅綠燈(簡潔版)

    前面我們通過控制LED燈和讀取按鈕狀態(tài),簡單演示了樹莓如何通過GPIO來與外部世界溝通。今天我們要用樹莓模擬一個(gè)
    的頭像 發(fā)表于 07-02 15:08 ?2051次閱讀
    <b class='flag-5'>用</b><b class='flag-5'>樹莓</b><b class='flag-5'>派</b><b class='flag-5'>控制</b><b class='flag-5'>交通紅綠燈</b>(簡潔版)