You need to enable JavaScript to run this app. 如何用Matplotlib实现Arduino MKR1000实时数据的同图更新?
优惠活动
大模型
产品
解决方案
定价
更多

如何用Matplotlib实现Arduino MKR1000实时数据的同图更新?

问题核心原因

原有代码的运行逻辑存在两个会导致“每0.1秒生成全新绘图”观感的问题:

  • 循环内每次迭代都直接调用plt.plot(),没有固定的绘图对象引用,每次循环都会在画布上叠加新的图层,长期运行后图层堆积、渲染卡顿
  • 没有固定坐标轴的显示范围,每次新增数据时Matplotlib会自动全量缩放坐标轴,视觉上和“重新生成一张新图”的效果高度相似
修改后可实现同图持续更新的代码
import serial
import matplotlib.pyplot as plt
import numpy as np

# 初始化串口连接
ser = serial.Serial('COM7', 9600)
plt.close('all')

# 提前创建固定画布与坐标轴对象,避免后续重复创建画布
fig, ax = plt.subplots(figsize=[10,8])
# 初始化固定的空折线对象,后续不再重新创建新的绘图图层
line, = ax.plot([], [], lw=2)
# 启用Matplotlib交互模式
plt.ion()

# 根据Arduino实际输出的传感器值范围固定y轴,避免自动缩放跳动
ax.set_ylim(0, 1023)
# 初始x轴显示长度适配最近采集的100个数据点
ax.set_xlim(0, 100)

data = np.array([])

while True:
    # 读取串口数据并去除首尾换行、空白字符
    raw_content = ser.readline().decode().strip()
    try:
        # 截取有效数值部分转换为浮点数
        current_val = float(raw_content[0:4])
    except ValueError:
        # 跳过串口偶发的乱码、不完整数据,避免程序崩溃
        continue
    
    data = np.append(data, current_val)
    # 只保留最近100个数据点用于绘图,避免长时间运行内存占用过高
    display_data = data[-100:]
    # 直接更新现有折线的x、y坐标,而非重新绘制新线
    line.set_ydata(display_data)
    line.set_xdata(np.arange(len(display_data)))
    # 同步调整x轴显示范围,适配当前展示的数据长度
    ax.set_xlim(0, len(display_data))
    
    # 刷新画布内容,在原有图面基础上更新最新数据
    fig.canvas.draw()
    fig.canvas.flush_events()
    plt.pause(0.1)
关键优化点说明
  • 全程只创建1次画布、1次折线对象,所有数据更新操作都在原有对象上完成,不会生成新的独立绘图窗口
  • 固定y轴量程,避免新增数据时坐标轴自动缩放带来的突兀感
  • 增加串口数据的异常捕获逻辑,解决串口通信不稳定时程序直接崩溃的问题
  • 采用滑动窗口方式只展示最近固定长度的采集数据,避免累计数据量过大导致绘图卡顿

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 02:36:02