树莓派Zero W机器人车BlueDot控制:后退循环阻塞按钮释放事件问题
解决方案
问题根源是backward()中的while循环阻塞了主线程,导致BlueDot的按键释放事件无法被及时处理。以下是两种可行的解决方法:
方法一:使用线程分离后退逻辑
把后退的循环逻辑放到独立线程中执行,让主线程能持续响应BlueDot的事件:
from bluedot import BlueDot from gpiozero import Robot, DistanceSensor from time import sleep import threading robot = Robot(left=(20,21), right=(12,16)) back_sensor = DistanceSensor(echo=25, trigger=8) run = False def backward_loop(): global run while run and back_sensor.distance * 100 >= 20: robot.backward() sleep(0.01) # 加短延时,降低CPU占用同时给主线程留处理时间 robot.stop() def backward(): global run run = True # 启动线程执行后退循环 threading.Thread(target=backward_loop, daemon=True).start() def stop(): global run run = False robot.stop() print("stopped") bd = BlueDot() bd[1,2].when_pressed = backward bd[1,2].when_released = stop
关键修改点:
- 导入
threading模块,将后退的循环逻辑移到backward_loop函数中 - 按下按键时启动一个守护线程执行循环,主线程不会被阻塞
- 循环中加入
sleep(0.01),既减少CPU占用,也让主线程有机会处理按键释放事件 - 释放按键时直接设置
run=False,线程会在下一次循环检测时终止
方法二:使用BlueDot的状态检测结合非阻塞循环
利用BlueDot的按键状态检测,在循环中定期检查释放状态和传感器数据:
from bluedot import BlueDot from gpiozero import Robot, DistanceSensor from time import sleep robot = Robot(left=(20,21), right=(12,16)) back_sensor = DistanceSensor(echo=25, trigger=8) def backward(): try: # 同时等待按键释放或距离过近 while back_sensor.distance * 100 >= 20: robot.backward() # 检查按键是否被释放 if not bd[1,2].is_pressed: break sleep(0.01) finally: robot.stop() def stop(): robot.stop() print("stopped") bd = BlueDot() bd[1,2].when_pressed = backward bd[1,2].when_released = stop
关键修改点:
- 循环中定期检查
bd[1,2].is_pressed状态,一旦按键释放就终止循环 - 用
try...finally确保无论循环因何终止,机器人都会停止
两种方法都能解决阻塞问题,方法一更灵活,适合后续扩展其他传感器逻辑;方法二更简洁,依赖BlueDot的内置状态检测。
内容的提问来源于stack exchange,提问作者AndrewSae
相关产品推荐
相关产品推荐

