pyQtgraph 绘图延迟串行绘图
Posted
技术标签:
【中文标题】pyQtgraph 绘图延迟串行绘图【英文标题】:pyQtgraph plotting is delayed for serial plot 【发布时间】:2019-03-03 08:26:08 【问题描述】:我正在尝试通过 python 中的 PyQTgraph 框架用我的 MPR121 和 arduino UNO 绘制 12 个通道。
一切都很好,我什至将数据写入 .csv 文件进行分析。但是,当我在 python 中运行代码时,“实时”绘图会延迟。我的代码附在下面。我想知道是否是我设置代码的方式导致了实时可视化的延迟。
# Importing required packages and libraries
import serial
import numpy as np
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import time
import csv
####################################################################################################################################
# Declaring variables SETUP!
csv_fileName = 'MPR_dataTest_20181909_T6.csv' # File Name
numberOfSamples = 500 # Specify number of samples
interactiveWindow = 100 # Interactive visualization window
numberOfChannels = 12 # Specifiy number of channels
serialPort = 'COM4' # Choose the Serial Port
baudrate = 19200 # Set the baudrate (bytes/s)
curveColour = 'b' # Set curve colour
yMin = 50 # y-axis limit minimum
yMax = 320 # y-axis limit maximum
####################################################################################################################################
####################################################################################################################################
channelData = []
t = [] # Time array
sample = [] # Sample count array
smpl = 1 # Sample counter (initialized at 0)
fileHeader = ['Sample','Time (s)','Ch1','Ch2','Ch3','Ch4','Ch5','Ch6','Ch7','Ch8','Ch9','Ch10','Ch11','Ch12', 'Ch13',\
'Ch14', 'Ch15', 'Ch16', 'Ch17', 'Ch18', 'Ch19', 'Ch20']
fileHeader = fileHeader[0:numberOfChannels+2]
with open(csv_fileName, 'a', newline = '') as f: # opens file in directory and appends to that file (does not erase existing data)
writer = csv.writer(f, delimiter = ',')
# Naming Column Headers
writer.writerow(fileHeader)
# Serial Port Communication
# Begin Serial Port Stream
serialData = serial.Serial(port= serialPort) # Open serial port object
serialData.baudrate = baudrate # Set baudrate
time.sleep(1) # Time delay
serialData.reset_input_buffer() # Clears the serial port queue so there's no overlap or erroneous data points
serialData.reset_output_buffer() # Flush output buffer, aborting current output and discard all in buffer
# Interactive Real-Time Plotting
app = QtGui.QApplication([]) # Initialize visulation GUI!
win = pg.GraphicsWindow(title="Signal from serial port") # Creates a plotter window
win.resize(1700,900)
pg.setConfigOption('background', 'w') # Switch to using white background and black foreground
pg.setConfigOptions(antialias=True) # Enable antialiasing for prettier plots
ptr = (-interactiveWindow)*np.ones((numberOfChannels, 1)) # set first x position
if numberOfChannels >= 1:
p1 = win.addPlot(title="Channel 1") # Creates empty space for the plot in the window
curve1 = p1.plot(pen = curveColour) # Create an empty "plot" (a curve to plot)
p1.setLabel('left', 'Capacitance') # Setting y-axis label
p1.setLabel('bottom', 'samples') # Setting x-axis label
p1.setYRange(yMin, yMax, padding=0) # Setting y-axis limits
ch1 = np.linspace(0,0,interactiveWindow) # create array that will contain the relevant time series
if numberOfChannels >= 2:
p2 = win.addPlot(title="Channel 2")
curve2 = p2.plot(pen = curveColour)
p2.setLabel('left', 'Capacitance')
p2.setLabel('bottom', 'samples')
p2.setYRange(yMin, yMax, padding=0)
ch2 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 3:
p3 = win.addPlot(title="Channel 3")
curve3 = p3.plot(pen = curveColour)
p3.setLabel('left', 'Capacitance')
p3.setLabel('bottom', 'samples')
p3.setYRange(yMin, yMax, padding=0)
ch3 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 4:
p4 = win.addPlot(title="Channel 4")
curve4 = p4.plot(pen = curveColour)
p4.setLabel('left', 'Capacitance')
p4.setLabel('bottom', 'samples')
p4.setYRange(yMin, yMax, padding=0)
ch4 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 5:
p5 = win.addPlot(title="Channel 5")
curve5 = p5.plot(pen = curveColour)
p5.setLabel('left', 'Capacitance')
p5.setLabel('bottom', 'samples')
p5.setYRange(yMin, yMax, padding=0)
ch5 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 6:
win.nextRow() # New row in visualization plot
p6 = win.addPlot(title="Channel 6")
curve6 = p6.plot(pen = curveColour)
p6.setLabel('left', 'Capacitance')
p6.setLabel('bottom', 'samples')
p6.setYRange(yMin, yMax, padding=0)
ch6 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 7:
p7 = win.addPlot(title="Channel 7")
curve7 = p7.plot(pen = curveColour)
p7.setLabel('left', 'Capacitance')
p7.setLabel('bottom', 'samples')
p7.setYRange(yMin, yMax, padding=0)
ch7 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 8:
p8 = win.addPlot(title="Channel 8")
curve8 = p8.plot(pen = curveColour)
p8.setLabel('left', 'Capacitance')
p8.setLabel('bottom', 'samples')
p8.setYRange(yMin, yMax, padding=0)
ch8 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 9:
p9 = win.addPlot(title="Channel 9")
curve9 = p9.plot(pen = curveColour)
p9.setLabel('left', 'Capacitance')
p9.setLabel('bottom', 'samples')
p9.setYRange(yMin, yMax, padding=0)
ch9 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 10:
p10 = win.addPlot(title="Channel 10")
curve10 = p10.plot(pen = curveColour)
p10.setLabel('left', 'Capacitance')
p10.setLabel('bottom', 'samples')
p10.setYRange(yMin, yMax, padding=0)
ch10 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 11:
win.nextRow() # New row in visualization plot
p11 = win.addPlot(title="Channel 11")
curve11 = p11.plot(pen = curveColour)
p11.setLabel('left', 'Capacitance')
p11.setLabel('bottom', 'samples')
p11.setYRange(yMin, yMax, padding=0)
ch11 = np.linspace(0,0,interactiveWindow)
if numberOfChannels >= 12:
p12 = win.addPlot(title="Channel 12")
curve12 = p12.plot(pen = curveColour)
p12.setLabel('left', 'Capacitance')
p12.setLabel('bottom', 'samples')
p12.setYRange(yMin, yMax, padding=0)
ch12 = np.linspace(0,0,interactiveWindow)
# Realtime data plot. Each time this function is called, the data display is updated
def update():
global ptr, ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10, ch11, ch12, \
curve1, curve2, curve3, curve4, curve5, curve6, curve7, curve8, curve9, curve10, curve11, curve12
if numberOfChannels >= 1:
ch1[:-1] = ch1[1:] # shift data in the temporal mean 1 sample left
ch1[-1] = dataArray[0] # vector containing the instantaneous values
curve1.setData(ch1) # set the curve with this data
curve1.setPos(ptr[0],0) # set x position in the graph to 0
ptr[0] += 1 # update x position for displaying the curve
if numberOfChannels >= 2:
ch2[:-1] = ch2[1:]
ch2[-1] = dataArray[1]
curve2.setData(ch2)
curve2.setPos(ptr[1],0)
ptr[1] += 1
if numberOfChannels >= 3:
ch3[:-1] = ch3[1:]
ch3[-1] = dataArray[2]
curve3.setData(ch3)
curve3.setPos(ptr[2],0)
ptr[2] += 1
if numberOfChannels >= 4:
ch4[:-1] = ch4[1:]
ch4[-1] = dataArray[3]
curve4.setData(ch4)
curve4.setPos(ptr[3],0)
ptr[3] += 1
if numberOfChannels >= 5:
ch5[:-1] = ch5[1:]
ch5[-1] = dataArray[4]
curve5.setData(ch5)
curve5.setPos(ptr[4],0)
ptr[4] += 1
if numberOfChannels >= 6:
ch6[:-1] = ch6[1:]
ch6[-1] = dataArray[5]
curve6.setData(ch6)
curve6.setPos(ptr[5],0)
ptr[5] += 1
if numberOfChannels >= 7:
ch7[:-1] = ch7[1:]
ch7[-1] = dataArray[6]
curve7.setData(ch7)
curve7.setPos(ptr[6],0)
ptr[6] += 1
if numberOfChannels >= 8:
ch8[:-1] = ch8[1:]
ch8[-1] = dataArray[7]
curve8.setData(ch8)
curve8.setPos(ptr[7],0)
ptr[7] += 1
if numberOfChannels >= 9:
ch9[:-1] = ch9[1:]
ch9[-1] = dataArray[8]
curve9.setData(ch9)
curve9.setPos(ptr[8],0)
ptr[8] += 1
if numberOfChannels >= 10:
ch10[:-1] = ch10[1:]
ch10[-1] = dataArray[9]
curve10.setData(ch10)
curve10.setPos(ptr[9],0)
ptr[9] += 1
if numberOfChannels >= 11:
ch11[:-1] = ch11[1:]
ch11[-1] = dataArray[10]
curve11.setData(ch11)
curve11.setPos(ptr[10],0)
ptr[10] += 1
if numberOfChannels >= 12:
ch12[:-1] = ch12[1:]
ch12[-1] = dataArray[11]
curve12.setData(ch12)
curve12.setPos(ptr[11],0)
ptr[11] += 1
QtGui.QApplication.processEvents()
#################################################################################################################################
#%%
startTime = time.time() # Start logging time
while smpl <= numberOfSamples: # Infinite (or set to num. of. samples) While loop
try:
while (serialData.inWaiting() == 0): # Waiting for there to be serial data
pass # Do nothing if there is no serial information
if smpl <= numberOfSamples: # If there is serial data
serialString = serialData.readline() # Read serial port line by line
decode_String = serialString.decode('utf-8') # Decodes the bytes from serial port (give value in b[value]\r\n)
dataStringArray = decode_String.split(' ') # Splitting the data 'comma' delimited
dataArray = [np.float16(i) for i in dataStringArray[0:numberOfChannels]]# Convert string to floating point number
update() # This is a brutal infinite loop calling the realtime data plot
print(smpl, dataArray)
sample.append(smpl)
t.append(time.time() - startTime)
channelData.append(dataArray)
smpl += 1 # Step increment for each good sample
if smpl > numberOfSamples: # Check for data completion
print('\n Data collection complete! Check file.') # Print check..
serialData.close() # Close serial port object
except:
print('\n Keyboard Interrupt!... Stopped Data Acquisition!')
serialData.close() # Close serial port object
break
timeElapsed = str(time.time() - startTime) # Time elapsed check!
print('Time elapsed = ', timeElapsed)
################################################################################
if __name__ == '__main__':
import sys
if sys.flags.interactive != 1 or not hasattr(QtCore, 'PYQT_VERSION'):
pg.QtGui.QApplication.exec_()
################################################################################
sample = np.array(np.reshape(sample, (len(sample), 1))) # Converting to array
t = np.array(np.reshape(t, (len(t), 1)))
channelData = np.array(channelData)
channelData = np.hstack((sample, t, channelData)) # Concatenating desired data
with open(csv_fileName, 'a', newline = '') as f: # Opens file in directory and appends to that file (does not erase existing data)
writer = csv.writer(f, delimiter = ',')
writer.writerows(channelData)
感谢您的帮助!期待解决这个问题。
【问题讨论】:
通过降低arduino脚本中的采样率解决(延迟从1ms增加到10ms) 【参考方案1】:通过降低arduino脚本中的采样率来解决(延迟从1ms增加到10ms)
【讨论】:
以上是关于pyQtgraph 绘图延迟串行绘图的主要内容,如果未能解决你的问题,请参考以下文章