PySerial与Arduino通信故障:调用inWaiting()时程序挂起
我来帮你搞定这个串口通信的坑!这种单步调试正常但运行时挂起的情况,大概率和串口配置、同步逻辑或者PySerial的使用方式有关,咱们一步步排查:
1. 先把PySerial的超时配置拉满
PySerial默认的超时是None(无限等待),这很容易导致某些操作卡住。你一定要在初始化串口时明确设置超时参数,比如:
import serial # 1秒超时,避免无限阻塞 ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
如果用的是树莓派原生串口,路径可能是/dev/ttyAMA0,别搞混了。
2. 核对Arduino和树莓派的同步逻辑
先确认Arduino的setup()代码是正确等待指令的,比如:
void setup() { Serial.begin(9600); // 等待树莓派发指令,加个小延迟避免空转 while (!Serial.available()) { delay(10); } // 读取指令(比如读取换行符结束的指令) String cmd = Serial.readStringUntil('\n'); // 给树莓派发确认回复 Serial.println("Arduino Ready"); } void loop() { // 这里是你要发送的数据,比如传感器值 Serial.println(analogRead(A0)); delay(100); }
对应的树莓派代码必须严格遵循先发指令→等回复→再收数据的顺序,要是搞反了(比如先等回复再发指令),肯定会挂起。
3. 别误用inWaiting()导致阻塞
很多人会写这种代码:
# 错误示例:无限循环等数据,看似没挂起但会占满CPU while ser.inWaiting() == 0: pass
如果是真的调用inWaiting()时挂起,那大概率是串口没正确初始化,或者系统把串口占用了。这时候可以试试用select模块来替代,实现非阻塞监听:
import serial import select ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=0) # 非阻塞模式 # 先给Arduino发启动指令 ser.write(b"Start\n") # 等待Arduino的回复 while True: # 用select监听串口,1秒超时 ready, _, _ = select.select([ser], [], [], 1) if ready: response = ser.readline().decode('utf-8').strip() if response == "Arduino Ready": print("收到Arduino确认,开始接收数据") break # 开始记录数据 while True: if ser.inWaiting() > 0: data = ser.readline().decode('utf-8').strip() print(f"收到数据:{data}") # 写入文件记录 with open("sensor_data.log", "a") as f: f.write(f"{data}\n")
4. 排查树莓派的串口硬件和权限问题
这是新手常踩的坑:
- 确保你的用户属于
dialout组,不然没权限访问串口:
执行完记得重启生效。sudo usermod -aG dialout pi - 禁用串口控制台:打开
raspi-config,选「Interface Options」→「Serial Port」,第一个问题(是否启用串口控制台)选「No」,第二个(是否启用串口硬件)选「Yes」,重启树莓派。
5. 调试小技巧
- 在树莓派代码里加打印日志,精准定位卡在哪一步:
这样就能确认是不是真的在print("准备检查串口缓冲...") buffer_size = ser.inWaiting() print(f"串口缓冲字节数:{buffer_size}")inWaiting()这里挂起,还是后续的读取操作出问题。 - 用PySerial的工具确认串口设备存在:
from serial.tools import list_ports for port in list_ports.comports(): print(f"设备:{port.device},描述:{port.description}")
内容的提问来源于stack exchange,提问作者user4984565
相关产品推荐
相关产品推荐

