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

求助:pyserial接收Arduino数据后输入缓冲区无法即时补充

解决PySerial接收Arduino串口数据延迟问题

我使用PySerial模块读取Arduino发送的串口数据,数据更新率约250Hz,单条数据包含29字节,波特率设置为230400。运行代码时发现,PySerial的输入缓冲区要等待约0.5秒才会自动从Arduino补充数据,请问如何实现数据接收后立即补充输入缓冲区?

我的代码如下:

import serial
import time 

ser = serial.Serial()
old = 0

while True:  # 修正原代码语法错误:添加冒号
    if ser.in_waiting > 29:
       print('buf: ', ser.readInputBuffer())
       new = time.perf_counter_ns()
       print(ser.readBinaryList(29))
       print('%.1f\n' % ((new - old)*1e-3))  # 修正原代码格式字符串语法错误
       old = new

# updated function definition_07/23
def readBinaryList(num):     # 修正原代码变量名:mum改为num
    data_r = ser.read(num)
    data_r = [i for i in data_r]   
    return data_r

def readInputBuffer():  # 修正原代码:移除多余的self参数
    return ser.in_waiting

解决方法

1. 正确初始化串口参数

原代码未指定串口核心参数,且默认阻塞模式会导致延迟。初始化时需明确配置非阻塞模式:

ser = serial.Serial(
    port='COM3',  # 根据你的Arduino实际串口端口修改
    baudrate=230400,
    timeout=0,  # 非阻塞模式,读取时立即返回当前缓冲区数据,不等待
    xonxoff=False,  # 禁用软件流控制
    rtscts=False,  # 禁用硬件流控制
    dsrdtr=False
)

timeout=0是核心设置,避免因等待填充缓冲区产生延迟。

2. 调整接收缓冲区大小

默认缓冲区可能过大,导致数据攒到一定量才触发读取,可设置略大于单条数据的缓冲区:

ser.set_buffer_size(rx_size=64)  # 大于单条29字节即可,减少数据累积

3. 优化读取逻辑

  • 函数定义需放在调用前,避免运行报错;
  • 每次读取后清空缓冲区残留数据,防止累积延迟;
  • 循环内持续检查缓冲区,有数据立即处理:
import serial
import time 

def readBinaryList(num):
    data_r = ser.read(num)
    return [i for i in data_r]

def readInputBuffer():
    return ser.in_waiting

# 初始化串口
ser = serial.Serial(
    port='COM3',
    baudrate=230400,
    timeout=0,
    xonxoff=False,
    rtscts=False
)
ser.set_buffer_size(rx_size=64)

old = time.perf_counter_ns()

while True:
    buf_size = readInputBuffer()
    if buf_size >= 29:
        print('buf: ', buf_size)
        data = readBinaryList(29)
        new = time.perf_counter_ns()
        print(data)
        print('%.1f\n' % ((new - old)*1e-3))
        old = new
        # 清空缓冲区剩余数据,避免累积
        if buf_size > 29:
            ser.read(buf_size - 29)

4. 检查Arduino端发送逻辑

确保Arduino发送严格的29字节二进制数据,避免使用Serial.println()(会添加换行符破坏数据结构),改用Serial.write()直接发送字节数组:

// Arduino示例代码
byte data[29];
// 填充29字节数据到data数组
Serial.write(data, 29);
Serial.flush();  // 强制立即发送数据,不滞留

内容的提问来源于Stack Exchange,提问作者Adam Shiau

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 17:36:21