LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

QSM query

Attached vi is in LV2009 version. Its just a sample to know whether the queued state machine coding is OK? Here I used a simple ENUM constant for state cases, but in real time large applications Im using typedef ctrl.

 

Thanks for any help.

 

Kousy

 

0 Kudos
Message 1 of 16
(3,556 Views)

My strong advice is to not use the same queue for both sending commands from the upper loop to the main "state-machine" loop, and for queuing "states" in the main loop.  This is because having two processes writing to the "state" queue will make the order of execution unclear.  For example, if the event structure triggers state A and then at some later time state B, and state A queues up states C and D, you could wind up with either ABCD, or ACDB or even ACBD, depending on timing.  This can lead to very difficult and annoying intermittent race conditions (very hard to debug!).  

 

Instead, have two queues, an internal "state queue" that only the main loop writes to, and a "message queue" from the upper loop.  The main loop should read the message queue only when there are no further states in the state queue (use the timeout output of the dequeue function).  That way, the handling of state A (requiring states C and D) can be completely finished without interference from state B.  The two queues can use the same enum if you want, or they message queue can use a set of "commands" different from the internal "states"

 

-- James

Message 2 of 16
(3,547 Views)

QSM's are not part of my coding vocabulary becuase they scale pooly and can develop into what looks like a knot if you tried to diagram the transitions. Whn finding a QSM on my desk (coming from an outside developer) I refactor them into state machines replacing many of the states with sub-VI that can be called from the various states rather than trying to use the QSM states as if they were subroutines.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 3 of 16
(3,541 Views)

Like Ben, I do not use the QSM.  I use queues to send "commands" from the GUI loop containing an event structure with ALL user inputs which require a response from the system.  This includes Start as well as Stop and Quit in your example.  The state machine receives the commands and determines what to do with them.  For example the Quit command does not shut down the loops directly but directs the state machine to halt any data acquisition in progress, write safe values (usually zero) to any outputs, save data and configuration to files, close files and other references, send "shut down" status to the GUI loop, and THEN stop the loop.  The state machine may go through several states in the process of shutting down, but the GUI/command loop need not know anything about them.  Further, the sequence during shutdown may not always be the same.  If the state machine has no unsaved data and no files open, then it does not need to go through the save or close files states.

 

Lynn

Message 4 of 16
(3,536 Views)

A question for Ben and Lynn. I understand what you are saying and in principle I agree. The question I have though is how do handle injecting something like an abort, stop or update into the state machine if you use the queue only for messaging from the outside? Is your state machine a simple value and the check for outside messages is performed outside (an action to be performed at each state transition) each state checking for the asynchronous events? Do you use a period state to check for these events?

 

In general a true state machine does not and cannot handle asynchronous events and will need some way to implement the "big red stop button" or similar type of asynchronous event that does influence the state machine but is not a true state within it. If the state machine contains a state which checks for events I could see where the response could be slow to detect the event of the state machine would need to transition to that between every state.

 

I know there has been frequent debate of this topic and am curious how folks resolve handling the necessary asynchronous events required for application control.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 5 of 16
(3,529 Views)

One way to add the big red stop button is use Enqueue Element at the Opposite End primitive to insert the stop or any other immediate or urgent command at the head of the queue. This won't stop the currently executing state but will cause the stop state to be next in line. If it's not urgent, then enqueue at the end of the queue and let the state machine finish whatever is in the queue before stopping. In the stop state, you can take care of cleaning up as johnsold suggests.  If you are prepared to allow an individual state to add to the queue, then you could enqueue stop in any state for any reason. 

 

JohnCS

 

 

0 Kudos
Message 6 of 16
(3,520 Views)

I have used multiple methods.

 

The sub-VI checks a queue regularly for an Abort.

The sub-VI registers for an event from the abort button.

The sub-VI checks a flag.

 

I don't use any single method since different situations warrent different approaches.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 7 of 16
(3,518 Views)

Mark,

 

While it is not strictly a state machine this way, I sometimes put a State Selector subVI between the left terminal of the state shift register and the select terminal of the case structure.  This sub VI takes as inputs Next State (from the shift register) and Command (from the queue form the GUI loop).  Its output is the next state to be entered by the state machine. It can set priorities so that the Halt command is processed immediately while a Save command might be held until the current acquisition and processing tasks are completed.

 

The other way is to let each state use the Command queue output as one of the factors it uses to decide the next state.

 

Either way the next state decision making can be messy when you need to deal with asynchronous events.

 

Lynn

0 Kudos
Message 8 of 16
(3,513 Views)

@johnsold wrote:

Mark,

 

While it is not strictly a state machine this way, I sometimes put a State Selector subVI between the left terminal of the state shift register and the select terminal of the case structure.  This sub VI takes as inputs Next State (from the shift register) and Command (from the queue form the GUI loop).  Its output is the next state to be entered by the state machine. It can set priorities so that the Halt command is processed immediately while a Save command might be held until the current acquisition and processing tasks are completed.

 

The other way is to let each state use the Command queue output as one of the factors it uses to decide the next state.

 

Either way the next state decision making can be messy when you need to deal with asynchronous events.

 

Lynn


I suppose if you draw the state transition diagram you simply have at least one implicit action/event which can occur on every state transition. That is, for every transition in your state diagram you would need to include any and all asynchronous events that can occur. As for my comment about not being a true state machine it was because I was thinking of the state machine as more of a closed system. Once in it everything that occurs happens within it.

 

Given your approach I am curious to you buffer the next state that was on the shift register or does that get overridden by the asynchronous event? If the previous state is buffered you are in essence creating a limited queued state machine. The only difference is that a single state itself cannot push multiple next states onto the system. However, unless the asynchronous events do push override and effectively flush the "next state" obtained from the shift register you do have a queue for your events.

 

Overall I like these types of discussions.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 9 of 16
(3,504 Views)

Mark,

 

I have "queued" states, usually just on by adding a left terminal on the shift register, but that tends to be confusing.  Another approach I have used is to have another enum called Mode which is somewhat like a group of states.  If Mode is Acquisition, the routine states might be acquire, scale, average, and check limit.  A Halt command which is received during "scale" might allow average and check limits before stopping the acquisition. The Shutdown mode might save, close the file, and write zeros to digital outputs before clearing the DO task, going through several states in the process.  Essentially the Mode is an additional state variable to be used in determining the next state.

 

It is not the cleanest architecture and has tended to occur in systems with lots of mission creep where the up front design became obsolete before the code was working and no one would allow time to re-design.  But that never happens in the real world, right?

 

Lynn

0 Kudos
Message 10 of 16
(3,489 Views)