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: 

What architecture for my application?

Solved!
Go to solution

Good morning!

 

For my test bench I have developed the software in LabVIEW. In the recent months, I had asked several questions in this forum, but always regarding details of my implementation. Until now I have never really questioned the general architecture (which surely is a mistake I want to learn from).

What prompts this desire to review my work is that I'm currently not able to abort the complete progam or its sub-functions in a controlled way prematurely or if errors occur.

I hope you could give me some suggestions what architecture would fit my application best. I'm not really experienced in structured programming using i.e. producer/consumer architectures etc., and I will read up on them, but first I need a general nudge in the right direction.

 

First a short overview of my hard- and software:

 

HW:

  • 3 different controllers controlling actuators
  • 2 different cameras

SW:

  • Front panel for user interaction
  • Several measurement routines that use different combinations of the actuators and the cameras. For example "move to position 1 and take a picture, then move to position 2 etc." These routines can be quite extensive, including image analysis and decisions based upon the results. These routines sit in event cases of an event structure which in turn sits in my main program (the front panel program).
  • Sub VIs (lowest level in my software) that send the actual commands to the controllers, e.g. "move", "read current position" etc. These Sub VIs are separate from my front panel VI and consist of event structures themselves, one event for each basic function. These event structures are controlled from the front panel via dynamic user events. So basically a remote button push.

Finally a very brief example of the workflow in my software:

  1. Front panel is started. Along the SubVIs for the controllers are also started
  2. User starts measurement routine no. 1 with a button
  3. The corresponding event in the front panel starts. In this event, other events are generated sequentally, depending on the measurement algorithm.
  4. These events remote control the Sub VIs from point 1, e.g. remotely push the buttons for the basic functions in the desired order (move, take picture etc.).

Problem is that the user cannot terminate the measurement routines before they are complete, because the program is locked in the corresponding event case.

Also, when a controller reports an error (e.g. power loss), the commands from the measurement routine keep coming resulting in more errors.

 

What should be possible with my new architecture:

  • User interaction in the front panel (as before)
  • Premature termination of any sub program if the user wants to or if error occurs. Then a defined state should be entered (especially closing of all references, power off all devices etc.)

I'm not at work right now, but I'll upload some screenshots later because let's face it - that was a wall of text 🙂

But maybe it is enough for some first thoughts from you?

Thanks!

0 Kudos
Message 1 of 14
(3,352 Views)

Which version of LabVIEW are you using? The Continuous Measurement and Logging example from the 'Create Project' menu is a very good scalable architecture for small/medium applications. It's a Queued Message Handler (QMH) architecture (which you can read about here: ftp://ftp.ni.com/pub/events/labview_dev_ed/2014/decisions_behind_the_design_of_the_queued_message_ha...) and the UI/Message loop would essentially become your process state machine. Because you immediately pass your user events to the message loop, it is then ready to process more commands and you can interrupt the process by enqueuing a message at the front of the queue.


LabVIEW Champion, CLA, CLED, CTD
(blog)
Message 2 of 14
(3,312 Views)

I'm using LabVIEW 2015 Prof Dev System.

 

The info in your link sounds very promising, thank you.

Just for my understanding: How many "levels" should my code have using the QMH architecture? Still three VI levels (UI, measurement routines, basic commands) or does it make sense to compress those last two into one?

0 Kudos
Message 3 of 14
(3,285 Views)
Solution
Accepted by topic author joptimus

I tend to like having hardware abstraction - so I tend to create a module which is dedicated just to communicating with the instrument and then my main program loop (e.g. measurement routine / program logic) interact with that and sends updates to the UI. This is because if I want to use that hardware in a different application, I can re-use the 'module'. It's perfectly OK to have your hardware loop combined with your message loop - but if it takes a long time to read data from the instrument, your application might not be as responsive to the front panel events (as it has to wait for that to finish first).

So you might have:
- UI Event Loop
- Main Message Loop (responds to UI Events and has your program 'flow')
- Hardware Loop (initialises and communicates with the instrument)


LabVIEW Champion, CLA, CLED, CTD
(blog)
Message 4 of 14
(3,265 Views)

@Sam_Sharp wrote:

So you might have:
- UI Event Loop
- Main Message Loop (responds to UI Events and has your program 'flow')
- Hardware Loop (initialises and communicates with the instrument)


Also very common for me is a Data Logging loop which just takes in data and stores it in a file.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 5 of 14
(3,257 Views)

Hi again,

 

I'm currently reading up on the QMH architecture and what would help me alot is a concrete example of a simple application using this design pattern. The basic example shipping with labview is not that helpful in terms of using the pattern in a larger application.

 

For example I don't know where to place the three different loops (UI, process logic, basic hardware commands) - three different VIs? How do I best call them, how do I transfer data between the loops if they are not in a single VI etc.

 

Thanks so much in advance!

0 Kudos
Message 6 of 14
(3,126 Views)

joptimus wrote: how do I transfer data between the loops if they are not in a single VI etc.

Well, we do call them a QUEUEd Message Handler for a reason.

 

I make each module its own VI.  This makes it simpler to debug and to reuse.

 

I also tend to use a Action Engines to store my queues in (on corresponding to each module).  This way, any module can send data to anybody else.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 7 of 14
(3,115 Views)

Thanks!

 

So to clarify:

If I have five actuators/cameras, then I would have 5 VIs (module), one for each?

 

What also bugs me is the number of queues. First I though of this:

 

1. One queue for each actuator/camera:

  • Initialization
  • Setting values at runtime (e.g. exposure time for camera)
  • Taking picture/moving
  • Closing references and exit

2. One queue for each measurement procedure:

  • Move to position x
  • Take picture with parameters y (file name, exposure time etc.)

But then, a camera might take a picture before it is at the correct position, because the queues are independent. As I see it, I have to put all my devices into a single queue and fill that queue with orders corresponding to the measurement procedure. Or is there a way to compartmentalize a more complex measurement routine using different queues with conditions?

0 Kudos
Message 8 of 14
(3,095 Views)

I also like to use User Events.  This way, each module just registers for the events/commands they care about.  So the main state machine can just send out one command to initialize and everybody who is listening for that command will do it.  It can reduce the number of communication paths and simplify things.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 9 of 14
(3,085 Views)

@joptimus wrote:

Thanks!

 

So to clarify:

If I have five actuators/cameras, then I would have 5 VIs (module), one for each?

 

What also bugs me is the number of queues. First I though of this:

 

1. One queue for each actuator/camera:

  • Initialization
  • Setting values at runtime (e.g. exposure time for camera)
  • Taking picture/moving
  • Closing references and exit

2. One queue for each measurement procedure:

  • Move to position x
  • Take picture with parameters y (file name, exposure time etc.)

But then, a camera might take a picture before it is at the correct position, because the queues are independent. As I see it, I have to put all my devices into a single queue and fill that queue with orders corresponding to the measurement procedure. Or is there a way to compartmentalize a more complex measurement routine using different queues with conditions?


I'd just use 1 queue with the general cluster[Command enum, Variant] as data.

That way you can queue commands such as SetExposure(70), MoveToPos(45) and so on. In this case taking picture will automatically wait, else you'll need some flag, Occurance or similar.

 

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 10 of 14
(3,066 Views)