LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Parallel loops in Queued State Machine not running independently

Solved!
Go to solution

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? 

 

 

Download All
0 Kudos
Message 1 of 13
(3,035 Views)

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.

 

 

0 Kudos
Message 2 of 13
(3,029 Views)

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

0 Kudos
Message 3 of 13
(2,997 Views)

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.

0 Kudos
Message 4 of 13
(2,981 Views)

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.

 

  1. First loop will dequeue the element and run the "Initialize" state.
  2. Second loop dequeues the element. There isn't a state specifically set to handle this so it runs the default state which just happens to be "Initialize2"

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.

Matt J | National Instruments | CLA
0 Kudos
Message 5 of 13
(2,957 Views)

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...) 

0 Kudos
Message 6 of 13
(2,928 Views)
Solution
Accepted by topic author Glibby1234

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:

  • Assumption #1 -- each of the QSMs is a little different (different states, different behavior, something requiring that you write 5 separate loops.
  • Assumption #2 -- each QSM gets State input from either the Main Routine (including such things as Init, Start, and Stop) and itself, but not from any other source.

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

Message 7 of 13
(2,919 Views)

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.

0 Kudos
Message 8 of 13
(2,910 Views)

 

 

0 Kudos
Message 9 of 13
(2,878 Views)

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

0 Kudos
Message 10 of 13
(2,863 Views)