LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Data transfer through the queue between while loop

Hello.
I need to data acquisition and write the file. My VI consists of two while loops. The first loop receives data from FPGA and performs signal processing. The running time of this cycle is 1 second.    The second loop writes the file. A queue is used to transfer data between loops. I need to record the signal for 1 minute. If I start VI and start recording a file, then when recording time is 1 minute I always get a signal recording with duration of 1 second. How to do the accumulation of data from the first cycle and write them to a file in second loop.

0 Kudos
Message 1 of 5
(3,530 Views)

hi there and welcome to the forum!

 

first some critique: please don't post screenshots of code .. and escpecially no spaghetti code.

attach your vi or better a mockup of your problem (often just by doing this step one finds faulty code).

also to better check your code and its dataflow paradigm have everything going left to right,

no up and down please (e.g. your destroy queue subvi).

 

from you description (the image is not very informative) you are on the right track.

one acquisition loop that writes to a queue,

second loop for reading/flushing from the same queue and writing to file/tdms.

 

without more information it is just guessing what the cause is.

on thing i saw that strikes me odd is your Error Feedback Node.

 

EDIT: also, you create/replace your tdms file every loop iteration, that might be it, can you verify, that you only get the last measurement in your tdms file?

 

regards


If Tetris has taught me anything, it's errors pile up and accomplishments disappear.
0 Kudos
Message 2 of 5
(3,517 Views)

Your LabVIEW code will be much easier for you to read/understand (and will help others, too) if you learn to use (lots of) sub-VIs, preferably that "do one thing", and organize them in folders and the LabVIEW Project file.

 

The notion of having two parallel loops doing parts of your code "in parallel" is a major strength of LabVIEW.  However, you need to also organize each loop better.  You will help yourself if you try to keep your VIs compact, your wires as straight as possible, and data flow moving left-to-right.  The Diagram Cleanup button (the Broom symbol on the upper Task Bar) can be helpful, but laying it out neatly yourself, in my opinion, is better.

 

Many parallel tasks (and yours, in particular) have the following logical structure:

  • Initialize -- do a bunch of steps that are done once, before the rest of the computation takes place.  This includes opening Queues (and getting a persistent Queue reference), opening Files (and getting a File reference), initializing DAQ (and getting a Task reference).
  • A Loop that uses persistent references or data structures created once in the Initialize step.  The Loop, in particular, does not repetetively create/destroy data that needs to persist throughout the loop.
  • Cleanup -- a number of steps that take place when the Loop(s) exit.  This can include closing files, stopping DAQ Tasks, disposing of Queues.
  • When dealing with parallel Loops, getting them both to stop takes some thought.  There is generally one or more "communication path" between the Loops, such as a Queue.  In a Producer/Consumer design, the Producer is generally "told" when enough data has been "produced" (e.g. a minute has passed) and can safely exit.  How to tell the Consumer?  One (reasonably elegant) way is to use the Loop-to-Loop Communication Path (such as the Data Queue) to send a signal that the Producer has finished.  Since Data Queues often send Arrays of Data, you could send an Empty Array (which would never be sent from within the Loop) as a Sentinel in the Producer's Finaliization code.  Your Consumer loop would check, when dequeuing the Data, and test for an Empty Array.  If it was Empty, then you know the Producer has finished, so you can end the Consumer Loop (and, in its Finalization code, release the Queue), otherwise you "consume" the Data as before.

@jwscs suggested that you might be creating, writing, and closing your TDMS file every time through the (Consumer) Loop, which might be your problem.  If so, move the Create to the Consumer's "Initialize" code, leave the Writing in the Loop, and move the Close to the Cleanup code.  And get those wires straight, and start using sub-VIs!

 

Bob Schor

0 Kudos
Message 3 of 5
(3,504 Views)

Hi Bob. Thanks for the response and recommendations. I will take them into account in my work. I made a change to VI on the advice of @jwscs. As a result, I was able to write a file longer than the period of the first data acquisition while loop. However, the recording time of the signal set in VI does not correspond to the time of the recorded signal. If a recording time of 1 second is set in VI, then the recorded file contains only 200 ms. Also, the recording time of a signal depends on the number of samples. Maybe I'm setting the queue parameters incorrectly. I did VI immetting the work of my VI and discovered the same problem.
How to reconcile the work of two cycles and transfer through the queue to record a file with a given signal size?

0 Kudos
Message 4 of 5
(3,464 Views)

The VI you uploaded looks like it should work - just be aware that you're generating 1000 samples at a sampling frequency of 1kHz, every 50ms. This results in producing what the timestamps suggest is (1s / 50ms) = 20s of data per second of acquisition.

 

Perhaps that's the problem you're seeing. I changed the wait in the top loop to 1000ms and although the graph is much less smooth (because it only updates once per second) the result in the TDMS file became 10s when I set the recording to 10s.

 

The option to have quick updates and appropriate sampling would be to keep the wait at a low-ish value (perhaps 100ms, or 50ms) and then lower the number of samples in the waveform. The combination of the two sampling values controls the data rate in a peculiar way (at least to me). I'd suggest reading the "Detailed Help" available either via the right-click menu, or the Context Help (Ctrl+h).

 

A couple of other quick points:

  • At the moment, you can get a "Refnum became invalid while ... waited for it" because you destroy the queue before the bottom loop stops (this is a race condition). You could wire the error output of the bottom loop towards the top and use merge errors to enforce ordering and make sure the bottom loop stops before the top loop disappears.
  • Since you have a dequeue function in the lower loop, you don't really need a Wait function
  • Since you have no timeout on the dequeue function, the only way the bottom loop is stopping is because it falls behind the top queue. Fixing the race condition in bullet point 1 will actually cause problems here if the bottom loop isn't behind - it will wait at the dequeue forever (currently, it errors when the queue is released). Bob's suggestion regarding empty arrays to terminate the loop is a good solution.

GCentral
0 Kudos
Message 5 of 5
(3,456 Views)