03-08-2013 06:28 PM - edited 03-08-2013 06:32 PM
Hello All,
Seems I've gotten stuck with running some Dynamic VI's . I'm still learning, so I might be close to what I want to do, or I could be completely off in left field.
The Project: Marine Aquarium Tank Controls / monitoring.
Goal: Control a number of Valves that direct water current while continually monitoring several sensors.
The Layout: the main vi reads the various sensors every 100 ms, selects the Valve control mode (1 of several possible, but for this explanation Automatic or manual modes), opens the vi for the mode selected, runs the valve control mode, sends feedback back to the main vi, compares the signals, rinse & repeat.
Details: Main VI is basically for output display. Valve Control is selected by Enum, connected to a case with Open VI ref. to run vi. (connected to shift registers) and close ref. When it gets in Valve information from the dynamic VI, compares the sensors on the valve to the data sent from the VI, if they match, indicate the match, if they don't match, indicate the fault on the valve that's faulting.
Automatic mode: passes time delay from the user input in the main VI to the automatic VI, checks to see if time has expired, if time has selects a valve from random, or holds the currently open valve open while looping every 100 ms, passing which valve is open back to the main VI. (time can be set anywhere from 1 sec to 10 hrs or more) then sends the output to the I/O device.
Manual mode: passes the Boolean switch information from the main VI to the manual VI, outputs to I/O device, sends the information back to the main VI for comparison.
Everything seems to work the way I want... Until I try to switch between modes. If I Stop the entire program using the Abort Execution Button in the toolbar, then change the enum, I have no problem. However, I'd like to just switch modes without stopping the whole program. What seems to be happening is that the sub vi's both stay running, and as they use the same passes, are conflicting with each other. I've tried to use the Invoke node Abort, a global stop, and a couple other methods, but nothing seems to stopping/closing the VI I want to end. I also Get a Error at the Close Ref. when hitting the loop stop button.
Error 1000 at Invoke node in main.vi
vi is not in a state incompatible with this operation
I'm sure by now people are thinking that they would like to check the code out. I'll post my Franken-code if you promise not to get too upset by the mess it is.
03-08-2013 07:55 PM
The manual and Automatic modes you have mentioned works in the same dynamic vi? The error you have stated usually occurs when you try to run a vi which is already running or broken. If you want to stop a vi that you have dynamically use the "Set value" method to set the value of the loop terminator to true so that you can stop the vi and then when you use the vi next time you don't get any error and you can run it. Also you can check the state of the vi and then you can run it instead of running the vi directly after opening the reference.
03-08-2013 10:39 PM
Each of the (4) Valve modes have their own Dynamic VI. I suppose I could combine them into one, but there may be more in the future, and would like to keep them as seperate VI's.
use the"Set value" method to set the value of the loop terminator to true so that you can stop the vi
Hmm... having issues trying to add this to the loop terminator... must be getting tired. This sounds so simple, yet I can't make this happen.
Well I've attached some screenshots of the main VI, Automatic VI, and Manual VI. maybe you can see what I'm doing wrong.
03-10-2013 09:53 PM - edited 03-10-2013 09:59 PM
It looks like the End control in the VI represented by manual.gif is only read once before entering the loop. So setting this control to true during operation will not actually stop the VI at all (it was only read once up front as false befiore entering the while loop).
That control should be in the loop to have any effect after the VI has started so that the control can actually end the loop. I am suspecting that the VI doesn't stop running when you execute the application due to the lack of while loop termination, and so when you attempt to re-start it you get an error when you attempt to dynamically call it (since it's already running). This is what P@Anand is suggesting.
A better solution in your case is to use a syncronisation object, such as a notifier, to send an abort message to the dynamically called VIs (or error on the notifier refnum) from the main VI. This reduces the coupling of using a named control in your main VI.
In my opinion even better would be the Async Call / Wait nodes which give you a strict terminal pattern type to wire to, but this depends on your use case and can be more complex.
03-10-2013 10:26 PM
Thanks for the replies. Well, a couple days have passed, and things have changed. I for the life of me could not figure out the control val.set control val.get commands.... set wasn't a problem, but the get just did not want to work for me, and I could not find an example of how to use it... (hint hint: if anyone can point me to a tutorial on the .get, I'd appreciate it)
Some days I just love programming... code that doesn't work, that suddenly starts working. I went back to a Global Variable for the Stop and suddenly it started to work. All the VI's opened and closed when I changed the Enum, However a new problem arose. The first 2 or 3 times changing VI's worked well, but by the 4th or 5th, the queues were getting full of miscellaneous data (even after using the flush queue command) and the port call/closes would frequently crash.
So the new plan is to start over, and use only 1 dynamic VI for valve control, and use a case structure to run just the specific section of code I want. This is less than Ideal, but it should get me running until I get a little better with Labview.
Thanks, Chris