如何使用 gpiozero 按钮方法检查某个按钮何时被按下
How to use gpiozero button methods to check when a button is pressed at a certain time
我目前正在做一个小项目,开始使用 Python 进行物理计算 - 使用 raspberry pi。我正在尝试使用 3 个 LED 和一个按钮制作游戏。 3 个 LED 将按特定顺序闪烁不同时间,您必须在琥珀色 LED 亮起时单击按钮。到目前为止,我已经使用 gpiozero 尝试了这段代码来识别按钮何时打开,并查看它是否在琥珀色 LED 灯打开的时间范围内。
游戏代码:https://codeshare.io/G7qk1j
(如果以上 link 不起作用请告诉我)
代码:
def gameEasy():
print("Level 1 - trial run")
how_long_to_react = 5
time_till_started = time.time() + 4
while time.time() < time_till_started:
button.when_pressed = None
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
redLed.on()
time.sleep(2)
redLed.off()
amberLed.on()
ambTime = time.time()
greenTime = ambTime + how_long_to_react
time.sleep(how_long_to_react)
amberLed.off()
greenLed.on()
time.sleep(0.1)
greenLed.off()
time.sleep(10)
目前,为了让它工作,首先,红色 LED 将亮起 2 秒,然后琥珀色 LED 将亮起(目前为 4 秒只是为了测试)。当琥珀色 LED 亮起时,即第一次被记录下来,稍后将检查按钮是否在该范围内被单击。我的问题是,如果在计算此变量 (ambTime) 之前单击按钮,则第 58 行将触发错误:
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
NameError: free variable 'ambTime' referenced before assignment in enclosing scope
我明白为什么会这样,但我不确定如何 'block' 在琥珀色 LED 亮起之前点击任何按钮。如您所见,我有一个 while 循环试图在前 4 秒内阻止任何命令,但它充当延迟而不是后台循环(因此它直到 4 秒后才会启动下一个代码)。
我注意到这个方法 - button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
- 它总是检查按钮按下,不管这行在代码中的什么地方,所以我是否放这行都没关系就在 amberLed.on()
之前
我希望我已经解释清楚了,这一直困扰着我很长一段时间,所以任何帮助都将不胜感激。我已经尝试过 multiprocessing 但对如何在此处集成它感到非常困惑,但我愿意接受任何建议。我完全理解您可能无法测试您的代码,因此我很乐意尝试任何事情并回应出现的任何问题(如果有的话)。
谢谢。
如您所见; 运行...
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
...立即启动一个线程来监视按钮点击,如果
您的 lambda
函数在定义 ambTime
之前运行,它将失败。
最简单的解决方案可能是将 ambTime
初始化为某个值
在设置 button.when_pressed
操作之前,例如:
def gameEasy():
...
ambTime = None
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
...
并且在您的 clickedRight
函数中,明确检查是否
ambTime
具有有效值。可能是这样的:
def clickedRight(led_clicked_time, led_after_turnedon_time, button_time):
if led_clicked_time is not None and (
button_time >= led_clicked_time and
button_time <= led_after_turnedon_time
):
print("Yay")
else:
print("Missed")
button.when_pressed = None
我目前正在做一个小项目,开始使用 Python 进行物理计算 - 使用 raspberry pi。我正在尝试使用 3 个 LED 和一个按钮制作游戏。 3 个 LED 将按特定顺序闪烁不同时间,您必须在琥珀色 LED 亮起时单击按钮。到目前为止,我已经使用 gpiozero 尝试了这段代码来识别按钮何时打开,并查看它是否在琥珀色 LED 灯打开的时间范围内。
游戏代码:https://codeshare.io/G7qk1j (如果以上 link 不起作用请告诉我)
代码:
def gameEasy():
print("Level 1 - trial run")
how_long_to_react = 5
time_till_started = time.time() + 4
while time.time() < time_till_started:
button.when_pressed = None
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
redLed.on()
time.sleep(2)
redLed.off()
amberLed.on()
ambTime = time.time()
greenTime = ambTime + how_long_to_react
time.sleep(how_long_to_react)
amberLed.off()
greenLed.on()
time.sleep(0.1)
greenLed.off()
time.sleep(10)
目前,为了让它工作,首先,红色 LED 将亮起 2 秒,然后琥珀色 LED 将亮起(目前为 4 秒只是为了测试)。当琥珀色 LED 亮起时,即第一次被记录下来,稍后将检查按钮是否在该范围内被单击。我的问题是,如果在计算此变量 (ambTime) 之前单击按钮,则第 58 行将触发错误:
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
NameError: free variable 'ambTime' referenced before assignment in enclosing scope
我明白为什么会这样,但我不确定如何 'block' 在琥珀色 LED 亮起之前点击任何按钮。如您所见,我有一个 while 循环试图在前 4 秒内阻止任何命令,但它充当延迟而不是后台循环(因此它直到 4 秒后才会启动下一个代码)。
我注意到这个方法 - button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
- 它总是检查按钮按下,不管这行在代码中的什么地方,所以我是否放这行都没关系就在 amberLed.on()
我希望我已经解释清楚了,这一直困扰着我很长一段时间,所以任何帮助都将不胜感激。我已经尝试过 multiprocessing 但对如何在此处集成它感到非常困惑,但我愿意接受任何建议。我完全理解您可能无法测试您的代码,因此我很乐意尝试任何事情并回应出现的任何问题(如果有的话)。
谢谢。
如您所见; 运行...
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
...立即启动一个线程来监视按钮点击,如果
您的 lambda
函数在定义 ambTime
之前运行,它将失败。
最简单的解决方案可能是将 ambTime
初始化为某个值
在设置 button.when_pressed
操作之前,例如:
def gameEasy():
...
ambTime = None
button.when_pressed = lambda:clickedRight(ambTime, greenTime, time.time())
...
并且在您的 clickedRight
函数中,明确检查是否
ambTime
具有有效值。可能是这样的:
def clickedRight(led_clicked_time, led_after_turnedon_time, button_time):
if led_clicked_time is not None and (
button_time >= led_clicked_time and
button_time <= led_after_turnedon_time
):
print("Yay")
else:
print("Missed")
button.when_pressed = None