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
Highlighted

@YannickB wrote:

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 ?


It depends on what your data logger is doing. Do you need to save all the data or only the most recent? If only the most recent then the notifier would be the better choice. if you need to save all of the data then you will need a queue.



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 11 of 25
(235 Views)
Highlighted

I actually do both in different tables of a database. I'll also probably need to do some general analysis to raise alarms for exemple.

My preference for notifier goes for easier addition of other subsystems. If I use queues I would need to have only a single consumer and It would be a bit more difficult to manage. Notifiers allow me to have the latest values available in the Main vi  and subsystems do wathever they need with them.

0 Kudos
Message 12 of 25
(220 Views)
Highlighted

I'd personally go for something that can use an event structure.

 

Everything else gets harder when more messages need to be processed. And that seem to happen sooner or later. A message to restart, reinit, reload configuration, stop, etc... Of course all doable with any of the mentioned synchronization tools, but I prefer the event structure, as GUI events fit in nicely.

0 Kudos
Message 13 of 25
(214 Views)
Highlighted

Unfortunatly... I can't use subpanels. I tried to implement it in my project but apparently it's not possible in a real-time target :,(

 

Is there any possibility to have controls in an other VI than my Main ? Otherwise my only option would be to put all controls in the main and isolate only the processing part of every system. but this will be very hard to do as I would need to do a lot of changes in some subsystems.

 

The only solution I see is to put my controls in a loop in the main and send them constantly to my subsystem through a notifier... but doesn't seem very appealing to me.

 


wiebe@CARYA wrote:

I'd personally go for something that can use an event structure.

 

Everything else gets harder when more messages need to be processed. And that seem to happen sooner or later. A message to restart, reinit, reload configuration, stop, etc... Of course all doable with any of the mentioned synchronization tools, but I prefer the event structure, as GUI events fit in nicely.


That would probably be my go to for the UI. I just would have enjoyed putting the structure elsewhere than in my main. The only problem will be to migrate some of my subsystem to this solution. I would need to completely rebuild the VIs. the subpanel was a really nice alternative for those: copy/past into subVI and return the VI reference.

 

If only I had a way to get a reference the control inside my subVi, so I can use it from outside... is there any way ?

0 Kudos
Message 14 of 25
(207 Views)
Highlighted

@YannickB wrote:

 

If only I had a way to get a reference the control inside my subVi, so I can use it from outside... is there any way ?


In general, yes. Not sure how well it works on RT. I heard some UI references only become valid when\if there is an active FP viewer. This probably also depends on the RT target (Linux\pharlap\VxWorks).

 

You can, in a sub VI, get all controls from the top level VI (getting the VI reference from the Call Chain), and then pick the control references by their label. All sorts of magic is possible with similar tricks. Problem is that it's all automatic, so it can get difficult to grasp what is happening. Normally, you have wires to see that...

0 Kudos
Message 15 of 25
(196 Views)
Highlighted

Take a good look at the example/template for Queue driven producer/consumer (or event driven). If you encapsulate the consumer as a VI with a queue in you're basically set to go. If you really need more or parallell loops they can be added with the same idea.

The main idea is that the UI or other leading processes queues up commands and the consumer performs them and if needed returns some result through a queue or event.

I usually try to keep all data and logic in my consumer, it really is the data+engine of the program, so if e.g. UI updates a setting, that setting is queued up, the consumer extracts it and stores it in its data cluster. Does that make sense?

/Y

G# - Award winning reference based OOP for LV, for free! ADDQ VIPM Now on GitHub
"Only dead fish swim downstream" - "My life for Kudos!" - "Dumb people repeat old mistakes - smart ones create new ones."
Certified-LabVIEW-Developer
0 Kudos
Message 16 of 25
(193 Views)
Highlighted

@Yamaeda wrote:

Take a good look at the example/template for Queue driven producer/consumer (or event driven). If you encapsulate the consumer as a VI with a queue in you're basically set to go. If you really need more or parallell loops they can be added with the same idea.

The main idea is that the UI or other leading processes queues up commands and the consumer performs them and if needed returns some result through a queue or event.

I usually try to keep all data and logic in my consumer, it really is the data+engine of the program, so if e.g. UI updates a setting, that setting is queued up, the consumer extracts it and stores it in its data cluster. Does that make sense?

/Y


This i understand, the consumer part is quite clear for me know. my problem resides more in the producer part. I don't want the main to be the producer, or at least it should use an interface define into my subsystem.

In orther words: the interface should be defined in my subsystem and not at top level. $

 

I'm getting quite close now by creating an AE for a subsystem so I can first initialize it, once this done I can get references from notifier/queue for the display/data-logging/... and It would make sense to get a reference to the control so I can use it from the Main VI.

 

For now I could get a reference to a control inside the subVi, now I would like to display the control in my Main VI in order to drive the subVI without creating a loop and some logics. so If my subVI changes, I automatically get the right front panel associated.

 

I actually find very strange that this doesn't seem to be a common problem. but for me decoupling parts of the system should be an important matter... and the subsystem should be able to have a way to define its own front panel.

0 Kudos
Message 17 of 25
(187 Views)
Highlighted

Don't use Control refs! Use User events to send data back to the UI for update if that's what you want to do. 🙂
1. E.g. your measurement loop reads your AI channels and generates the event AI, [3,7,5,6,11] (name and an Array of values)

2. The Main UI recieves event, extract the data and updates the Control.

In order to have general queues and events the most common solution is to have a simple Cluster consisting of a string and a variant as data. In this case you'll Unbundle data, wire the String to a case and inside each case use a Variant to data to handle the specific type (in the example an Array)

It might sound like a lot, but after the inital setup, it only requires a Variant to data in each case (apart from your functional code which is the same).

 

This way the UI is completely disconnected from the Engine, it Always works from the event and you can remove or replace it without the consumer noticing.

/Y

G# - Award winning reference based OOP for LV, for free! ADDQ VIPM Now on GitHub
"Only dead fish swim downstream" - "My life for Kudos!" - "Dumb people repeat old mistakes - smart ones create new ones."
Certified-LabVIEW-Developer
0 Kudos
Message 18 of 25
(182 Views)
Highlighted

@Yamaeda wrote:

Don't use Control refs! Use User events to send data back to the UI for update if that's what you want to do. 🙂
1. E.g. your measurement loop reads your AI channels and generates the event AI, [3,7,5,6,11] (name and an Array of values)

2. The Main UI recieves event, extract the data and updates the Control.

In order to have general queues and events the most common solution is to have a simple Cluster consisting of a string and a variant as data. In this case you'll Unbundle data, wire the String to a case and inside each case use a Variant to data to handle the specific type (in the example an Array)

It might sound like a lot, but after the inital setup, it only requires a Variant to data in each case (apart from your functional code which is the same).

 

This way the UI is completely disconnected from the Engine, it Always works from the event and you can remove or replace it without the consumer noticing.

/Y


I understand but my problem is not decoupling the UI from the Engine, that's fine.

My problem is to define how my UI looks like outside of the main VI, but display it in the main VI. Control reference might not be what I need but it make sense to me. (still, i'm not sure it could do the trick, i can't find any way to display the control from the reference...)

 

The closest to this I could find out is to create a control for my subsystem, get this control from the init part and then bundle every element with a control created in the main VI and send it to my subVI through a notifier/queue.

But I still have to write a lot of code, that must be in a loop placed in my mainVI. 

 

In simple what I want to achieve is a subpanel without subpanel 😛

Capture.PNG

 

 

 

0 Kudos
Message 19 of 25
(178 Views)
Highlighted

So, this is my result so far :

Capture.PNG

This is not too bad, but I would have really enjoyed no having to put this loop in the main for all my subsystems. but maybe want to simplify it too much and it it just not possible.

At least the controls and indicator are not defined in the main but as typedefs in my subsystem.

 

The only problem here would be migrating every subsystem to this principle: it will not be an easy task.

 

edit:

I put the send notification in an event structure, should be more efficient to avoid polling.

A good thing would be to avoid polling for receiving from the subVI but I don't see how yet

0 Kudos
Message 20 of 25
(167 Views)