06-06-2019 11:51 AM
I'm new to Queued message handlers in Labview but I'm trying to learn to use them as I believe they're more suitable to what I develop. Im try to create a relatively simple program that will detect if a signal exceeds a threshold over a period of time, after ignore the signal startup. I had a version of that working using the QSM template provided (here).
Eventually I need to get this same process to happen across simultaneous loops (5+) that can be started and stopped independently for different data sources.
My first stab was to duplicate the main loop with differently named states, assuming that differently named messages in the queues would kick off the different states of the machine independently. Note, I'm sure even this method is ugly by any standard, but walk before you run and all that.
However, in trying to implement this, I've noticed that starting one loop immediately kicks off both loops, despite the state machines being named differently. When I try to highlight execution, it seems like the lower loop is indeed waiting for the "Initialize2" message, however, in full execution it doesn't seem to work that way. Any guidance?
Solved! Go to Solution.
06-06-2019 12:09 PM - edited 06-06-2019 07:04 PM
I'll; have a look later, but your time indicator won't update until the loops have finished. If you want to see updated values, the terminals belong inside the loop. Also latch action terminals belong inside the respective event cases.
Your dequeue functions wait forever or until a new element is enqueued, preventing the consumer loops from spinning most of the time.
06-06-2019 06:03 PM
If you want 5 loops to run independently, then they can't be members of a single QSM. There's nothing wrong, however, with writing a QSM that does one "thing", coding it as a sub-VI (so it occupies only a little space, 32 x 32 pixels, on the Block Diagram), making it a Pre-Allocated Clone VI (Execution property), and then plunking 5 of them down on your Main Block Diagram and starting them all at the same time. If they only have the single "Init State" input, they'll run independently and as close to simultaneously as LabVIEW (and Windows) can make them.
Bob Schor
06-07-2019 01:51 AM
Some tips I might add:
- Put the indicators into the loop so they will update
- Put the controls triggering an event structure into the corresponding event case in the structure to make sure proper mechanical action will happen
I think the most important concept to consider is the fact that once an element is read from the queue it will no longer be there. For example, since State Machine 1 removes the shutdown message the second state machine will not get the message. I think this particular example is supposed to present QSM with one state machine only. However you can change the architecture to use Notifiers which has a different mechanism. Tthey do not fave FIFO but multiple instances can read them without cleaning the up at reading. This might be a problem if the states need to be queued.
06-07-2019 09:26 AM
As other people have mentioned, the problem is due to your two consumer loops sharing the same queue. Each consumer will randomly dequeue elements regardless of whether your consumer loops are "handling" the request. When you hit "Start" one of two things will happen.
Each one of these cases happens to enqueue other elements which basically starts this cycle of each consumer loop kicking off the other consumer loop and them kind of bouncing back and forth.
06-10-2019 06:51 AM
Thanks for the responses all! I understand why this doesn’t work, but I’m not clear on where to go from here. Can the basic framework be re-used with notifiers instead of queues? As shown in my example, each state machine is self contained (I.e update data never needs to trigger init2) but there are some over arching commands that should impact all (start, stop, etc...)
06-10-2019 07:40 AM
I don't understand what you fail to understand about our comments on how to accomplish your goal. Let me try to simplify it, making some assumptions along the way. For the purpose of this discussion, I'll assume you want 5 simultaneous independent QSMs:
The first thing to realize is that you need independent Queues for each of the QSM. It is probably convenient to design the Queues so they are the same type (i.e. to use a String for the State rather than an Enum unless Assumption #1 can be "relaxed" to have the Queues use the same Enum definition). You will therefore need to create an Array of 5 Queues in the Main routine and pass them individually to each of the 5 QSMs. When you want to, say, Init all of the QSMs, just use a For Loop to enqueue 5 Init States (depending on how you organize your VIs, you may want to bundle your Queue wires in an Array of Queues or a Cluster of Queues just to keep the Block Diagram neater).
Obviously, having 5 QSMs sharing a single Block Diagram takes up a whole lot of space. For this reason, several posts ago, I recommended writing the QSM as a sub-VI, either 5 separate sub-VIs or, if they are all identical (violating Assumption #1), they could be written as a Pre-allocated Re-entrant Clone, enabling them to be placed on Main's Block Diagram as 5 32 x 32 pixel Icons (taking up very little Block Diagram space).
Since a State Machine needs to respond to all of its states, you need a loss-less Synchronizing Structure such as a Queue (or, my preference, a Messenger Channel Wire). Do not use a Notifier unless you are willing to have States be "ignored" or "forgotten" (or unless you do a lot of extra coding to basically turn your Notifier into a loss-less communication method, effectively "re-inventing" the Queue).
Bob Schor
06-10-2019 08:24 AM
Instead of naming the queue, give the enum a label. That label will actually show up in the probe window. Naming the queue creates a global, and at some point could give naming collisions.
If you are going to clone the entire thing, the named queue will give a collision for sure.
Don't name queues unless it can't be avoided.
06-12-2019 08:42 AM
Got it now, thank you! Just needed the more simplified explanation, I was missing the part that each Queue needed to be independent, and how to simultaneously kick-off independent queues.
I'm not sure I understand this. Wouldn't naming queues prevent conflicts? I'd think that if you have queues "QSM1" through "QSM5" then the state machine would ignore the queue named for a different state machine. I've got this working now with un-named queues, just want to understand the issue for the future.
06-12-2019 01:40 PM
Unnamed Queues get "secret Individual names" when they are created. The purpose of naming Queues is something of a "cheat" or "trick" to avoid passing a Queue Wire to a sub-VI -- the Sender and Receiver of the Queue can both create it (in principle) and when they do, they'll be "connected". Safer to run the Wire ...
Bob Schor