LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Multiple front panels for different instances of the same subVI

Hello,

 

I am currently rebulding LabView program to control multiple devices over GPIB. In order to make the main control program mudular I decided to go with "Server" - "Slave VIs" scheme. Each devices is governed by a separate subVI and all data are gathered and timed by a server VI. Timing is not crucial here so I'm using rendezvous to sync all VIs together. Each subVI can also run as an independent program (without server). I plan to control each device through the front panel of an appropriate subVI - this front panel can be opened or closed or subVI stopped if needed. Here are my two current problems:

 

1. Since I have several same devices (SRS1, SRS2, and SRS3) I want to control I'd like to use one VI to run them. That means that I need to be able to open front panels for individual VIs. Is there a way to do this? --- I tried reentrant option coupled with "preallocate clone for each instance" option with no luck.

 

2. I need to dynamically change variable linking from subVIs to variables of the server. This is due to the fact that each device can be connected to the different part of the experiment depending on current configuration. Since the configuration can change I am looking for dynamic linking. There is an example of what I mean:

three subVI provide three voltage variables: V1, V2, adn V3. The server varibles are A, B, and C. I need to be able to specify e.g

V1=B, V2=A, and V3=C and them change it to V1=C, V2=A, V3=B, etc. 

 

I would really appreciate any help with this.

 

Thank you.

Radovan

0 Kudos
Message 1 of 19
(5,618 Views)

I hope this doesnt totally confuse you but...

 

I would create a VI template (*.vit) for each device type (SRS1, SRS2 etc). You can create as many on the fly instances of each front panel as are needed by calling the VIT file using VI server. Use the Open VI reference.VI with a path to the VIT file to instanciate each device. Each Instance will have the name of the template followed by a number for each instance.

 

To address the dynamic variable linking, I would create a queue in the server VI. The template vi's would each send back data using the same queue (referenced by name) along with their own identifier. The Server VI could have some kind of interface that tells you which template VI's are transmitting data to it and allow you to configure the destination of the data. There are probably many ways to do this but at its simplest the software could create a 1D string array of sources and you can specify a 1D array of output variable names. Let the program monitor the input variables from the subVI's and retransmit them to the target variable. As local variables cannot be chosen from the front panel or relinked to different controls or indicators during run time, I would make the server variables out of shared variables or datasocket variables, both of these variable types will allow you to select the destination on the front panel unlike the local variable

 

For example, this approach would allow you to have 1 x SRS1's and 2 x SRS2's. The server VI will read the queue and get 4 values (perhaps in strings with the format SRS1_1.volts=1.2345V). You could then assign an output variable for each unique identifier SRS1_1, SRS2_1, SRS2_2 and so on.

 

I do appreciate that this is not code for beginners but I would like to think that if you are au fait with using the rendezvous VI's, its not a far stretch to use some name referenced queues and implement some VI server functionality to dynamically call multiple instances of a VIT file. Tying it all together is always the fun bit.

 

I would instictively think to use dynamically loaded VIT files whenever...

1. I need multiple instances of the same VI's front panel and function.

2. I don't know how many instances are needed but I want the software to allow me to create as many as I want.

 

I hope this gives you some food for thought.

Senior Software Engineer
www.Adansor.com
0 Kudos
Message 2 of 19
(5,609 Views)

 

Thanks, Dave. 
I never used .vit files before, but I am going to try it (after appropriate reading). I will only need 3-4 instances of the VI running (controlling 3-4 same devices with different GPIB addresses, obviously). I suspect the template VI can be saved in the project library just like a regular VI, correct? Also, I am using VI nodes to pass variables to the device VIs such as GPIB address ... again I think that still should work with the template VI (I do use "open VI reference"; from what you said all this is done the same way after .vit file is loaded).
I realized that local variable are not gonna work for this. I was hoping to use an array, but I could not figure out how. I got "dynamic linking" done using brute force (making case structure for each destination variable while specifing a case for each input variable; slection is made by a menu ring variable for each destination) ... it works, but I would be pain to scale that up. Your suggestion seems far more elegant. Again, it will require some reading on my part.
I've been using LabView for many years, but since it is not really my job to write LV code I mostly use "simple" approaches whenever possible. This is really the first time I am trying to play programmer a bit more creating modular LV code. That being said the rendezvous business took me a week to make it work. I expect the same with the new stuff you mentioned. That's where the fun is 🙂 
I'll give it a try and report back in couple of days.
Cheers, Radovan

@dave Briscoe wrote:

I hope this doesnt totally confuse you but...

 

I would create a VI template (*.vit) for each device type (SRS1, SRS2 etc). You can create as many on the fly instances of each front panel as are needed by calling the VIT file using VI server. Use the Open VI reference.VI with a path to the VIT file to instanciate each device. Each Instance will have the name of the template followed by a number for each instance.

 

To address the dynamic variable linking, I would create a queue in the server VI. The template vi's would each send back data using the same queue (referenced by name) along with their own identifier. The Server VI could have some kind of interface that tells you which template VI's are transmitting data to it and allow you to configure the destination of the data. There are probably many ways to do this but at its simplest the software could create a 1D string array of sources and you can specify a 1D array of output variable names. Let the program monitor the input variables from the subVI's and retransmit them to the target variable. As local variables cannot be chosen from the front panel or relinked to different controls or indicators during run time, I would make the server variables out of shared variables or datasocket variables, both of these variable types will allow you to select the destination on the front panel unlike the local variable

 

For example, this approach would allow you to have 1 x SRS1's and 2 x SRS2's. The server VI will read the queue and get 4 values (perhaps in strings with the format SRS1_1.volts=1.2345V). You could then assign an output variable for each unique identifier SRS1_1, SRS2_1, SRS2_2 and so on.

 

I do appreciate that this is not code for beginners but I would like to think that if you are au fait with using the rendezvous VI's, its not a far stretch to use some name referenced queues and implement some VI server functionality to dynamically call multiple instances of a VIT file. Tying it all together is always the fun bit.

 

I would instictively think to use dynamically loaded VIT files whenever...

1. I need multiple instances of the same VI's front panel and function.

2. I don't know how many instances are needed but I want the software to allow me to create as many as I want.

 

I hope this gives you some food for thought.


 

0 Kudos
Message 3 of 19
(5,602 Views)

@rurban wrote:

Hello,

 

 

1. Since I have several same devices (SRS1, SRS2, and SRS3) I want to control I'd like to use one VI to run them. That means that I need to be able to open front panels for individual VIs. Is there a way to do this? --- I tried reentrant option coupled with "preallocate clone for each instance" option with no luck.

 

 

I would really appreciate any help with this.

 

Thank you.

Radovan


What exactly did you do?

You can load a reentrant VI with option set to '8'  to load a new instance into memory. That should be exactly what you need and behave like a VIT instance.

 

Ton

Free Code Capture Tool! Version 2.1.3 with comments, web-upload, back-save and snippets!
Nederlandse LabVIEW user groep www.lvug.nl
My LabVIEW Ideas

LabVIEW, programming like it should be!
0 Kudos
Message 4 of 19
(5,596 Views)

Hi Ton,

 

I played with reentrant run, but could not make it work. That was before template attempet (which worked by the way). 

 

If I remember correctly I used option zero and used vi property node to set reentrant flag. That did not work. I tried option eight as you suggested and it kind of worked; I can access two different panels using my original .vi file rather than current .vit one. The execution status reports back "3" (running) rather than "2" as with the .vit file and I cannot control my devices. Everything works as expected with the .vit file. I am not sure why this is, but I am not going to investigate right now since I got it working. I can even run the .vit file independently on the server. 

 

Thanks for your suggestions.

 

Best, 

Radovan

 

PS. I wonger if some of the functionality is lost (well it does not work as it should) in your model since there are number of sub-sub-VIs in the subVI I excute multiple times. I am not sure. As I mentioned I did notice different excution status (3 rather than 2 with .vit file).

0 Kudos
Message 5 of 19
(5,582 Views)

I have done this kind of architecture a couple of times and there are some issues you will need to deal with.  I do have a question for you, though, and it may help determine what kind of architecture you use.  Do you need to interact with multiple instruments simultaneously?  If so, you will need to use .VITs to run multiple similar displays.  If not, you can use a single display and central data repository for you instruments (reinitialize the display when you change instruments).

 

The biggest issue with multiple displays is keeping your data separate.  To do this, do not use any sort of named data mechanism (e.g. globals, shared variables, queues, notifiers, etc.) unless you are very sure it will not cause issues.  I usually use data value references and unnamed queues.  Pass references around as you launch things.  A typical launch sequence would be to open the target VIT (which creates another instance), set a value for a response queue, then run it and wait for response.  The response is a command queue for the object.  You now have unnamed queues established for both directions of communication.  I would highly recommend you use LabVIEW classes for the commands.  This avoids the variant transform issue you would otherwise have and simplifies your code.

 

I wrote a short series on multiple top-level VIs that includes launching VITs awhile back.  The end post of the series with links to the other posts may be found here.  I know I just firehosed you with info.  Please keep asking questions...

0 Kudos
Message 6 of 19
(5,561 Views)

Hi Damien,

 

Thanks for your input. I also looked at the link you provided and I find it useful to see how queues are working (I never used it before ... more on it later).

 

I think I got hold of .vit files and I managed to run separate instances for each device. I need to run all separate instances in parallel and interact with all devices at the same time. The main reason I going through this exercise is reusability, maintenance (to use your words), and portability. Here is what I am trying to do in more details:

> Server VI will verify presence of various devices/instruments and connect them if they are there. It will also collect all data inputs, save files (images, videos, and data logs based on settings).

> Each devices will have separate VI running it with its own front panel that can be opened (to make changes to that device) or closed (while VI runs to keep desktop neat and clean). For time being I have number of GPIB devices, PCI-e or FW400 high sensitivity camera, serial port device, and NI PCI-e DAQ card to get data from. 

> I will have several devices that can use the same VI if running as a separate instance (.vit files ... I think that is fixed now).

> I am still not sure what is the best way to manage data streams from device VIs to the server.

 

I already tried queues, but I ran into a timing problem. I mentioned in the very beginning that precise timing is not crucial. However the way I implemented it before was just a mess. I was filling the queue using different rate that I was reading it out and it just did not work. That's why I opted for rendezvous to time different devices and server VI together and used global variables to pass data from device VIs to server. I do not need to send commands from server to device VIs (except to open/close front panel; all inputs are done via device front panels which are closed when not needed). I later realized that I might not even need rendezvous and I might just use "ctrl val.get" function to pass data from device VIs to server (device VIs typically run faster that server). For time being I still use rendezvous to keep things together since I have it in place already. Is there a drawback to my implementation (speed, memory usage, timing, other)?

 

There is my other question regarding dynamic mapping of input variables to output ones (look couple posts up). I think I found OK solution with acceptable implementation as well. Here it is:

I created a boolean matrix where inputs are rows and outputs are columns. I highlight cross-points to link inputs to outputs. Two simple for-loops will redirect input signals to appropriate output variables. The only drawback is, that these loops will have to ALWAYS run (in each step). They are not big (I think 5x5 will do), but it is still crude solution. Any other ideas?

 

By the way, is there a way to access/control one PCI-c DAQ from separate VIs talking to different cahnnels? I tried that in past but soon or later I get a conflict when both VIs trying to read/write at the same time. I am going to use my DAQ card to control/read different devices and gather different data streams. It would be useful to have those VI separate.

 

I just realized a solution 🙂 I can have a DAQ server to assign channels and bunch of secondary VIs (with their own front panels to open) doing their stuff. I think that should work the way I want it to ...

 

Thanks again for useful tips nad hints.

 

Cheers,

Radovan

0 Kudos
Message 7 of 19
(5,545 Views)

The best way to pass data from a client to server is a queue.  I usually use one queue for all the clients, so this is a many to one communication method.  The message contains client identification.  Alternately, you can have a separate queue for each client, but that is harder to program on the server side.   Using globals and rendezvous works, but is an invitation to a race condition.  It is too easy to miss something, especially if anyone but you will be maintaining this software.  Do not throttle or time the queue handler on the server side.  It should process queue commands as fast as they come in.  The queue will efficiently wait when there is not data.

 

For server to client, I would also use queues. Using front panel controls forces the program through the UI thread, which serializes all data commands for every client.  Queues do not have this issue.  You will need a command processor or state machine to handle the queue input, but should already have something like this, anyway.

 

Alternately, you can use user events, but user events work better as a broadcast mechanism than a point to point communication mechanism.

 

Check out dynamic dispatching of LabVIEW classes as an alternate solution to your variable mapping issue.  Look in the LabVIEW help for examples.  It is a simple and elegant method, but is a little mind-bending if you have never used object-oriented programming before.

 

Good luck!

0 Kudos
Message 8 of 19
(5,518 Views)

This Nugget was written to show-case Occurences and VI templates but may be helpful.

 

Replace the occurences with queues and you are close.

 

mix in a little "Self-addressed Stamped Envelope" and that should work.

 

take care,

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 9 of 19
(5,511 Views)

Thanks everybody for help.

 

I got it working reasonably well with queues; version 0 so to speak. I am still struggling a bit with a "proper" way to use queues thou. Since I am using number of different devices providing different data (voltage, current, pressure, etc) I created specific protocol to pass data around (e.g. "devicename.channel.variable:value"). The "central" VI that collects all data had to parse it, process data, and post it. Over time it became more and more cumbersome and I created separate queues for each device (sometimes two for passing inputs and outputs). Now I have over 10 queues running around and getting more and more busy. Moreover, adding new devices results in more coding. 

 

From programming point of view, what is the "proper" way to deal with queues? Also, does using multiple queues increase memory usage and/or cpu time?

 

Thanks,

Radovan

0 Kudos
Message 10 of 19
(5,244 Views)