From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Best practice to access large number of controls

Hi,

I would like to know how the "pros" handle programmatic interaction with a large amount of controls at once when a program reaches a substantial size (many tens or >100 controls over several tab pages). There are two actions in particular I have to do all the time, especially in scientific programs (but I'm sure it applies to many other categories):

1. Enable/disable (large) groups of controls during certain times/modes of operation.

2. Initialize all/most control values (usually at startup) by reading settings from some data source (e.g. a config file).

 

My approach to this, which developed over the years, works "ok" but I assume there is a better practice for that. For case 1, I create a huge array of explicit references to all controls I want to enable/disable this way (right click on terminal -> create -> reference) and then this array can be used anywhere in the program to set the enable/disable property in a For loop (typically via a subvi). This requires a large section somewhere on the block diagram of the main program to explicitly build that large reference array from all the control references. This cannot go into a subvi because a reference is linked only within the same vi. For case 2, reading the initialization values (e.g. from a config file) can be done in a subvi and returned as a cluster (or array of variants) to the main program. Still, I have to explicitly wire every single control (via a local variable) to the corresponding cluster/array element to set the value of that control. All this results in quite a bit of spaghetti when the program gets large.

 

I thought about how this would be normally done in a text-based language and I guess the easiest way would be to loop through a list of variable names and do all the stuff programmatically which I do explicitly (i.e. get references, assign values etc.). While this is certainly possible in Labview (list control references by name lable), the concept of "variable names" is not as strong, simply due to the fact that a control's name can be changed at any time without messing anything up (i.e. all references, local variables, events etc. are updated accordingly). So I'm wondering what's the best practice in that case to access a large number of controls programmatically with minimal spaghetti. Having a list of control names would be elegant (because it could go in a subvi) but then I could never change the name lables of controls or manually update the list when I do. Is there a better way?

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

Hi Novgorod,

 

For case 1, I create a huge array of explicit references to all controls I want to enable/disable this way (right click on terminal -> create -> reference) and then this array can be used anywhere in the program to set the enable/disable property in a For loop (typically via a subvi).

Why don't you read the control elements property of your panel/pane? Much easier than to collect all references one by one! This also belongs into a subVI which takes a reference of the panel as input…

 

I thought about how this would be normally done in a text-based language and I guess the easiest way would be to loop through a list of variable names and do all the stuff programmatically which I do explicitly (i.e. get references, assign values etc.). While this is certainly possible in Labview (list control references by name lable),

I do it this way: create a key-value-pair list with the control label as key and it's reference as value. Read only once at start of the VI and stored in a FGV (aka AE)…

 

the concept of "variable names" is not as strong, simply due to the fact that a control's name can be changed at any time without messing anything up (i.e. all references, local variables, events etc. are updated accordingly).

When YOU (as "the programmer") change a control label then YOU (as "the programmer") are responsible to track any resulting problems!

I use some guidelines for control labels like using AO_01, AO_02, … to mark controls used to set analog output values. Once you implement such guidelines it is very easy to filter for needed control references by their name!

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
Message 2 of 8
(2,216 Views)

i think there'ssomething wrong

0 Kudos
Message 3 of 8
(2,203 Views)

@GerdW wrote:

I thought about how this would be normally done in a text-based language and I guess the easiest way would be to loop through a list of variable names and do all the stuff programmatically which I do explicitly (i.e. get references, assign values etc.). While this is certainly possible in Labview (list control references by name lable),

I do it this way: create a key-value-pair list with the control label as key and it's reference as value. Read only once at start of the VI and stored in a FGV (aka AE)…

 


Just to add to GerdW's answer, a convenient way of storing and accessing the key-value pairs is by using variant attributes as a look-up table.  See https://forums.ni.com/t5/LabVIEW/Darren-s-Weekly-Nugget-10-09-2006/m-p/425269 for more information.  Of course, if you are using LV2019, you can use the new Maps feature.

 

Andy

Message 4 of 8
(2,172 Views)

For a group of controls that would always be enabled/disabled together, put them in a cluster.  Then you just need to enable/disable one item (the cluster).

 

For saving recalling control values, using XML files can be cleaner than .INI files.  Even better is to use LV object class data and store it in a binary file. This provides automatic data mutation which greatly simplifies updates to your data set.

"If you weren't supposed to push it, it wouldn't be a button."
0 Kudos
Message 5 of 8
(2,146 Views)

In cases like that, one thing I do to clarify the block diagram, is to use the very-frowned-upon practice of nesting event structures.  For example, an outer event structure that captures Value Change events on clusters, then within each case, another event structure that captures Value Change events on the individual elements of the cluster.  This results in a nice hierarchy of cases.  But if you don't do it right, your VI can seize up.

"If you weren't supposed to push it, it wouldn't be a button."
0 Kudos
Message 6 of 8
(2,139 Views)

All(?) terminals has the parameters Label (variable name) and Caption. To reduce problem with changing variable name, let the Label be as constant as possible while changing the Caption.

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

Thanks for the suggestions so far.

 


@GerdW wrote:

Why don't you read the control elements property of your panel/pane? Much easier than to collect all references one by one! This also belongs into a subVI which takes a reference of the panel as input…

Typically it's only a subset of all controls that I want to enable/disable or initialize values for. Getting all references first and then removing those I don't want to access seems to be a similar effort as what I'm doing. This way would be faster if I want to access more than 50% of all controls in the program - then I just have to make an explicit array of controls I don't want to access and remove them from the "all controls" list.

 

I do it this way: create a key-value-pair list with the control label as key and it's reference as value. Read only once at start of the VI and stored in a FGV (aka AE)…

Sounds good, but again, how do you populate this list? Do you make a list of control labels (array of strings) and then programmatically get the references? This seems to be the easiest way but requires "discipline" with regards to labels.

 

When YOU (as "the programmer") change a control label then YOU (as "the programmer") are responsible to track any resulting problems!

That's certainly not a problem once you're aware of it (as you have to do in text-based languages). What I meant was that Labview's "source code" structure is very different from text-based languages and one such difference is that instead of "variable names" we have references as unique identifiers for "objects" (such as controls) whose labels are non-unique properties. Sure, we can follow similar conventions as with text-based languages, i.e. always use unique labels and never change them (or track the changes carefully), but is that best practice for Labview? Well, all I'm saying is that it would be neat to use explicit control references (create -> reference) as unique identifiers across vis (instead of non-unique labels) but I guess that's not possible because the actual reference numbers are generated dynamically when the vi is loaded into memory.

 


@paul_cardinale wrote:

For a group of controls that would always be enabled/disabled together, put them in a cluster.  Then you just need to enable/disable one item (the cluster).

 

For saving recalling control values, using XML files can be cleaner than .INI files.  Even better is to use LV object class data and store it in a binary file. This provides automatic data mutation which greatly simplifies updates to your data set.


I do put them in a cluster when it makes sense in terms of UI structuring but it's not really possible when they are separated by other controls or UI elements or when they are on different tabs. Regarding the storage of control values, I prefer ini files because they are easily human readable and editable, which is a great and quick way to adjust settings without implementing a GUI for that (or just for some of the settings) in the main program. Of course I'm aware of the limitations and don't store fancy data types or large amounts of data there.

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