【问题标题】:plotting serial data using arduino and pyserial使用 arduino 和 pyserial 绘制串行数据
【发布时间】:2014-09-10 09:03:14
【问题描述】:

我正在尝试使用 arduino 和 pyserial、numpy 和 matplotlib 绘制加速度计的串行数据。问题是每当 GUI 打开时,传入的数据速率变得非常慢并且绘图也非常慢,如果我不打开 GUI 并简单地在命令窗口上打印数据,则接收到的数据很快。请帮忙!!

这是我的python代码:

import serial
import matplotlib.pyplot as plt
import numpy as np
import time


ser = serial.Serial('COM3', 9600, timeout=0) #sets up serial connection (make sure baud          rate is correct - matches Arduino)

ser.flushInput()
ser.flushOutput()

plt.ion()                    #sets plot to animation mode

length = 500       #determines length of data taking session (in data points)
x = [0]*length               #create empty variable of length of test
y = 0
z = 0
fig, ax = plt.subplots()
line, = ax.plot(np.random.randn(100))
plt.show(block=False)
xline, = plt.plot(x)         #sets up future lines to be modified
plt.ylim(30,120)        #sets the y axis limits

#for i in range(length):     #while you are taking data
tstart = time.time()
n = 0
while time.time()-tstart < 5:
   y = (ser.readline().decode('utf-8')[:-2])
   if not (len(y)==0):
       z = float(y)
       x.append(float(z))   #add new value as int to current list

       del x[0]

       xline.set_xdata(np.arange(len(x))) #sets xdata to new list length

       xline.set_ydata(x)                 #sets ydata to new list

       #  ax.draw_artist(ax.patch)
       #  ax.draw_artist(line)
       #  fig.canvas.update()
       fig.canvas.draw()
       fig.canvas.flush_events()   
       #plt.pause(0.0001)                   #in seconds                                      #draws new plot
       #plt.show()
       n +=1
       print (z)
       print(n)




 ser.close() #closes serial connection (very important to do this! if you have an error   partway through the code, type this into the cmd line to close the connection)

【问题讨论】:

  • 希望能帮您解答这个问题。我自己有 Arduino(s) 并且玩过(还没有 Python)。我无法确定减速/延迟的特定原因。您是否尝试过分析代码?

标签: python numpy matplotlib arduino pyserial


【解决方案1】:

有几件事可以加快这个过程。当我们尝试使用 arduino 读取地震检波器时,我们遇到了同样的问题。

主要技巧是在绘制之前缓冲十个或更多值,而不是为每个新事件绘制。

使用动画包代替手动绘制也可能加快进程。

看看我们的 github 代码: https://gist.github.com/ibab/10011590

你为什么要让 z 2 次浮动:

z = float(y)
x.append(float(z))

【讨论】:

    【解决方案2】:

    根据我的经验,用 10 000 个点重绘一条线可能需要 5 毫秒,但这取决于后端和计算机。如果你想更快地做到这一点,那么你就有麻烦了。另一方面,由于感知延迟,不需要或不合理地更新图形超过每秒 50 次。

    因此,正如MaxNoe 所说,如果数据是快速数据,您应该缓冲数据。您可以使用固定缓冲区,也可以使用超时缓冲区。 (看来您仍在接收稳定的数据流,否则ser.readline 会出现问题而没有超时。)

    您还可以采取其他一些措施来加快代码速度。在不知道数据量的情况下,我无法说这些是否会对性能产生任何实际影响。分析是关键(正如James Mills 所说)。

    首先,您应该将x 和y 设置为ndarray(NumPy 数组),以避免将列表转换为数组的开销。基本上:

    # initializing the array
    x = np.zeros(length)
    
    # adding one item to the array:
    # shift the existing items and add an item to the end
    x[:-1] = x[1:]
    x[-1] = float(z)
    

    另外,请注意,不需要每轮都set_xdata,因为xdata 保持不变。只需在循环之前执行一次即可。

    如果您最终使用缓冲,则基于时间的缓冲在每个刷新周期中大致以这种方式进行:

    databuf = []
    # collect data until you have something and at least 20 ms has gone
    t0 = time.time()
    while time.time() - t0 < 0.02 or len(databuf) == 0:
        ln = ser.readline()
        try:
            databuf.append(float(ln[:-2]))
        except:
            # something went wrong, but now we don't care
            pass
    
    n_newpoints = len(databuf)
    x[:-n_newpoints] = x[n_newpoints:]
    x[-n_newpoints:] = databuf
    
    # draw etc ...
    

    这里databuf是一个列表,但由于它是一个简短的列表,因此转换开销是微不足道的。

    通过这些改进,您应该能够流畅地更新包含 10000 个点的图表,而无需让计算机停止运行。如果您在性能非常低的机器(RaspberryPi 等)上执行此操作,那么秘诀就是降低更新频率。

    【讨论】:

      【解决方案3】:

      从 arduino 的串行端口绘制数据时,我遇到了类似的速度问题。解决方案在以下地址中描述:http://asaf.pm/wordpress/?p=113#comment-273 在这种情况下,我实现了大约 700fps 的速度来绘制一个包含 50 个数据点的数组。

      【讨论】:

        【解决方案4】:

        我认为您面临这些性能问题的主要原因是 matplotlib 并非主要用于实时数据。它在从脚本创建出色的数据图表方面确实很出色,但添加单个样本和重绘可能不是 matplotlib 的亮点。

        请考虑其他实时查看数据的选项,例如(无耻插件)lognplot:https://github.com/windelbouwman/lognplot

        可在此处找到另一个有用的实时数据查看程序列表:https://arduino.stackexchange.com/questions/1180/serial-data-plotting-programs

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-12
          • 1970-01-01
          • 1970-01-01
          • 2012-12-09
          • 1970-01-01
          • 2021-10-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多