Using a State Machine (Event Driven) Architecture

Publish Date: Nov 30, 2018 | 35 Ratings | 3.23 out of 5 | Print

Table of Contents

  1. Description
  2. Simple Example
  3. State Transitions
  4. Common Applications

1. Description

A state machine is a programming architecture that can be used to implement any algorithm that can be explicitly described by a state diagram or flowchart. It introduces a way to create a program such that it responds to user events (such as key strokes and mouse events) or in-state calculation (such as comparing system variables). This architecture provides a distinct advantage over using a sequential architecture that uses data dependency to force execution in exactly the same way every time. Almost all programs that have more than a rudimentary user interface employ the state machine architecture—they wait for an event (user interaction or calculation result), and then take appropriate actions based on this input.

A state machine consists of a set of states and a case selector that determines which state the program transitions to next. In LabVIEW, a state machine is created with a while loop, a shift register, a case structure, and some form of case selector. The exact form of the case selector can vary, and will be discussed later. The while loop is the main program loop, and executes until the conditions for exiting the program are met. The while loop executes one case per iteration. The shift register keeps track of which case should be the next to execute (which is decided by the case selector code). Finally, each case of the case structure contains the action for one specific use action. Often, the default case is used as a timeout (i.e., if the use did nothing, check again to see if he's done something yet).



Back to Top

2. Simple Example

Here is a simple example that demonstrates the functionality and structure of a state machine. This example computes the cumulative result of simple arithmetic operations between the previous cumulative result and a constant. The arithmetic operation is decided by the user through an enumerated control (enum). The value of this enum is what decides which case to enter in each iteration of the while loop.  

 

 

This example doesn't make any determination of which state to transition to next based on any logic or code inside each state. The transition is entirely based on the value of the user-selectable enum control. In the next section, we'll see how to expand upon this example to implement more complex behavior. 

 

Back to Top

3. State Transitions


There are many ways to transition between cases in a state machine. Which method you choose will depend on your specific application, needs, and preference. Here we'll discuss the different transition methods, and how each could be implemented in the simple example above. 

 

Default Transition

A default transition causes your state-machine to behave as if you were using a sequential programming model, as there is only one possible state that occurs next. Use a default transition when you know that you want to do the same thing every time you exit that particular state. The default transition is usually used for a "Stop" state, because the only action that the user usually wants to happen in the stop state is stopping the program. 

 

Select Function

Use the select function to make a true/false decision to transition between two possible states. You can use the select function to take the result of a logic decision and output the appropriate state transition to based on that decision. We'll use the select function to transition from the "Divide" case to the "add" case if the cumulative output becomes too small (less than 1). Adding this transition to the "Divide" case effectively keeps our cumulative result from becoming excessively small.   

 

Case Structure

The case structure case selection method is self-documenting and scalable. You can add as many possible transitions out of a particular state as you need to. One disadvantage is that not all of the code is visible at once, therefore the complete behavior of you transition code may not be readily apparent. The case structure is one of the most flexible transition methods. In this example, a case structure is used to determine which case to transition to next based on the value of the cumulative result: 

  • If the result is less than or equal to zero: Add
  • If the result is between 1 and 500: Multiply
  • If the result is between 501 and 1000: Subtract
  • If the result is greater than 1001: Divide

Transition Array

The decision making code produces an index, which is then used to select the appropriate case from an array constant containing all of the possible state transitions.

Other Methods

You do not always need to use the same transition method in all of your cases. Modify your state machine and use the most appropriate transition for each of your states. More complex logic is also possible, and can build upon or combine the state transition methods mentioned here. The various ways you can effect state transitions are not limited to the methods shown above—you may choose to implement your state transitions in a completely different way:  


This example uses the menu VIs as the case selector. In this case, it may be useful to have the case statement make decisions based on strings rather than integers.

Back to Top

4. Common Applications

Consider a state machine architecture for any program whose execution is controlled by user events, or any program that executes the same set of operations, but not necessarily in the same order, or the same number of times per operation.

A state machine is a polling architecture. Polling is the action of checking for repeatedly checking for a condition, in this case at set time intervals. This means that the state machine will constantly be executing one case or another, even if it is only a default or timeout case. In most cases this does not present a problem. If creating a user interface, having the loop run 5 or 10 times a second, and having a timeout case that executes if no action is taken by the user is usually fine. If you a have a state machine that implements process testing, or some other repetitive task, there is not usually the need to have the program remain idle for an extended period of time. 

If polling is undesirable in your application, or conflicts with other requirements of the application, consider using an event structure.   

 


Back to Top

Bookmark & Share


Ratings

Rate this document

Answered Your Question?
Yes No

Submit