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

如何使用Python实现串口实时数据的动画可视化绘图

串口实时绘图问题

我需要对串口传入的数据进行实时绘图,无需通过文件读写中转数据。我了解到需要单独开启一个线程实时接收串口数据,在线程运行过程中,animation.FuncAnimation需要每次获取串口数据并完成绘图渲染,但我不清楚如何编写数据传递逻辑让动画正常运行。

这就是我目前卡壳的地方,不知道如何编码实现数据交接让动画生效,我编写的代码如下:

import serial
import threading
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import itertools


def thread_data_gen():
    i = 0
    counter = itertools.count()

    ser = serial.Serial('/dev/tty.SLAB_USBtoUART', 1000000, timeout=1)  # 打开端口读取数据
    ser.reset_input_buffer()  # 清空输入缓冲区,丢弃所有缓存内容

    while True:
        ser_bytes = ser.readline()  # 逐行读取串口数据
        # 接收的行格式为 -> b'$ 32079 32079 32079 32079 32079 32079 32079 32079;\r\n'
        # 每个值代表一个数据通道,可测量扭矩、温度等参数
        # 当前所有值都设置为扭矩,所以数值完全一致
        # 共有8个可用数据通道

        decoded_bytes = ser_bytes.decode('utf-8')

        decoded_bytes = decoded_bytes.lstrip('$').rstrip().split()
        # 重新格式化为 ['32274', '32274', '32274', '32274', '32274', '32274', '32274', '32274;']

        if i == 0:
            i += 1
            continue
        # 跳过第一次读取结果,因为第一次传输的行为空,原因未知

        t = next(counter)  # 生成x轴数值
        y = decoded_bytes[0]  # 读取通道1的数值作为y轴数据
        yield t, y  # 尝试用生成器返回数据,但没有生效


def run(data):  # 接收thread_data_gen()返回的生成器数据
    t, y = data  # 报错TypeError:"cannot unpack non-iterable int object",不知道怎么修复
    # 我需要把运行线程里的while循环改成能返回可迭代整型数据的形式,但找不到解决方案
    
    xdata.append(t)  # 把数据加入x值列表
    ydata.append(y)  # 把数据加入y值列表
    line.set_data(xdata, ydata)  # 生成传给plt的数据集
    return line,


if __name__ == '__main__':
    dgen = threading.Thread(target=thread_data_gen)
    dgen.start()

    fig, ax = plt.subplots()
    line, = ax.plot([], [], lw=2)
    ax.grid()
    xdata, ydata = [], []

ani = animation.FuncAnimation(fig, run, interval=100)
plt.show()

更新

我已经自行解决了这个问题,最终的实现代码如下:

# 传动系统中的传感器升级联轴器通过蓝牙输出数据
# 数据包括:扭矩、力、温度和xyz三轴加速度
# 硬件网关通过天线接收数据
# 本代码的作用是读取硬件网关的串口数据并绘图,网关通过USB-C连接到笔记本
# USB-C转UART软件桥可以在MacOS或Windows系统上将数据映射为串口设备

import time
import serial
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import itertools


def data_gen():
    i = 0
    counter = itertools.count()  # 创建计数器

    ser = serial.Serial('/dev/tty.SLAB_USBtoUART', 1000000, timeout=1)  # 打开端口读取数据
    ser.reset_input_buffer()  # 清空输入缓冲区,丢弃所有缓存内容
    

    while True:
        # 逐行读取串口数据
        # 接收的行格式为 -> b'$ 32079 32079 32079 32079 32079 32079 32079 32079;\r\n'
        # 每个值代表一个数据通道,可测量扭矩、温度等参数
        # 当前所有值都设置为扭矩,所以数值完全一致
        # 共有8个可用数据通道
        ser_bytes = ser.readline()

        decoded_bytes = ser_bytes.decode('utf-8')

        # 重新格式化为列表 ['32274', '32274', '32274', '32274', '32274', '32274', '32274', '32274;']
        decoded_bytes = decoded_bytes.lstrip('$').rstrip().split()

        # 跳过第一次读取结果,因为第一次传输的行为空,原因未知
        if i == 0:
            i += 1
            continue

        t = next(counter)  # 生成x轴数值
        y = decoded_bytes[0]  # 读取通道1的数值作为y轴数据
        yield t, float(y)  # 返回绘图用的x和y值


def run(data):
    x, y = data
    y_cal = round(y * 0.00166, 1)  # 校准计算
    xdata.append(x)  # 把数据加入x值列表
    ydata.append(y_cal)  # 把数据加入y值列表
    line.set_data(xdata, ydata)  # 生成传给绘图的数据集
    return line,


if __name__ == '__main__':
    fig, ax = plt.subplots()  # 初始化画布和坐标轴
    line, = ax.plot([], [], lw=2)  # 初始化折线

    ax.set_ylim(40, 80)  # 设置y轴范围
    ax.set_xlim(0, 1000) # 设置x轴范围
    ax.grid()  # 生成网格

    xdata, ydata = [], []  # 创建空数据列表

    # frames参数:从串口连接接收生成的数据
    # run参数:提供折线绘图数据

    ani = animation.FuncAnimation(fig, run, frames=data_gen, blit=True, interval=10)
    plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 20:18:02