美文网首页
树莓派 GPIO Input 部分高级应用技巧

树莓派 GPIO Input 部分高级应用技巧

作者: 有事没事扯扯淡 | 来源:发表于2018-12-07 16:09 被阅读0次

此篇为《树莓派使用基础》 中,RPI.GPIO Input功能高级应用技巧。GPIO的简单使用请参考博文树莓派3B+ GPIO输入输出使用

目前有几种途径可以在程序中获得 GPIO 的输入信息。

  • 第一种也是最简易的一种,在某个时间点检查输入值。这即是所谓的“轮询(polling)”,而且如果程序在错误的时间里进行了读取,可能会错过某个输入值。在循环中运用轮询,有可能使处理器资源紧张。
  • 另一种对 GPIO 输入进行响应的方式为“中断(interruots)”(边缘检测(edge detection))。边缘可以是从 HIGH 到 LOW 的过度(下降临界值(falling edge))或从 LOW 到 HIGH 的过度(上升临界值(rising edge))。

上拉/下拉电阻

如果在输入针脚上没有连接任何元件,那么它将是“浮动(float)”的。换句话说,因为没有连接任何元件,在按下按钮或开关之前,读取的值是没有意义的。由于电源的波动,获取到的值可能会有很大的变化。

为了解决这个问题,我们需要使用上拉/下拉电阻。这样,我们就可设定输入的默认值了。在这里,可以使用硬件或软件对电阻进行上拉/下拉。使用硬件方式,将一个 10K 的电阻连接在输入通道与 3.3V(上拉)或 0V(下拉)之间是常用的做法。而 RPi.GPIO 也允许您通过软件的方式对配置 Broadcom SOC 来达到目的:

GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)

或者

GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

通道编号是基于所使用的编号系统所指定的(BOARD 或 BCM)。

中断和边检检测

边缘的定义为电信号从 LOW 到 HIGH(上升临界值)或从 HIGH 到 LOW(下降临界值)状态的改变。正常情况下,对于输入的值来说,我们更关心的是输入的状态是否发生了改变。这种状态上的改变是很重要的。

为了避免程序在忙于处理其它的事物时而错过了按下按钮的操作,这里有两种方法可以解决:

wait_for_edge()
event_detected()

在检测到边缘时执行线程回调函数

  • wait_for_edge() 函数

wait_for_edge() 函数被设计用于在检测到边缘之前阻止程序的运行。

GPIO.wait_for_edge(channel, GPIO.RISING)

注意,可以输入 GPIO.RISING、GPIO.FALLING、GPIO.BOTH 对边缘进行检测。这种方式的优点是占用 CPU 资源很少,因此系统可以有充裕的资源处理其它事物。

  • event_detected() 函数

event_detected() 函数被设计用于循环中有其它东西时使用,但不同于轮询的是,它不会错过当 CPU 忙于处理其它事物时输入状态的改变。这在类似使用 Pygame 或 PyQt 时主循环实时监听和响应 GUI 的事件是很有用的。

GPIO.add_event_detect(channel, GPIO.RISING)  # 在通道上添加上升临界值检测
do_something()
if GPIO.event_detected(channel):
    print('Button pressed')

线程回调

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)

注意,在该示例中,回调函数为顺序运行而不是同时运行。这是因为当前只有一个进程供回调使用,而回调的运行顺序是依据它们被定义的顺序。

开关防抖

可能会注意到,每次按钮按下时,回调操作被调用不止一次。这种现象被称作“开关抖动(switch bounce)”。这里有两种方法解决开关抖动问题:

  • 将一个 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)

原文链接
参考链接

相关文章

网友评论

      本文标题:树莓派 GPIO Input 部分高级应用技巧

      本文链接:https://www.haomeiwen.com/subject/grxthqtx.html