如何解决串行通讯中的绘图问题?

时间:2019-01-12 06:17:42

标签: python python-3.x python-2.7 matplotlib serial-port

下面是简单的代码:

#import serial
from tkinter import *
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import serial

fig = plt.gcf()
fig.show()
fig.canvas.draw()



ser = serial.Serial('COM35', 115200, timeout=.1)
while True:
  data = ser.readline()
  print(data)
  plt.plot(data)
  fig.canvas.draw()

现在,当我运行此程序时,我得到的是这样的图片。.enter image description here
数据值就是这样enter image description here

但是我需要输出类似这样的东西(它是连续图)。enter image description here

但是在将 list 关键字添加到list(ser.readline())上后,出现此错误。enter image description here

2 个答案:

答案 0 :(得分:1)

此答案不如使用animation-api优雅-可以。

您必须进行很多调整-为了提供Minimal, Complete, and Verifiable example,我必须实现自己的“串行”数据提供程序:

from itertools import cycle 
data = [0,0,0,0,0,0,0,0,0,2,25,64,92,119,132,139,124,123,103,71,38,3]
cyc = cycle(data)

def serial():
    from random import randint
    def create_data():
        for k in range(randint(2,3)): 
            yield next(cyc) 
    return list(create_data())

一种解决方法:

您还需要获取绘图的轴以调整显示的“区域”,然后需要提供正确的x值作为“时间”,并提供y值作为从串行读取的值(您可以在时间)的每次绘制中增加一个“接收到多少数据”变量:

from tkinter import *
from matplotlib import pyplot as plt 


fig, ax = plt.subplots() 
ax.set_ylim(-200, 200)
ax.set_xlim(0,110)
fig.show()
fig.canvas.draw() 

time = 0
last = 0
while True:
    # "animate" x-axis
    if time > 100:
        ax.set_xlim(time-100,time+10)
    data = serial()
    print(data)
    # add the last datapoint again so you get a continuous curve
    plt.plot([time-1]+[time+x for x in range(len(data))], [last]+data)
    # increment time
    time += len(data)
    # remember last data-value
    last = data[-1]
    fig.canvas.draw()

要获取(省略了文本输出-只是从不同的分块重复上面的数据):

animation

您可以通过彩色线段看到哪些数据已添加在一起。

答案 1 :(得分:0)

您还可以更改为使用matplotlib的animation模块-此答案在很大程度上受tacaswell answerHow to update values from serial port in matplotlib animations?的启发

相同的数据生成器:

from itertools import cycle 
data = [0,0,0,0,0,0,0,0,0,2,25,64,92,119,132,139,124,123,103,71,38,3]
cyc = cycle(data)

def serial():
    from random import randint
    def create_data():
        for k in range(randint(2,3)): 
            yield next(cyc) 
    return list(create_data())

from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np

fig = plt.figure()
ax = plt.axes(xlim=(0, 150), ylim=(-200, 200)) 
max_points = 150
# fill initial artist with nans (so nothing draws)
line, = ax.plot(np.arange(max_points), 
                np.ones(max_points, dtype=np.float)*np.nan, 
                lw=2)
def init():
    return line,

def animate(i):
    y = serial() # arduino.readline()
    old_y = line.get_ydata()               # adjusted here for this question data, coming
    new_y = np.r_[old_y[len(y):], y]       # in as chunks rather then single values
    line.set_ydata(new_y)
    return line,


anim = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=False) 
plt.show()

对@tacaswell代码进行的改编是由于以下事实:此问题数据对输出图形需要其他限制,并且此问题的数据提供了多个分块的数据点,而不是单个价值观。 def animate(i)中的“数据刷新”必须为此进行修改。