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

串口数据动态绘图延迟过高问题优化求助

实时绘图延迟优化方案

核心问题原因

你的代码延迟主要来自以下冗余设计:

  • 每次收到新数据都调用plt.cla()清空画布后重绘全量历史数据,执行耗时会随数据量增长线性上升,运行越久延迟越高
  • 强制添加plt.pause(0.05)固定50ms暂停,每秒最多只能刷新20次,延迟会持续累积
  • 绘图操作和串口读取强绑定,数据刷新率高时会触发大量无效重绘

优化后实现代码

import serial
import time
import matplotlib.pyplot as plt

# 配置参数
MAX_SHOW_POINTS = 100  # 最多显示最近100个数据点,可根据需要调整
REFRESH_INTERVAL = 0.02  # 绘图刷新间隔20ms,可根据帧率需要调整
COM_PORT = 'COM6'
BAUD_RATE = 2000000

# 初始化变量
start = time.time()
x = []
y = []
last_refresh_time = start

# 初始化串口
ser = serial.Serial(COM_PORT, BAUD_RATE, timeout=0)
time.sleep(2)

# 初始化绘图对象,只创建一次曲线
plt.ion()
fig, ax = plt.subplots()
line, = ax.plot([], [], 'red')  # 提前创建Line2D对象,后续只更新数据
ax.set_xlabel('流逝时间(s)')
ax.set_ylabel('传感器数值')

# 预先启动画布渲染
fig.canvas.draw()
plt.show(block=False)
# 缓存背景,加快刷新速度
background = fig.canvas.copy_from_bbox(ax.bbox)

while True:
    # 优先处理串口数据读取
    line_data = ser.readline()
    if line_data:
        try:
            num = float(line_data.decode().strip())
        except (ValueError, UnicodeDecodeError):
            # 跳过解析失败的脏数据
            continue
        time_elapsed = time.time() - start
        x.append(time_elapsed)
        y.append(num)
        
        # 限制数据列表长度,只保留最近MAX_SHOW_POINTS个点
        if len(x) > MAX_SHOW_POINTS:
            x.pop(0)
            y.pop(0)
    
    # 按设定间隔刷新绘图,和数据读取解耦
    current_time = time.time()
    if current_time - last_refresh_time >= REFRESH_INTERVAL:
        # 增量更新曲线数据,不重绘整张画布
        line.set_data(x, y)
        # 自适应调整坐标轴范围
        ax.relim()
        ax.autoscale_view()
        # 快速刷新画布
        fig.canvas.restore_region(background)
        ax.draw_artist(line)
        fig.canvas.blit(ax.bbox)
        # 处理画布事件,避免界面无响应
        fig.canvas.flush_events()
        last_refresh_time = current_time

关键优化点说明

  • 提前创建Line2D对象,后续仅更新曲线数据,不需要每次清空重绘,刷新效率提升数倍
  • 限制显示的最大数据量,避免数据列表无限膨胀导致的性能下降;如果需要保留全量历史数据做后续分析,可额外定义列表存储所有数据,绘图仅使用裁剪后的最近N个点即可
  • 绘图刷新和串口读取逻辑解耦,既保证数据不丢,也控制绘图调用频率不会过高
  • 使用blit机制增量刷新画布,仅更新曲线变动的区域,减少冗余渲染开销
  • 移除了plt.pause固定延迟,仅保留必要的界面事件处理逻辑
  • 可选优化:如果传感器数值范围和观测时间窗口固定,可以预先设置ax.set_ylim(最小值, 最大值)、ax.set_xlim(0, 观测窗口时长),去掉ax.relim()和ax.autoscale_view()调用,刷新效率会更高

内容的提问来源于stack exchange,提问作者user3643087

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 14:06:02