品味樹莓派:GPIO Zero庫使用入門

目的

樹莓派有很多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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章