目的
樹莓派有很多GPIO口可供用戶使用,官方同時也提供了一些方式來操作這些IO口,其中目前主要推薦的是基於Python的GPIO Zero庫,本文將簡單介紹該庫的基礎使用方法。
基礎說明
GPIO Zero庫是樹莓派官方目前推薦的用於操作樹莓派上GPIO口的Python庫,該庫最早是在RPi.GPIO庫之上開發而來的,現在默認情況下也有許多功能是基於RPi.GPIO庫實現的,不過用戶可以自行設置其它庫用在底層。
GPIO Zero庫將常用的功能進行封裝(LED、Button、Motor……),使一般用戶和軟件開發者更加容易實現需要用到GPIO口的功能,而不需要像RPi.GPIO庫一樣去了解GPIO口的輸入輸出、上下拉電阻等底層硬件相關的參數。
GPIO Zero庫官方文檔:https://gpiozero.readthedocs.io/en/stable/
可以看到官方文檔的基礎說明裏都是具體的LED、Button、Motor等應用
帶圖形界面的Raspbian系統默認就安裝了GPIO Zero庫,Raspbian Lite上可以使下面命令來安裝該庫:
sudo apt update
sudo apt install python3-gpiozero
其它樹莓派上的系統可以使下面命令來安裝該庫:
sudo pip3 install gpiozero
使用過程中需要的樹莓派GPIO口定義可以參考下圖:
入門使用
GPIO Zero庫中具體實現的功能還是比較多的,這裏挑選一部分介紹演示。
LED
控制LED是嵌入式入門實驗,GPIO Zero庫可以使用LED類來控制LED,首先按下圖連接LED:
上圖中左側爲實物連接,右側爲原理圖,電路中的電阻是用來限制電流大小的。
可以使用下面代碼來控制LED亮滅交替閃爍:
from gpiozero import LED # 引入LED類
from time import sleep
red = LED(17) # 聲明LED對象red,該對象連接至樹莓派GPIO17引腳
while True: # 使下面程序持續循環運行
red.on() # 點亮LED
sleep(1) # 延時1秒
red.off() # 熄滅LED
sleep(1) # 延時1秒
或者用下面代碼也能實現一樣的效果:
from gpiozero import LED # 引入LED類
from signal import pause
red = LED(17) # 聲明LED對象red,該對象連接至樹莓派GPIO17引腳
red.blink() # 使LED反覆亮滅
pause() # 暫停當前腳本的進程
#(使腳本不會結束,這樣red.blink()就會一直運行,不會因爲腳本結束而被釋放)
上面是簡單的演示,每隔一秒分別開關了LED,同時打印了其狀態。
LED類更多說明如下:
class gpiozero.LED(pin, *, active_high=True, initial_value=False, pin_factory=None)
LED構造函數,輸入參數如下:
pin: GPIO口編號(填入數字或字符串均可);
active_high: LED是否在GPIO口電平爲High時點亮,默認True表示GPIO口輸出高電平時點亮LED;
initial_value: 初始值,默認False表示初始不點亮LED;
pin_factory: 一般不用到,以後會單獨進行講解,下同;blink(on_time=1, off_time=1, n=None, background=True)
控制LED閃爍,輸入參數如下:
on_time: 一次閃爍中LED點亮持續時間,單位秒;
off_time: 一次閃爍中LED熄滅持續時間,單位秒;
n: 閃爍次數,默認None表示LED將持續閃爍;
background: 默認True表示該動作將新開一個線程運行,函數會立即返回。如果設置爲False,函數將阻塞在次直到閃爍完成才返回;off()
熄滅LED;on()
點亮LED;toggle()
翻轉LED狀態;is_lit
以布爾值方式表示LED是否點亮狀態;pin
以字符串形式表示LED連接的pin編號;value
以數值形式表示LED是否點亮狀態;
PWMLED
上面的LED只是單純的點亮或熄滅,GPIO Zero庫中還可以使用PWM來調節KED亮度,或是實現呼吸燈功能,比如下面代碼:
from gpiozero import PWMLED # 引入PWMLED類
from time import sleep
from signal import pause
led = PWMLED(17) # 聲明PWMLED對象led,該對象連接至樹莓派GPIO17引腳
led.value = 1 # 以100%亮度點亮LED(這裏用了特別的方式,以後會單獨進行講解)
sleep(2) # 延時2秒
led.value = 0.5 # 以50%亮度點亮LED
sleep(2) # 延時2秒
led.value = 0 # 熄滅LED
sleep(2) # 延時2秒
led.pulse() # 使LED以呼吸燈方式閃爍
pause()
PWMLED類更多說明如下:
class gpiozero.PWMLED(pin, *, active_high=True, initial_value=0, frequency=100, pin_factory=None)
LED構造函數,輸入參數如下:
pin: GPIO口編號(填入數字或字符串均可);
active_high: LED是否在GPIO口電平爲High時點亮,默認True表示GPIO口輸出高電平時點亮LED;
initial_value: 初始值,可選0和1之間的值,0表示熄滅,1表示完全點亮;
frequency: PWM頻率,默認值100表示100Hz;blink(on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, n=None, background=True)
控制LED閃爍,輸入參數如下:
on_time: 一次閃爍中LED完全點亮持續時間,單位秒;
off_time: 一次閃爍中LED完全熄滅持續時間,單位秒;
fade_in_time: 一次閃爍中LED從熄滅到點亮的過程時間,單位秒;
fade_out_time: 一次閃爍中LED從點亮到熄滅的過程時間,單位秒;
n: 閃爍次數,默認None表示LED將持續閃爍;
background: 默認True表示該動作將新開一個線程運行,函數會立即返回。如果設置爲False,函數將阻塞在次直到閃爍完成才返回;off()
熄滅LED;on()
點亮LED;pulse(fade_in_time=1, fade_out_time=1, n=None, background=True)
控制LED閃爍,輸入參數如下:
fade_in_time: 一次閃爍中LED從熄滅到點亮的過程時間,單位秒;
**fade_out_time:**一次閃爍中LED從點亮到熄滅的過程時間,單位秒;
n: 閃爍次數,默認None表示LED將持續閃爍;
background: 默認True表示該動作將新開一個線程運行,函數會立即返回。如果設置爲False,函數將阻塞在次直到閃爍完成才返回;toggle()
翻轉LED狀態至1 - value
;is_lit
以布爾值方式表示LED是否點亮狀態;pin
以字符串形式表示LED連接的pin編號;value
返回當前LED的PWM佔空比值;
Button
外接物理按鍵是一個非常常用的功能,GPIO Zero庫中直接封裝了一個Button類,這個類的使用非常方便,首先按照下圖方式連接設備:
按上圖連接電路,等下再在程序裏啓用GPIO2的內部上拉電阻,這樣的話按鈕在未被按下時GPIO2上爲高電平,當按鈕被按下後會變爲低電平。
使用下面代碼可以簡單進行測試:
from gpiozero import Button # 引入Button類
button = Button(2) # 聲明Button對象button,該對象連接至樹莓派GPIO2引腳
button.wait_for_press() # 等待按鈕被按下
print(button.is_pressed) # 當按鈕被按下時觸發該行
button.wait_for_release() # 等待按鈕被鬆開
print(button.is_pressed) # 當按鈕被鬆開時觸發該行
上面是個簡單的演示,實際操作中不太會用wait_for_press()和wait_for_release(),更多的會用事件與回調函數形式來處理按鈕按下鬆開時的動作:
from gpiozero import Button # 引入Button類
from signal import pause
def btn_held(): # 回調函數
print('held:{} - {}'.format(button.is_pressed, button.is_held))
print('{} - {}'.format(button.pressed_time, button.held_time))
def btn_pressed(): # 回調函數
print('pressed:{} - {}'.format(button.is_pressed, button.is_held))
print('{} - {}'.format(button.pressed_time, button.held_time))
def btn_released(): # 回調函數
print('released:{} - {}'.format(button.is_pressed, button.is_held))
print('{} - {}'.format(button.pressed_time, button.held_time))
button = Button(2) # 聲明Button對象button,該對象連接至樹莓派GPIO2引腳
button.when_held = btn_held # 註冊按鈕長按事件回調函數
button.when_pressed = btn_pressed # 註冊按鈕按下事件回調函數
button.when_released = btn_released # 註冊按鈕鬆開事件回調函數
pause()
上面演示了基礎的回調函數功能,事實上按鈕事件的回調函數在觸發時還可以傳入Button對象,這在多個按鈕綁定同一個回調函數的時候挺好用,可以知道具體是哪個按鈕觸發了該動作:
from gpiozero import Button # 引入Button類
from signal import pause
def btn_callback(btn): # 回調函數
print(btn.pin) # 打印觸發該函數的Button對象連接的GPIO編號
button = Button(2) # 聲明Button對象button,該對象連接至樹莓派GPIO2引腳
button.when_pressed = btn_callback # 註冊按鈕按下事件回調函數
pause()
Button類更多說明如下:
class gpiozero.Button(pin, *, pull_up=True, active_state=None, bounce_time=None, hold_time=1, hold_repeat=False, pin_factory=None)
Button構造函數,輸入參數如下:
pin: GPIO口編號(填入數字或字符串均可);
pull_up: 內部上下拉電阻設置,True啓用內部上拉,False啓用內部下來,None不啓用上下拉;
active_state: 如果爲True,則IO外部爲高時軟件顯示該IO口爲高,如果爲False,則IO外部爲高時軟件顯示該IO口爲低。當pull_up不爲None時該值將自動設置;
bounce_time: 軟件消抖時間,None則爲不啓用軟件消抖;
hold_time: 按下按鈕後直到觸發when_held的時間,單位秒;
hold_repeat: 如果爲True,則只要按鈕持續被按下when_held會每隔hold_time時間持續被觸發,如果爲False,則when_held只會觸發一次;wait_for_press(timeout=None)
等待按鈕被按下,timeout爲超時時間,單位秒;wait_for_release(timeout=None)
等待按鈕被釋放,timeout爲超時時間,單位秒;pressed_time
從按鈕被按下開始持續經過的時間;held_time
從when_held觸發開始按鈕被持續按下的時間;is_held
如果該值爲True,則說明按鈕至少被按下hold_time秒;is_pressed
如果按鈕被按下該值爲True,否則爲False;pin
以字符串形式表示LED連接的pin編號;value
如果按鈕被按下該值爲1,否則爲0;when_held
當按鈕被按下hold_time後觸發的回調函數,填寫None則禁用該事件;when_pressed
當按鈕被按下時觸發的回調函數,填寫None則禁用該事件;when_released
當按鈕被鬆開時觸發的回調函數,填寫None則禁用該事件;
更多入門例程
GPIO Zero庫文檔中提供了非常多的常用的元器件、傳感器、執行器等的例程,比如人體紅外傳感器、超聲波測距傳感器、電機等等。更多內容可以參考官方文檔:
https://gpiozero.readthedocs.io/en/stable/recipes.html
注:GPIO Zero官方例程中有很多內容是基於特定某個電路或電路模塊而來的,請根據自己的實際情況進行閱讀。
類基礎說明
GPIO Zero庫中各個類的關係如下圖(點擊看大圖):
上圖中深藍色的是實體類、淺藍色的是抽象類、紫色的是mixin類。越靠近右邊的越具體、越接近用戶,比如LED、Button等。
從上圖可以看到LED和Buzzer都是基於DigitalOutputDevice類的(如果你去看源碼的話就會發現LED類幾乎就只是DigitalOutputDevice類換了個名稱而已),該類用於控制GPIO口數字輸出,如果你想單獨控制GPIO口用作數字輸出就可以直接用該類,參考下面例子:
同樣的如果你想單獨控制GPIO口用作數字輸入就可以使用上圖中DigitalInputDevice類。其它情況同理,可以在上圖中找到合適的類使用。相關的類說明可以從參考官方文檔中以 API -
開頭的相關章節中查詢:
當然對於Python而言庫寫的好的話用help方法也很方便:
注意事項
GPIO Zero庫中的對象在被釋放時受控的GPIO口會恢復到系統啓動後的初始狀態。除系統自動釋放外你也可以使用close()方法手動進行釋放。
總結
GPIO Zero庫使用起來還是比較簡單的,特別適合沒有硬件基礎的用戶使用,更多內容可以參考下面鏈接:
https://github.com/gpiozero/gpiozero