LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
0 Kudos
Bob_Schor

Do Once loop structure

Status: Declined
Functionality is already in LabVIEW.

My apologies if this has already been suggested ...  I've written many VIs with a While loop that has True wired to the Stop terminal, making it a "Do Once" loop.  This is such a common construct (i.e. a VIG) that it might merit its own "structure", something that "looks like" a While loop but has no Stop terminal, no "i" indicator, and is guaranteed to "Run Once".  I think having a unique "look" for this common special use of the While loop would be a useful addition.  Among other things, it would clearly distinguish "purpose" as different than a While construct.

 

Bob Schor

9 Comments
tst
Knight of NI Knight of NI
Knight of NI

Some relevant points: 

 

Old versions allowed you to have a while loop without wiring into the conditional terminal. I understand this was changed when the option to change the behavior of the conditional terminal was implemented.

 

You can use a for loop with 1 wired into the N terminal (which I don't like).

 

In current versions you can use a feedback node without a loop.


___________________
Try to take over the world!
Knight of NI
The only real place I've used this type of construct is when creating LabVIEW 2-style global variables, AKA functional globals, AKA Action Engines. Not sure where else this would come in useful. Can you provide some use cases for this?
G-Money
NI Employee (retired)
Status changed to: Declined
Functionality is already in LabVIEW.
Bob_Schor
Knight of NI

I use this all the time to create routines that run periodically or get called from several places to do several things.  For example, if I'm using a queue to send information between two asynchronously-running processes, I create a VI called something like "Manage Queue" that looks like a State Machine inside a "Do Once" loop.  I pass in an enum that has values like "Create Queue", "Enqueue", "Dequeue", and "Destroy Queue".  The queue, itself, "lives" entirely inside this VI on a shift register.  Both the "caller" and "callee" call it with "Create Queue" (which means that neither one needs to "know the name" of the queue, because this can be a constant internal to the VI, hence guaranteed to be the same for both caller and callee).  Typically, the Caller would then call it with Enqueue requests (passing in stuff to go on the queue) and the callee would call it with Dequeue requests (letting it return the next queue element, or optionally a Timed Out boolean, as I see fit).  All of the details and "messy stuff" are hidden inside the VI.  This enables me to code the "real program" (the one that actually uses the queue) by simply putting a single VI in the initialization step with "Create Queue" wired to it, a copy in the "producer loop" that has "Enqueue" wired in, as well as the element being produced, and in the separate "Consumer" VI, a similar initialize/Dequeue series of calls.  Keeps things very neat and understandable.

 

Another example would be a routine that makes a "chart-like" 2-D graph.  For example, if I have something moving in X-Y space and I want to plot its position as it moves, I can create a "Make Plot" VI that has a State Machine with "Initialize Plot" and "Update Plot".  "Initialize" creates something analogous to a chart's "History", an array of the last N points (you'll see why shortly), and an index into this array.  It also makes the initial plot (where all the points are at (0, 0) from the Initialize step).  Each call to Update Plot, which is done "once-per-clock-tick", so happens on a regular (timed) schedule), another point is passed in, where it is placed in the plotted array in the "next" (circular) point.  What this does is to make a plot that "moves leaving a trail", that is, if you have 5 points in your history, you'll see the most current point and the last 4 as well, letting you visually see (by the length of the trail) how fast the points are moving.  Again, all the data are contained inside the shift register of this VI, which executes as a "Do-Once" loop.  Numerous other examples can be dreamed up.

 

The point is that the "memory" aspect of a Do-Once loop, namely the ability to save things in shift registers, goes well beyond the concept of a "Functional Global Variable" or a "Virtual Global" (or whatever VIG means).  Yet I still have to explain to my students why I'm coding a While Loop with "true" wired to the Stop terminal ...  It has nothing to do with "repetition" (= While), and everything to do with shift registers and "persistence".  Hence a unique structure would have mnemonic value, in my opinion.

 

BS (there's no connection between my initials and my opinion of my opinion!)

tst
Knight of NI Knight of NI
Knight of NI

> It has nothing to do with "repetition" (= While), and everything to do with shift registers and "persistence".  Hence a unique structure would have mnemonic value, in my opinion.

 

 

Like I said, in modern versions you can use a feedback node without a loop. Isn't that good enough for you?


___________________
Try to take over the world!
Bob_Schor
Knight of NI

The point isn't whether it is "good enough for me", but rather more an issue of LabVIEW "style".  I will definitely concede that this "isn't needed" (particularly in LV2010, where boolean constants are pretty tiny and "disappear into the background").  To be honest, it didn't occur to me to use a "feedback node" in a situation that doesn't involve "feedback" (hence the lack of mnemonic "power").

 

So I gave it a try!  Where there is only a single quantity in a shift register, replacing it with a (somewhat visually-more-cumbersome) feedback loop certainly works.  However, when one has multiple "static variables" in shift registers, it gets very messy and difficult to visualize using feedback nodes (in my opinion).

 

Again, the point I was trying to make was that a "Do Once" structure that has the ability to "remember" variables in shift registers is a particularly useful LabVIEW construct, one that goes way beyond Functional Global Variables.  For this reason, I posted the suggestion that this structure be elevated to have its own identity, rather than be cobbled together as either (a) a For Loop with 1 wired to the count (I just thought of this!), (b) a While loop with True wired to Stop, or (c) a Feedback node.  One would use this special construct only for the purposes that it was intended, giving it mnemonic power, the ability to glance at the structure and realize what the user was trying to accomplish.  Note that using loops "suggest" ("imply" may be too strong) that some "looping", i.e. repetition, is involved, when the intent is "Do Once!".

 

For now, I'll stick with the While formulation, as it seems (logically) cleanest and closest to "Do Once".

 

Bob Schor

JackDunaway
Trusted Enthusiast

I'll second the support of the Feedback Node as the more desirable alternative for maintaining local data on a diagram between calls. It has exclusively replaced the "True-wired-to-While-Loop-with-USRs" structure in my code, beginning in early 2009 with Darren's endorsement. Enhanced functionality (e.g., Initializor Terminal configuration) of the FN in LV2009 was icing on the cake.

AristosQueue (NI)
NI Employee (retired)

I'm with Bob on the feedbacknodes. I definitely prefer a loop syntax to a feedback node syntax -- I can't read the damn things.

 

Having said that, I keep imagining what I would draw to represent a "Do Once" structure, and I keep coming up with a For Loop with a 1 in the corner instead of an N. Doesn't seem worth it.

tst
Knight of NI Knight of NI
Knight of NI

Incidentally, in the link Jack posted you should find some mockups I did of potential improvements to FNs. From all of them, I like the top one the most.

 


___________________
Try to take over the world!