LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Timing issue (P/C design patern)

Hello eveyrone,

 

This post follows this one: Click here

 

I've had a lot of help and encouragments from the pervious thread that lead me to re-think my code into a more "efficient" one. The one I present here is not the best I can do I am sure, but I need it to work pretty soon (work requirement), and will enhance it through time. 

 

1) I've followed most of your advices and shrinked a little bit the loops (expect the 3rd one, but it will come)

2) Bob Schor is privately helping me a LOT! If by any way, Bob, you are reading this post: I am still in the process of enhancing my code with your help

3) the code itself: I want to aquire my data every 500ms (hence the timer on the dequeue element of the 2nd loop). My aquisition is done in the True case of this loop. What I'd like is to acquire a set of data every 1/2s, bundle it, and send it to the 3rd loop where it will be displayed and averaged every minute.

4) what it does: as you can see i've put indicators for displaying the iterations of my loops, and obviously my code doesn't iterate every 1/2s...

 

Is there a way where I could get closer to one iteration every 1/2s (or every 1s)? For a reason I ignore, my loops are slower than the set timer...

 

As I said, I am in the process of cleaning that code, and enhancing it, but I am obviously keen to take any critics about it.

 

(btw, this piece of code works properly right now: data are aquired, averaged, and saved, etc.).

 

Thank you  for you help,

Flo

0 Kudos
Message 1 of 7
(2,828 Views)

First of all, you should organize your project files better. You could use real or virtual folders to keep subVIs in one, typdef ctrls in another, and you should clearly name your top level VI, like "Main.vi" or "Top-level.vi"...

 

I can really see that you improve (I saw some of your earlier versions). Keep on learning, and you will get even further with LV programming.

 

About your timing problem:

  1. You have a Dequeue Element func. with a 500 msec timeout wired. When this times out at every half sec, you get to the True case of the Case structure. First, you should move the DAQmx Read function inside the True case, since you do not do anything with the DAQmx data in the False case!
  2. You want to read DAQmx data at every 500 msec. In this case, it is totally ok only to use software timing, so delete the "DAQmx Timing.vi" from your DAQ init subVI ("DAQ.vi").
  3. You have some serial DAQ vi also in your Case structure: "CP_READ.vi". Its execution takes time too. So if your DAQmx Read + this serial DAQ together takes more time than 500 msec, your While loop will not be able to iterate at a speed of 500 msec. This might be your problem here. Could you test how much execution time the "CP READ.vi" requires in a simple little test VI?
  4. If the problem is the above, you could use an additional loop only for the serial reads, together with a Notifier. So in your Consumer loop you just Dequeue the DAQmx data from the Queue, plus read the latest Notification from the Serial DAQ loop...

EDit: more about timing. Imagine what happens now: your Dequeue function times out, and you acquire data from the DAQmx channels, plus the Serial line. These two steps lets say require "N msec" time. When these steps stop execution, we start the next iteration of the While loop, and THEN we wait an additional 500 msec. It means, the elapsed time between two acquisition steps will be N+500 msec. As an ugly workaround, just change the timeout value of the Dequeue function to zero (immadiately time out), and put a "Wait until Next ms multiple" function with a value of 500 wired to it, into the True case of the Case structure.

 

Edit2: actually i discovered, there are even TWO serial DAQ subVIs in your True case. I wonder how fast they can execute...

 

controller v6_BD.png

 

 EDit3:

Actually I never used the Dequeue with a zero timeout before, I did not know the behaviour. I think it is better if you specify some lower value than 500 for timeout, but not zero, so your code has the chance to process incoming commands. Set the Dequeu timeout like 200 msec for example.

0 Kudos
Message 2 of 7
(2,805 Views)

A simple way to get the timing it to have a new loop that simply queues the Sample command with a 500ms. If you try to solve it within the consumer you'll inevitably get issues with execution times and what if, e.g. a command is queued after 400ms? The timeout will reset ...

The main point being you want as few disruptions as possible. Maybe it's even better to simply have a 500ms loop that samples and does nothing else.

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 3 of 7
(2,788 Views)

Thank you for you for your help. Some good news after some good advice:

 

- I've tested the true case in a simple while loop (attached to this post)

- I've tried to set the dequeue at 0/100/200ms. I dont realy see any change.

- I've put a wait until next 500ms inside the true case + moved my daq reading function there too

 

and:

 

- the number of iteration reaches 120 after 1min of running. that was perfect. so the code /daq/pumps are able to answers a request every 1/2s (for display purpose only)

- here is a picture of the result after 0:59:59m of running (almost a minute). the first loop runs at 1/2s, but the third one doesnt exactly follows the second one. I don't understand why...

 

troubleshoot.png

 

 

Yamaeda, I see that there may be a good idea in running another loop, not sure that I've understood your idea behing it. could you please be more specific? I am almost there, and it feels good 🙂

 

Cheers,

Flo

0 Kudos
Message 4 of 7
(2,751 Views)

Up ?

 

Sorry for that, but I am struggling with that slight offset between my loops. Any idea? or examples?

 

 

Flo

0 Kudos
Message 5 of 7
(2,723 Views)

Why do you expect that the iteration numbers are matching at the Data Producer and Consumer loops? That is the whole point behind the Producer/Consumer design, that you decouple the code running in the Consumer from the code running in the Producer 🙂

 

You produce data in the producer loop, in a frequent and more or the less precise manner, and Enqueue this data at regular times into the Queue, which is a lossless way of data transfer. Then you Dequeue this data in your Consumer loop, and your code has time there to do file logging, data analysis, calculations, etc. So that is the point, the Consumer can be a bit slower, and it will process the data as it can available in the Queue. So it is totally normal, that a Consumer loop is "lagging behind" the Producer loop, lets say, "expected behaviour"! That is why it is important, you produce some kind of time information (Waveform, absolute time stamps, etc.) in the producer, and then it just does not matter when this data gets saved into disk: the time info is preserved since it was created in the Producer loop...

 

0 Kudos
Message 6 of 7
(2,719 Views)

okay, Thank you.

 

I think I will bundle the data in the scond loop then, and average everything in the third one...

 

That shoul do the job 

0 Kudos
Message 7 of 7
(2,711 Views)