Matplotlib - 来自串行数据的多个图

时间:2017-07-24 14:38:53

标签: python matplotlib serial-port

我正在使用串行通信从4个不同的传感器读取数据,并希望在单独的图中绘制每个传感器数据。我的代码是:

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

connected = False

comPort = 'COM4'        

ser = serial.Serial(comPort, 115200)    # Sets up serial connection (make sure baud rate is correct - matches Arduino)

while not connected:
    serin = ser.read()
    connected = True

plt.ion()                               # Sets plot to animation mode

fig1 = plt.figure()
fig2 = plt.figure()
fig3 = plt.figure()
fig4 = plt.figure()

length = 20                             # Determines length of data taking session (in data points); length/10 = seconds

w = [0]*length                          # Create empty variable of length of test
x = [0]*length               
y = [0]*length
z = [0]*length

wline, = plt.plot(w)                    # Sets up future lines to be modified
xline, = plt.plot(x)                    
yline, = plt.plot(y)
zline, = plt.plot(z)

plt.ylim(0,64535)                       # Sets the y axis limits - 16 bits resolution

for i in range(length):                 # While you are taking data
    data = ser.readline()               # Reads until it gets a carriage return (/n).
    sep = data.split()                  # Splits string into a list at the tabs

    w.append(int(sep[0]))               # Add new values as int to current list
    x.append(int(sep[1]))   
    y.append(int(sep[2]))
    z.append(int(sep[3]))

    del w[0]
    del x[0]
    del y[0]
    del z[0]

    wline.set_xdata(np.arange(len(w)))  # Sets wdata to new list length  
    xline.set_xdata(np.arange(len(x)))  
    yline.set_xdata(np.arange(len(y)))  
    zline.set_xdata(np.arange(len(z)))  

    wline.set_ydata(w)                  # Sets ydata to new lists 
    xline.set_ydata(x)                 
    yline.set_ydata(y)
    zline.set_ydata(z)

    print i
    print sep

    ax1 = fig1.add_subplot(111)
    ax1.plot(wline.set_ydata(w))
#    ax1.plot(sep[0])
    plt.pause(0.001)                   
    plt.grid(True)
    plt.draw()                         # Draws new plot

    ax2 = fig2.add_subplot(111)
    ax2.plot(xline.set_ydata(x))
    plt.pause(0.001)                   
    plt.grid(True)
    plt.draw()                         # Draws new plot

    ax3 = fig3.add_subplot(111)
    ax3.plot(yline.set_ydata(y))
    plt.pause(0.001)                   
    plt.grid(True)
    plt.draw()                         # Draws new plot

    ax4 = fig4.add_subplot(111)
    ax4.plot(zline.set_ydata(z)) 
    plt.pause(0.001)                   
    plt.grid(True)
    plt.draw()                         # Draws new plot

plt.show()

ser.close()                             # Closes serial connection

正确采集数据并生成4个数字,但只有最后一个数据正在绘制数据。此外,它正在绘制所有4个传感器,其他子图的Y轴也是错误的(请参阅输出屏幕截图)。我也打印包含数据的数组(“print sep”),以检查数据是否存在。

Screenshot of the program output

我错过了一些明显的东西吗? 非常感谢你的帮助

1 个答案:

答案 0 :(得分:1)

当您创建4行时,它们将全部在活动图上创建(即在这种情况下,您创建的最后一行)。

您可以将4个子绘图轴的创建移动到循环之前,然后在正确的轴上创建matplotlib线实例(使用面向对象的ax.plot而不是plt.plot)。然后,他们将出现在正确的数字上。

fig1 = plt.figure()
fig2 = plt.figure()
fig3 = plt.figure()
fig4 = plt.figure()

ax1 = fig1.add_subplot(111)
ax2 = fig2.add_subplot(111)
ax3 = fig3.add_subplot(111)
ax4 = fig4.add_subplot(111)

length = 20                             # Determines length of data taking session (in data points); length/10 = seconds

w = [0]*length                          # Create empty variable of length of test
x = [0]*length               
y = [0]*length
z = [0]*length

wline, = ax1.plot(w)                    # Sets up future lines to be modified
xline, = ax2.plot(x)                    
yline, = ax3.plot(y)
zline, = ax4.plot(z)

然后你可以删除for循环中的以下代码行:

ax1 = fig1.add_subplot(111)
ax1.plot(wline.set_ydata(w))
...
ax2 = fig2.add_subplot(111)
ax2.plot(xline.set_ydata(x))
...
ax3 = fig3.add_subplot(111)
ax3.plot(yline.set_ydata(y))
...
ax4 = fig4.add_subplot(111)
ax4.plot(zline.set_ydata(z)) 

您还需要将每个plt.draw()更改为

fig1.canvas.draw()
fig2.canvas.draw()
fig3.canvas.draw()
fig4.canvas.draw()

并且plt.grid(True)应更改为:

ax1.grid(True)
ax2.grid(True)
ax3.grid(True)
ax4.grid(True)