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: 

The main strength of a QMH in State machine applications

Hi all,

I am raising this topic as a discussion to enable me learn more about the concept of Queued Message handlers and to get endorsements or criticisms regarding a few personal opinions (myths) that I have developed since reading up the subject and looking at templates/examples for first time a few days ago 🙂

Now kindly note that I am very new to this entire "Labview / code business" so please bear with me 🙂

I have been used to simple single loop state machine architecture for a a few weeks now so using the QMH is new to me but I guess I realized how useful it could be in triggering "priority events"

I am now beginning to think that the ability of the QMH to communicate between parallel loops ( event and message loops) as well as the ability to send priority messages which I believe can interrupt an executing SubVi ( correct me if I am wrong) appear to be the two key strengths of this architecture over the SSM architecture.

Would be glad to have feedback ( corrections or expansion of the same views as applicable ) on my above comments.

[BADGE NAME]

0 Kudos
Message 1 of 22
(3,691 Views)
So i guess sending a priority message from the event loop to the message loop to handle an idle case can be a way to perform a cancel ( truncate) execution of a subvi where the user does not want to wait for that subvi to complete its execution ?

[BADGE NAME]

0 Kudos
Message 2 of 22
(3,688 Views)

I feel like you are not understanding an important thing here.  The whole point of a QMH is to separate parts of your code so that you have a single QMH that takes care of one specific thing.  You then use queues and/or user events to send commands and data everywhere.

 

Here is a prime example that I did a couple of years ago.  I was tasked with developing a program to help the torquing process of a very large nut.  For proprietary reasons, I cannot give any more details than that as for as the actual task.  But there was a specific process of how the torque and angle would behave and that was used to determine when the nut was torqued properly.

 

So I had my main state machine that stepped through the process from user input, pretesting, running the process, checking the torque and angle through the entire process, keeping track of where we were in the process, and throwing errors in various situations.

 

Then let's count my QMHs:

1. Data logger

2. Measurement loop (read torque and angle from a third party device)

3. Error Handling

4. A loop that made a beep sound when there was an angle change and/or an error (most annoying feature I have ever implemented, not because the code was hard but because I had to test it in my cube a lot)

 

See, my state machine did not have to worry about where the data was coming from or how the errors were handled, etc.  I just kept the state, told the other loops to do stuff, and data from everybody.  The QMHs could accept commands and/or data from anybody.receive

 

If I had everything in a single loop, I guarantee I would have missed a lot of samples, my logging would have slowed things down, and it would have been a lot harder to code.

 

This idea (the separate QMHs) in the CS world is called Actors.  I like to call them modules.


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 3 of 22
(3,673 Views)

@crossrulz wrote:

 

 

See, my state machine did not have to worry about where the data was coming from or how the errors were handled, etc.  I just kept the state, told the other loops to do stuff, and data from everybody.  The QMHs could accept commands and/or data from anybody.receive

 


And if you program everything like crossrulz is suggesting, you have a lot of potential for code reuse and splitting tasks between developers. If you can just make a call to your datalogging QMH which basically says "log this data" you could, in theory, just put that module in another application entirely and start making calls to log data.

Matt J | National Instruments | CLA
0 Kudos
Message 4 of 22
(3,667 Views)
Waoh. I guess I am looking at a very elementary level of a QMH example 🙂 - The one that shows up in the "create project template". Was simply looking at executing subvis in the "message loop" based on enqueued messages from the "event loop". Probably when I move a little step forward I can fully understand this concept you are explaining though I think I get that a bit. I will note all the comments that come in and keep them for future reference as I learn more. One question I would like to ask is whether a priority message from the event loop can trigger a new case in the message loop which interrupts an executing SubVi ( even if it has not finished running?.

[BADGE NAME]

0 Kudos
Message 5 of 22
(3,660 Views)

If you pass a priority message, which I imaging you are doing by using the enqueue at opposite end function, you are not going to act on that message until you dequeue the next item.

Matt J | National Instruments | CLA
0 Kudos
Message 6 of 22
(3,657 Views)
I mean using the enqueue message (single).vi.

[BADGE NAME]

0 Kudos
Message 7 of 22
(3,653 Views)

You will not be able to stop a case from finishing.  Only when the Dequeue is performed will your new message be handled.  So maybe what you should do is remove any looping that is done in your subVI.  You can then use the Timeout of the Dequeue.  You get a command to start and set your timeout to 0.  So if there are no messages in the queue, you perform the timeout case immediately.  That is how you can handle your looping.  When you recieve the stop command, set your timeout to -1 (wait forever).

 

And be sure to use an actual command to tell the QMH to stop.  Do not just destroy the queue.  That is a hack!  Let the QMH destroy the queue in its Quit state.


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 8 of 22
(3,646 Views)

I didnt quite understand what you meant by " remove any looping done in your subvi",  Kindly use the "create project template" as base for your explanation as this may make it easier for me to grasp. I think the explanation is beginning to get clearer but there are still some grey areas.

 

If i understood a bit of what you said, i need to make the time-out terminal in the event structure located  inside the "event handling loop" 0ms at all other times except when a user event -stop occurs, then it becomes -1. By so doing , there is no enqueued message in the event structure hence the dequeued message string output in the "message handling loop" which feeds the case selector terminal becomes empty and trigggers a timeout case in the case structure within the "message handling loop".

 

I dont know if I am making any sense or if i understood this at all.

 

I also want to add that after the interruption of a subvi execution, i would like to be able to trigger any other event i desire right afterwards - The interruption is like a "cancel' event and should not quit the main vi.

 

 

[BADGE NAME]

0 Kudos
Message 9 of 22
(3,635 Views)

See if this helps clear things up.


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 10 of 22
(3,607 Views)