08-10-2009 04:06 PM
I need some education. My plea begins:
When executing a Labview VI in a Teststand sequence, it seems that it gets an entirely new scope from the Labview project manager. At least, the VI will go into a locked, "reserved" state and if I force the sequence to open the VI front panel, it opens a separate copy or view of the VI at that time.
Given that, how long does the setting of a FGV or Global Variable last when executing a sequence? Does it last during that execution only or will it persist between executions? What happens to global and FGV values when a new thread is spun off? How about a sub-sequence call in a new execution?
To make matters even more fun, I'm going to be running this application in a customized version of the "full" Labview OI. Internal to that piece of compiled code, I assume that all globals and FGV's will last while the code is running (I've got static references to them all in the Launcher VI). Are any of those variables available to a VI launched by a Teststand sequence that is launched by the OI without going through the Teststand variable engine?
Getting back to threads and executions, if I launch a sequence in a new thread (or if I launch a VI asynchronously), when the master sequence is done, all of those subsequences and VI's will be terminated, right? I ask because there's an option when launching a sequence in a new thread to "automatically wait for the thread to complete at the end of the current sequence", but even if I remove the checkmark from that box, the execution will stall at the end unless I end that subsequence call myself (clicking on a frontpanel VI button, not terminating or aborting, btw).
But if I launch a new execution and tell the master sequence not to wait for it, will it keep running after the master sequence terminates?
Thanks for your time,
Mike
08-11-2009 03:14 AM
Hi Mike,
FGV or Global variables, are you referring to LabVIEW or TestStand?
regards
Ray
08-11-2009 08:41 AM
08-11-2009 03:47 PM
Mike,
I built an example that answers most of your question, it writes values to a functional global variable and then uses the persistance to pass the values to another step in TestStand. It also does the same thing for Global variables. Both of them do persist in memory between steps, in order to get rid of the values I had to close the sequence file, and unload modules. So both of those data types will persist in memory between sequences, executions, and sequence files. When active they act much like Globals in TestStand, be careful because their values are not stored when you close TestStand (as in StationGlobals) and it can be unclear wether or not they are still in memory. We always recomend using the smallest scope of variable that you can get away with, I mainly stick to Locals and Parameters, using FileGlobals, and stationGlobals very sparingly. That way you don't have to worry about the state of your variables, and never have deal with race conditions. Since these two data types can be written at any time between different threads and executions, use them very carefully. If possible I would recommend to use only the TestStand datatypes for passing information between your steps. This provides for much more readable sequences, that are much easier to debug without having to leave the TestStand environment. If you do choose to pass data between steps using LabVIEW, please document the process very well, or whoever inherits your code may be left scratching their head. For your other question:
To make matters even more fun, I'm going to be running this application in a customized version of the "full" Labview OI. Internal to that piece of compiled code, I assume that all globals and FGV's will last while the code is running (I've got static references to them all in the Launcher VI). Are any of those variables available to a VI launched by a Teststand sequence that is launched by the OI without going through the Teststand variable engine?
I believe you can pass globals between your LabVIEW OI and TestStand steps but once again wouldn't recommend it as a best practice (also I haven't ever tried to do this). If you find out that it behaves differently please let us know.
Getting back to threads and executions, if I launch a sequence in a new thread (or if I launch a VI asynchronously), when the master sequence is done, all of those subsequences and VI's will be terminated, right? I ask because there's an option when launching a sequence in a new thread to "automatically wait for the thread to complete at the end of the current sequence", but even if I remove the checkmark from that box, the execution will stall at the end unless I end that subsequence call myself (clicking on a frontpanel VI button, not terminating or aborting, btw). But if I launch a new execution and tell the master sequence not to wait for it, will it keep running after the master sequence terminates?
If you call a sequence in a new thread it will finish regardless of what happens to the calling sequence (unless you abort all executions). When you launch a sequence in a new thread you can choose to have the calling sequence wait for it to finish as you mentioned. When you call a subsequence in a new thread and choose not to have the parent sequence wait, its execution will finish before the subsequence thread is done, however teststand will keep the execution of the sequence file up untill the thread is finished so that it can be properly cleaned up. You can see teststand not wait if you call a subsequence normally from MainSequence and have that subsequence call another subsequence in another thread without waiting then. That would show TestStand implementing this feature is a little more clearly.
I hope this helps you out, let me know if you need me to elaborate on something.
08-11-2009 04:09 PM
Thanks for your help Richard.
Believe me, I would much rather be without the globals myself, but one of my program requirements is to have a parallel maintenance mode program that can peer into and, if a test isn't actively running, control the DAQ hardware. It also needs to keep running between steps to perform some closed-loop pressure control. I believe I have a solution 95% done that will work, but it involves using FGV's to hold control ouputs and a circular buffer (glorified FGV) to hold the analog inputs.
The true LV globals are only being used as a central configuration page that is filled with default values at startup. I just wanted to be sure if a value there was changed from the VI "default" when the OI starts that it would propagate between the compiled OI and a VI called in a teststand execution. Now that I type that out, I'm even less sure that this will work correctly since the compiled OI's global.vi is part of the executable while the Teststand-launched VI will be using the global.vi from its disk location. I'm sure I'll figure it out at some point.
08-12-2009 12:50 AM
Hi,
[I just wanted to be sure if a value there was changed from the VI "default" when the OI starts that it would propagate between the compiled OI and a VI called in a teststand execution. Now that I type that out, I'm even less sure that this will work correctly since the compiled OI's global.vi is part of the executable while the Teststand-launched VI will be using the global.vi from its disk location.]
I believe this will fail because labVIEW can not have the same VI in memory from two location. The OI will have already loaded the VI, when the sequence file is loaded it will try to the same the VI from a different location which clearly cannot have derived from the OI executable.
You might be better to have the OI save to a TestStand StationGlobal and have your step code module pick up from the that StationGlobals.
Regards
Ray Farmer
08-12-2009 02:31 PM - edited 08-12-2009 02:31 PM
Ray,
You're absolutely correct, i tested it out today, and the functional globals and regular globals were not able to pass data between TestStand and the operator interface.
08-13-2009 12:45 AM
Hi,
Maybe another way would be to used LabVIEW Shared variables.
Regards
Ray Farmer
08-20-2009 09:28 AM
Mike,
TestStand can call LabVIEW code modules in two ways, through the LabVIEW Development Environment or the LabVIEW Run-Time Engine (this can be set by going to Configure»Adapters and modifying the LabVIEW Adapter settings).
Based on your question, I believe the functionality of your test will be dependent on which of the above mentioned settings you specify. Calling a LabVIEW code module from the TestStand Sequence Editor using the LabVIEW Development Environment executes the called VI in a process separate from the TestStand process (using Dev Environment calls VIs out-of-process). In your particular case, if you are calling the VIs from the Sequence Editor it is okay to use the LabVIEW Dev Environment because every VI that is called will be called in the same process (outside of the TestStand process).
TestStand loads code modules into memory based on the Load/Unload options that you have specified (can be set at the Step or Sequence File level). By default, TestStand loads all code modules into memory at the beginning of the execution and does not unload them until the Sequence File is unloaded. While a VI remains loaded into memory, it will maintain it's Functional Global values. This means that as long as the Sequence File remains open, the VI remains in memory and the Functional Global values will persist across threads, executions, etc (as long as the VI that is called is not re-entrant).
When you introduce a LabVIEW User Interface into the equation things become slightly more complex. There are two ways of executing the LabVIEW User Interface, run the source code in the LabVIEW Development Environment or build an executable and run it using the LabVIEW Run-Time Engine.
If you run the source code in the LabVIEW Development Environment, then calling code modules from the TestStand sequence using the LabVIEW Development Environment will call the VIs in-process with the LabVIEW User Interface VIs. So, if you run your User Interface source code using the LabVIEW Dev Environment and call your VI code modules using the LabVIEW Dev Environment, your Functional Global Variables will persist and maintain their values from both the User Interface and the code modules.
If you build an executable and run it using the LabVIEW Run-Time Engine, then calling code modules from the TestStand sequence using the LabVIEW Dev Envrionment will call the VIs out-of-process with the LabVIEW User Interface VIs. Thus, your Functional Global Variables will not persist and will not maintain their values from both the User Interface and the code modules. If you've built your User Interface into an executable, you must ensure that you configure the LabVIEW Adapter to call VIs using the LabVIEW Run-Time Engine AND it must call the VIs using the same Run-Time Engine that the User Interface executable was built in. Then your Functional Global Variables will persist and maintain their values from both the User Interface and the code modules.
Hope this helps and clarifies some things.
08-24-2009 02:40 PM
Mike,
I feel I need to provide a little more clarification and detail on my comments above.
I previously stated: So, if you run your User Interface source code using the LabVIEW Dev Environment and call your VI code modules using the LabVIEW Dev Environment, your Functional Global Variables will persist and maintain their values from both the User Interface and the code modules.
The above statement is only true if you open the User Interface top-level VI from disk and not from within a project. If you are organizing your User Interface files within a LabVIEW Project, opening the top-level VI from the Project Explorer will open the top-level VI and all of its subVIs in the context of the project namespace. However, TestStand does not currently support calling VI code modules in the context of a LabVIEW Project. Therefore, opening the User Interface top-level VI from the LabVIEW Project will open one instance of your Functional Global Variable in the context of the project, then executing your sequence will open a separate instance of your Functional Global Variable from disk. To avoid this behavior and ensure that both your User Interface and Sequence execution reference the same instance of your Functional Global Variable, you will have to browse to the User Interface top-level VI and open it directly from disk.
I also stated: If you've built your User Interface into an executable, you must ensure that you configure the LabVIEW Adapter to call VIs using the LabVIEW Run-Time Engine AND it must call the VIs using the same Run-Time Engine that the User Interface executable was built in.
It is a little bit trickier to get this working. First and foremost you must ensure that your User Interface VIs AND code module VIs are all mass-compiled to the same version of LabVIEW. The tricky part here is that in order to be able to reference the same Functional Global Variable in both the User Interface executable and the sequence execution, you have to call the Functional Global Variable as a subVI of a code module that your sequence calls. This is the only way to achieve the functionality you want when you've built the User Interface into an executable.
I hope my explanations have been clear and complete. Please let me know if any questions remain regarding this topic.