You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:03:33