Streaming mode while drawing a plot | LabJack
 

Streaming mode while drawing a plot

2 posts / 0 new
Last post
steve6540
steve6540's picture
Streaming mode while drawing a plot

Hi,

I am trying to have my program plot the data it retrieves from the U3 every request. I am running into errors with missed readings: I keep getting Error 40. Also, when I graph my voltages, the missed packets appear as a voltage of ~2.5V, skewing my data and making the graph unreadable. Also, it seems that the updating progresses slower as the program runs longer. Is there any reason for this? I chose to have calibrated readings on in Stream Mode because I need to graph the voltages while the stream mode is active. I am currently running it at a higher resolution and slower speed (0,2400Hz) instead of the settings I'd like to be running it at (3,50kHz). 

# We need the date and time in order to plot our data

import traceback
from datetime import datetime

#importing matplotlib in order to plot what we get
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as numpy
from drawnow import drawnow

import u3 #import the u3

# Open the U3
d = u3.U3()

# Set the FIO4 to analog (and all channels below) which is AIN4 later for low level commands in command/response mode.
d.configIO(FIOAnalog=31)

# MAX_REQUESTS is the number of packets to be read.
MAX_REQUESTS = 75

# For applying the proper calibration for readings from unsigned values to voltages
d.getCalibrationData()

# Set the steam parameters. 1 channel, positive channel #4, negative channel #31 = singled ended, resolution 3 -> higher noise but faster sampling
# Sample rate = scanrate * numchannels, max ~50k samples/s. Samples per packet = 25 for data transfer efficiency. packetsPerRequest =48
print "Configuring U3 Stream..."
d.streamConfig(NumChannels=1, PChannels=[4], NChannels=[31], Resolution = 0 , ScanFrequency = 2500, SamplesPerPacket = 25)

# exception handling
try:
d.streamStart()
rawDataList = []
runTimeList = []
start = datetime.now() # print the scan start time
print "Started stream at ", datetime.now(), '\n'
missed = 0 # initialize counters
dataCount = 0
packetCount = 0

# make an initial figure and enable interactivity
plt.ion()
fig = plt.figure()

def makeFig():
plt.scatter(xList, yList)
# initialize our plotted lists
xList = list()
yList = list()

for r in d.streamData():
xList.append(runTimeList)
yList.append(rawDataList)
drawnow(makeFig)

if r is not None:

# Our stop condition
if dataCount >= MAX_REQUESTS:
break

if r['errors'] != 0:
print "Error: %s ; " % r['errors'], datetime.now()

if r['numPackets'] != d.packetsPerRequest:
print "----- UNDERFLOW : %s : " % r['numPackets'], datetime.now()

if r['missed'] != 0:
missed += r['missed']
print "+++ Missed ", r['missed']

packetStartTime = datetime.now()

if dataCount < 1:
packetStartTime = datetime.now()
miniRuntime = (packetStartTime - start).seconds + float((packetStartTime - start).microseconds) / 1000000

rawDataList.append(r['AIN4'])

# old comment: add the current raw bytes. we cannot use command/response commands (such as getFeedback or AIN)
# because we are in Stream Mode. We need to utilize r['XX'] instead

if dataCount == 0:
for i in range(0, 1200, 1):
runTimeList.append(i * (miniRuntime/(25*48)))
#print runTimeList[-1]

if dataCount >= 1:
theTimeBefore = runTimeList[-1]
theTimeNow = datetime.now()
theTimeBetweenNowAndTheStart = (theTimeNow - start).seconds + float((theTimeNow - start).microseconds) / 1000000
theTimeDifference = theTimeBetweenNowAndTheStart - theTimeBefore

for j in range(1, 1201, 1):
runTimeList.append(j*(theTimeDifference/(48*25)) + theTimeBefore)

dataCount += 1
packetCount += r['numPackets']

else:
# Got no data back from our read.
# This only happens if your stream isn't faster than the
# the USB read timeout, ~1 sec.
print "No data, timeout", datetime.now()

except:
print "".join(i for i in traceback.format_exc())

finally:
d.streamStop() #stop the stream
stop = datetime.now() #record the system time now for timing purposes
print '\n' , "Stream stopped at", datetime.now(), '\n'
d.close() #close the u3 for now

averageVoltage = sum(rawDataList)/len(rawDataList) #find the average voltage
sampleTotal = packetCount * d.streamSamplesPerPacket #find the total amount of samples taken

scanTotal = sampleTotal / 1 # sampleTotal / NumChannels

print "%s requests with %s packets per request with %s samples per packet = %s samples total." % (
dataCount, (float(packetCount) / dataCount), d.streamSamplesPerPacket, sampleTotal)
print "%s samples were lost due to errors." % missed
print "%f percent of total samples were lost" % (float(missed) * 100 / sampleTotal)

sampleTotal -= missed
print "Adjusted number of samples = %s" % sampleTotal
print '\n'

runTime = (stop - start).seconds + float((stop - start).microseconds) / 1000000

print "The experiment took %s seconds." % runTime
print "Scan Rate : %s scans / %s seconds = %s Hz" % (scanTotal, runTime, float(scanTotal) / runTime)
print "Sample Rate : %s samples / %s seconds = %s Hz" % (sampleTotal, runTime, float(sampleTotal) / runTime)
print "The average voltage was %s milivolts over the scan period" % (averageVoltage*7.97*1000) # 1/8 measured voltage, multiply by 8
print "length of processed data list %s, length of runtime list %s" % (len(rawDataString),len(runTimeList))

Thanks

LabJack Support
labjack support's picture
If you are getting missed

If you are getting missed readings, it is probably due to the U3's stream buffer overflowing since your application is not reading the stream data at a fast enough rate. Streaming by itself using LabJackPython shouldn't cause slowdown over time, and your plot code is probably slowing down your stream read loop enough to cause the missed readings (stream buffer overflow) issue. You can confirm if your plot code is the cause of the issue by removing the plot code in your stream read loop and seeing if the missed readings still occur.

Keep in mind that other than the streamData call, the stream read loop should not have code that causes long delays otherwise stream buffer overflow errors on the U3 can occur.

First, see if you can speed up or optimize your chart code so it doesn't slowdown as much.

Next, typically when plotting or doing other time consuming operations while streaming we recommend using multiple threads in your application. One thread is dedicated to reading the stream data, and the other thread/threads perform the other operations in your application such as plotting. However multiple threads in Python are still technically one thread which still may not help much. Try threading in your code and see if it helps the issue. If not, look into using Python's multiprocessing and pass the stream data between processes.

https://docs.python.org/2/library/multiprocessing.html

Note when using multiple processes, have one process do the U3 operations and the other process/processes handle your other operations since device handles cannot be shared among mutiple processes.