Raspberry Pi - Python 中的 GPIO 事件
Posted
技术标签:
【中文标题】Raspberry Pi - Python 中的 GPIO 事件【英文标题】:Raspberry Pi- GPIO Events in Python 【发布时间】:2013-04-15 03:53:22 【问题描述】:我使用 Raspberry Pi 上的 GPIO 引脚和 PIR 传感器来检测运动。当传感器检测到运动时,我想将软件移至其他功能。
目前,为了检测运动,我的程序在等待检测运动时不断循环运行。虽然这目前有效,但对于将来的使用,这将是非常低效的,我希望通过将其分配给一个事件来改进这一点。
有什么方法可以将我的 GPIO 输入绑定到程序检测到的事件,而无需手动运行循环。
这是我当前用于检测运动的循环:
var = 1
counter = 0
while var == 1:
if GPIO.input(7):
counter += 1
time.sleep(0.5)
else:
counter = 0
time.sleep(1)
if counter >= 3:
print "Movement!"
captureImage()
time.sleep(20)
计数器和多次检测运动用于减少传感器检测到的误报数量。
【问题讨论】:
【参考方案1】:kapcom01 提供了一些很棒的想法,但最好不要在中断中做很多指令。
通常在调用回调时将标志设置为 1,然后在主函数中进行处理。以这种方式没有释放程序的风险。
类似这样的:
from time import sleep
import RPi.GPIO as GPIO
def init():
# make all your initialization here
flag_callback = False
# add an interrupt on pin number 7 on rising edge
GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)
def my_callback():
# callback = function which call when a signal rising edge on pin 7
flag_callback = True
def process_callback():
# TODO: make process here
print('something')
if __name__ == '__main__':
# your main function here
# 1- first call init function
init()
# 2- looping infinitely
while True:
#3- test if a callback happen
if flag_callback is True:
#4- call a particular function
process_callback()
#5- reset flagfor next interrupt
flag_callback = False
pass
【讨论】:
【参考方案2】:RPi.GPIO Python 库现在支持事件,在Interrupts and Edge detection 段落中进行了说明。
因此,在使用 sudo rpi-update
更新您的 Raspberry Pi 以获得最新版本的库后,您可以将代码更改为:
from time import sleep
import RPi.GPIO as GPIO
var=1
counter = 0
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
def my_callback(channel):
if var == 1:
sleep(1.5) # confirm the movement by waiting 1.5 sec
if GPIO.input(7): # and check again the input
print("Movement!")
captureImage()
# stop detection for 20 sec
GPIO.remove_event_detect(7)
sleep(20)
GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)
GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)
# you can continue doing other stuff here
while True:
pass
我选择Threaded callbacks 方法是因为我认为您的程序会并行执行一些其他操作来更改var
的值。
【讨论】:
【参考方案3】:现在 RPi GPIO 库具有内置的中断驱动 GPIO 控制,可以在单独的线程中释放资源。 您不妨阅读以下http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3
【讨论】:
【参考方案4】:您可以将 GPIO 代码包装到它自己的线程中,并让程序的其余部分在 GPIO 等待输入时执行其他操作。查看threading module
首先我将你的代码包装成一个函数
def wait_input():
var=1
counter = 0
while var == 1:
if GPIO.input(7):
counter += 1
time.sleep(0.5)
else:
counter = 0
time.sleep(1)
if counter >= 3:
print "Movement!"
captureImage()
time.sleep(20)
然后在你的主程序中你可以这样
input_thread = threading.Thread(target = wait_input)
input_thread.start()
# do something in the meanwhile
input_thread.join()
关于 python 线程的 SO 有很多问题,所以你可能想挖掘它们。请注意,在使用线程时还需要考虑很多事情,尤其是在具有全局解释器锁 (GIL) 的 python 中,它一次只允许一个进程运行。查看multiprocessing module 可能也很聪明,可以通过它绕过 GIL。
【讨论】:
这种方法是否适用于 GUI?我想要做的是从我的 GUI 调用这个循环在其中运行的运动检测器类,但是使用循环它只会使 GUI 崩溃。如果我在线程中使用它,它会导致运动检测循环在后台运行,同时 GUI 侦听与其关联的输入吗? @Stefoth 这就是 GUI 编程的工作原理。您的 GUI 将在其自己的线程中运行,而运动检测代码将在其自己的线程中运行。以上是关于Raspberry Pi - Python 中的 GPIO 事件的主要内容,如果未能解决你的问题,请参考以下文章
Raspberry Pi - Python 中的 GPIO 事件
Adafruit_DHT不适用于python 3 Raspberry Pi 3 B.
使用 Raspberry Pi 将图像发送到 Python 中的 QL-800 打印机时如何解码此错误?
我无法列出 Raspberry Pi 附近的 BLE 设备(python、btmgmt)