使用MatplotlibAnimation的Arduino Live Serial Plotting变慢

时间:2016-12-19 09:48:58

标签: python matplotlib arduino pyserial pyqtgraph

我正在制作一个实时绘图仪,以显示Arduino传感器的模拟变化。 Arduino以Baudrate 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()

在情节中获得正确的响应时间,但是当我绘制超过20分钟时,反应时间增加到约1分钟。即图表需要1分钟才能更新新值。我也试过PyQtGraph但是从一开始就推迟了。

除了超过20分钟的延迟时间外,我在剧情中遇到了一些过冲和下冲。

任何帮助?

2 个答案:

答案 0 :(得分:1)

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

  • 你会继续将传入的数据附加到你的数组,这会在一段时间后变得很大
  • 清除轴并在每次迭代时创建一个新的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。关于SO的问题也很多,已经回答了你的问题。例如,this answer包含使代码正常工作所需的所有元素。

答案 1 :(得分:0)

正如评论所指出的那样,从阵列中读取因其大小而自然变慢。波特率为9600时,我在 xar yar 变量中获得大约130个串行读数和每秒时间戳;在20分钟后得到156000的大小。将波特率降低到2400会将变量的长度减少到36000,并且可以很容易地重新绘制。