12-15-2009 12:07 PM
I am converting a older LV program with Traditional Daq to LV 8.6 on WinXP using DAQmx.
I have an S series board acquiring multiple channels at 2,500,000 S/sec. I acquire 500,000 samples at a time, 5 times a second, analyze the buffer of data, save any events that are found, then get the next buffer of 500,000 points. Sometimes the analysis and saving takes more than 0.2 seconds, in which case I need to get the most recent 500,000 points and skip any old points.
My first attempt was to use standard continuous acquisition. My loop waits for 0.16 seconds, then does a Daq Read. The Read pauses until there are 500,000 points, so that syncs the loop timing to the hardware. This falls apart when my program falls behind. If I miss reading a bunch of data, then when my analysis load lightens up and I am able to run full-steam again, the Daq calls don't wait for 0.2 seconds between calls. The Daq driver has kept track of all the points taken by the hardware, even though they have been overwritten in the buffer. So after the 0.16 seconds the program waits, the Daq Read just reads 500,000 points right away, so that it gets 0.04 seconds of old data and 0.16 seconds of new.
I rewrote the loop to use a Daq event - Every N Samples Acq In Buffer, but that has the same problem. When I fall behind, the internal N counter still counts all the samples that were acquired even though many of them are already overwritten, so it lets the Read happen early.
I've played with the Relative To and Offset properties of Daq Read, but I can't find a way to use them to get what I want either.
Can anyone think of a way to configure this or a way to do the timing such that if the program keeps up with the acquisition, it waits for a full, new buffer, but if it falls behind, it gets the most recent buffer-full of data? Perhaps a timed-loop that is tied to an independent counter? It would need a mechanism that lets it fall behind and go from there, rather than trying to catch up. And if I use an independent timer/counter, how well will that synchronize to the data acquisition clock? If they are on the same board, do they originate from the same master clock?
Thanks,
DaveT
12-15-2009 12:11 PM
12-15-2009 01:56 PM
Dave,
I have used "double buffering" to solve this kind of problem in other types of systems, but never in LabView.
The strategy goes something like this.
Two buffers, with two flags (binaries) for each, one called ready set by the Daq, and one called busy...set by the reading
Daq checks the busy flag on 1, finds it notbusy, fills buffer 1, sets the ready flag...
Daq checks the busy flag on 2, finds it not busy, begins loading buffer 2. When complete it sets the ready flag...and resets the ready flag on buffer 1...(this way ... the most recent data has a ready flag set.
As the data is being read (from the buffer marked "ready"...the reader sets a busy flag, to keep the daq system from overwriting the buffer as you are unloading it...when unload is complete, the reading vi would reset both the busy and the ready flags...making that buffer ready to load again. (it is possible to do this with just the ready flag...reader reads only buffer with ready set...writer writes only buffer with ready not set)...
In the case where the daq has completed writing buffer 1, then completed writing buffer 2...and the reading process is reading 2...then daq finishes writing 1 again while the read of 2 is going on, the writer must check to see if the busy flag is set on 2...if it is, then it simply overwrites the most recent data set that it just wrote, and moves on...
Clear as mud....?
There are probably better ways to do this...but this has worked in the past...
Asynchronous read write buffers..
Hope that helps
Hummer1
12-15-2009 02:01 PM
There is a DAQmx property to let you read the backlog (number of samples waitng in the buffer) to do the same thing we did with traditional DAQ. The data is then shared via a queue.
Ben
12-15-2009 02:03 PM
Ben,
In vision, there is an option to read the latest buffer or read the buffer circularly...or close to that...
Is there a simular option with this?
Hummer1
12-15-2009 02:11 PM
Hi Hummer,
I work with a bunch other CLA's where two of them are into image processing so.... they get all of the vision projects .... so I can't answer your question.
Ben
12-15-2009 02:32 PM
I could maybe post the code if necessary, but it will take a good while to trim it down to something manageable that still shows the issue.
Hummer,
What you describe is basically what I'm trying to do. The problem is finding the right hooks into DAQmx from within LabVIEW to gain enough control over the buffers...
Ben,
I can find properties for Current Read Position, Available Samples Per Channel, and Total Samples Per Channel Acquired. These sound similar to the buffer position you refer to. But I cannot find any way of manipulating the buffer position. The Current Read Position is Read Only. So I kind of get the first half of your idea. The second half remains opaque to me...
Thanks for all the suggestions.
Regards,
DaveT
12-15-2009 02:39 PM
The idea is to nver fall behind on the DAQ reads.
Only read in big chunks and transfer them out via a queue for other threads to crunch. Let the queeu be your buffer.
Then again maybe I did not understand your question so don't get stuck if my reply does not makes sense*.
Ben
* I turned in a 14.5 hour day yesterday and then sat for my CLA re-certifaction earlier today. I have license to be a little scattered today.
12-15-2009 02:48 PM
Ben,
THANKS! Yes, I see now. Set up a separate loop for the Daq, buffer it up, pull it out as you can. I don't know why I didn't see this before. With your extra bit of explanation, it seems rather obvious now...
I'd still be interested in seeing if it is possible jut by tweaking the Daq properties. Seems like it should be. And it would mean I had to revise the code less. But I definitely see how what you suggest should work quite well.
Regards,
Dave