ES101 - Lesson 11 : State Machine and Board IO

From Embedded Systems Learning Academy
Revision as of 22:03, 6 November 2012 by Preet (talk | contribs) (Switch Statement)

Jump to: navigation, search

Objective

The objective of this lab is to learn how to design a state machine.

State Machine Design

State machine design can be constructed by considering what you want to do based on a certain system state. For example, you might want consider building a state machine for an obstacle-avoidance robot, in which you have various states that dictates robot behavior such as :

  • No Obstacle --> Move forward
  • Obstacle to the left --> Turn right
  • Obstacle to the right --> Turn left

ENUM

The enum provides a way to assign names to a sequence of integer values. For example, if a state machine contains two unique states, you should use an enum to declare the names. The alternative is to declare separate variables set to a different value, but this approach uses more unnecessary memory and is error-prone.

// Each enumeration value is unique :
typedef enum{stateSTART, stateEND, stateSENSOR} myStateType;

// Manually set the enumeration values :
typedef enum{stateSTART = 1, stateEND = 2, stateSENSOR = 3} myStateType;

The enumerator variables can be automatically assigned a value, or the value can be manually chosen. In either case, unique values should be set for enumerator variables. An enumerator does not have to be used just for a state machine design, but it can be used anytime when you need to simply set unique identifiers to certain names.

Switch Statement

The C/C++ programming languages feature switch/case statements. This is similar to using a series of if/else statements. However, it is easier to read and write code using switch/case statements.


// Test the "currentState" variable with one of the cases given below
switch(currentState)
{  
   case stateSTART:
      // Your code goes here
      break;
   case stateEND:
      // Your code goes here
      break;
   default:
      // Your code goes here
}


Lets clarify the syntax of the switch/case code :

  • Variable inside switch() is what is being compared
    This variable will be compared with each case.
  • case is followed by a variable you want to compare, followed by a colon.
  • break is required at the end of every case
    See the next section for more clarification
  • Default case is like an else statement when neither cases equal the variable being compared.
    See the Default case section below for details.

Why break?

If currentState was equal to stateSTART and there was no break statement at the end of the stateSTART case, the code would continue without currentState comparison with stateEND and execute the code inside the stateEND case as well. This may appear to be a programming flaw, however, the switch/case statements were designed this way and some complex designs omit the break statements on purpose.

Default case

The default case should be the last case. It is for the case if the variable currentState does not match any of the case statements, and this case does not have the break statement. The default case should be used to indicate an error state or unexpected state fault.

Assignment

Build the state machine given in the next figure. You will notice that the SENSOR state goes to IDLE state upon Button#1, and using the same button, the IDLE state transitions to SENSOR state. First, answer the question in the "Questions" section of this document.

State Machine Design

Whenever the state is changed, print on the screen what state the system is in. The statement should only print once - not every time the state machine function is called.

Sample Code


int main()
{
   // Use typedef to create a new variable type called States
   typedef enum {start, end} myStateType; // Name your states inside { and }
   myStateType currentState = start;      // Initialize static variable of States

   switch(currentState)
   {
      case start:
         // Check if button 0 is pressed in this state and transition out of this state
         if( /*button 0 is pressed */)
         {
            currentState = end;
            printf("Current state: END. Press Button 1 to go to START");
         }
         break;

      case end:
         // Check if button 0 is pressed in this state and transition out of this state
         if( /*button 1 is pressed */)
         {
            currentState = start;
            printf("Current state: START. Press Button 0 to go to END");
         }
         break;

       default:
         printf("State machine ERROR!\n");
   }
}


Questions

  1. Describe the behavior you see if you press and hold Button#1 for longer than 100ms in the SENSOR state.