cancel
Showing results for 
Search instead for 
Did you mean: 
Reply

Running two tasks simultaneously

Re: Running two tasks simultaneously

Thank you for the suggestions! I tried both Kay and Paul's suggestions on my VI, they don't seem to work. The total run time will still be the sum of run time + loop time. I have attached the VI with Paul's suggestion. Yet, if I use my idea to fix this, the elapsed time count will not be the same as run time value and I found this is a little odd. Is this a good fix for the problem?

I have also another question. It seems like the time elapsed count is a little off, see attached Front Panel picture. Is there a way to improve the count?

 

To answer mcduff's question - the reason I am not using the finite set of data point is because I'd like the user has an option to run the code continuously or to specify a run time.

0 Kudos
Message 21 of 24
(305 Views)
Highlighted

Re: Running two tasks simultaneously

  1. Drake,

     Thanks for giving me "another chance to teach".  Please forgive the somewhat-rambling nature of this Post -- I'm putting in the effort because I sense you are interested in becoming better (and maybe even proficient) in LabVIEW development, but you need some guidance.

     I'm attaching a "partly-cleaned-up" version of your code, with lots of comments, in no particular order.  I also know why your "timing" is off, and (more important) "how to fix it".  That will come later.  First:

  • The name of your file, "...3 input R3 testing R2", suggests this is #3, Revision 3, test Revision 2, and you are (therefore) not using any form of Version Control, like Subversion or Git.  Look into learning about Subversion or Git (I use Subversion, myself).
  • There is no reason to use 8 point labels on Controls and Indicators.  I changed (some of) them to 14 point, so I can see what they are.
  • You almost never need (nor should have) a Frame, much less a Frame Sequence.  I replaced your Sequence with a single Frame around the initial "Get Time" function.
  • Reorganizing your code and keeping wires as straight and left-right as possible can help eliminate White Space and make your Block Diagram smaller and much more readable.  I did the first part, leaving the rest for you.

Now, let's talk about Time, a key concept in LabVIEW (dealing, as it does, with timed events like DAQ, and with Time as a primitive Data Type (Timestamps).  Here is a Principle -- DAQ Hardware Is the Best Clock!  If you really want to time something, and you have DAQ functions, use the DAQ, don't depend on the CPU clock!  You appear to be doing all of your Sampling at once, taking 10,000 samples a second for 10 seconds from 4 channels -- I certainly hope your cDAQ device has a 400,000-sample buffer!  Assuming that it does, the DAQ Read is guaranteed to take 10 seconds, at which point it will transfer all of the data to the Array of Waveforms coming out of the DAQ Read function.  Until this happens, almost nothing else in the Loop can run (as the Principle of Data Flow says it can't run until there is "Data on the Wire").  Now, everything else in the loop needs to run before the loop can finish, which might take a little extra time (and explains why your Elapsed Time is > 10 seconds).

 

How can you fix this?  Simple, don't do all that processing before ending the While Loop!  "But I have to process the data!", you say.  Yes, but not in that loop.  The Principle of Data Flow also means that LabVIEW can run two loops at the same time in something called the Producer-Consumer Design Pattern (there are LabVIEW Examples and Templates illustrating this).  Here's how it works:

  1.  Let's assume your DAQ device has sufficient buffering to allow you to hold all of the Samples you need to acquire (i.e. 10s * 10kHz * 4 channels = 400,000 samples).
  2. Put the DAQms Read function in a small While Loop.  Put nothing else (yet) in the While Loop.  Put in a Stop button to end the While loop.  Try it out, and observe that no matter when you push the Stop button, the loop will run for (almost exactly) a multiple of 10 seconds.  In actuality, when it executes the DAQmx Read, anything that depends on the Read finishing (i.e. anything that uses either the Data Out or Error Out wire from that Function) will wait for the Read to finish (by the Principle of Data Flow).
  3. In particular, anything you do with the data will delay taking any more data.  So you don't want to do anything "time-consuming" inside the loop.
  4. Here's where the Magic Happens.  This While Loop is the "Producer" -- it "produces" data every 10 seconds.  It wants to get rid of the data quickly and send it to another Loop, the Consumer, that can run at the same time that the Producer is doing the next DAQmx Read.
  5. Do you know about Queues?  A Queue is a data structure that says "I'm going to put some data in here, and take it out over there, taking very little time to do this".  The data don't actually move in a Queue, what you are really doing is passing a reference to the data, which takes very little time.  I'm not going to try to tell you all about Queues and how they are used in Producer/Consumer Loops, but if you do a little research, look at the LabVIEW Help, look at the LabVIEW Examples, and look at the Producer/Consumer Design Pattern Template (open LabVIEW, go to File, New ... (the dots are important), From Template, Design Patterns, Producer Consumer Design Pattern (Data), you'll get an Example to study and adapt to your situation.
  6. You put your Data Processing code in the Consumer Loop.  Assuming "Consuming" takes less than the 10 seconds the Producer loop spends "producing" the data that the Consumer is "consuming", the two Loops run "in parallel", with the Producer running at full speed and the Consumer, when it runs, not "blocking" the Producer from running again.
  7. A wonderful side effect of this is that if your DAQ device does not have a big enough buffer, so what?  Instead of generating all 100,000 samples at once, generate them 1000 at a time, sending them to the Consumer, and run the Producer for 100 iterations until all 100,000 samples have been Produced and Consumed.  The Producer will still "produce" the data as fast as before (since nothing it blocking it from running continuously) and the Consumer will follow right along.

I'm attaching my revised version of your code.  When you rewrite your DAQ loop and transform it into a Producer/Consumer design, try to copy the "style" of compactness, less white space, straighter (and shorter) wires, and a level Error Line ("The Error Line Runs Through It").

 

Post your New and Improved Code.  Does it work (much) better?

 

Bob Schor

Message 22 of 24
(310 Views)

Re: Running two tasks simultaneously

Thank you for the thorough elaboration, Bob. I will take some times to study the Producer/Consumer design and post the improved code. 

 

Best,

Drake

 

 

0 Kudos
Message 23 of 24
(260 Views)

Re: Running two tasks simultaneously

Hi Bob,

I have modified my VI using your suggestion. Few questions have came up:

1) When the VI is running, the FFT Graph and the corresponding data value are working fine. Yet, When I pressed the stop button/when the VI stopped, the graph is cleared and the data value is not properly shown, see attached 123 picture.

2) I set the run time to be 10sec, yet the time elapsed indicator only shows 9sec. I believe the loop starts counting with 0, that's why it gives me 9. Is it necessary to have this fixed.

3) I get rid of the Get Time Function because even with the producer/consumer design pattern, the timestamp count will still not be an integer; and replaced with the loop count as the timestamps. Is this what you referred to as "DAQ Hardware clock"?
4) In my previous version, by changing the "timeout" of the DAQmx Read, let say 5sec, the FFT graph will produce a FFT for this 5sec. However, when I used producer/consumer design pattern, I noticed that the 5sec "timeout" of the DAQmx Read will multiply the total run time. For example, "Run Time" is set to 10sec, "timeout" is set to 5sec. the total run time will be 50sec instead of 10sec specified (the time elapsed indicator will still remain 9sec). How can I fixed this issue?

 

Thank you,

Drake

 

0 Kudos
Message 24 of 24
(51 Views)