树莓派三轮机器人传感器数据读取与运动控制故障排查
三轮机器人前进/停止控制循环逻辑问题修复
你的核心问题是内层while循环阻塞了串口数据读取:当drive = True时,程序会进入while drive == true:的死循环,一直执行forward(),再也不会回到外层循环去读取Arduino发送的传感器数据,导致机器人一旦启动就无法响应新的距离检测结果。
同时代码里还有几处语法和逻辑错误,以下是完整的修正方案:
错误点与修正说明
- 循环逻辑重构:移除内层while循环,把前进动作放到主循环中,每次主循环先读取串口数据,再根据
drive状态决定是否执行前进步骤,保证串口数据能被持续读取。 - 语法错误修正:
- Python布尔值区分大小写,
true改为True ser.flush改为ser.flush()(调用方法需要加括号)- 关键字
If改为小写if - 拼写错误:
STEPS改为STEP3,修复引脚引用错误 - 重复引脚操作:
forward()和stop()中重复设置STEP的LOW状态,改为操作STEP3
- Python布尔值区分大小写,
- GPIO使能引脚初始化:添加EN引脚的低电平输出,启用步进电机(多数步进驱动器低电平启用)
- 函数优化:
stop()函数无需重复设置方向,直接关闭所有步进脉冲即可;forward()中的方向设置移到初始化阶段,避免重复调用浪费资源
修正后的完整代码
import RPi.GPIO as GPIO from time import sleep import serial if __name__ == '__main__': ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1) ser.flush() # 修正:调用flush方法 # 引脚定义 DIR = 17 DIR2 = 24 DIR3 = 6 STEP = 27 STEP2 = 23 STEP3 = 5 EN = 22 EN2 = 25 EN3 = 13 CW = 1 CCW = 0 # GPIO初始化 GPIO.setmode(GPIO.BCM) # 配置所有引脚为输出 GPIO.setup(DIR, GPIO.OUT) GPIO.setup(STEP, GPIO.OUT) GPIO.setup(EN, GPIO.OUT) GPIO.setup(DIR2, GPIO.OUT) GPIO.setup(STEP2, GPIO.OUT) GPIO.setup(EN2, GPIO.OUT) GPIO.setup(DIR3, GPIO.OUT) GPIO.setup(STEP3, GPIO.OUT) GPIO.setup(EN3, GPIO.OUT) # 启用步进电机(低电平启用) GPIO.output(EN, GPIO.LOW) GPIO.output(EN2, GPIO.LOW) GPIO.output(EN3, GPIO.LOW) # 初始化前进方向 GPIO.output(DIR, CCW) GPIO.output(DIR2, CW) GPIO.output(DIR3, CW) drive = False def forward(): # 发送步进脉冲 GPIO.output(STEP, GPIO.HIGH) GPIO.output(STEP2, GPIO.HIGH) GPIO.output(STEP3, GPIO.HIGH) # 修正:STEPS改为STEP3 sleep(0.000008) GPIO.output(STEP, GPIO.LOW) GPIO.output(STEP2, GPIO.LOW) GPIO.output(STEP3, GPIO.LOW) # 修正:重复的STEP改为STEP3 sleep(0.000008) def stop(): # 停止所有步进脉冲 GPIO.output(STEP, GPIO.LOW) GPIO.output(STEP2, GPIO.LOW) GPIO.output(STEP3, GPIO.LOW) try: while True: # 优先读取串口数据 if ser.in_waiting > 0: line = ser.readline().decode('utf-8').rstrip('\0') try: convert = int(line) if convert < 20: stop() print('stop') drive = False else: drive = True except ValueError: # 处理串口数据格式错误 print(f"无效数据: {line}") drive = False # 根据drive状态执行前进动作 if drive: forward() finally: # 程序退出时清理GPIO GPIO.cleanup() ser.close()
额外说明
- 添加了
try-finally块,确保程序退出时能正确清理GPIO和关闭串口,避免引脚状态异常 - 增加了串口数据的异常捕获,防止非整数格式的数据导致程序崩溃
- 步进电机的延时时间(
sleep(0.000008))可以根据实际电机转速需求调整,数值越小转速越快
内容的提问来源于stack exchange,提问作者Norman
相关产品推荐
相关产品推荐

