透過 Python 的 gpiozero 函式庫,可以輕鬆控制樹莓派的 GPIO 與按鈕和開關互動。文章涵蓋了基本按鈕連線偵測、使用中斷避免程式阻塞、透過按鈕切換 LED 狀態,以及更進階的三位式切換開關應用。程式碼範例簡潔易懂,搭配流程圖說明,更能理解程式邏輯與硬體互動方式。此外,也提到了按鈕去抖動的議題,確保程式穩定執行。
連線按鈕開關
問題 您想要連線一個按鈕開關到您的樹莓派(Raspberry Pi),使得當您按下按鈕時,某些Python程式碼會被執行。
解決方案
連線一個按鈕開關到一個GPIO腳位,並使用gpiozero
函式庫在您的Python程式中偵測按鈕按下。
要完成這個食譜,您需要以下元件:
-麵包板和跳線(參考「原型設計裝置和套件」)
- 觸控按鈕開關(參考「雜項」)
圖12-1顯示如何使用麵包板和跳線連線一個觸控按鈕開關。
圖12-1. 連線按鈕開關到樹莓派
使用麵包板和觸控按鈕開關的替代方案是使用鱷魚按鈕(圖12-2)。這是一個具有女性頭部引腳的按鈕開關,您可以直接將其連線到GPIO聯結器(食譜9.11)。
圖12-2. 鱷魚按鈕
開啟一個編輯器並貼入以下程式碼(ch_12_switch.py):
from gpiozero import Button
button = Button(18)
while True:
if button.is_pressed:
print("按鈕被按下")
與本文中的所有程式範例一樣,您也可以下載這個程式碼(參考食譜3.22)。
當您執行程式並按下按鈕時,您將看到以下內容:
pi@raspberrypi ~ $ python3 ch_12_switch.py
按鈕被按下
按鈕被按下
按鈕被按下
按鈕被按下
事實上,「按鈕被按下」的訊息可能會迅速地從螢幕底部滾動而過。這是因為程式正在非常頻繁地檢查按鈕是否被按下。另一個問題是,這個程式在等待按鈕按下的時候,不能做其他事情。
我們可以改進這個程式,既可以在按鈕被按下時只做一次事情,也可以在等待按鈕按下的時候做其他事情。您可以在以下程式碼(ch_12_switch_2.py)中找到這些改進:
from gpiozero import Button
from time import sleep
內容解密:
- 我們首先匯入必要的函式庫,包括
gpiozero
用於與GPIO進行互動,以及time
用於暫停執行。 - 我們建立一個
Button
物件,指定GPIO腳位為18。 - 我們進入一個無限迴圈,持續檢查按鈕是否被按下。
- 當按鈕被按下時,我們印出「按鈕被按下」的訊息。
圖表翻譯:
flowchart TD A[開始] --> B[初始化GPIO] B --> C[建立Button物件] C --> D[進入迴圈] D --> E[檢查按鈕狀態] E -->|按鈕被按下| F[印出訊息] E -->|按鈕未被按下| D
此圖表展示了程式的流程,從初始化GPIO開始,建立Button
物件,進入迴圈檢查按鈕狀態,當按鈕被按下時印出訊息。
使用中斷來偵測按鈕按下
在許多應用中,程式需要在按鈕被按下時觸發特定動作,但同時也需要執行其他任務。為了實作這種功能,我們可以使用中斷(interrupts)的概念。
中斷機制
中斷是一種機制,允許程式在執行其他任務的同時,偵測到特定事件(如按鈕按下)並立即執行相關的處理函式。這種方式可以確保程式對事件的反應迅速,同時不會阻塞其他任務的執行。
實作中斷
以下是一個使用Python實作中斷的範例:
import time
from gpiozero import Button
def handle_button_press():
print("按鈕被按下")
button = Button(18)
button.when_pressed = handle_button_press
while True:
print("程式正在執行其他任務")
time.sleep(2)
在這個範例中,我們定義了一個函式handle_button_press()
,它將在按鈕被按下時被呼叫。然後,我們建立了一個Button
物件,並將其when_pressed
屬性設定為handle_button_press
函式。這樣,當按鈕被按下時,handle_button_press()
函式將被自動呼叫。
注意事項
注意,在設定when_pressed
屬性時,我們沒有在函式名稱後面加上括號()
。這是因為我們要參照函式本身,而不是立即呼叫它。只有當按鈕被按下時,函式才會被呼叫。
執行結果
當你執行這個程式時,你會看到如下輸出:
程式正在執行其他任務
程式正在執行其他任務
按鈕被按下
程式正在執行其他任務
程式正在執行其他任務
當你按下按鈕時,handle_button_press()
函式將被呼叫,並列印預出"按鈕被按下"的訊息。同時,程式將繼續執行其他任務。
內容解密:
- 我們使用
gpiozero
函式庫來控制GPIO口。 Button
類別用於建立按鈕物件。when_pressed
屬性用於設定按鈕按下時的處理函式。handle_button_press()
函式是按鈕按下時被呼叫的函式。time.sleep(2)
用於模擬程式執行其他任務的過程。
圖表翻譯:
flowchart TD A[程式啟動] --> B[設定按鈕中斷] B --> C[執行其他任務] C --> D[按鈕被按下] D --> E[呼叫處理函式] E --> C
這個流程圖展示了程式的執行流程:設定按鈕中斷、執行其他任務、按鈕被按下、呼叫處理函式。
使用按鈕切換LED狀態
在本文中,我們將探討如何使用按鈕切換LED的狀態。這是一個基本的電子工程專案,需要使用Raspberry Pi、麵包板、跳線、按鈕和LED。
按鈕連線
按鈕通常有四個接點,但實際上只有兩個電氣連線,因為內部的接點是相互連線的。圖12-3顯示了按鈕的接點安排。
按鈕去抖動
按鈕去抖動是一種技術,用於消除按鈕按下時產生的電氣噪音。這是因為按鈕按下時,接點可能會多次開關,產生多個電氣脈衝。為瞭解決這個問題,我們可以使用去抖動電路或軟體去抖動演算法。
切換LED狀態
要切換LED狀態,我們需要讀取按鈕的最後狀態(即按鈕是否按下),然後在每次按鈕按下時反轉該狀態。以下是實作此功能的Python程式碼:
from gpiozero import Button, LED
from time import sleep
led = LED(23)
def toggle_led():
print("切換LED狀態")
led.toggle()
button = Button(18)
button.when_pressed = toggle_led
在這段程式碼中,我們建立了一個Button
物件,連線到Raspberry Pi的18號引腳,並定義了一個toggle_led
函式,用於切換LED狀態。當按鈕按下時,toggle_led
函式被呼叫,反轉LED的狀態。
連線麵包板和LED
圖12-4顯示瞭如何連線麵包板、按鈕和LED到Raspberry Pi。除了使用公母跳線連線Raspberry Pi到麵包板外,我們還需要一根公公跳線或固體線。
程式碼解釋
在程式碼中,我們使用gpiozero
函式庫建立Button
和LED
物件。Button
物件連線到Raspberry Pi的18號引腳,LED
物件連線到Raspberry Pi的23號引腳。當按鈕按下時,toggle_led
函式被呼叫,反轉LED的狀態。
使用 Raspberry Pi 與按鈕和開關進行互動
按鈕控制 LED 的範例程式
在這個範例中,我們將使用 Raspberry Pi 的 GPIO 引腳來控制一個 LED,當按鈕被按下時,LED 會切換其狀態。
import gpiozero
from time import sleep
# 初始化按鈕和 LED
button = gpiozero.Button(17)
led = gpiozero.LED(23)
# 定義一個函式來切換 LED 的狀態
def toggle_led():
led.toggle()
# 設定按鈕的中斷事件
button.when_pressed = toggle_led
while True:
print("忙於做其他事情")
sleep(2)
這個程式使用 gpiozero
函式庫來控制 GPIO 引腳,當按鈕被按下時,會呼叫 toggle_led
函式來切換 LED 的狀態。
使用兩位元切換開關
如果您想要使用兩位元切換開關,您可以按照以下步驟進行:
- 連線開關的中間接點和其中一端到 Raspberry Pi 的 GPIO 引腳。
- 使用以下程式碼來讀取開關的狀態:
import gpiozero
# 初始化開關
switch = gpiozero.Button(17)
# 讀取開關的狀態
if switch.is_pressed:
print("開關已經被按下")
else:
print("開關尚未被按下")
這個程式使用 gpiozero
函式庫來控制 GPIO 引腳,當開關被按下時,會印出「開關已經被按下」的訊息。
解決按鈕彈跳問題
當使用按鈕或開關時,您可能會遇到按鈕彈跳(switch bounce)的問題,這是因為按鈕或開關在被按下時會產生多次的觸發事件。為瞭解決這個問題,您可以使用以下程式碼:
import gpiozero
from time import sleep
# 初始化按鈕
button = gpiozero.Button(17)
# 設定按鈕的中斷事件
def button_pressed():
# 在按鈕被按下後等待一段時間,以避免彈跳問題
sleep(0.1)
# 執行您想要的動作
button.when_pressed = button_pressed
這個程式使用 gpiozero
函式庫來控制 GPIO 引腳,當按鈕被按下時,會呼叫 button_pressed
函式來執行您想要的動作,並在按鈕被按下後等待一段時間,以避免彈跳問題。
圖表翻譯:
flowchart TD A[開始] --> B[初始化按鈕和 LED] B --> C[設定按鈕的中斷事件] C --> D[讀取按鈕的狀態] D --> E[執行動作] E --> F[結束]
這個圖表展示了使用 Raspberry Pi 與按鈕和開關進行互動的流程。
連線三位式切換開關至樹莓派並偵測其位置
問題描述
您想要將一個三位式(中間為關閉位置)的切換開關連線到您的樹莓派,並在Python程式中偵測開關的位置。
解決方案
將開關連線到兩個GPIO腳位,如圖12-6所示,並使用gpiozero函式庫在Python程式中偵測開關的位置。要完成這個食譜,您需要以下元件:
*麵包板和跳線(參考「原型裝置和套件」) *迷你中間關閉三位式切換開關(參考「雜項」)
圖12-6:將三位式切換開關連線到樹莓派
開關的公共(中間)連線點連線到地線,每個開關端連線到一個GPIO腳位,並啟用內部拉高電阻。
程式碼實作
開啟編輯器並貼入以下程式碼(ch_12_switch_3_pos.py):
from gpiozero import Button
switch_top = Button(18)
switch_bottom = Button(23)
switch_position = "unknown"
while True:
new_switch_position = "unknown"
if switch_top.is_pressed:
new_switch_position = "top"
elif switch_bottom.is_pressed:
new_switch_position = "bottom"
else:
new_switch_position = "center"
if new_switch_position!= switch_position:
# 處理開關位置變化
switch_position = new_switch_position
print(f"Switch position: {switch_position}")
原理解釋
- 我們使用gpiozero函式庫建立兩個
Button
物件,分別代表開關的上下兩個端。 - 在無限迴圈中,我們不斷檢查每個開關端的狀態。
- 如果上端被按下,則開關位於「top」位置;如果下端被按下,則開關位於「bottom」位置;否則,開關位於「center」位置。
- 如果開關的位置發生變化,我們更新
switch_position
變數並印出新的位置。
圖表解釋
flowchart TD A[開始] --> B[初始化GPIO] B --> C[讀取開關狀態] C --> D{上端按下?} D -->|是| E[設定開關位置為「top」] D -->|否| F{下端按下?} F -->|是| G[設定開關位置為「bottom」] F -->|否| H[設定開關位置為「center」] E --> I[檢查位置變化] G --> I H --> I I -->|有變化| J[更新開關位置並印出] I -->|無變化| A
圖表翻譯:
此流程圖展示了程式的邏輯流程。首先,初始化GPIO腳位,然後不斷讀取開關的狀態。如果上端被按下,則設定開關位置為「top」;如果下端被按下,則設定開關位置為「bottom」;否則,設定開關位置為「center」。最後,檢查開關位置是否發生變化,如果有變化,則更新開關位置並印出新的位置。
從使用者經驗視角來看,連線按鈕和開關到樹莓派實作互動控制,能顯著提升使用者與嵌入式系統的互動體驗。本文深入探討瞭如何使用 gpiozero
函式庫簡化按鈕、兩位元切換開關和三位式切換開關的連線與控制,並解析了程式碼邏輯和電路連線。
分析段落: 我們分析了三種不同的開關型別:簡單按鈕、兩位元切換開關和三位式切換開關。針對簡單按鈕,我們利用中斷機制實作了非阻塞式的事件處理,提升了程式效率。對於兩位元切換開關,程式碼清晰地展示瞭如何讀取開關狀態。而對於三位式切換開關,我們巧妙地利用兩個 GPIO 腳位和拉高電阻,準確地判斷開關的三種不同位置。同時,程式碼中加入了去抖動的處理,避免了按鈕彈跳造成的誤觸發,提升了系統的穩定性。
前瞻段落: 隨著物聯網技術的發展,人機互動的重要性日益凸顯。未來,更複雜的互動控制需求將推動更精細的開關控制技術發展,例如結合電容式觸控感測、手勢識別等技術,實作更自然、更直觀的使用者經驗。同時,軟體層面也將持續最佳化,例如發展更低延遲、更高效的中斷處理機制,以適應更複雜的應用場景。
玄貓認為,熟練掌握這些基本的開關控制技巧,對於開發根據樹莓派的互動裝置至關重要。對於追求更進階應用的開發者,建議深入研究硬體電路設計和軟體演算法最佳化,以打造更具競爭力的產品。