Jump to content

Where are Sub-VI's physically deployed to on the Real Time system?


AlexA

Recommended Posts

Hey guys,

I've stumbled across a problem when trying to use the "Application path" constant along with the name of a sub-VI to obtain a reference for dynamic launching (using the asynchronous call and forget VI).

Putting the Sub-VI in the application folder, or alternatively a special "Sub-VI" folder, then using "Application Path" constant plus the name of the Sub-VI to obtain a reference works fine on a windows PC. When deployed to real-time you get "Error 7", sub-VI not found. So I'm wondering, where exactly does a dynamically launched sub-VI go when it's deployed to real-time, and how do I build a path to it programmatically for the purposes of dynamic launching?

Thanks in advance,

Alex

Link to comment

Hi Alex,

create an empty startup executable, build and run as startup. If you use the default settings the "App.Dir" property will now always point to /c/ni-rt/startup, even if you connect with your development system and run VIs from within. That way you can build your Sub-VI path relatively to "App.Dir".

For loading VIs by path you have either to include them in your build spec with "Always included" just like on windows machines. Or tranfer them by ftp using e.g. filezilla. I never found any VIs saved on the RT target when just deploying from development system.

Link to comment

Hey Swenp, thanks for the advice, in my explorations I created a build that had the sub-vis included under the "always included" box, it didn't seem to help. if I include them in a build via the "always included" box, how should I path to them? Simply via the App.Dir plus name method? In which case, what was I missing previously?

Link to comment

Alex,

in the build spec you have to set the destination directory for all of your dynamic VIs to a folder, not to the executable.

And the dynamic VIs need their frontpanel to be called by the Run VI method, so change the settings in the build spec accordingly. you can do all this on the Source File Settings page of the build spec.

I attached a simple RT project that works for me. It calls a dynamic VI in app.dir\data. This VI just writes a txt file to the same folder containing the actual timestamp.

RT_dynamic.zip

Edited by swenp
Link to comment

I see swenp just beat me to it - but let me post my comment anyway:

I do this in a lot of different applications. For built applications deployed on RT the main thing to remember is that you have to ensure that the VIs are actually put where the code expects it to be.

It is not enough to just add them to the always included box, - you also have to define a destination (on the destinations tab in the build script) and set the destination of the VIs to that target (on the source file settings tab). Do that, build and deploy - then FTP onto the target and check if the destination folders got created and the VIs put there. The base directory of the application is normally ni-rt\startup\ so if e.g. I want to put the subVIs in a folder named Objects that I can refer to as "Current VIs Parent Director\Objects" (see later explanation) then create a destination (I would call it Objects) on the Destinations tab that has the path c:\ni-rt\startup\Objects, and then set the destination of the VI to "Objects" on the source file settings tab (I would normally have folders of such VIs so I would just select the folder, check the "Set destination of all contained items"-box and set the destination...

To actually find the directory of the executable I normally use the OpenG VI called "Current VIs Parent Directory__ogtk.vi". I use this instead of e.g. the App.Dir property, because then I always know where it points to; the directory of the calling VI (unlike App.Dir which might be the directory of LabVIEW, during development...).

One bothersome thing when you do dynamic calls like this is that during debugging you have to make sure you have deployed a copy of the VIs to the target prior to running your app...otherwise thecallers will be downloaded to memory on the target and never find the VIs they want to dynamically launch because then they will look for the directory on the RT target...So do a deploy then run to debug, but the problem then is that you cannot debug the instances that gets launched on the RT target. Unfortunately that's just part of the game as LV RT works now.

Edited by Mads
Link to comment

Hmmmmmm, I've had a tiny break through with my problem. Thanks to you guys above but your answers didn't really help my problem. Mads, I think the answer might have been somewhere in your post but my brain did flips trying to follow your example.

So, the problem was, when a Labview Real-Time VI is run in Development mode (i.e. just by pressing the arrow), any sub-VI's which are called dynamically (via a "Start Asynchronous Call") will NOT be deployed in the correct sense.

The only way I could find to get Asynchronously Called VI's to launch in development mode was to manually deploy them. As in, go to the project window, right click them all and select deploy. This opens up their windows, and as long as the windows aren't closed, they will be recognised using the App.Dir property plus their name and subsequently launched correctly via the main VIs dynamic launch process.

I'm really not sure why this is, but I think it's a bug in Labview not recognising the potential dependencies of Asynchronously Called VIs during deployment.

Now, to see if there is a programmatic way to deploy these VIs so I can just hit Run in my windows host code.

Link to comment

Hi Alex,

This is expected behaviour. LabVIEW does not identify the subject of a dynamic call as a dependency because this could change by you changing the path. The same is the case on Windows but this is not so much of an issue because all the files are on your local system anyway but on RT they have to be deployed down.

Not sure if there might be an easier way but you could whip up a VI that uses the project API to programmatically deploy the VIs in one hit to make your life a little simpler. I haven't used a huge amount of dynamic VIs on RT so there may be a better way. (See Mads last paragraph as well).

Cheers,

James

Link to comment

Yes, during development you need to deploy the VIs that you are going to launch dynamically manally prior to running the calling VIs. You only have to redo that if you change them,as long as they do not change the previous deployment is valid for the next run...

It would be nice if we could mark the dynamic VIs to always be deployed upon run if they are missing or have changed. (Perhaps you could suggest that on the RT Idea Exchange:-))

Link to comment

Yeah, I've already dropped a suggestion regarding having to deploy an RT project as a startup. Will drop another one regarding Dynamic VIs. The solution I've come up with in the mean time is to call each Dynamic VI once in a normal fashion (sub-vi directly placed on block diagram) and shut it down immediately as part of the host code start-up, this forces the VI to be deployed as a dependency which can subsequently be launched dynamically.

Link to comment

Yeah, I've already dropped a suggestion regarding having to deploy an RT project as a startup. Will drop another one regarding Dynamic VIs. The solution I've come up with in the mean time is to call each Dynamic VI once in a normal fashion (sub-vi directly placed on block diagram) and shut it down immediately as part of the host code start-up, this forces the VI to be deployed as a dependency which can subsequently be launched dynamically.

I wonder if placing those VIs in a disable structure or opposing case of a constant-wired case structure would trick the deployment into including them as well? It would feel a little less kludgy to me and you'd probably see an improvement in start-up time.

  • Like 1
Link to comment

Hmm, had a little play and it appears the compiler is too smart for its own good. If you put the VIs in a constant wired case structure (opposing side), they will NOT be included.

I thought this might be the case. I know the IDE will still try to load VIs in a disable structure. I'm not sure how smart the compiler tries to get with controls, but you could try wiring a control to the selector instead, then hiding the control on the FP. The compiler might be smart enough to realize the control doesn't/can't ever get used, though. This approach starts to feel more kludgy to me, though.

Link to comment

I'm not sure how smart the compiler tries to get with controls, but you could try wiring a control to the selector instead, then hiding the control on the FP. The compiler might be smart enough to realize the control doesn't/can't ever get used, though.

The compiler can't realize this (because the control might be controlled externally, for instance by the Set Control Value method), which is why NI used this method (converting constants to controls) to maintain backward compatibility when you upgrade code from before this optimization was added to the compiler (which was LV 8.0, if memory serves).

  • Like 1
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.