Arduino Live Serial Plotting with a MatplotlibAnimation 变慢

Arduino Live Serial Plotting with a MatplotlibAnimation gets slow

我正在制作一个实时绘图仪来显示来自 Arduino 传感器的模拟变化。 Arduino 以 9600 的波特率向串口打印一个值。Python 代码如下所示:

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

ser = serial.Serial("com3", 9600)
ser.readline()

optimal_frequency = 100

fig = plt.figure(figsize=(6, 6))
ax1 = fig.add_subplot(1, 1, 1)

# the following arrays must be initialized outside the loop

xar = []
yar = []

print(time.ctime())

def animate(i):
    global b, xar, yar # otherwise a

    for i in range(optimal_frequency):

        a = str(ser.readline(), 'utf-8')
        try:
            b = float(a)
        except ValueError:
            ser.readline()
        xar.append(str(time.time()))
        yar.append(b)
    ax1.clear()
    ax1.plot(xar, yar)

ani = animation.FuncAnimation(fig, animate, interval=optimal_frequency)
plt.show()

A 在绘图中获得了不错的响应时间,但是当我绘制超过 20 分钟时,反应时间增加到大约 1 分钟。 IE。图表需要 1 分钟才能更新为新值。我也尝试过使用 PyQtGraph,但从一开始就延迟了。

除了超过 20 分钟的延迟外,我在情节中出现了一些过冲和下冲。

有什么帮助吗?

如评论中所述,您做错了两件事:

  • 您不断将传入数据附加到数组,一段时间后这些数据会变得很大
  • 您清除轴并在每次迭代时创建一个新的 ax.plot()

你想做的是:

在初始化函数中,创建一个空的 Line2D 对象

def init():
    line, = ax.plot([], [], lw=2)
    return line,

然后在您的更新函数 (animate()) 中,您使用 line.set_data() 来更新您的点的坐标。但是,为了保持性能,您必须将数组的大小保持在合理的大小,因此当新数据进来时您将不得不删除旧数据

def animate(i):
    (...)
    xar.append(str(time.time()))
    yar.append(b)
    line.set_data(xar, yar)
    return line,

查看一些教程like this one. There are also plenty of questions on SO that already answers your question. For instance, this answer 包含让您的代码正常工作所需的所有元素。

正如评论中提到的那样,由于数组很大,读取数组的速度自然会变慢。波特率为 9600 时,我在 xaryar 变量中每秒获得大约 130 个串行读数和时间戳; 20 分钟后大小为 156000。将波特率降低到 2400 会将变量的长度减少到 36000,这可以很容易地重新绘制。