0

旨在响应树莓派按钮按下事件的单线程 python 程序还希望每分钟唤醒一次以更新 LCD 显示屏。

主功能:

btn_1 = 21
GPIO.setup(btn_1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(btn_1, GPIO.FALLING, callback=btn_1_press_callback, bouncetime=100)

lcd.display()
lcd.messsage("text to display on lcd"

每当按下物理按钮时,前面的代码都会运行 btn_1_press_callback 函数。main 函数的其余部分不是在繁忙的循环中休眠,而是执行以下操作:

signal.signal(signal.SIGALRM, wake_every_min)
signal.alarm(60)
signal.pause()

这样,按下按钮就会立即发出信号。wake_every_minute() 函数只是用当前显示的数据(从数据源更新)刷新显示,因此它每分钟更新一次,无论是否按下按钮:

def wake_every_min(sig, frame):
  lcd.clear()
  lcd.message("new string here")
  signal.alarm(60)
  signal.pause()

然后它调用 signal.pause() 来休眠/但再次监听信号。这非常有效,除了一段时间后,我得到了RecursionError: maximum recursion depth exceeded while calling a Python object

有趣的是它总是在同一时间,意思是“上一行重复 482 次”总是 482:

Traceback (most recent call last):
File "./info.py", line 129, in <module>
  main()
File "./info.py", line 126, in main
  signal.pause()
File "./info.py", line 111, in wake_every_min
  signal.pause()
File "./info.py", line 111, in wake_every_min
  signal.pause()
File "./info.py", line 111, in wake_every_min
  signal.pause()
[Previous line repeated 482 more times]

有没有另一种方法可以在没有while True循环的情况下完成这个time.sleep()?如果我这样做,按钮按下没有响应,因为总是有可能延迟 1.9999 分钟,最坏的情况。

4

1 回答 1

0

更新:我在想这个错误。time.sleep() 不会阻止信号的发生——信号会中断 sleep()。

正确的解决方案是在主循环中休眠,并且永远不要调用signal.pause()。使用 SIGINT 处理程序,您还可以在按下 ^c 时立即退出:

signal.signal(signal.SIGALRM, wake_every_min)
signal.alarm(60)
signal.signal(signal.SIGINT, int_signal_handler)
while True:
    # Sleep and wait for a signal.
    sleep(10)
    signal.alarm(60)

将警报的重新设置移动到主循环中可以防止 RecursionError,因为新信号不会从处理程序调用堆栈中堆积。如果有人好奇这是为了什么,那就是加密 LCD 代码:https ://github.com/manos/crypto_lcd/blob/master/info.py

于 2021-01-23T17:24:36.777 回答