vinayk Posted October 20, 2007 Report Share Posted October 20, 2007 I have a VI with tasks that need to be running continuously no matter what as these tasks control the valves on a machine. But when I try to open a sub-VI to show the status of all the components on the machine, my main VI tasks were paused until I close the sub-VI window which hinders my application purpose. So I set the main VI priority to 'Time Critical' and the sub-VI to 'Background' but still doesn't work, moreover LabVIEW hung up on me when I called the sub-VI. Then I noticed in the help file this quote: "If another VI with higher priority calls this VI, the priority of this VI rises to match the priority of the calling VI." So when I called the sub-VI its priority is also raised to 'time critical' as that of the main VI. How else can I call sub-VIs without pausing the tasks in the calling VI? I created this simple example so that I can explain better. Block Diag of main VI : Block Diag of Sub VI : Main VI Front panel : Sub VI Front panel : Quote Link to comment
Mads Posted October 20, 2007 Report Share Posted October 20, 2007 You have two options - either have a separate loop in the main VI and (statically) call the subVI from there (then only that loop will wait for the SubVI to return, the rest of the main VI will continue to run), OR call the subVI dynamically by opening a reference to it and then use the run method on that reference with the wait until done set to false. To set the inputs of the subVI you use the Set Control Value method: The latter method is great in many situations - I use it to call VI templates (.vit files), then you automatically get a unique instance for each call. A typical use of this is to allow the users to open as many graph windows as he wants... Regards, Mads Quote Link to comment
robijn Posted October 20, 2007 Report Share Posted October 20, 2007 Hi, What you can do is have the subVI run continously by placing it parallel to your other code in the main=UI VI. Then communicate the status of the subsystem via globals or (usually better) via functional globals to your main VI. The subVI should store its status when it changes into the global or functional global. The main VI should poll the global or functional global at a limited rate (i.e. not continously, but with a wait in a loop). This is the base of many templates. Instead of polling queues are then usually used to communicate with a subprocess, but that is not required if you want to learn how get a subVI to run independently. In many such templates there is a main VI which calls a UI VI and 1 or multiple hardware interface VI and optionally for example a processing VI. These VI's loop autonomously and when they have all stopped looping the main VI stops. Joris Quote Link to comment
Justin Goeres Posted October 20, 2007 Report Share Posted October 20, 2007 QUOTE(vinayk @ Oct 19 2007, 06:18 AM) I have a VI with tasks that need to be running continuously no matter what as these tasks control the valves on a machine. But when I try to open a sub-VI to show the status of all the components on the machine, my main VI tasks were paused until I close the sub-VI window which hinders my application purpose. So I set the main VI priority to 'Time Critical' and the sub-VI to 'Background' but still doesn't work, moreover LabVIEW hung up on me when I called the sub-VI. Then I noticed in the help file this quote: "If another VI with higher priority calls this VI, the priority of this VI rises to match the priority of the calling VI." So when I called the sub-VI its priority is also raised to 'time critical' as that of the main VI. How else can I call sub-VIs without pausing the tasks in the calling VI? You've got a couple misconceptions that are common among beginners. First, setting the priority of a VI or subVI doesn't work the way you think it does. A VI's priority refers (basically) to its execution priority relative to other VIs/subVIs when those other pieces of code are executing in parallel with it. In general, the execution model of LabVIEW is pretty good at doling out execution time, and I find myself changing a VI's priority only in very specific cases. In your example, there's no need to mess with the priorities of the various subVIs, and you should probably set them all back to Normal. Second, the reason your code seems to "pause" when the dialog opens is because you've got a dataflow dependency between the code that does the "counting" and the code that does the "dialog". The While loop can only iterate when all the code inside it has finished executing. But the dialog subVI doesn't finish executing until you close the dialog. That blocks the While loop from finishing its iteration. What you need to do is restructure the code so that the "count" loop doesn't depend directly on the dialog. Here's a very simple example of one way you could refactor your code: Notice that the two loops (the count loop and the dialog loop) are now completely independent of each other. Information (like "count" and "stop") is passed from the bottom loop to the top loop using Local Variables. This allows the dialog box to be displayed without blocking the execution of the count loop. NOTE 1: There are about 1000 ways to skin this particular cat, and the example above is one of the simplest. The above example may work well in a very small application, but for anything more serious you will find that it may not scale well. There are more advanced techniques that are necessary for bigger applications. EDIT: The other posts above this one touch on some of those techniques... NOTE 2: I suspect this is your first exposure to Local Variables. PLEASE DO NOT FALL IN LOVE WITH LOCAL VARIABLES. They're going to seem like the solution to all your problems, but they're not. The excessive use of Local Variables is considered poor style and their use in large or complicated VIs can make the code buggy, unreliable, and (most importantly) almost impossible to debug. Attached Example: Download File:post-2992-1192804918.vi Quote Link to comment
LAVA 1.0 Content Posted October 20, 2007 Report Share Posted October 20, 2007 I did not see this mentioned so please forgive me it this is a repeat. The "property >>> value" node executes in the UI thread. Ben Quote Link to comment
vinayk Posted October 20, 2007 Author Report Share Posted October 20, 2007 Thank you all. I was banging my head all evening yesterday trying to figure out how to get the main tasks running on my NI Panel PC. Your replies were very helpful. Vinay Quote Link to comment
vinayk Posted October 20, 2007 Author Report Share Posted October 20, 2007 As suggested, I used a parallel while loop to seperate the calling of the sub-VI and it was working great, like said in the above posts, for very small applications. But for my actual application this method of calling sub-VIs is not working great. So I was trying to implement the 'Call by reference' method as suggested. But my 'Open VI reference' is giving an error 4001 which I could not figure out why. This is what I did to the 'Open VI reference': 1. created a constant at 'Type specifier VI refnum' by right clicking at that terminal 2. right clicked on the constant -> 'select VI server class' -> 'browse..' -> selected the sub-VI that was supposed to be opened 3. created a constant at 'file path' terminal and specified the location of the sub-VI This is the sample application... Download File:post-9618-1192817648.zip Quote Link to comment
Rolf Kalbermatter Posted October 22, 2007 Report Share Posted October 22, 2007 QUOTE(vinayk @ Oct 19 2007, 01:14 PM) As suggested, I used a parallel while loop to seperate the calling of the sub-VI and it was working great, like said in the above posts, for very small applications. But for my actual application this method of calling sub-VIs is not working great. So I was trying to implement the 'Call by reference' method as suggested. But my 'Open VI reference' is giving an error 1004 which I could not figure out why. This is what I did to the 'Open VI reference': 1. created a constant at 'Type specifier VI refnum' by right clicking at that terminal 2. right clicked on the constant -> 'select VI server class' -> 'browse..' -> selected the sub-VI that was supposed to be opened 3. created a constant at 'file path' terminal and specified the location of the sub-VI http://lavag.org/old_files/monthly_10_2007/post-9618-1192817535.jpg' target="_blank"> This is the sample application... The error means as the error handler VI can tell you, that the VI is not in memory. Why you may ask! Because you think you provide a path to the VI to the Open VI primitive, but you don't. This VI will interprete a string input as VI name and nothing else. And when you provide a VI name only the VI must be already in memory. What you want to do is change the string constant into a path constant instead! And with that we are at the next problem. Using absolute path names to refer to VIs is ABSOLUTELY the worst you can do. This will immediately break when you move your project, or build an executable and/or install this on another machine. So reconsider how you want to refer to those dynamic VIs. The way I do this is having a VI somewhere whose location is relative to the dynamically called VIs, for instance in the same directory. Then this VI queries its own path and strips its name from that path and returns that. Now append to that path the VI name you want to load et voila. Rolf Kalbermatter Quote Link to comment
Mads Posted October 23, 2007 Report Share Posted October 23, 2007 + If you want the subVI to run in parallell with the main VI you need to run it using the run method like I showed in the previous reply, not a call by reference node. Quote Link to comment
Justin Goeres Posted October 23, 2007 Report Share Posted October 23, 2007 QUOTE(Mads @ Oct 22 2007, 07:29 AM) + If you want the subVI to run in parallell with the main VI you need to run it using the run method like I showed in the previous reply, not a call by reference node. I think what you're really pointing out is that the Call By Reference node doesn't remove the dataflow dependency on the subVI call -- it just allows you to dynamically choose which subVI to call each time it executes. I know that's simplifying it somewhat , but the point is the dataflow difference between Call By Reference and the Run VI invoke node. So in http://forums.lavag.org/index.php?showtopic=9330&view=findpost&p=37362' target="_blank">Vinay's previous post, the Call By Reference node will still block the bottom loop, but not the top one. Of course, as Vinay's example is written, the Call By Reference (with a constant VI path) is basically the same as a subVI call. (He mentions that his actual application is different, so I'm assuming that's an artifact of him just trying to rig up examples for his questions). Quote Link to comment
vinayk Posted November 1, 2007 Author Report Share Posted November 1, 2007 QUOTE(rolfk @ Oct 21 2007, 02:08 PM) The error means as the error handler VI can tell you, that the VI is not in memory. Why you may ask!Because you think you provide a path to the VI to the Open VI primitive, but you don't. This VI will interprete a string input as VI name and nothing else. And when you provide a VI name only the VI must be already in memory. What you want to do is change the string constant into a path constant instead! And with that we are at the next problem. Using absolute path names to refer to VIs is ABSOLUTELY the worst you can do. This will immediately break when you move your project, or build an executable and/or install this on another machine. So reconsider how you want to refer to those dynamic VIs. The way I do this is having a VI somewhere whose location is relative to the dynamically called VIs, for instance in the same directory. Then this VI queries its own path and strips its name from that path and returns that. Now append to that path the VI name you want to load et voila. Rolf Kalbermatter As suggested I created a path constant and moved the sub-VI to the same location as the main-VI. Well...that solved the error problem but now the execution stops and is waiting at the 'call by reference node'. I do not see any errors. What should I do ? Download File:post-9618-1193846344.zip Quote Link to comment
Mads Posted November 3, 2007 Report Share Posted November 3, 2007 The path does not refer to the correct VI in the sample, however I'm not sure why you insist on using a call by reference node :question: I've updated your sample to a working one. As you will notice I've also added a wait in the subVI loop, you should always have something that prevents the loop from running as fast as possible, otherwise it will use up all the CPU time. On a side note I would also recommend sticking to dialog controls and colors, that will give the users a familiar and professional looking interface, the advantage of using a OS-standard interface should not be underestimated. I also noticed that you are using the place as icon feature for the diagrams...that is the default and it's probably easier to read for beginners, however it takes a lot of space so in the long run it's a good idea to not use that, just a tip The example can easily be expanded to show cool ways to use the run method...you could e.g. make the subVI a template and have as many of them running in parallell as you want. You can also use e.g. a notifier or read the front panel properties in the subVIs to close all windows when the main app window is stopped. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.