LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Create a Save Data Button, General VI Improvement help.

Here's the Future Feedback, which involves "How to Start and Stop a Producer/Consumer Design".

 

Let's start with the Producer and not (yet) worry about starting or stopping.  Because you sent only the Top Level VI, I can't see what is going on in the sub-VIs like DMM_Write_Read_SUBVI or Read Outputs.  I also don't see the Timing functions in the Producer.  What I do see is the Producer Loop, when Graph is False, just "spins", running as fast as it possibly can, doing nothing (oops!).  When Graph is True, then it does one Read from the DMM top device, and two Reads from the bottom device.  These two sets of data are passed in two separate Queues, and the Producer continues.  As the Principle of Data Flow still applies, when Graph is True, the While loop runs as fast as the slowest code in the Case structure, which might or might not be "timed".

 

It is sort of "awkward" acquiring sampled data without having a reliable "clock".  It could well be that the slowest device is very "regular", and can allow you to say "Every X ms I'll get a point, so I know the loop runs at 1000/X Hz".  This still does nothing for the Graph=False case, but you could put a Wait X ms in there.  What I'd probably do, however, is put the DAQ code outside the Case Statement -- if Graph is True, Enqueue the results to the Consumer, otherwise just throw them away.  Now your Producer runs at a defined rate, regardless of whether or not Graph is True or False.

 

But why two Queues?  Twice the mess to worry about!  Instead, take your Read Buffer (string) from the top Device and combine it (in a Cluster) with the simultaneously-acquired Array of 6 Dbls.  When you dequeue the data in the Consumer, simply unbundle the Cluster into its components and plot away!  [Incidentally, I strongly recommend using "Bundle by Name" and "Unbundle by Name" with Clusters, and building a TypeDef for the Cluster -- trust me, it will serve you well].

 

So did you notice I haven't said anything about stopping the P/C Design?  You are using the "Usual Method" (which I dislike intensely) -- close the Queue on the Producer and (deliberately) generate an Error on the Consumer, which you take as the Stop condition.  Bad!  What if there really is an Error in the Consumer?  It will stop "prematurely".

 

The trick is to use something called a "Sentinel" -- arrange a special signal for the Producer to send in its Queue that the Consumer tests each time it "consumes", and if the signal says "Exit", it does not process the data, but exits the Consumer.  When does the Producer generate this Sentinel?  Well, when you push the Stop Button, the Producer exits and "knows" the Queue is done.  But as I've just argued, it isn't done because the Consumer still needs it.  So the Producer puts the Sentinel on the Queue, then leaves the Queue alone and does whatever "Closing" routines it needs for the DAQ devices.

 

Meanwhile, back at the Consumer, it reads the (now combined) data and asks "Is this the Sentinel?".  If False, it just processes the data, as normal.  But if True, there is no data to process, so it write "True" to the Stop Terminal and exits the While loop.  So the Producer has exited its loop (because it sent the Sentinel), and the Consumer has exited its loop (because it has received the Sentinel), so now the Consumer knows it is safe to Release the Queue (and close TDMS, and any other thing).

 

So what makes a good Sentinel?  Look at your Queue's Data.  If it is (or includes) an Array, an Empty Array would certainly work (as the Producer would never put an Empty Array on a data Queue except if it were a Sentinel).  If you are using a Cluster, you could add a Boolean element ("All Done") whose default value is False, and set it True to create the Sentinel.  [This is what I'd suggest if you decide to combine the two Queues of your original routine into a single Queue of a Cluster.  Booleans take very little room, and are very fast (and "logical") to process -- if "All Done", then stop the Consumer.

 

Bob Schor (I'm keeping track -- that's two "virtual drinks")

0 Kudos
Message 11 of 11
(275 Views)