LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Isolate parts of a system in subVis (Architecture for large application)

Solved!
Go to solution

Hello,

 

I have been recently working on a large project, running on a NI cRIO. This system has various devices, each one needing to be controlled from the same application.

In the current state of the project, the acquisition and the control of all devices is done in the main Vi (of course there are numerous subvi but the "process" is done in the main VI)

Although, it is organized and I can easily find what i need, I often have trouble moving things around, encountering numerous bugs and unexpected behaviors, probably due to the size of the VI.

 

My wish is to isolate the various elements of this system in separate VIs, but I still need communication between some of those VIs (an exemple being all "Devices Vi" and the "datalogging VI").

For the last addition in this system, I could achieve some improvement by having 2 Vis (control and communication), communicating through queues and notifiers. However I'm still far from satisfied with the result. My goal would be to have the smallest possible Main vi.

 

So my first question is : How small can it be while working properly ? The thing I'm imagining is having only as many subVis with some kind of connection between them. Is that realistic ?

 

Trying to realize that, I'm encountering one large problem : controlling the subVi from the main panel.
One solution I come across often is to use control reference. However It seems that by doing that, I will have unwanted coupling between the mainVi and the subVI. I would like to use the control defined in my subVI from the mainVI and not the opposite.

Is that possible ? The closest I get to this is by defining typedefs for the inputs/outputs and and communicating with queues and notifiers. but I'm not really satisfied with this solution.

 

What I'm looking for in general, is an architecture for my whole system, with all controls and indicator visible on the main front panel. In my view, the main Vi purpose should only be to organize the system and link everything together and none of the process should be implemented there. Is this realistic ? Looking into other subject talking about similar issues I have trouble finding useful indication, so I might be thinking it all wrong.

 

Best regards,

 

Yannick

 

 

0 Kudos
Message 1 of 25
(2,660 Views)

That's a lot of information. Still not enough to know all the details, but I think it's clear what you're going for.

 

Usually the main is one of the bigger VIs. Usually that's acceptable, and not worth the trouble to avoid that.

 

However, there are ways to keep the main clean. Of course, you can put the main in another VI and call that main, and you'll have a clean main. Probably not what you had in mind.

 

The UI elements on the main can be separated with sub panels. So each sub panel would contain a VI managing just that part of the UI. That usually cleans things up.

 

Another way is to start VIs that manage controls\indicators on the main VI. The VIs could even get their controls\indicators by name, so the main would only need to start the VI, statically. So simply put it somewhere and it will do it's thing. No need for VI server\dynamic calling here.

 

Then you can make classes for each group of controls. The init would take the references and sub VIs (or one handler) could manage that group of UI objects. All these classes could live in a hierarchy, and with a composite, you can invoke actions on all of them, without caring which class\object actually uses it. This will again clean up the main nicely.

 

 

 

So tons of options...

0 Kudos
Message 2 of 25
(2,633 Views)

thank you for your answer. Yes I think you got the right idea of what I meant as all you said makes a lot of sense.

 

You give me here a good first direction for my research: I don't know anything about subpanels, but the name of it seems promising.

 

For classes I've never used it. I have experience in object oriented programming, but I'm a little reluctant with using "non usual" labview techniques for now. As I'm still getting used to Labview, it seems preferable to avoid going there for know.

But I guess I could keep the similar idea with simple labview controls.

 

Also I feel that I will still have my main problem even with subpanels(I will definitly have a look a those things): A clean communication between the parts of my system.

 

Here is a small sample of the way I started to use, and It seems a bit off... but maybe it is me.

I feel like with multiple systems, It will start to be very difficult to manage in a clean way. It also simply feel wrong to me regarding the dataflow to have this "system1" Vi here without initialization and controlling it like that. for simple cases it would probably work but I'm a bit afraid of some future work creating various unexpected problems.

 

 

0 Kudos
Message 3 of 25
(2,627 Views)

For communication between loops:

 

queues, user events, channel wires, the usual suspects...

 

OO has been a full feature for 10 years now. It's only non usual for you because you don't usually use it. It's pretty usual for me. I wouldn't know how to do (non trivial) thinks without OO...

Message 4 of 25
(2,620 Views)

What I meant was more that I should prefer traditional labview programming method and avoid adding too much at the same time or I will never go forward with my project.

However it would probably make a good choice. I'll have a look at it and see what the necessary investment would be.

0 Kudos
Message 5 of 25
(2,611 Views)

@YannickB wrote:

What I meant was more that I should prefer traditional labview programming method and avoid adding too much at the same time or I will never go forward with my project.

However it would probably make a good choice. I'll have a look at it and see what the necessary investment would be.


Nothing wrong with that. If you're new to user events, queues and channel wires, you might as well go straight for the channel wires. Fastest way to make a data bridge between loops. Some work well with event structures, so you get events when data is pushed. Haven't tried yet, but sound good to me.

0 Kudos
Message 6 of 25
(2,607 Views)

In fact notifiers and queues seems fine in theory. But The core of my problem is probably that I m lacking a knowledge to do it well and my code becomes even messier.

Like with the files I sent above, something is not clean and doesn't feel right.

 

I'm currently looking at AE and it seems promising. I could initialize my notifiers from the VI it's used in (witch would make the decoupling I'm looking for). Although , the method to store data into shift registers seems to be very odd and look more like a sort of workaround to me. It seems in fact to be an "approved" method to do it.

In fact, doing that might even reduce my need for notifiers. as I could just call a "get" method to get all the current values of my system. This would not completely split the subsystem from the main VI but might simplify things a lot.

Would I be going in the right direction doing so ?

This would in fact resemble a class quite a lot...

 

The only problem left would be to organize this damn front panel... In the current version of my project, since every control create a local variable it is a terrible mess... would be so great to isolate those front panel outside of my main VI and have only the one I really need.

0 Kudos
Message 7 of 25
(2,596 Views)

Ok, I had a look into those sub panel  (this seems to be exactly what I needed !!) and AE and came up with a solution that seems acceptable to me.

 

I get to control the VI from the sub panel and I can access all values from this VI through the notifier for another used such as analysis/logging/....

The interface is clearly defined through the typedef and allow a good decoupling. The AE allow me to initialize my subsystem properly and acquire all needed references.

 

Would this solution be acceptable and considered good practice ? I'm always afraid to fall into a "labview pitfall" that would make me regret it.

 

Download All
0 Kudos
Message 8 of 25
(2,584 Views)

That is the basic idea. I would suggest you look at using state machines for your different sub tasks. Also recommended is that you completely decouple the UI from the business logic of your system. All of your processing tasks would receive and send messages (via queues, notifiers, user events). Your UI processing loops would have a single way to receive messages from the actual processing tasks. I would recommend using a queue or user events for this. Each processing task would have a method to receive messages from the UI task. Again, I would recommend queues or user events for this. My prefered method is queues though. You do know that you can name queues, right? By doing so you don't actually need to pass queue references around. Simply use Obtain Queue with the correct name and you are good to go.  If you have several sub processes your UI process would need to have a queue reference for each sub process and some one to identify the process. This can be store in an array of clusters or two arrays that you keep in sync. One array would be the process ID and the other array would be the queue reference. Keeping them in synch the process ID and queue reference would be at the same index in the two arrays. A simple search of the first array for the ID will give you the index to the corresponding queue reference. I would create a cluster typedef for your basic message. One that works well is a cluster of a string and a variant. The string is the message name/type and the variant is the data. The receiver of the message will know how to access the data since each message would have a defined (hopefully typedefed) data set.

 

LabVIEW OO is nothing to be scared of. If you already know OO concepts then using OO in LabVIEW should be straightforward. Defining good classes is a great way to design a system and decouple things. I would recommend looking at the SOLID principles would using OO. Once you feel comfortable with OO in LabVIEW you can look at the Actor Framework. This is a great way to accomplish exactly what you are looking to do. However, that is probably a bit advanced at this moment.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 9 of 25
(2,569 Views)

Thank you for your answer.

 

That is the basic idea. I would suggest you look at using state machines for your different sub tasks. Also recommended is that you completely decouple the UI from the business logic of your system. All of your processing tasks would receive and send messages (via queues, notifiers, user events). Your UI processing loops would have a single way to receive messages from the actual processing tasks. I would recommend using a queue or user events for this. Each processing task would have a method to receive messages from the UI task. Again, I would recommend queues or user events for this.

I actually did that for a part of the system. I found a great builtin exemple in Labview doing exactly what you describe and I've been often using it since. I guess I could do that with the UI in an even lower subVI and give its VI id to the main VI.

As I said my main problem is to isolate the UI of a specific subsystems and being able to display them in my main VI, and after some more fiddling with the subpanels it seems that they are indeed my best option doing so !

 

However I won't be able to do that for my whole system. It has been built by various people having various knowledge of labview and using various techniques. What I'm trying to do is more making sense of that by creating a general layout, extract each separable part and making them coexist together.

 

@Mark_YedinakSimply use Obtain Queue with the correct name and you are good to go.  If you have several sub processes your UI process would need to have a queue reference for each sub process and some one to identify the process. This can be store in an array of clusters or two arrays that you keep in sync. One array would be the process ID and the other array would be the queue reference. Keeping them in synch the process ID and queue reference would be at the same index in the two arrays. A simple search of the first array for the ID will give you the index to the corresponding queue reference. I would create a cluster typedef for your basic message. One that works well is a cluster of a string and a variant. The string is the message name/type and the variant is the data. The receiver of the message will know how to access the data since each message would have a defined (hopefully typedefed) data set.

Yes this would probably work very nicely for the processes that gather data from my multiple subsystems such as datalogging ! But wouldn't notifiers be a bit better ? especially if the data is accessed by multiple other system ?

0 Kudos
Message 10 of 25
(2,562 Views)