Control references vs. global variables

I guess my question centers on the appropriate application of control references.
I am writing a complex program that has a state machine at the top level, and, for one frame of the state machine, a while loop containing a couple subVIs, each of which contains many subVIs. The lower-level subVIs are affected by buttons on the top-level VI. Information from the lower-level VIs must be shown on the top-level front panel within the loop. My question is: what is the best way to do this?
(I have a previous version of the program that I wrote that keeps just about everything on the top level so that I can update the front panel, but this is not at all modular.
In addition, I considered breaking things up into more than on
e front panel, but this doesn't seem to be a good option for this section of this program.)
Last week I read about control references, and decided that this could be the way to deal with this issue. I have not worked with them before, so I want to know: Are control references an appropriate solution for this issue? Is it good programming practice to use them, especially to update data on charts and graphs? How do they compare programming-wise and efficiency-wise to global variables?
Global variables are another solution, I think, but I would have way too many variables to update. I think the advantage with global variables is that one could just insert a global variable in a subVI and not have to wire it up through the different subVI levels, which one would have to do (I think) with control references.
Can you offer any advice?
Thanks!

Paul,
The actual implementation of the solution is up to you. This is indeed a complex question.
I would offer the following advice:
On globals:
Try to avoid them. I try to restrict the use of globals to unidirectional. If you have ever dealt with a race condition, you will know why. Mistakes are often made with globals, and they are quite apt to become the biggest source of bugs in a program, especially in one as large and/or complex as your appears to be. If you must use globals, try using a shift register, or LabVIEW 2 style global instead. Basically, you use an unitialized shift register with two (or more) cases: Read and Write. This prevents race conditions, but only if the VI is non reentrant. However, implementation is still difficult.
Control References:
I also have read and heard about control references. I have had much use for them, for controlling the appearance of controls and indicators (and decoratiopns too, I guess...). However, I would caution you on using them to pass data around. This violates dataflow in a big way, as you are passing around pointers, instead of data. I believe this is difficult to implement, and even more difficult to keep straight. I personally recommend using them only for attributes of FP components, not for passing data.
So, what do I believe is the most elegant solution? I think a data server is your best bet. This is close to a LabVIEW 2 style global, but a little more active. Simply write all of your data into a subVI in any manner, a queue, a FIFO, LIFO, etc. Then, retrieve the data as desired. Buffering, queuing, etc are all handled by the data storage and retrieval subVI. It becomes sort of a small active database. The two sides (storage and retrieval) are independent of each other, and the code is all handled in the function. A basic version is a LIFO, Last In First Out, wherein the data is overwritten constantly. The data is then read by the reading VI, the front panel VI in your case, at any time, and the data is always the latest. You can add complexity as you need, such as making it a FIFO. This is done by simply writing the data to an array, then reading back the oldest value (by reversing the array and reading index 0.)
I believe this is an elegant solution to your problem. It does maintain dataflow, except that time is taken out of the equation, depending on how you look at it. It simplifies your program because you only need to do three things. Write the data handler, then drop in the function into the VI that writes, and the one that reads. It is also flexible in handling the data.
Good luck, and let us all know how you do.

Similar Messages

  • How do I store VI References in global variables and access them later

    From what I know, Labview automatically deletes VI references when they go out of use. Is there a way for me to override this so that I can access a set of preloaded references in a separate VI? Essentially I would like to open the VI's dynamically into the memory, store the references in global variables and access them at a later time. The VI's I'm referencing won't be known until runtime. I know its not the safest way to do it, but it would be the most productive on my end.
    Thank you
    Clay Upton

    I'm not sure what you mean by "a later time", but a VI reference will remain valid as long as the VI is in memory. If you don't unload the VIs, the references will remain valid.
    If you do need to unload the VIs, for whatever reason, I would suggest the following:
    Create a functional global as your interface for obtaining the references.
    Feed the paths to the VIs into the VI when initializing it (since you don't know which VIs in advance).
    When calling the VI to obtain the references, have the VI check them first (using the Not a Number... primitive). If it sees that they're invalid, it can open a new reference and return that.
    You should note that when a VI is removed from memory, the data space is used is released, so if those VIs are expected to hold data (using shift registers, etc.) this will be a problem.
    The description I've given will only be usable in certain instances (and it has its intricacies), but you didn't really give any details about what you're actually trying to accomplish.
    Try to take over the world!

  • Control global variable used in sub vi

    Hi,
    I've created a vi to read an instrument and to initiate its calibration with labview. This VI stores data in a global variable containing measurments and status of the instrument.
    Now what I'm trying to do is create a sub vi with this to read&write 2 exactly identical instruments so I can finally create a VI that read all 3 instruments simultaneously.
    How could I create a control on the global variable used by the sub VIs since it is the only thing that will change along with its COM port ?
    I included a screetshot of the current VI.
    Thanks,
    Attachments:
    Read_Calibrate.PNG ‏61 KB

    I would make an array of values and then you just pass in which value to update.  I would actually take it a step further and make an Action Engine that can update the data and return the data.
    There are only two ways to tell somebody thanks: Kudos and Marked Solutions
    Unofficial Forum Rules and Guidelines

  • How to Set multiple Global Variables without using Controls or Indicators

    I have to set many Global Variables (i.e. declare and initialize them) in a subVI in order to pass them to various other subVI's. The only way I know how to do it in LabView is to create a Globals.vi on which you create a control or indicator for EACH Global Variable. That's fine if you have only a few variables. But I have close to a hundred Global Variables (which come from a configuration file for a large program) and clearly it is impractical and cumbersome to create a control for each global variable. In Agilent Vee, there is a simple function called "Set Variable" that sets the data value of a global variable. Then in other module, you simply use the "Get Variable" function to get back the v
    ariable and its value.
    In LabView you can use the "Invoke Node / Set Control Value" and "Get Control Value" properties to achieve the same thing. But as mentioned above, you need to create a control for each global variable and that is a big pain in my case, with many global variables. Furthermore, the global variables are read from a Configuration Text File to this VI. Is there a way to do it without using the control? Thank you in advance for any help.

    Actually you could create the same sort of facility in LV. All you have to do is create a LV2-style global that behaves as follows:
    To write a value to it, you supply a value name and the value. These pieces of data are save internally in seperate arrays.
    To read a value, you supply a value name. The VI looks up this name in the value name array to return an index into the value array. Output the value you find.
    Frankly though, it sounds like what you really need is not hundreds of globals, but a good way to manage configuration data.
    Mike...
    Certified Professional Instructor
    Certified LabVIEW Architect
    LabVIEW Champion
    "... after all, He's not a tame lion..."
    Be thinking ahead and mark your dance card for NI Week 2015 now: TS 6139 - Object Oriented First Steps

  • Is there a way to check which VI and it's subVI are using which item in a global variable.vi

    While i writing the program, the program is growing and i also use global variable for it, but sometime some variables is delete from the VI (due to modify of the VI)
    But usually I don't update the Global Variable.vi, there are is some indicator or control in the Global Variable.vi is not being select as a item in main VI.
    So how can i differentiate between the still using control/indicator(selected item in main VI) and extra control/indicator(not selected item in main VI)

    From your global definitions .vi, select one of the global variables, then right click. Select 'Find Global References'. This will give you a list of .vis using that global variable. You can also get the same info by right clicking a global variable reference on one of your .vis and selecting 'Find', then 'Global References'.
    Hope I understood your question!
    Matt

  • Adding tab to typedef tabcontrol causes class conflict with global variable

    Hi,
    I am quite new to labview. I have to update an existing program and I have a problem whith a tabcontrol. In attachement, I give you a very simple solution showing my problem.
    I have defined a simple tabControl in a typedef ctl. I had it to a VI and in block diagram of this VI, I want to fill a global variable with this control and this global variable is set as "Include Data Type".
    When creating my ctl file with a simple tabcontrol, there is no problem but my tabcontrol only contains 2 tabs. When I use "Add page after" in my ctl file to create a third one, after saving, I get a class conflict error on wire to global variable in my block diagram.
    If I remove added page, all is OK again. I don't understand why adding a new page causes a class conflict. In my attachement, it is very simple but in program that I have to modify, I already have 15 tabs and I just want to add a 16th one so, I am sure there is a mean, but impossible to fond it after many hours...
    If someone can tell me how to make my example works with "Include Data Type" (if I remove it, it always works but that is not what I want) and adding an additional tab, it would hemp me a lot!
    Thanks in advance.
    Yohann
    Attachments:
    test2.zip ‏11 KB

    The problem is that the tab is an enum, and you can't wire two strictly typed references of two different enums together, because they are considered different data types. What you can do is right click the reference control in the global variable and select Show Control, which will show the data type of the reference. You can then replace the control inside the reference with the typedef, which will cause it to update correctly.
    Although that will solve the problem, if you have the reference to a tab control in a global variable, you probably have some issues with your code, but that's not something which can be commented on without more details.
    Try to take over the world!

  • Why not to store notifier reference in global

    Hi all,
    I am working with notifiers and queues in multiple VIs. I have strange behaviours, when I store the queue and notifier references in global variables.
    I have read some entries in this forum, and some says, it is a "bad idea", that "should not be done", to store the refs in globals.
    Can anybody tell me, what is the real background?
    regards
    mitulatbati
    Solved!
    Go to Solution.

    Besides that globals are simply evil (just slightly an over the top statement as I really advocate to minimize the use of globals to nothing more than a status boolean or sometimes some single skalar value), all LabVIEW refnums employ some garbage collection.
    The reason to use globals usually implies that you want to create the according resource at one place and use it someplace else. But that often does not work with LabVIEW refnums if the producer and consumer are not in the same VI hierarchy (for instance you create the resource in a startup VI and then spawn a plugin VI that continues while the startup VI terminates). All LabVIEW refnums are automatically disposed at the moment the top level VI in whose hierarchy the refnum was opened goes idle. So at the time your plugin VI gets to work, the refnum and its object has been already disposed and is therefore invalid.
    Rolf Kalbermatter
    CIT Engineering Netherlands
    a division of Test & Measurement Solutions

  • Setting global variable that are static but I want them to change

    I'm trying to set a global variable so I can let the user change the state in the Plugin Manager.  I've created a checkbox (in PluginManager.lua)
    f:checkbox {
         title = 'Show HTTP response',
         value = _G.showHttpResponse,
    that references the global variable (in PluginInit.lua)
    _G.showHttpResponse = true
    The state of the checkbox accurately reflects the initial value as set.  Everything seems fine but after unchecking the checkbox, the value is always true in my plugin.  I expected _G.showHttpResponse to change to reflect the setting in the checkbox.
    What have I overlooked?  Is this only for setting static globals?
    Abe

    Reading the Lightroom SDK manual seemed to indicate that using globals would be the way to go.  I'm thinking that it is only appropriate for static text.
    I've taken both your suggestions and have used the plugin preferences.  I didn't think you could get and set them in the Plugin Manager but they work just fine.  Now I set my debug flags in the plugin manager screen and they are available to the plugin and are persisted as well.
    Thanks for the suggestion.  Everything is working.

  • How can I obtain a reference to a global variable?

    I wish to change the contents of the columns in a global multicolumn listbox. As far as I can see, the only way to access the columns in a multicolumn listbox is to create a reference to it and access the ItemNames property. But how can I create a reference to a to a global variable?

    You can open a reference to a global as if it is a normal VI and then get a reference to a control on that VI. I have included a little VI here with a test global variable to get the item names from an MCL in that global. I needed the MCL in the main program just to force the reference to a strict MCL reference. You could turn this into a sub VI that just returns the item names of a named MCL if that works better (then the MCL that's only used for reference would not be on your main front panel).
    This VI searches through all the names of the controls on the referenced VI until it finds the one that's asked for.
    Have fun with it.
    Rob
    Attachments:
    Get_Ref_to_MCL_in_Global.zip ‏158 KB

  • What is the difference between using a global variable,passing a valuee and using a reference?

    I have created a project that consists of several VIs.  Only the main VI has a front panel and the others perform functions.  The function VIs are dependent on controls on the main VI's front panel.  I have several ways of passing the value of the controls.  One is to use a global variable and just place it on the dependent VIs.  Another option is to strictly connect the terminal from the control to a VI connector block and pass the value directly.  My last option is to create a reference of the control and reference it inside the dependent VIs, but this would also require connections to be made to the VI block.
    What are the advantages/disadvantages of these options?
    -Stephen

    5thGen wrote:
    I have created a project that consists of several VIs.  Only the main VI has a front panel and the others perform functions.  The function VIs are dependent on controls on the main VI's front panel.  I have several ways of passing the value of the controls. 
    1) One is to use a global variable and just place it on the dependent VIs.
    2) Another option is to strictly connect the terminal from the control to a VI connector block and pass the value directly. 
    3) My last option is to create a reference of the control and reference it inside the dependent VIs, but this would also require connections to be made to the VI block.
    What are the advantages/disadvantages of these options?
    -Stephen
    1) Globals are evil and introduce race conditions.
    2) The sub-VI only get the value when it was called and updates that occur while the sub-VI is runing are not sensed by the sub-VI
    3) This uses property node "value" or "value signaling" both of which run the user interface thread which is single-threaded and you incur a thread swap hit to performance. You also have a potential for race conditions.
    The are various methods for sharing dat to/from sub-VI which include Queues and Action Engines.
    I hope that hleps,
    Ben
    Ben Rayner
    I am currently active on.. MainStream Preppers
    Rayner's Ridge is under construction

  • How do you reference a created global variable in a report text field?

    I have created a parameter using the Globaldim statement in a script file. when I reference this parameter in any other script file during the current DIAdem session the value is passed without any issue.  Call the variable parmxyz where I assign it a value of 25.3 
    The help section under Globaldim mentions that global variables can be referenced in all panels, scripts, and dialogue boxes.  When I try to insert a text box on a report page using the @@parmxyz@@ it returns NOVALUE where I expect to see 25.3 (for example).
    When I substitute @@CurrDate@@ I do get the date, so I know the text box is valid.  What am I doing wrong?
    Steve    M 

    Hello Steve!
    It should work the way you did it. But their are some circumstances wich might prevent it:
    You have reseted the global script engine. All variables will be lost.
    You have a Sub with the same name in a command extension script. There is no warning ;-)
    One Test you can make is to put in '@@TypeName(paramxy)@@' as the expression to see the variable type. You can also try a realy unique variable name. The last option is to use ItemInfoGet to get detailed infos about your variable.
    Matthias
    Matthias Alleweldt
    Project Engineer / Projektingenieur
    Twigeater?  

  • Dynamic call of a vi with a reference stored in a global variable

    Hello,
    I am trying to program a VI which calls DAQmx functions in some cases, in other cases DAQmx may not even be installed. To prevent a broken arrow on machines where DAQmx is not installed, I want to use a sub-VI containing the DAQmx function calls which is called dynamically by a main VI. For speed I want to prevent continuous opening and closing the VI reference, so I want to store the reference to the sub VI in a global variable. In this variable I also want to store the Analog Input Task. I want to use an initialization VI to write the VI reference of the sub VI and to configure and start the Analog Input Task and write the Task ID to that Global, too. In that way I was hoping to be able to improve the performance of the dynamic calls and the Task calls. BUT - when I write the refererence and task to the Global and read it out from another VI, the reference is not valid anymore and the Analog Input task is also not valid, even if both the initialization VI and the Global are still open (but not running). Does somebody have an idea how to solve that? It is a bit difficult to describe, so here is what I want to do in a shorter description :
    - run a initialization VI which
      defines a reference to a sub VI which will be called dynamically later on
      and a AI task ID definining a DAQmx physical channel configuration to use for subsequent read cycles
      and writes both (VI reference and AI task) to a global variable
    - run another VI which
      reads the VI reference of the VI to call dynamically from that global
      runs the corresponding VI dynamically
      the dynamically called VI performs an AI task corresponding to the DAQmx task ID read from that global (it reads an analog value for instance from the  
      physical channel configured by that AI task) 
    Why all that? To prevent creating and destroying the VI reference for each call of the sub VI for speed. And to use the configured DAQmx channel for subsequent read tasks only if the subVI is called dynamically - if it is not, then the application will not see the DAQmx calls and therefore no broken arrow will occur if no DAQmx is installed on the machine.
    Can somebody help me with this? Why can't I store and read out the reference to the sub VI to/from a global, and why is the AI task not valid when read out from the dynamically called sub VI? I am somewhat lost with all that...
    Thanks in advance,
    Gabs

    Uh - I am almost getting crazy with that
    Kevin, that solution is the right one for programming an application. In that case everything will work fine. But during testing, it is more convenient to call all VIs from their front panels one after another. That's how I'm doing it for everything that needs to be exchanged between such VIs: store them either in a global or in a functional global variable. In that way the user can "play around" with the VIs without wiring them together in a main VI. Therefore, after some thinking I liked Davids idea with that daemon VI (I solved that by adding a boolean in the initialization VI to choose if that daemon is necessary - during testing phase - or not - when using the VIs in a main application). BUT:
    David: It does not work!!! I have exactly done what you proposed and this daemon VI is really running, having a True/False frame with a constant of False wired to the selector and holding both the functional global and the dynamically to call VI in the True frame. In that way, after initialization is finished, both VIs are still running but idle. Anyway, when I read back the value of the reference or the DAQmx task, it is invalid again!
    That really costs just too much time. Does anybody have any idea what to do now? David, I was hoping that your suggestion would solve the problem, because it would be logical that it would - why then is LabVIEW destroying the reference and task anyway even if that daemon VI containing the functional global is still running???
    Regards,
    Gabs

  • ABAP Objects: Private variable with reference to global internal table

    Hello. I want an object that can hold a private reference
    to a global internal table so that when one of it's methods are invoked, the global table contents are modified.
    Simplification of scenario:
    class myObject definition.
      public section.
        methods:
          set_global_table
            importing reference(i_table) type standard table,
          change_global_table.
      private section.
        data:
          m_pointer_to_table " not sure how to type this"
    endclass.
    class myObject implementation.
      method set_global_table.
        m_pointer_to_table = i_table. " this needs to  "
                                      " assign a pointer to "
                                      " the global variable "
      endmethod.
      method change_global_table.
        refresh m_pointer_to_table. "this should change "
                                    "the contents of global "
                                    "variable "
      endmethod.
    endclass.
    data: gt_itable   type standard table of t_widget,
          go_myobject type ref to myobject.
    * Main code
      create object go_myobject.
    * phantom code fills gt_itable
      call method go_myobject->set_global_table
                    exporting i_table = gt_itable.
      call method go_myobject->change_global_table.
      if gt_itable is initial.
         write 'this should output'.
      endif.
    The code here doesn't work and I've tried messing with field-symbols, etc. all to no avail. Thank you for any help you could provide!
    Brett

    Just typed in this editor - so no syntax-check but you will get the idea:
    Pass the internal table and get the reference of it
    Store the reference and manipulate the global contents with local field-symbols to which you have assigned the reference.
    Hope this helps
    Christian
    >
    > class myObject definition.
    > *
    >   public section.
    > *
    >     methods:
    >       set_global_table
    > importing reference(i_table) type standard
    > standard table,
    > *
    >       change_global_table.
    > *
    >   private section.
    > *
    >     data:
    > m_pointer_to_table type ref to data
    > *
    > endclass.
    > *
    > class myObject implementation.
    > *
    >   method set_global_table.
    > *
         GET REFERENCE of i_table into m_pointer_to_table.
    >   endmethod.
    > *
    > *
    >   method change_global_table.
    > *
      field-symbols: <lit_table> type any table.
        assign m_pointer_to_table to <lit_table>.
    * manipulate <lit_table>
    >   endmethod.
    > *
    > endclass.
    > *
    > *
    > data: gt_itable   type standard table of t_widget,
    >       go_myobject type ref to myobject.
    > *
    > * Main code
    > *
    >   create object go_myobject.
    > *
    > *
    > *
    > * phantom code fills gt_itable
    > *
    > *
    >   call method go_myobject->set_global_table
    >                 exporting i_table = gt_itable.
    > *
    >   call method go_myobject->change_global_table.
    > *
    > *
    >   if gt_itable is initial.
    > *
    >      write 'this should output'.
    > *
    >   endif.
    >
    >
    > The code here doesn't work and I've tried messing
    > with field-symbols, etc. all to no avail. Thank you
    > for any help you could provide!
    >
    > Brett

  • Table Reference Global Variable

    Hi,
    Inorder to update a table in One VI from another VI, i need a Global Variable Reference of that Particular Table. How  shall i create it.
    Anybody please comment on this.
    regards,
    mfp.

    You can use LV2G,
    an example is attached, you may work on same lines.
    I am not allergic to Kudos, in fact I love Kudos.
     Make your LabVIEW experience more CONVENIENT.
    Attachments:
    Another VI.vi ‏16 KB
    LV2G.vi ‏11 KB
    Table owning VI.vi ‏13 KB

  • Global variable reference problem

    Hai all,
    Am facing a problem in assigning a control as a global one.
    Actually i have assigned two OK buttons g1 and g2 as global ones. In 1.vi i have created control c1 (Switch when pressed) and in 2.vi i used g1. when i run both VI's, the g1 get updated with the change in values i gave in c1 in 1.vi (NO PROBLEMS).
    But in 1.vi i created another control c2 (Latch when released) and in 2.vi i used g2. when i run both the vi's, the g2 didn't get updated with the change in values i gave in c2 in 2.vi
    Anybody please suggest a immediate reply.
    Regards,
    Mathan

    Hai,
    Thanks for the timely help. Actually am using parallel port read and write loop.vi from the example finders in Labview 8.5 in my application.
    In my project, USB device test using USBCV utlity, am in need of two controls (buttons). One will be a switch which give a high/low value when pressed/released. Other one will be a latch which will be used for remote wakeup of the device (a pulse). i have done this in labview.
    But the test needs to be automated. That is when the USBCV utlity asks to connect/disconnect a device, automatically the switch control should be handled accordingly. when the utility asks for a remote wakeup, the latch control will get pressed automatically.
    That is when i run my VI and the USBCV utility, when the utility prompts for certain action (connect/disconnect, remote wakeup), the VI should give appropriate inputs (from switch or latch) automatically without any user inputs.
    Kindly give suggestions.

Maybe you are looking for

  • I am a victim of " Your apple ID has been disabled" (not for security reasons, only disabled), is there any way to solve this?

    Is there any possible way to achieve my goal? I really want to solve this, looking forward for your assistance. Note: This is only "Your Apple ID has been Disabled", it did not mention security reasons and other words / things. Random Facts: 1- I had

  • Quicktime on Safari - no video only audio - why?

    I have Safari 2.0.4 I have OSX 10.4.10 I have G4 PowerMac with 1.4 Ghz upgrade, 1.5 Gb ram and Ati Radeon9200 Pci card. When I want to view a Quicktime video on Safari - no visuals, only sound. Quicktime on it's own is fine. Quicktime on Firefox is o

  • Enhancement Request for Webutil

    Hello Duncan, When would webutil include a facility to append client file to another client file, Application Server File to a Client File, and a Client File to an Application Server File? Currently, when there is a file transfer, the contents of the

  • BO Fix Pack Deatils

    Hi , Could you please tell me BO XI 3.1 Fix Pack versions and what are the issue that has been fixed on each version? We are planning to go for new installation of XI 3.1.And would like to Migrate reports, universe, users, and groups from XI R2 versi

  • Acl.NotOwnerException when starting managed server

    I have installed the evaluation version of WL 6.0 and sp1 on Solaris and can run applications using the administration server. I created a new server with the WL console, and then tried to start it as a managed server, but I get a java.security.acl.n