LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Outputting values from a while loop in a subVI

Solved!
Go to solution

Hi all,

 

So I have a problem which apparently doesn't really have a solution (or at least I couldn't really find one). Here's the deal:

Counter_subVI.png

I have a subVI which just increases a counter at a given time interval, inside a while loop. This loop has a stop button. When tested separately the counter updates correctly and the stop button works fine. Now, let's take the counter and the stop button, route them as terminals and put everything into a subVI. When using the subVI neither the counter is updated, nor the stop button works.

 

How to solve this? I want the value from the counter from the subVI to propagate to the main VI. I also want the stop button to work from the main VI.

Please note that this is a very oversimplified example. I reality I have an event driven communication protocol and therefore needs to be inside of a loop (in order to wait for the event to occur) and then output the data from the transmission (via a terminal, because it all needs to be implemented inside a subVI to be used later). But I feel if I have the solution to the simplified example, it will also work for the more complex scenario.

 

subVI and main VI attached.

 

Thank you in advance for any suggestions!

 

Ray

Download All
0 Kudos
Message 1 of 9
(1,848 Views)

At this moment your sub-vi receive either a True or False from your main and either insta-kill the subvi or perma-block it.

 

Several possibilities to update the values :

- Use references and properties nodes to get/set the values

- Use FGV in a parrallel loop to get/set the values

- Use producer/consumer architecture and drive this with events and queues

 

You can mix all of this to solve your problem :

 

How to solve this? I want the value from the counter from the subVI to propagate to the main VI. I also want the stop button to work from the main VI.

Please note that this is a very oversimplified example. I reality I have an event driven communication protocol and therefore needs to be inside of a loop (in order to wait for the event to occur) and then output the data from the transmission (via a terminal, because it all needs to be implemented inside a subVI to be used later). But I feel if I have the solution to the simplified example, it will also work for the more complex scenario.

 

The stop button push is creating an event. This event update the FGV to stop the subvi.

The data in the subvi is reference linked to update the GUI. The same data is written into a FGV to store it for later.

0 Kudos
Message 2 of 9
(1,824 Views)

Hello Defaphe and thank you!

 

Functional global variables were indeed a good solution. To anyone else wondering, here's how the final solution looks like:

 

FGV.png

 

You can learn more about FGV here.

 

Thank you again!

0 Kudos
Message 3 of 9
(1,799 Views)

You might as well just use an actual global variable.

 

References:

A Look At Race Conditions

Are Global Variables Truly Evil?

 


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 4 of 9
(1,795 Views)

@crossrulz wrote:

You might as well just use an actual global variable.

 

References:

A Look At Race Conditions

Are Global Variables Truly Evil?

 


Indeed.  As I understand it, Functional Globals existed because In early LV, there was no such thing as an actual global, so the FG was born to fill that need.  Unless you are actually doing stuff other than getting and setting in your FG (at which point it becomes an Action Engine), you may as well just use an actual global, as it is a lot faster.

billko_0-1651759093127.png

 

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 5 of 9
(1,791 Views)
Solution
Accepted by jano_rajmond

@crossrulz wrote:

You might as well just use an actual global variable.

 

References:

A Look At Race Conditions

Are Global Variables Truly Evil?

 


While in this case I would agree that a regular global variable would be better than a FG, I still cringe when I see this as a solution. I generally work on larger systems and there is no way I would allow the use of globals or FG to pass data through the system. The one exception would be WORM values (Write once, read many) which are static values that are initialized at start up. IN all other cases I prefer and recommend an explicit method (queue, class, notifier) to pass data between subsystems. Once you start using global variables you start tightly coupling the code and make re-use much harder. It also signifies a poorly designed system since you are allowing different subsystems access to other subsystems data implicitly. There is also no control to prevent outside actors from modifying the data. Global variables don't provide any protection to prevent writes from happening anywhere in the code.

 

Unless someone can describe to me why a global variable should be used, that they are aware of all of the risk factors involved with using them and have made a very conscience decision to use them I will not recommend them.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 6 of 9
(1,780 Views)

Thank Mark and everybody else for the replies!

 

I did end up using queues (once I figured out how to correctly design the loops in parallel) and it works indeed better than FGV.

 

However, I still have a problem with the Stop button to stop all activity. For that a queue is not suitable )I would "push" only one element (when the button is pressed), but would to "pop" several to stop multiple loops). Notifications don't work because the "Wait on notification" action pauses the loops until a notification arrives. I'm looking into somehow creating a "custom" event when the button is pressed and then having multiple event structures that all trigger on the same custom event. Would that work?

 

Any better ideas for this? Thanks!

0 Kudos
Message 7 of 9
(1,727 Views)

@jano_rajmond wrote:

 

Notifications don't work because the "Wait on notification" action pauses the loops until a notification arrives.


Did you notice the timeout terminal on the "Wait on notification"? This is definitely an option.

 

I personally like to have a communications loop that communicates with all of the loops and with the calling vi. I use a messaging approach where the queue contains a cluster with a string and a variant. The string contains the message name ("Stop" for instance) and the variant contains any data that is associated with that message (usually not necessary for the stop message). This allows me to communicate Stop as well as any other messages to the loop, thereby increasing the ability to add functionality in the future (perhaps, for instance I later want to send some kind of configuration information from the main loop to one of the loops in the subvi - I already have the structure to do it). An example of this can be found in the queued message handler fundamentals example.

0 Kudos
Message 8 of 9
(1,712 Views)

@jano_rajmond wrote:

However, I still have a problem with the Stop button to stop all activity. For that a queue is not suitable )I would "push" only one element (when the button is pressed), but would to "pop" several to stop multiple loops). 


Well, I try to make all of my parallel loops (especially the ones that run as "detached Clones") stop when I push the Stop button wired to the Stop terminal of the Main VI's State Machine, for example by sending "exit" messages to "helper" loops.  But the other technique I've used is to create a Global Variable that I call "Global Stop" and make sure it is connected (sometimes via an OR gate) to the Stop terminal of all of my Loops.  This certainly qualifies as a Write Once/Read Many  (WORM) situation, as after the Read, the loop shuts down and won't read any more!

 

Bob Schor

0 Kudos
Message 9 of 9
(1,695 Views)