From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Simplifying block diagram for VI with many front panel items

Solved!
Go to solution

Hi folks,

 

A few months ago, I received some fantastic advice on how to modularize a large VI with many front panel items across several tabs. Having modularized much of the VI's architecture and implemented a loose actor framework, I'm now struggling to make the block diagram more manageable. When I look at some of the architecture (snippets attached), I can't help but feel that there must be a better way. I know there's no way I can fit everything on one screen with the current architecture, which currently spans 16 screens. Prominent examples that look wrong to me include:

  • Passing a cluster of arrays of queues to a subVI. The subVI reads multiple data streams from an instrument and then parses it out to each queue. Arrays of queues in different cluster elements receive different data (in the same format). Queues in the same array (assigned to a cluster element) receive the same data (for different uses). Is there a less ugly way to do this?
  • The front panel contains many asynchronously updating indicators, such as graphs. I currently have a consumer loop for each graph. These take a lot of block diagram space, and I can't imagine how I would fit all of them on a single screen.
  • For some modules with many task-specific controls, I use a subpanel to contain all the front panel items for that module. This setup appears to take up a decent amount of space, and I suspect the way I've coded it makes it susceptible to race conditions. The code also needs to be modified to center the subpanel on the subVI front panel items. There's no way I can fit all of these on one screen.
  • All of these things currently reside within a nest of dozens of queue wires running between subVIs and loops.

I have read about some creative ideas in other forum posts, but want to make sure that my approach and understanding are sound before I go about applying them willy-nilly.

  • Apparently all the cool kids are using channel wires now. They look very cool to me, but I don't see how they'd cut down on the massive number of wires running across the block diagram, aside from obviating the use of queue initializers. Functionally, I can't tell them apart from classic synchronization tools, like notifiers and queues.
  • Use of Action Engines to store and interact with queue references "wirelessly". My understanding of this approach is that I would need a a separate AE for each queue. That seems to be a whole lot of individual AEs, and would violate the "logic by wire" design philosophy of LabVIEW. Are these generally a good idea over old fashioned wires?
  • Use actor frameworks for control of everything. I admit that I do occasionally pass a cluster of front panel references to control subVIs, especially to trigger event structures within them. How bad is this practice? I've found this approach to be easily adaptable across different subVIs, but get the feeling that it's frowned upon.

If there are other ways to simplify the block diagram, to improve either readability or functionality, I would love to hear it. Y'all are always super helpful and I appreciate your advice.

 

Thanks!

0 Kudos
Message 1 of 6
(2,323 Views)

Your screen shots don't look bad to me.

 

One comment I do have regarding your cluster of arrays of queues.  I've done a cluster of queue references so that I can send the references into different "modules" in a VI.  Make that cluster a typedef!  Otherwise later on you'll add another queue, or perhaps change a datatype in one of those existing queues and you'll find your wires break all over the places because the controls and indicators of that cluster will no longer be the correct type.

 

In general, any time I have a cluster or an enum, those items become a type definition.

Message 2 of 6
(2,289 Views)

@charleslu wrote:

 

  • Passing a cluster of arrays of queues to a subVI. The subVI reads multiple data streams from an instrument and then parses it out to each queue. Arrays of queues in different cluster elements receive different data (in the same format). Queues in the same array (assigned to a cluster element) receive the same data (for different uses). Is there a less ugly way to do this?

I got tired of doing this and moved away from queues and queued message handlers. Queues are great, but sometimes can feel like one way streets. I haven't used Channel wires, but I believe they have cases of 1-to-N communications, that way you can send the same data to multiple places. I use User Events, coupled with JKI State Machines, to communicate across modules. I use something similar to this and this. This allows me to have "one" wire to pass messages around various modules.

 

@charleslu wrote:

  • The front panel contains many asynchronously updating indicators, such as graphs. I currently have a consumer loop for each graph. These take a lot of block diagram space, and I can't imagine how I would fit all of them on a single screen.

I have all my indicators in a "single" loop that is called whenever a value needs to be updated. Never had a problem with this. The only exception I normally use, if I have a "busy" indicator, ie, a spinning beach ball. I usually have that in its own loop in order to have a smooth updates.

 

mcduff

 

Message 3 of 6
(2,285 Views)

If this is the kind of stuff you are fretting over now, I'd say you tamed the beast very well!

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 4 of 6
(2,276 Views)

Thanks everyone for the helpful replies. These are good tips and I'm glad to hear that things seem to be headed in the right direction, albeit a bit disappointed that maybe not all VIs can look as nice as the examples I see in tutorials.

 

mcduff, can you tell me a bit more about how you update multiple asynchronous indicators in a single loop? I'm not aware of an elegant way to implement that.

 

Thanks!

0 Kudos
Message 5 of 6
(2,196 Views)
Solution
Accepted by charleslu

@charleslu wrote:

Thanks everyone for the helpful replies. These are good tips and I'm glad to hear that things seem to be headed in the right direction, albeit a bit disappointed that maybe not all VIs can look as nice as the examples I see in tutorials.

 

mcduff, can you tell me a bit more about how you update multiple asynchronous indicators in a single loop? I'm not aware of an elegant way to implement that.

 

Thanks!


I operate under the assumption that it does not matter if all my indicators update exactly at the same time. In fact some indicators may update more frequently than others. However, updates greater than a 20-30Hz rate are usually not necessary for anything except video.

 

Below is a front panel that only has 3 indicators that need constant updating.

Snap32.png

Plot, table, and progress bar all need to be updated.

Snap33.png

Loop receives User Events which carry the update, the user event also includes a "state", that is, which indicator should be updated.

Snap34.png

Table is updated here in this state

Snap35.png

Progress bar updated here in this state

Snap36.png

Plot updated here in this state

 

The progress bar is updated every 100ms, the table and plot updates are user dependent, that is, they depend on the acquisition settings. No reason to try and update everything at exactly the same time.

 

All of the pictures above are from 1 loop, for me, it is my indicator loop. I send all my messages to update the indicators to that loop and it takes care of them.

 

Snap37.png

The block diagram for the front panel I showed earlier. Top loop handles all User Interactions (Menu clicks, resizing, button pushes, etc and sends appropriate messages to different loops, none of the "real" processing is handled in that loop), bottom loop updates indicators.   The loops on the left hand side handle instrument, data, UI, and watchdog functions. For example the data loop may perform a FFT on the acquired data and when complete messages the indicator loop to update the plot. The watchdog may watch when the main window is minimized and then tell the data loop to stop processing data for display since the user cannot see it.

 

With one user event wire I am able to communicate to any loop that it connected to that wire, that is what you see in the block diagram.

 

mcduff

Message 6 of 6
(2,189 Views)