LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Are global variables frowned upon for calibration and context data?

Anyone who has read any forums about LabView knows that Global variables are typically frowned upon. I have a use case which seems common enough that I'd imagine most users have come across it once or twice, but GVs are rarely mentioned in those threads, so my intuition tells me I might be missing something.

 

I need to store hardware calibration data and some context data somewhere, and it's likely going to be referenced multiple places in nested VIs. I have some motorized travel stages which will have physical offsets set by the user only when assembling the system for the first time, and some context data that will impact algorithms. This context data will ideally be stored in the program's config file, and will never be changed except in situations where execution of everything else should be stopped. Having this data as a wire passing through many sub-VIs seems like a way to clutter the entire program. 

 

Is this the mythical correct application for Global Variables?

0 Kudos
Message 1 of 8
(2,987 Views)

Are Global Variables Truly Evil? 

 

In your case, I would probably have a class for each stage.  The class would include these offsets, current positions, communication port, etc.



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 2 of 8
(2,973 Views)

@Nokaroa wrote:

Anyone who has read any forums about LabView knows that Global variables are typically frowned upon. I have a use case which seems common enough that I'd imagine most users have come across it once or twice, but GVs are rarely mentioned in those threads, so my intuition tells me I might be missing something.

 

I need to store hardware calibration data and some context data somewhere, and it's likely going to be referenced multiple places in nested VIs. I have some motorized travel stages which will have physical offsets set by the user only when assembling the system for the first time, and some context data that will impact algorithms. This context data will ideally be stored in the program's config file, and will never be changed except in situations where execution of everything else should be stopped. Having this data as a wire passing through many sub-VIs seems like a way to clutter the entire program. 

 

Is this the mythical correct application for Global Variables?


This would be an appropriate use of globals, but if you can manage it, I like   solution better.

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 3 of 8
(2,954 Views)

Thank you for the video, I will watch it when I get the chance.

 

I am confused by the suggestion to use a class though. My goal is to be able to set these from outside of the program and store them in a file which can be edited during setup of the program. If I have a class for each stage, and I need to reference that data in multiple places, I still need to wire that class through every relevant VI which brings leaves me with the original problem, unless I make those classes global.

0 Kudos
Message 4 of 8
(2,945 Views)

It's not that using Locals/Globals are always wrong (Like the Stacked Sequence.. 😛 ) but they are too often misused and cause race conditions. 

 

I tend to put things like Calibration values, sailing factors, and etc. in a Type-Def Cluster and pass it through my sub-vi's, the use Unbundle by name to get the values out.

 

Similar to what you want, I store all my instruments specifications, scaling factors, and lots of other information in an XML file that is parsed and puts everything into my "instrument cluster" and passed through the VI's as needed

========================
=== Engineer Ambiguously ===
========================
Message 5 of 8
(2,938 Views)

@Nokaroa wrote:

If I have a class for each stage, and I need to reference that data in multiple places, I still need to wire that class through every relevant VI which brings leaves me with the original problem, unless I make those classes global.


Are you not already doing that for your stage references?

 

Additionally, unless something in your object gets changed in a method, you do not really need to "wire it through" a VI.  You just need to wire it into the VI.  This makes it more obvious where objects get updated and therefore easier to debug.  Look up Darren Natinger's "End Brainless Programming" presentation.  He hits on this.

 

And one more thing I'll add.  I tend to use an Action Engine to store my objects or DVRs to objects for a particular device type.  The AE stores them in a Map, allowing me to perform the actions on a particular object by a name.  This does add an additional level of wrapping, but I have found it to help in test sequences.  And, yes, all settings are managed by a file of some type (currently JSON or XML).



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 8
(2,927 Views)

@Nokaroa wrote:

Anyone who has read any forums about LabView knows that Global variables are typically frowned upon. I have a use case which seems common enough that I'd imagine most users have come across it once or twice, but GVs are rarely mentioned in those threads, so my intuition tells me I might be missing something.

 

I need to store hardware calibration data and some context data somewhere, and it's likely going to be referenced multiple places in nested VIs. I have some motorized travel stages which will have physical offsets set by the user only when assembling the system for the first time, and some context data that will impact algorithms. This context data will ideally be stored in the program's config file, and will never be changed except in situations where execution of everything else should be stopped. Having this data as a wire passing through many sub-VIs seems like a way to clutter the entire program. 

 

Is this the mythical correct application for Global Variables?


I have used globals in this manner in the past, without too much issue. As said previously some care needs to be taken to ensure no problems or race conditions. Here are a couple of things I do that are helpful with global variables:

 

For something like calibration data where you want to ensure that that the value is not changed while a process is running, I do this below:

The False Case is wired straight through.The False Case is wired straight through.

In the above case, the Global Variable (GV) is read on the first call of the process and that value is used throughout the lifetime of the process. If the user in this case wants to change FFT Units, then only new asynchronously called processes will have this change, currently running processes are unaffected.

 

The other thing I like to do is store all GVs in a single file. This makes it easy to write and read preferences at the beginning of a program. (If you allow your user to change options, this makes updating an INI file easy.) You can do something like below:

Read file with all global variables. Get the names and values programmatically.Read file with all global variables. Get the names and values programmatically.Write file with all global variables. Get the names and values programmatically.Write file with all global variables. Get the names and values programmatically.Write subVI: Use the variant pallete for data type parsing. Make a case for each data type.Write subVI: Use the variant pallete for data type parsing. Make a case for each data type.Read subVI: Use the variant pallete for data type parsing. Make a case for each data type.Read subVI: Use the variant pallete for data type parsing. Make a case for each data type.

0 Kudos
Message 7 of 8
(2,919 Views)

I typically build a class in these situations, but by reference using a type-def control packaged in a Data Value Reference (DVR) as the class' private data. I then have setters and getters for all of the main elements within the DVR. This allows me to manage read and write access and track down which methods, functions etc. use the data. You can still end up with race conditions, but I much prefer by-ref than by-value classes for ease of use when wiring. I know this generally goes against the whole LabVIEW by-value paradigm, but I've been using it for years with good success.

 

You could also have a read-only class type which doesn't expose any of the setters and then have a write class inherit from this or have it as a component of the write class. That way you can prevent calibration data being inadvertently modified by VIs that should only ever be consuming the data.

0 Kudos
Message 8 of 8
(2,637 Views)