使用arduino和pyserial加密串行数据

问题描述 投票:2回答:4

我正在尝试使用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)
python numpy matplotlib arduino pyserial
4个回答
0
投票

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

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

使用动画包而不是手动绘制也可能会加快该过程。

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

为什么要将z投2次以使其浮动:

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

0
投票

根据我的经验,以1万点重画一条线可能需要5毫秒,但这取决于后端和计算机。如果您尝试更快地执行此操作,那么您将遇到麻烦。另一方面,由于感知延迟,每秒更新图形超过50次是不需要的或不合理的。

因此,正如[C​​0]所说,如果数据是快速数据,则应该对其进行缓冲。您可以使用固定缓冲区,也可以使用具有超时的缓冲区。 (似乎您仍在接收稳定的数据流,否则在没有超时的情况下MaxNoe会遇到问题。)

同样,您还可以做一些其他的事情来加快代码的速度。在不知道数据量的情况下,我无法说出这些数据是否会对性能产生实际影响。概要分析是关键(正如ser.readline所说。)>

[第一件事是,您应该将James Millsx设为y(NumPy数组),以避免将列表转换为数组的开销。基本上:

ndarray

此外,请注意,由于# 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 ... 是一个列表,但由于它是一个简短列表,因此转换开销微不足道。

通过这些改进,您应该能够流畅地更新10000点的图形,而计算机不会停顿。如果您是在性能非常适中的机器(RaspberryPi等)上执行此操作的,则可以采用减少更新频率的方法。


0
投票

从arduino的串行端口绘制数据时,我也遇到了类似的速度问题。在以下地址中描述了该解决方案:databuf在这种情况下,通过绘制一个包含50个数据点的数组,我可以达到约700fps。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.