樹莓派RPi.GPIO使用手冊
參考源:http://blog.csdn.net/qq_35893742/article/details/53428679
1.RPi.GPIO模組基本使用
匯入模組
匯入 RPi.GPIO 模組:
import RPi.GPIO as GPIO
- 1
通過下面的程式碼可以檢測匯入是否成功
try:
import RPi.GPIO as GPIO
except RuntimeError:
print("Error importing RPi.GPIO! This is probably because you need superuser privileges. You can achieve this by using 'sudo' to run your script" )
- 1
- 2
- 3
- 4
引腳編號方式
RPi.GPIO中有兩種引腳的編號方式。第一個是使用電路板編號系統。這指的是在樹莓派電路板上P1開頭的。使用這個編號系統的優勢是,您的硬體將總是工作,不管電路板是哪個版本的。你不需要重新修改程式碼。
第二個編號系統是BCM數字。這是一個低水平的工作方式,它指的是電路板引腳的位置號。電路板版本變化時指令碼程式需要對應修改。
必須指定使用哪種:
GPIO.setmode(GPIO.BOARD)
# or
GPIO.setmode(GPIO.BCM)
- 1
- 2
- 3
可以查詢使用的哪種編號方法
mode = GPIO.getmode()
#輸出: GPIO.BOARD, GPIO.BCM or None
- 1
- 2
設定一個通道
作為輸入
GPIO.setup(channel, GPIO.IN)
#chanel與使用的編號方式對應
- 1
- 2
作為輸出:
GPIO.setup(channel, GPIO.OUT)
GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)
- 1
- 2
設定多個通道
chan_list = [11,12] # add as many channels as you want!
GPIO.setup(chan_list, GPIO.OUT)
- 1
- 2
輸入
讀取一個GPIO口的值
GPIO.input(channel)
#返回:0 / GPIO.LOW / False or 1 / GPIO.HIGH / True.
- 1
- 2
輸出
設定一個GPIO口的輸出值
GPIO.output(channel, state)
#State 可以是 0 / GPIO.LOW / False or 1 / GPIO.HIGH / True.
- 1
- 2
設定多個通道的輸出
chan_list = [11,12] # also works with tuples
GPIO.output(chan_list, GPIO.LOW) # sets all to GPIO.LOW
GPIO.output(chan_list, (GPIO.HIGH, GPIO.LOW))
# sets first HIGH and second LOW
- 1
- 2
- 3
- 4
清空
在程式的末尾可以加上
GPIO.cleanup()
- 1
如果想清理特定的通道
GPIO.cleanup(channel)
GPIO.cleanup( (channel1, channel2) )
GPIO.cleanup( [channel1, channel2] )
- 1
- 2
- 3
2.GPIO 輸入
要得到GPIO輸入到你的程式的幾種方法。第一個和最簡單的方法是在時間點上檢查輸入值。這被稱為“輪詢”,如果你的程式在錯誤的時間讀取值,可能會錯過一個輸入。輪詢是在迴圈中進行的。另外一種方法來響應一個GPIO輸入是使用“中斷”(邊沿檢測)。邊沿是由高到低(下降沿)或低到高(上升沿)的過渡的名稱。
上拉或者下拉電阻
如果您沒有連線到任何硬體的輸入引腳,它將’浮動’。換句話說,讀取的值是未定義的,因為它沒有連線到任何事情,直到你按一個按鈕或開關。由於受電干擾,它的值可能會改變。
為了實現這一點,我們使用了上拉或下拉電阻。以這種方式,可以設定輸入的預設值。在硬體和軟體上有上拉/下拉電阻是可能的。在硬體上,在輸入通道和3.3V(上拉)之間的或0V(下拉)使用10K電阻是常用的。通過rpi.gpio模組配置GPIO口可以實現同樣的功能
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# or
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
- 1
- 2
- 3
測試輸入(輪詢)
可以在一個時間點檢視輸入
if GPIO.input(channel):
print('Input was HIGH')
else:
print('Input was LOW')
- 1
- 2
- 3
- 4
在迴圈中使用輪詢來檢測按鈕是否按下
while GPIO.input(channel) == GPIO.LOW:
time.sleep(0.01) # wait 10 ms to give CPU chance to do other things
- 1
- 2
中斷與邊沿檢測
邊沿是電訊號從低到高(上升沿)或從高到低(下降沿)的改變。這種改是一種事件,為了使程式在執行的過程中檢測到按鈕按下這樣的事件:
• wait_for_edge()
• event_detected()
• 另外一個執行緒的回撥方法
wait_for_edge()方法不會執行,只到檢測到邊沿,檢測按鈕按下也可以寫成:
GPIO.wait_for_edge(channel, GPIO.RISING)
- 1
這種檢測邊沿( GPIO.RISING, GPIO.FALLING or GPIO.BOTH)的優勢是使用CPU的資源很少
可以加一個timeout引數
#wait for up to 5 seconds for a rising edge (timeout is in milliseconds)
channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000)
if channel is None:
print('Timeout occurred')
else:
print('Edge detected on channel', channel)
- 1
- 2
- 3
- 4
- 5
- 6
event_detected()方法是用在迴圈事件中,在Pygame或PyQt這種存在一個主迴圈監聽GUI時非常有用.
GPIO.add_event_detect(channel, GPIO.RISING) # add rising edge detection on a channel
do_something()
if GPIO.event_detected(channel):
print('Button pressed')
- 1
- 2
- 3
- 4
執行緒回撥
RPi.GPIO執行第二個執行緒來處理回撥函式:
def my_callback(channel):
print('This is a edge event callback function!')
print('Edge detected on channel %s'%channel)
print('This is run in a different thread to your main program')
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback) # add rising edge detection on a channel
...the rest of your program...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
多個回撥函式:
def my_callback_one(channel):
print('Callback one')
def my_callback_two(channel):
print('Callback two')
GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, my_callback_one)
GPIO.add_event_callback(channel, my_callback_two)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
這裡的回撥函式是按順序執行的,不是同時執行的,因為只有一個程序(process)在執行
開關去抖
開關在按下的過程中回撥函式會執行多次,這是因為開關按下的過程中由於抖動產生多個邊沿的原因,下面的方法可以解決這個問題:
• 增加一個0.1uF的電容與開關串接
• 軟體去抖
• 結合上述兩種方法
在程式中增加一個bouncetime引數可以現實去抖:
# add rising edge detection on a channel, ignoring further edges for 200ms for switch bounce handling
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200)
or
GPIO.add_event_callback(channel, my_callback, bouncetime=200)
- 1
- 2
- 3
- 4
移除事件監聽
GPIO.remove_event_detect(channel)
- 1
3.GPIO 輸出
設定RPi.GPIO
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
- 1
- 2
- 3
- 設定為高電平輸出:
GPIO.output(12, GPIO.HIGH)
# or
GPIO.output(12, 1)
# or
GPIO.output(12, True)
- 1
- 2
- 3
- 4
- 5
設定低電平輸出
GPIO.output(12, GPIO.LOW)
# or
GPIO.output(12, 0)
# or
GPIO.output(12, False)
- 1
- 2
- 3
- 4
- 5
同時設定多個通道的輸出
chan_list = (11,12)
GPIO.output(chan_list, GPIO.LOW) # all LOW
GPIO.output(chan_list, (GPIO.HIGH,GPIO.LOW)) # first LOW, second HIGH
- 1
- 2
- 3
清空
GPIO.cleanup()
input()方法可以讀取目前通道的輸出:
GPIO.output(12, not GPIO.input(12))
- 1
- 2
- 3
4.PWM(脈衝寬度調製)
建立PWM 例項
p = GPIO.PWM(channel, frequency)
- 1
啟動PWM
p.start(dc) # where dc is the duty cycle (0.0 <= dc <= 100.0)
- 1
改變頻率
p.ChangeFrequency(freq) # where freq is the new frequency in Hz
- 1
改變佔空比
p.ChangeDutyCycle(dc) # where 0.0 <= dc <= 100.0
- 1
停止PWM
p.stop()
- 1
變數P超出範圍時PWM也會停止.
LED每兩秒閃爍一次:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p = GPIO.PWM(12, 0.5)
p.start(1)
input('Press return to stop:') # use raw_input for Python 2
p.stop()
GPIO.cleanup()
An example to brighten/dim an LED:
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p = GPIO.PWM(12, 50) # channel=12 frequency=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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
gpio_function(channel)
顯示一個GPIO口的功能:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
func = GPIO.gpio_function(pin)
#返回值:GPIO.IN, GPIO.OUT, GPIO.SPI, GPIO.I2C, GPIO.HARD_PWM, GPIO.SERIAL, GPIO.UNKNOWN
- 1
- 2
- 3
- 4
- 5