RPi.GPIO模块

RPi.GPIO Python模块

本文搬运于https://sourceforge.net/p/raspberry-gpio-python/wiki/Home/,进行了机器翻译与部分修改,2020.06.13更新。如有错误或翻译不当之处,劳烦各位指出,我会及时修改。

Wiki: 代码示例

基本用法

要导入RPi.GPIO模块:

import RPi.GPIO as GPIO

通过这种方式,您可以在其余脚本中将其仅称为GPIO。

导入模块并检查是否成功:

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")

引脚编号

RPi.GPIO中的Raspberry Pi上的IO引脚编号有两种方法。第一种是使用BOARD编号系统。这是指Raspberry Pi板的P1接头上的引脚号。使用此编号系统的优点是,无论RPi的主板版本如何,您的硬件将始终可以工作。您无需重新连接连接器或更改代码。

第二个编号系统是BCM编号。这是一种较低级别的工作方式-指Broadcom SOC上的通道号。您必须始终使用哪个通道号转到RPi板上哪个引脚的图表。您的脚本可能会在Raspberry Pi板的修订版之间中断。

要使用(强制)指定要使用的对象,请执行以下操作:

GPIO.setmode(GPIO.BOARD)
  # or
GPIO.setmode(GPIO.BCM)

要检测设置了哪个引脚编号系统(例如,通过另一个Python模块):

mode = GPIO.getmode()

模式可设置为GPIO.BOARD,GPIO.BCM或无

警告事项

Raspberry Pi的GPIO上可能有多个脚本/电路。结果,如果RPi.GPIO检测到某个引脚已配置为默认值(输入)以外的其他值,则在尝试配置脚本时会收到警告。要禁用这些警告:

GPIO.setwarnings (False)

设置频道

您需要设置用作输入或输出的每个通道。要将通道配置为输入:

GPIO.setup(channel, GPIO.IN)

(其中channel是基于您指定的编号系统(BOARD或BCM)的通道号)。

有关设置输入通道的更多高级信息,请参见此处

要将通道设置为输出:

GPIO.setup(channel, GPIO.OUT)

(其中channel是基于您指定的编号系统(BOARD或BCM)的通道号)。

您还可以为输出通道指定一个初始值:

GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)

设置多个频道

您可以为每个使用设置多个频道(从0.5.8版本开始)。例如:

chan_list = [11,12]    # add as many channels as you want!
                       # you can tuples instead i.e.:
                       #   chan_list = (11,12)
GPIO.setup(chan_list, GPIO.OUT)

输入项

读取GPIO引脚的值:

GPIO.input(channel)

(其中channel是基于您指定的编号系统(BOARD或BCM)的通道号)。这将返回其中一项 0 / GPIO.LOW / False or 1 / GPIO.HIGH / True.

输出量

设置GPIO引脚的输出状态:

GPIO.output(channel, state)

(其中channel是基于您指定的编号系统(BOARD或BCM)的通道号)。

状态可以是0 / GPIO.LOW / False or 1 / GPIO.HIGH / True.

输出到多个通道

您可以在同一使用中输出到多个频道(从0.5.8开始支持)。例如:

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

清理

在任何程序的最后,清理您可能使用过的所有资源都是一个好习惯。这种思想同样存在于RPi.GPIO中。通过将您使用过的所有通道返回到没有上拉/下拉的输入状态,可以避免因为引脚短路意外损坏你的树莓派。请注意,这只会清除脚本已使用的GPIO通道。另外,GPIO.cleanup()还会清除使用中的引脚编号系统。

在脚本末尾进行清理:

GPIO.cleanup()

可能不希望清理每个通道而在程序退出时留下一些设置。您可以清理单个频道,频道列表或频道组:

GPIO.cleanup(channel)
GPIO.cleanup( (channel1, channel2) )
GPIO.cleanup( [channel1, channel2] )

RPi板信息和RPi.GPIO版本

要查看有关您的树莓派的信息:

GPIO.RPI_INFO

要查看树莓派的主板版本:

GPIO.RPI_INFO['P1_REVISION']
GPIO.RPI_REVISION    (deprecated)

要查看RPi.GPIO库的版本:

GPIO.VERSION

输入

有几种方法可以将GPIO输入程序中。第一种也是最简单的方法是在某个时间点检查输入值。这称为“轮询”,如果程序在错误的时间读取值,则可能会丢失输入。轮询是循环执行的,可能会占用大量处理器资源。响应GPIO输入的另一种方法是使用“中断”(边沿检测)。边缘是从HIGH到LOW(下降沿)或从LOW到HIGH(上升沿)的过渡的名称。

上拉/下拉电阻

如果您没有将输入引脚连接到任何东西,它将“浮动”。换句话说,读入的值是不确定的,因为在按下按钮或开关之前,它没有连接任何东西。由于受到电源干扰,它可能会改变很多值。

为了解决这个问题,我们使用上拉或下拉电阻。这样,可以设置输入的默认值。可以在硬件中和使用软件中具有上拉/下拉电阻。在硬件中,通常在输入通道和3.3V(上拉)或0V(上拉)之间使用10K电阻。RPi.GPIO模块允许您配置Broadcom SOC以在软件中执行此操作:

GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  # or
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

(其中channel是基于您指定的编号系统-BOARD或BCM的通道号)。

测试输入(polling)

您可以随时对输入进行快照:

if GPIO.input(channel):
    print('Input was HIGH')
else:
    print('Input was LOW')

要等待按钮,请循环轮询:

while GPIO.input(channel) == GPIO.LOW:
    time.sleep(0.01)  # wait 10 ms to give CPU chance to do other things

(这假设按下按钮会将输入从LOW更改为HIGH)

中断和边缘检测

边沿是电信号的状态从低到高(上升沿)或从高到低(下降沿)的变化。通常,我们更关心输入状态的变化而不是其值的变化。状态的改变是一个事件

为了避免在程序忙于执行其他操作时错过按键,有两种方法可以解决此问题:

  • wait_for_edge()函数
  • event_detected()函数
  • 当检测到边缘时运行的线程回调函数(a threaded callback function that is run when an edge is detected)

wait_for_edge()函数

wait_for_edge()函数旨在阻止程序执行,直到检测到边缘为止。换句话说,上面等待按钮按下的示例可以重写为:

GPIO.wait_for_edge(channel, GPIO.RISING)

请注意,您可以检测到GPIO.RISING,GPIO.FALLING或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)

event_detected()函数

event_detected()函数旨在与其他事物循环使用,但是与轮询不同,它不会丢失CPU在忙于其他事情时的输入状态变化。当使用诸如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')

请注意,您可以检测到GPIO.RISING,GPIO.FALLING或GPIO.BOTH的事件。

线程回调

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...

如果您需要多个回调函数:

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)

请注意,在这种情况下,回调函数是顺序运行的,而不是同时运行的。这是因为只有一个线程用于回调,每个线程都按照其定义的顺序运行。

开关反跳

您可能会注意到,每次按下按钮都会多次调用回调。这是所谓的“开关弹跳”的结果。有两种处理开关反弹的方法:

  • 在开关两端添加一个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)

或者

GPIO.add_event_callback(channel, my_callback, bouncetime=200)

删除事件检测

如果由于某种原因,您不再希望程序检测边缘事件,则可以将其停止:

GPIO.remove_event_detect(channel)

输出

  1. 首先设置RPi.GPIO
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
  1. 高电平输出:
GPIO.output(12, GPIO.HIGH)
 # or
GPIO.output(12, 1)
 # or
GPIO.output(12, True)

3.低电平输出:

GPIO.output(12, GPIO.LOW)
 # or
GPIO.output(12, 0)
 # or
GPIO.output(12, False)

4.同时多个通道输出:

chan_list = (11,12)
GPIO.output(chan_list, GPIO.LOW) # all LOW
GPIO.output(chan_list, (GPIO.HIGH,GPIO.LOW))  # first LOW, second HIGH

5.在程序结束时进行关闭输出通道

GPIO.cleanup()

请注意,您可以使用input()函数读取设置为输出的通道的当前状态。例如,切换输出:

GPIO.output(12, not GPIO.input(12))

脉宽调制(PWM)

要创建PWM输出实例:

p = GPIO.PWM(channel, frequency)

要启动PWM:

p.start(dc)   # where dc is the duty cycle (0.0 <= dc <= 100.0)

更改频率:

p.ChangeFrequency(freq)   # where freq is the new frequency in Hz

更改占空比:

p.ChangeDutyCycle(dc)  # where 0.0 <= dc <= 100.0

停止PWM:

p.stop()

请注意,如果实例变量“ 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()

增亮/调暗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()

GPIO通道检查功能

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

Wiki:技术参考

Raspberry Pi / BCM2835技术参考

详细的技术参考可以在以下位置找到:

请注意,RPi引脚3和5(Rev2和B + GPIO 02和03,Rev1-GPIO 00和01)具有1K8上拉电阻至3v3。

Wiki:安装

RPi.GPIO安装

树莓派中默认安装了RPi.GPIO模块。为确保它是最新版本:

$ sudo apt-get update
$ sudo apt-get install python-rpi.gpio python3-rpi.gpio

要从项目源代码库安装最新的开发版本:

$ sudo apt-get install python-dev python3-dev
$ sudo apt-get install mercurial
$ sudo apt-get install python-pip python3-pip
$ sudo apt-get remove python-rpi.gpio python3-rpi.gpio
$ sudo pip install hg+http://hg.code.sf.net/p/raspberry-gpio-python/code#egg=RPi.GPIO
$ sudo pip-3.2 install hg+http://hg.code.sf.net/p/raspberry-gpio-python/code#egg=RPi.GPIO

要恢复为Raspbian的默认版本,请执行以下操作:

$ sudo pip uninstall RPi.GPIO
$ sudo pip-3.2 uninstall RPi.GPIO
$ sudo apt-get install python-rpi.gpio python3-rpi.gpio

其他

建议您使用pip程序以超级用户的权限(root)安装RPi.GPIO:

# pip install RPi.GPIO

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值