04-23-2011 06:00 PM
I am writing a control system for a an optical research probe. We need to be able to keep this control system on screen along with the image capture program we use. As long as I keep both programs windowed, I can just keep them next to one another...but because of the size of the image capture program and the aspect ratio of my screen, I have an L - shaped region of free space to use. My solution right now is to have two separate VI's...one that is taller than it is wide that sits on the side of the screen and another that is wider than it is tall that sits along the bottom. This works fine because the two VI's are completely self contained and don't depend on one another. However, a major goal of this project was to be able to open one program and start working with the probe (I use an exec block to open the image acquisition program when one of the VI's starts).
So what I need to do is find a way to open one VI and have it spawn a second, completely independant window running a different vi. I thought about pulling the system exec trick again, as these will be compiled for the runtime, but that seems like a shady way to do it.
Just so I'm clear, I'm not looking to run a subvi in a subpanel, run multiple instances of the same VI, or run multiple VI's and share data between them. I just want to have a single VI spawn two independant panels in their own windows.
04-24-2011 10:17 AM - edited 04-24-2011 10:19 AM
Don't use system exec, use vi server. There are additional methods and properties that you can use before Run VI that you might or might not need. One is Set Control Value. You give it the name of a control as a string and a variant to set the value. You also will want to look at the state property for the vi and only call Run VI if the state is idle - you get an error if it is already running.
Attached is the example saved for version 8.2.
04-24-2011 02:13 PM
Thanks, that is exactly what I was looking for.
Another quick question. I've decided to structure it so that you open a single VI and can toggle the other windows on or off using a boolean button. I use an event handler to watch the state of the bool, then either open or close the sub vi based on the new position of the bool (testing the state of the VI first).
The problem I'm running into is that if I close out the sub VI by closing the window (without aborting execution first), the main VI continues to see the sub vi in the "running top level" state. This is causing an error when I turn the button off, as the code is attempting to abort and close a VI that isn't actually running anymore. I've attached a snippet that shows the code I'm running.
04-24-2011 04:56 PM - edited 04-24-2011 05:04 PM
The problem is that you are trying to close a front panel that is already closed. You need to look at the FP.State property after your Abort VI method which returns an enum indicating Invalid, Standard, Closed, Hidden, Minimized or Maximized. If it is closed then don't call the FP.Close method. Get the property by right clicking the reference wire and Create/Property for VI Class/Front Panel Window/State.
The bottom loop has a problem. It looks like you just want to make sure your boolean control is true if the called vi is running otherwise false. You need to put the Open VI Reference outside the loop otherwise you keep opening a new one every 500mS.
In general you should open a vi reference once and store it in a FGV.
04-24-2011 07:03 PM
thanks for all of your help. I think I'm finally getting the hang of it. I've attached my revised code, which appears to working. If you could take a look and tell me if I'm doing it completely wrong or not, I'd appreciate it.
For your reference, the top loop is what opens and closes the new window when the button is changed. The bottom loop continually checks the state of the window and when it sees that the state has changed, it makes sure the state of the button matches, and in this case, it makes sure that when the window is closed, that the VI is aborted.
04-24-2011 09:17 PM
For the most part it looks good. I know this is just sample code or I would point out that there is no way to stop the bottom loop. As far as the VI Server stuff goes it looks like you are getting it all figured out. You just need to make sure that you close references. There is no reason that you need the Wait For Front Panel Activity function. That is really intended for vis that do not have an event structure.
04-24-2011 10:01 PM
To close those references, I can just put a close block outside the while loops and conect it through right?
As for the loop conditions...I've been making the loops run infinately like that and using the abort button to halt execution. Is this considerd bad practice? This program will be compiled for the runtime, so I am considering going back and using an event handler to break all the loops when the window is closed.
As for the wait for front panel activity...I thought I had read that using that with the event handler saved resources, but of course, I can't seem to find that source again. I'll pull them out and see if there is a difference.
thanks again for all your help.
04-24-2011 11:34 PM
@mjbeals wrote:
As for the loop conditions...I've been making the loops run infinitely like that and using the abort button to halt execution. Is this considered bad practice? This program will be compiled for the runtime, so I am considering going back and using an event handler to break all the loops when the window is closed.
Yes that is bad practice. The Abort button should only be used to Abort a runaway program. It is a debugging tool, not intended to be the normal way to stop the program.
Please read this thread.
04-25-2011 08:51 AM
that's good to know. Thanks.
That does bring up how I'm closing out the sub vi's that are in their own windows though. When the button is changed to false, I call abort VI followed by FP.close. It seems that would be bad practice as well. I did try to use Ctrl Val.set to change the loop control variable to kill all of the loops and cause the VI to exit by itself, but that didn't seem to work. What would be the best way of handling this?
Thanks
04-25-2011 09:33 AM
I would probably use a named notifier to send messages between them. I don't have time to put an example together but there are probably examples included with LabVIEW. Help/Find Examples and look for notifier.