目錄
- 樹莓派筆記(三) 使用 RPi.GPIO 模塊
- RPi.GPIO
- 引腳簡介
- 引腳編號
- 引腳圖
- 引腳設定
- 指定引腳編號系統
- 配置通道
- 釋放引腳
- 輸出
- pwm
- 輸入
- 上拉/下拉電阻
- 輪詢輸入
- 中斷和邊檢檢測
- 執行緒回呼
- 開關防抖
樹莓派筆記(三) 使用 RPi.GPIO 模塊
RPi.GPIO
RPI.GPIO是python的一個模塊,樹莓派官方系統默認已經安裝
使用python控制GPIO需要匯入RPI.GPIO模塊
- 匯入模塊
#匯入模塊并檢查它是否成功:
import RPi.GPIO as GPIO
try:
import RPi.GPIO as GPIO
except RuntimeError :
print("匯入RPi.GPIO時出錯,可能是權限問題")
引腳簡介
引腳編號
RPi.GPIO中使用的IO引腳編號有兩種方法,
- BOARD編號系統,如下圖中物理介面,使用此編號系統的優點是,無論樹莓派的版本如何,您的硬體將始終可以作業,您無需重新連接連接器或更改代碼,
- BCM編號系統,不同版本的樹莓派不一樣可能要重新修改代碼,這是一種較低級別的作業方式-指Broadcom SOC上的通道號,您必須始終使用哪個通道號到達樹莓派板上哪個引腳的圖表,您的腳本可能會在樹莓派板的修訂版之間中斷,
引腳功能
如下圖,功能名一欄寫名了樹莓派引腳的功能
主要有如下分類
- 電源引腳
- 5v、3.3v :為輸出5v、3.3v電源
- 0v /GND :即負極,或接地級
- GPIO引腳
- 通用輸入輸出引腳,可編程控制高低電平
- 其他功能引腳
- i2c --> SDA,SCL
- SPI —> MOSI,MISO,SCLK 等等
查詢引腳編號
若忘了引腳編號,又找不到圖,你可以在樹莓派linux終端中輸入命令查詢引腳編號,如下
gpio readall
引腳圖

引腳設定
指定引腳編號系統
上面提到,樹莓派有多個編號系統,在編程之前需要指定一個編號系統,指定后,即使用該編號進行編程,若使用其他編號會導致錯誤
GPIO.setmode(GPIO.BOARD) #指定為BOARD編號
# or
GPIO.setmode(GPIO.BCM)#指定為BCM編號
若要檢測已經使用了什么編號可使用
mode = GPIO.getmode()
mode為GPIO.BOARD,GPIO.BCM、None,其意義顯而易見
配置通道
GPIO引腳是通用輸入輸出引腳,其是可以作為輸入或輸出所用
因此使用之前,你需要告訴系統,該引腳你需要作為輸入還是輸出
設定為輸入模式
GPIO.setup(引腳,GPIO.IN)
還可以設定上拉電阻(具體用處后面會介紹)
GPIO.setup(引腳,GPIO.IN,pull_up_down=GPIO.PUD_UP)
下拉電阻
GPIO.setup(引腳,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
設定為輸出模式
GPIO.setup(引腳,GPIO.OUT)
設定為輸出并初始為為HIGH或LOW
GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)
可以同時 設定多個引腳
chan_list = [ 11 ,12 ]
#你可以用元組代替,即:
#chan_list =(11,12)
GPIO.setup(chan_list, GPIO.OUT)
注意 引腳的編號為你上面指定的編號系統 ??????
釋放引腳
程式結束不釋放引腳是一個很危險的行為????????????
假如執行程式時 你設定引腳輸出為高電平,而程式結束時你未釋放引腳它將保持這一狀態,一旦意外接觸到該引腳與GND將會短路,啥訓你的樹莓派
釋放引腳:
GPIO.cleanup()
注意,同時GPIO.cleanup()也會清除正在使用的引腳編號系統,
輸出
根據上文,進行輸出操作前,應有
import RPi.GPIO as GPIO
try:
import RPi.GPIO as GPIO
except RuntimeError :
print("匯入RPi.GPIO時出錯,可能是權限問題")
GPIO.setmode(GPIO.BCM)#指定為BCM編號
GPIO.setup(17,GPIO.OUT)
設定 GPIO 針腳的輸出狀態:
GPIO.output(channel, state)
state可以是0 / GPIO.LOW / False --- 低電平
或者 1 / GPIO.HIGH / True --- 高電平
輸出切換,高變低,低變高
GPIO.output(channel, not GPIO.input(channel))
pwm
脈寬調制(PWM)是指用微處理器的數字輸出來對模擬電路進行控制,是一種對模擬信號電平進行數字編碼的方法
創建一個 PWM 實體:
p = GPIO.PWM(channel, frequency)
啟用 PWM:
p.start(dc) # dc 代表占空比(范圍:0.0 <= dc >= 100.0)
更改頻率:
p.ChangeFrequency(freq) # freq 為設定的新頻率,單位為 Hz
更改占空比:
p.ChangeDutyCycle(dc) # 范圍:0.0 <= dc >= 100.0
停止 PWM:
p.stop()
示例
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p = GPIO.PWM(12, 50) # 通道為 12 頻率為 50Hz
p.start(0)
try:
while 1:
for dc in range(0, 101, 5):
p.ChangeDutyCycle(dc)
time.sleep(0.1)
for dc in range(100, -1, -5):
p.ChangeDutyCycle(dc)
time.sleep(0.1)
except KeyboardInterrupt:
pass
p.stop()
GPIO.cleanup()
輸入
輸入要比輸出復雜一些
上拉/下拉電阻
如果輸入引腳沒有接其他器件(或者開關關閉),那么這個引腳將處于浮動的狀態,即可能高電平可能低電平,或者在兩者之間切換,這時候讀取引腳的值沒有意義,所以我們需要上拉/下拉電阻,使引腳狀態確定
- 物理方法
將一個 10K 的電阻連接在輸入通道與 3.3V(上拉)
或 輸入通道與0V之間(下拉) - 程式方法
上拉電阻
GPIO.setup(引腳,GPIO.IN,pull_up_down=GPIO.PUD_UP)
下拉電阻
GPIO.setup(引腳,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
輪詢輸入
這是最簡易的一種方式,在某個時間點檢查輸入值,這即是所謂的“輪詢 ”,而且如果您的程式在錯誤的時間里進行了讀取,可能會錯過某個輸入值,在回圈中運用輪詢,有可能使處理器資源緊張,
示例
if GPIO.input(channel):
print('Input was HIGH')
else:
print('Input was LOW')
回圈中等待按鈕被按下后進行輪詢
while GPIO.input(channel) == GPIO.LOW:
time.sleep(0.01) # 為 CPU 留出 10 毫秒,供其處理其它事物
中斷和邊檢檢測
用這種方法輸入不會因為cpu在忙其他事而錯過輸入,且占用 CPU 資源很少
邊緣就是是從 HIGH 到 LOW 的過度(下降臨界值falling edge)或從 LOW 到 HIGH 的過度(上升臨界值rising edge)
檢測到邊緣時執行執行緒回呼函式
-
wait_for_edge(channel, state) 函式
用于在檢測到邊緣之前阻止程式的運行,
上面的示例中,等待按鈕被按下的陳述句可以改寫為:
GPIO.wait_for_edge(channel, GPIO.RISING)如果您只想等待一段時間,則可以使用timeout引數:
#上升沿等待最多5秒(超時以毫秒為單位)
pin= GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000)
if pin is None:
print('Timeout occurred')
else:
print('Edge detected on pin', pin)
-
event_detected(channel, state) 函式
函式被設計用于回圈中有其它東西時使用,但不同于輪詢的是,它不會錯過當 CPU 忙于處理其它事物時輸入狀態的改變,這在類似使用 Pygame 或 PyQt 時主回圈實時監聽和回應 GUI 的事件是很有用的,
GPIO.add_event_detect(channel, GPIO.RISING) # 在通道上添加上升臨界值檢測
do_something()
if GPIO.event_detected(channel):
print('Button pressed')
state可以為GPIO.RISING、GPIO.FALLING、GPIO.BOTH
執行緒回呼
RPi.GPIO 在第二條執行緒中執行回呼函式,這意味著回呼函式可以同您的主程式同時運行,并且可以立即對邊緣進行回應,例如:
def my_callback(channel):
print('這是一個邊緣事件回呼函式!')
print('在通道 %s 上進行邊緣檢測'%channel)
print('該程式與您的主程式運行在不同的行程中')
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback) # 在通道上添加上升臨界值檢測
... 其它程式代碼 ...
如果您需要多個回呼函式:
def my_callback_one(channel):
print('回呼 1')
def my_callback_two(channel):
print('回呼 2')
GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, my_callback_one)
GPIO.add_event_callback(channel, my_callback_two)
注意,在該示例中,回呼函式為順序運行而不是同時運行,這是因為當前只有一個行程供回呼使用,而回呼的運行順序是依據它們被定義的順序,
開關防抖
每次按鈕按下時,回呼操作被呼叫不止一次,這種現象被稱作“開關抖動 ”,這里有兩種方法解決開關抖動問題:
- 物理方法 將一個 0.1uF 的電容連接到開關上,
- 軟體方法防止抖動
使用軟體方式抖動,可以在您指定的回呼函式中添加 bouncetime= 引數,
抖動時間需要使用毫秒為單位進行書寫,例如:
在通道上添加上升臨界值檢測,忽略由于開關抖動引起的小于 200ms 的邊緣操作
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200)
或者
GPIO.add_event_callback(channel, my_callback, bouncetime=200)
remove_event_detect()
如果你不希望你的程式檢測邊緣事件,可以將它停止:
GPIO.remove_event_detect(channel)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/163918.html
標籤:其他
