Raspberry Pi, Python - 处理 pi 上的多个传感器

Raspberry Pi, Python - Dealing with multiple sensors on the pi

我有一个使用 Raspberry Pi 和两个电容话筒的个人项目。我在每个麦克风上使用以下听众:

GPIO.add_event_detect(mic1, GPIO.BOTH, bouncetime=500)
GPIO.add_event_callback(mic1, soundHeard)

GPIO.add_event_detect(mic2, GPIO.BOTH, bouncetime=500)
GPIO.add_event_callback(mic2, soundHeard)

当检测到声音时(我在麦克风上使用数字触发器),事件将 PIN 码发送到回调。我用pin码来运行一个函数。虽然该函数是 运行ning,大约 10 秒,但我希望这两个事件完全停止触发,直到该函数交回控制权。目前,侦听器不断发送事件,这些事件似乎堆叠在函数之上,然后在函数完成后所有 运行 串行。

我试过使用带有时间戳的全局变量和各种其他方法来停止事件侦听器,但都无济于事。如果我尝试关闭侦听器并重新打开它们,我会收到分段错误错误。任何帮助表示赞赏,

干杯,

维特纳

来自 docs on SOURCEFORGE(就在该部分上方:开关去抖):

"Note that in this case, the callback functions are run sequentially, not concurrently. This is because there is only one thread used for callbacks, in which every callback is run, in the order in which they have been defined."

我会尝试通过将回调包装在一个函数中来避免这种行为,该函数创建一个新线程来处理每个事件,从而让回调本身立即 return。然后我会使用 threading.Lock 以便在评估第一个事件期间触发的任何事件立即被抛出,而不是尝试解除绑定和 re-bind 回调。

from threading import Thread, Lock

def callback_dispatcher(fun):
    def wrapped(*args):
        t = Thread(target=fun, args=args)
        t.start()
    return wrapped

#lock is defined in main thread so all child threads will have a copy of the same object
soundHeard_lock = Lock()

def soundHeard(channel):
    if soundHeard_lock.acquire(False): #False so Lock.acquire() is non-blocking 
                                       # otherwise calling lock.acquire will wait until the 
                                       # lock is freed by whatever thread currently owns it
        #if the lock is successfully acquired (no other thread has ownership currently
        try:
            #handle event
        finally: #we want to release the lock even if something else goes wrong
            soundHeard_lock.release()
    #else: #do nothing, we didn't get ownership of the lock

GPIO.add_event_detect(mic1, GPIO.BOTH, bouncetime=500)
GPIO.add_event_callback(mic1, callback_dispatcher(soundHeard))

GPIO.add_event_detect(mic2, GPIO.BOTH, bouncetime=500)
GPIO.add_event_callback(mic2, callback_dispatcher(soundHeard))

**为清楚起见编辑

我使 callback_dispatcher 函数比您的情况所需的更复杂一些,以便使其更通用。一个更简单的版本可以直接用线程调用你的 soundHeard 函数而不创建闭包(函数内定义的函数)。

def soundHeard_thread(*args) #replaces callback_dispatcher
    # *args uses tuple packing to pass along any args provided by the event
    #   this is a very powerful tool that you should definitely learn to leverage
    #   if you want to take your python to the next level. A quick google search
    #   gave me this tutorial: https://www.geeksforgeeks.org/packing-and-unpacking-arguments-in-python/
    t = Thread(target=soundHeard, args=args) 
    t.start()

#...

GPIO.add_event_callback(mic1, soundHeard_thread)