简体   繁体   English

使用 arduino 和 pyserial 绘制串行数据

[英]plotting serial data using arduino and pyserial

i'm trying to plot serial data of the accelerometer using arduino and pyserial,numpy and matplotlib.我正在尝试使用 arduino 和 pyserial、numpy 和 matplotlib 绘制加速度计的串行数据。 The problem is whenever the GUI opens, the incoming data rate becomes very slow and the plot is also very slow and if I don't open the GUI and simply print the data on the command window, the received data is fast.问题是每当 GUI 打开时,传入的数据速率变得非常慢,绘图也非常慢,如果我不打开 GUI 并简单地在命令窗口上打印数据,则接收到的数据很快。 Plz do help out!!请帮帮忙!!

Here's my code for python:这是我的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)

there are several things that could speed up the process.有几件事可以加快这个过程。 We had the same problems, when we tried to read out geophones using an arduino.当我们尝试使用 arduino 读取地震检波器时,我们遇到了同样的问题。

the main trick was to buffer ten or more values before plotting and not to plot for every single new event.主要技巧是在绘图之前缓冲十个或更多值,而不是为每个新事件绘图。

Using the animation package instead of manually drawing might also speed up the process.使用动画包而不是手动绘制也可能会加快该过程。

Have a look on our github code: https://gist.github.com/ibab/10011590看看我们的 github 代码: https : //gist.github.com/ibab/10011590

An why do you cast z 2 times to float:你为什么要施放 z 2 次来浮动:

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

In my experience, redrawing one line with 10 000 points takes maybe 5 milliseconds, but this depends on the backend and computer.根据我的经验,用 10 000 个点重绘一条线可能需要 5 毫秒,但这取决于后端和计算机。 If you are trying to do it much faster, then you are in trouble.如果你想做得更快,那么你就有麻烦了。 On the other hand, updating the graph more than, say, 50 times per second is not needed or reasonable due to perception delay.另一方面,由于感知延迟,不需要或合理地更新图形超过每秒 50 次。

So, as MaxNoe says, you should buffer the data, if it is fast data.因此,正如MaxNoe所说,您应该缓冲数据,如果它是快速数据。 You may either use a fixed buffer, or a buffer with timeout.您可以使用固定缓冲区或带超时的缓冲区。 (It seems that you are still receiving a steady stream of data, otherwise you'd have problems with the ser.readline without a timeout.) (似乎您仍在接收稳定的数据流,否则您将在没有超时的情况下遇到ser.readline问题。)

There are a few other things you might do to speed up your code, as well.您还可以执行其他一些操作来加速代码。 Without knowing the amount of data, I am unable to say whether these have any real performance impact or not.在不知道数据量的情况下,我无法说这些是否对性能有任何实际影响。 Profiling is the key (as James Mills says).分析是关键(正如James Mills所说)。

First thing is that you should have your x and y as ndarray (NumPy array) to avoid the overhead of converting lists to arrays.首先,您应该将xy作为ndarray (NumPy 数组),以避免将列表转换为数组的开销。 Basically:基本上:

# 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)

Also, note that there is no need to set_xdata every round, as the xdata remains constant.另请注意,无需set_xdata都设置set_xdata ,因为xdata保持不变。 Just do it once before the loop.在循环之前只做一次。

If you then end up with buffering, the time-based buffering goes approximately this way for each refresh cycle:如果您随后进行缓冲,则每个刷新周期的基于时间的缓冲大致如下:

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 ...

Here databuf is a list, but as it is a short list, the conversion overhead is insignificant.这里databuf是一个列表,但由于它是一个短列表,转换开销微不足道。

With these improvements you should be able to fluently update a graph of 10000 points without your computer grinding to a halt.通过这些改进,您应该能够流畅地更新 10000 个点的图形,而不会让您的计算机停止运行。 If you are doing this on a machine with very modest performance (RaspberryPi, etc.), then the recipe is to reduce the update frequency.如果您在性能非常适中的机器(RaspberryPi 等)上执行此操作,则方法是降低更新频率。

I had a similar problem of speed when plotting data from a serial port of arduino.从 arduino 的串行端口绘制数据时,我遇到了类似的速度问题。 The solution is described in the following addresss: http://asaf.pm/wordpress/?p=113#comment-273 In this case I achieve about 700fps plotting an array with 50 points of data.解决方案在以下地址中进行了描述: http://asaf.pm/wordpress/?p=113#comment-273在这种情况下,我实现了大约 700fps 绘制具有 50 个数据点的数组。

I think the primary reason why you face these performance issues, is that matplotlib is not primarily intended for live data.我认为您面临这些性能问题的主要原因是 matplotlib 并非主要用于实时数据。 It really shines in creating excellent charts of data from a script, but adding a single sample and redrawing might not be an area where matplotlib shines.从脚本创建出色的数据图表确实很出色,但是添加单个样本和重绘可能不是 matplotlib 的优势所在。

Please consider other options for live viewing of data, such as (shameless plug) lognplot: https://github.com/windelbouwman/lognplot请考虑其他实时查看数据的选项,例如(无耻插件)lognplot: https : //github.com/windelbouwman/lognplot

Another helpful list of programs for live data viewing can be found here: https://arduino.stackexchange.com/questions/1180/serial-data-plotting-programs另一个有用的实时数据查看程序列表可以在这里找到: https : //arduino.stackexchange.com/questions/1180/serial-data-plotting-programs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM