07-23-2018 12:23 PM
Hey everyone,
I am trying to set up a Read function on an Analog Input pin, in a loop, with the goal of being able to collect and handle pseudo-continuous data for an 8-hour period (overnight). To do this, my current code is the following:
from PyDAQmx import * import numpy from ctypes import * import matplotlib.pyplot as plt import time # Example from https://pythonhosted.org/PyDAQmx/usage.html to develop understanding # Declaration of variable passed by reference taskHandle = TaskHandle() read = int32() samples = 1000000 # 1 full second of data num_secs = 5 data_sec = numpy.ndarray((samples,), dtype=numpy.float64) data_bulk = [] pulseAmpAvg = [] pulseWidths = [] #DAQmx Configure Code DAQmxCreateTask(b'', byref(taskHandle)) DAQmxCreateAIVoltageChan(taskHandle, #Handle of task to associate voltage channel b'Dev1/ai0', #Name of physical channel to be used (Device 1, Analog Input 0) b'', #Name to associate with newly associated channel DAQmx_Val_Diff, #Configuration of channel -10, #Minimum expected measurement (in units) 10, #Maximum expected measurement (in units) DAQmx_Val_Volts, #Defines units, in this case Volts None) #Name of custom scale to apply, must be null if "units" set to Volts DAQmxCfgSampClkTiming(taskHandle, #Handle of task to associate sampling info b'', #Source terminal of samp clock. To use device internal clock, use NULL 1000000.0, #Sampling rate in samples/sec/channel DAQmx_Val_Rising, #Specifies clock edge to acquire samples DAQmx_Val_ContSamps, #Defines continuous or finite operation of task samples) #Number of samples to acquire DAQmxCfgInputBuffer(taskHandle, #Overrides automatic buffer creation samples) #Size of input buffer to be created, in samples # DAQmxCfgAnlgEdgeRefTrig(taskHandle, #Handle of task to associate trigger # b'Dev1/ai0', #Selected channel for measurement # DAQmx_Val_RisingSlope, #Slope of signal on which trigger should occur # 2, # Trigger reference voltage # 3) # Number of pretrigger samples to collect for i in range(1, num_secs): #DAQmx Start Code DAQmxStartTask(taskHandle) #DAQmx Read Code DAQmxReadAnalogF64(taskHandle, #Handle of task whose data will be read samples, #Number of samples per channel to read 10.0, #Timeout limit in seconds DAQmx_Val_GroupByChannel, #Specifies whether samples are interleaved data_sec, #Size of the array into which samples are read samples, #Reserved for future use, pass NULL byref(read), #Array to read samples into None) #Actual number of samples read from each channel (in this example, don't care) data_bulk.append(data_sec) DAQmxStopTask(taskHandle) #print ("Acquired %d points"%read.value) pulseCount = 0 pulseInt = 0.0 dataInPulse = 0 # Boolean switch to identify pulse falling edge manually, distinguish between pulses # Summing samples from pulse for later averaging for data_sec in data_bulk: for i in data_sec: if i > 1: dataInPulse = 1 pulseInt += i pulseCount += 1 elif (dataInPulse and i < 1): pulseAmpAvg.append(pulseInt/pulseCount) pulseWidths.append(pulseCount) pulseInt = 0 pulseCount = 0 dataInPulse = 0 # Ensures that further non-pulse data points won't add to pulseAmpAvg array if taskHandle: # DAQmx Stop code DAQmxClearTask(taskHandle) print('Average Pulse Amplitudes:') print(pulseAmpAvg) print('Pulse Widths (in us):') print(pulseWidths) plt.hist(pulseAmpAvg, bins = 10, density = True, stacked = False, edgecolor = "#666666", color = "#808080") plt.hist(pulseWidths, bins = 10, density = True, stacked = False, edgecolor = "#666666", color = "#808080") plt.show()
At present, I have StartTask and StopTask inside the for loop, which I know is incorrect. Originally I had only the Read function and some brief data handling within the for loop, but I generated Error 50103 (Attempting to use reserved resources). This makes it seem like I will need to run all of the task creation and clearing functions within the loop, but this will greatly reduce the amount of data within the 8-hour period that I will have access to, due to the large increase in overhead. The only solutions to this problem that I've seen have been in LabView, so I'd appreciate any advice on making this collect the data as efficiently as possible. It doesn't have to be able to read ALL of the values placed in the internal buffer during the 8-hour period, but I'd like to get as close as possible to that ideal.
Thanks in advance for the help!
07-23-2018 03:49 PM
I still don't speak python and the call to DAQmxReadAnalogF64 still has some (but not all) of the questionable appearance I mentioned in an earlier thread. If the argument variables are now known to be correct, you should update the comments to avoid confusion.
That said, I think the more immediate problem here is attempting to read the entire buffer all at once in a high-rate continuous task. At most, I might plan to read 1/2. A more common approach is to read about 1/10 sec worth of data per iteration. Frankly, I'm pretty surprised you haven't gotten buffer overflow errors.
My advice: get the Start and Stop out of the loop. Just iterate over reading. Read 100k or 200k samples per iteration. I don't know what "data_bulk.append()" does, but it could become a speed-limiting factor after a while.
-Kevin P