LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Local variable/global variable/ FGV: when to use them? ( Scenario outlined)

Solved!
Go to solution

So I have a situation where am using events triggered by a button press to start a motor and perform data acquisition. But before this the user inserts some input paramters. Since those inputs have controls on the FP: the issue is where to put those controls and how to write to them from at least 2 locations ( from front panel user input or from within a subvi due to a programmatic change; and read from them from multiple locations ( subvis)? 

 

What I tried: I put the controls inside events: value change triggers update of global variables. These global variables I then use anywhere. However from within a subvi if I need to write to the global variable, how to change the value on the Front panel: guess I will need to update a local variable. Is there a better way? 

 

Other question: What is the rational of using FGV compared to a global variable apart from solving certain types of race conditions? 

 

 

 

 

0 Kudos
Message 1 of 23
(4,478 Views)

To update a control value from within a subVI, you might want to use a value property node. Just use the control references as an input to the subVI.

(If the new value should also trigger an event, use a signaling property node).

Message 2 of 23
(4,466 Views)
Solution
Accepted by rajiv85

@rajiv85 wrote:

Since those inputs have controls on the FP: the issue is where to put those controls and how to write to them from at least 2 locations ( from front panel user input or from within a subvi due to a programmatic change; and read from them from multiple locations ( subvis)? 


You have a few options.  As Christian mentioned, you can just store the control references inside of your fgv and then use property nodes to read/write value.  However, if you are frequently setting these values (on the order of once every few ms vs every few s), this is a bad idea.  Property nodes have quite a bit of overhead.

 

Another option would be to use get/set value by index. For these functions you need to know the index of the control you're referencing, but they have a considerably lower overhead than property nodes.

 

The final option here would be to just store all of the values inside of your fgv, but don't actually update the controls directly from there.  In your main GUI you just have a loop or something reading the values out of your fgv and updating the controls there, while the subvis can update just the fgv.

 


@rajiv85 wrote:

Other question: What is the rational of using FGV compared to a global variable apart from solving certain types of race conditions?


Another term for "fgv" that I've seen used is "Action Engine".  To me this is much more clear and descriptive.  You can have an fgv do much more than just store your data.  You can have it manipulate data, read files, write your data, etc.

 

Ben did a great writeup on action engines some years ago.  You can find it here.

 

Message 3 of 23
(4,454 Views)

THANK YOU VERY MUCH both the legendary Altenbach and BowenM !! 

0 Kudos
Message 4 of 23
(4,442 Views)

I'd just like to add that a "Many to one"-function is Type A example of when a Queue is a good tool. 🙂

You can use an AE (FGV+) to create and store a queue ref and use it to send commands.

So, AE with Init, Get queue ref, Queue data, Close

Init AE at start of program

Use Queue data whenever you want to update something

A loop which uses 'Get queue ref' to actually update the indicator

Close ref as you exit program.

/Y

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

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 5 of 23
(4,379 Views)

@Yamaeda wrote:

So, AE with Init, Get queue ref, Queue data, Close

Init AE at start of program

Use Queue data whenever you want to update something

A loop which uses 'Get queue ref' to actually update the indicator

Close ref as you exit program.


I have learned over the years that this is not quite a good setup.  You should only have 1 loop that is a consumer of the queue.  So I do not even have the Get Queue Ref.  The consumer calls the Init and gets the queue reference as part of that.  It can then dequeue for the lifetime of the process.  The consumer should then also be the one calling the Close.  So what this points to is a library for the Consumer.  The AE should be a private member of this library and you make public message VIs that call the Send case of the AE.  This way, the reference is protected and the messages that can be sent to the consumer are explicitly defined.


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
0 Kudos
Message 6 of 23
(4,370 Views)

@rajiv85 wrote:

Other question: What is the rational of using FGV compared to a global variable apart from solving certain types of race conditions?


A Look At Race Conditions


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
0 Kudos
Message 7 of 23
(4,367 Views)

Big kudos for outlining these possibilities. 

 

Some things are not clear to me:

 

Let us have a basic program that has no subvis: all the variables are being updated by local variables. But as the program gets larger we need to compact them in subvis and within the subvis other subvis etc. This is a common scenario. Now comes the question how to link the front panel variables to the subvis, how to update them from within SubVis etc..

 

>> So far am going with the idea of using a value change event to the variables to update global variables. The globals are then used everywhere. Except when they are written to: in that case they need to be written to a property node of the variable through the subvi, via a reference or a local variable. Am still wanting to know if this is the best way. Well it does not use dataflow in that case. So how else to do that? 

 

Now we are speaking of queues. It is not clear to me how can they be used for the scenario above. And using libraries for the consumer with private etc.. not making sense to me. Any example of such implementations would be greatly appreciated!

 

 

p.s: am checking this video from Time Robinson/ aka. crossrulz 🙂https://forums.ni.com/t5/2016-Advanced-User-Track/TS9454-Are-Global-Variables-Truly-Evil/gpm-p/35386... !!  Great Stuff..excited to check it out. 

 

haha.. this is the funniest labVIEW pic ever...

haha..so funny.PNG

 

 

 

0 Kudos
Message 8 of 23
(4,335 Views)

It sounds like you're looking for general advice and best practices.

 

A. You started with a big unwieldy block diagram full of code without subvi's.

B. It seems you relied heavily on local variables to share data from code in one part of the diagram to another. 

C. Now you want to select chunks of code to turn into subvi's, but the presence of these local variables is complicating things.

 

1. The first simple thing you can do is not to select those local variables when creating a subvi.  Move them outside the rectangle before selecting, or manually unselect them before creating the subvi.  Now the *value* going into or out of a local variable will instead pass through a subvi terminal.  LabVIEW won't try to include the local variable itself as part of the subvi.

 

2. That simple approach is only a first step.  Heavy reliance on local variables is not a "best practice".  What it *is* is easy and fast to throw into the code.

   In other words, you might solve some of your problems with that relatively simple step.  But odds are, you won't be solving the most important ones.  Keep reading.

 

3. Heavy use of local variables often makes you vulnerable to race conditions, *ESPECIALLY* if more than one part of the code can write new values to them at any given time.   You will not solve this part of the problem by making subvi's.  Instead, you will need to rethink some things about how the code as a whole is structured and how the different parts interact.

 

4. A lot of the folks offering help are LabVIEW experts.  The way *they* solve this kind of problem is to not get themselves into it in the first place.  They've developed an understanding of how LabVIEW works, the implications of parallel operations, the vagaries of OS timing, and a bunch of other stuff that helps them choose a better code structure and better data-sharing methods right from the start.

    LabVIEW makes it very easy to write code that executes in parallel.  The programmer still needs to carefully think about the *implications* of the parallel-running code and take measures to avoid possible pitfalls.  This part is less easy.

 

Item #1 is about all I can suggest to specifically address your problem without knowing your app and seeing your code.  Items #2-4 are meant to be some very general cautions and comments.  There might be some more difficult race condition problems ahead, and those are often easier to *avoid* than to fix (or even sometimes find) after the fact.

 

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 9 of 23
(4,315 Views)

kevin please help me here, and am sure this will be of help to others who stumble on this topic.

 

What you explained i understand this. Am at the stage where this is what am doing:

I put the controls inside events where value change triggers the update of global variables. These global variables I then use anywhere including the subvis. However from within a subvi if I need to write to the global variable I then use a property node of the variable via reference through the subvi. 

 

I want to know what is the best practice to avoid the use of too many local variables.In general what is the best practice to have a lot of subvis and events loops that refer to controls from the front panel: how to link and communicate, write and read to the subvi from the subvi and the front panel controls as the subvis either work in a parallel loop or via an events button..? This is what I want to know. 

 

''

They've developed an understanding of how LabVIEW works, the implications of parallel operations, the vagaries of OS timing, and a bunch of other stuff that helps them choose a better code structure and better data-sharing methods right from the start.

    LabVIEW makes it very easy to write code that executes in parallel.  The programmer still needs to carefully think about the *implications* of the parallel-running code and take measures to avoid possible pitfalls.  This part is less easy.'' => I want to learn more about all these. Where can I learn about it? i did not encounter any material explaining how to do these so far. 

0 Kudos
Message 10 of 23
(4,292 Views)