2017-07-24 26 views
0

我正在使用串行通信從4個不同的傳感器讀取數據,並且想要將每個傳感器數據繪製在單獨的圖中。我的代碼是:Matplotlib - 來自串行數據的多個圖

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

當您創建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) 
+0

非常感謝,有效地解決了這個問題。我也通過應用相同的推理(例如使用'ax1.set_ylim()'而不是'plt')來修正比例尺('ylim')。另一個問題出現了:只有活動人物實時更新「其」圖,即通過點擊/選擇一個特定圖形,該圖將隨着即將到來的數據而更新,但另外3個數字將被凍結,除非我點擊/選擇它們。任何想法?再次感謝。 – Denis

+0

啊,那是因爲'plt.draw'只對當前數字起作用。你應該把它們切換到'fig1.canvas.draw()'等等。看看我上面的編輯。 – tom

+0

我正在編輯我之前的評論。謝謝@湯姆,它的作品。所有繪圖正確更新。 – Denis