You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移除print语句后树莓派GPIO事件为何触发两次?

问题原因分析

这是按键机械抖动+回调执行时间差异导致的,具体逻辑如下:

  1. 物理按键按下时,金属触点会有短暂的机械回弹,产生多次电平跳变(也就是抖动),持续时间通常在几十到几百毫秒不等。
  2. 你设置的bouncetime=1000是RPi.GPIO的软件防抖机制,本意是触发一次中断后,忽略1000ms内的后续边缘触发,但这个机制有个特点:当回调函数正在执行时,防抖计时是暂停的。
  3. 保留print("BUTTON PRESSED")时,加上subprocess.Popen读取子进程输出的阻塞操作,整个回调的执行时间会超过按键抖动的持续时间。等回调执行完毕,抖动已经结束,自然不会触发第二次中断。
  4. 移除print语句后,回调的执行时间大幅缩短,第一次回调跑完时,按键的抖动还没停止。此时防抖计时重新启动,抖动产生的第二次FALLING电平跳变就会触发第二次回调。
解决办法
  • 给回调加短暂延迟,直接覆盖抖动时间:
    在subprocess.Popen之前或之后加一行time.sleep(0.2)(200ms足够覆盖绝大多数按键抖动)。
  • 改用硬件防抖:在GPIO19引脚和GND之间并联一个0.1μF的陶瓷电容,从根源上消除抖动。
  • 调整bouncetime参数:把bouncetime从1000改成200-300(足够覆盖抖动,又不影响响应速度),同时确保回调执行时间不会超过这个值。
  • 手动加防抖标志:在回调外定义一个全局变量,每次回调先检查时间间隔,小于阈值就直接返回:
    last_trigger = 0
    def interrupt(channel):
        global last_trigger
        now = time.time()
        if now - last_trigger < 0.2:
            return
        last_trigger = now
        p = subprocess.Popen(['node', '/btn.js', str(channel)], stdout=subprocess.PIPE)
        out = p.stdout.read()
        print(out)
    

内容的提问来源于stack exchange,提问作者Raed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:22:21