Tuesday 5 June 2012

Simple Finite State Machine for Beginners


What is FINITE STATE MACHINE?

A finite state Machine is a simply state Machine which composed of different States, events, Actions and Transition of states based on events.

A finite state Machine generally represented in the form of two dimensional Matrix.

The vertical (or horizontal) dimension indicates current states, the horizontal (or vertical) dimension indicates events, and the cells (row/column intersections) in the table contain the next state if an event happens (and possibly the action linked to this state transition).

State Transition Table
  Events
State
E1
E2
  ...  
En
S1
-
Ay/Sj
...
-
S2
-
-
...
Ax/Si
...
...
...
...
...
Sm
Az/Sk
-
...
-


(S: state, E: event, A: action, -: illegal transition)

Generally in real time code, these action functions are implemented using function pointers.

Real time FSM code contain states and events defined in enums . And there is event handler which handles the events and based on respective events the appropriate action is being taken.

Below you can find a small example of finite state machine and it is implemented in C language. 

I have implemented BULB( or LIGHT) - SWITCH state Machine.
If  the switch is ON, bulb is in OFF then state should change to ON state( Action: Bulb is ON)
If  the switch is ON, bulb is in ON then state should remain in  ON state( No Action is Taken)
If  the switch is OFF, bulb is in ON then state should change to OFF state( Action: Bulb is OFF)  
If  the switch is OFF, bulb is in OFF then state should remain in OFF state( Action: Bulb is OFF)  

STATES/EVENTS
SWITCHOFF_BULB
SWITCHON_BULB
STATE_OFF
STATE_OFF, Action -> Nothing [ Bulb Remain in OFF)
STATE_ON, ACTION-> Bulb is ON
STATE_ON
STATE_OFF, ACTION-> Bulb is OFF
STATE_ON, Action -> Nothing [ Bulb Remain in ON)

 
Implementation of FSM in simple C code:
==============================
#include<stdio.h>
#include<stdlib.h>

#define MAX_STATES 2

/* This Program implements a state Machine for
 * simple switch( ON/OFF) Which does the action to switch ON/OFF bulb.
 */

/*
 * Generally FSM Implemented in Two Dimensional Matrix
 */
/*
 * FSM_STATES
 */
typedef enum FSM_STATES
{
    STATE_OFF,
    STATE_ON

}FSM_STATES;

/*
 * FSM_STATES
 */
typedef enum FSM_EVENTS
{
    SWITCHOFF_BULB,
    SWITCHON_BULB       
}FSM_EVENTS;

/*
 *  Event handler function
 */
 void FSM_Event_Handler_Function(FSM_EVENTS fsm_event);

 /*
 *   Action Functions
 */
 
 /* Switch On*/
 void SwitchOn_Bulb(FSM_EVENTS fsm_event,  char *p);
 
 /* Switch off */
 void SwitchOff_Bulb(FSM_EVENTS fsm_event,  char *p);
 
 
 /*
  *    Function Pointer, Declare array of pointers.
  * One way of declaring the Array of pointers by using below syntax
  */
 typedef void (*action_func)(FSM_EVENTS fsm_event,  char *p);
 
 /*
  *  Array of Action Functions
  */
 action_func  array_of_func_Pointers[MAX_STATES] = { SwitchOff_Bulb, SwitchOn_Bulb };
 
 /*
  * Intialise the FSM_STATE Declared it as Global
  */
 FSM_STATES fsm_state = STATE_OFF;
 
/* Declaration Ends Here */
 
 
 /*
  * SwitchOn_Bulb()
  */
 void SwitchOn_Bulb(FSM_EVENTS fsm_event,  char *p)
 {
    printf(" \nBefore Switch On FSM State is :%d\n", fsm_state);
   
    /* Change the fsm_state to switch OFF */
    fsm_state = STATE_ON;
 
    printf(" The Event is :%d\n", fsm_event);   
    printf(" The FSM State changed to :%d\n", fsm_state);   
    printf(" The Trigger from this Function :%s\n", p);
       
 }
 
 /*
  * SwitchOff_Bulb()
  */
 void SwitchOff_Bulb(FSM_EVENTS fsm_event, char *p)
 {
    printf(" \nBefore Switch OFF FSM State is :%d\n", fsm_state);
 
    /* Change the fsm_state to switch OFF */
    fsm_state = STATE_OFF;
   
    printf(" The Received Event is :%d\n", fsm_event);   
    printf(" The FSM State changed to  :%d\n", fsm_state);   
    printf(" The Trigger from this Function :%s\n", p);
       
 }
 
 /*
 *  Event handler function
 */
 void FSM_Event_Handler_Function(FSM_EVENTS fsm_event)
 {
    switch(fsm_event)
    {
        case SWITCHOFF_BULB:
        {
       
            /* State is ON */
            if(fsm_state == STATE_ON)
            {
                /* OFF THE BULB */
                array_of_func_Pointers[SWITCHOFF_BULB](fsm_event, " HEY SWITCH OFF THE BULB, SAVE THE POWER \n");
            }
            else       
            {
                if(fsm_state == STATE_OFF)
                {               
                    printf(" \nHEY  ALREADY BULB is in OFF STATE, SO NO ACTION is TAKEN, RELAX \n");
                   
                }
            }
        }
        break;
   
        case SWITCHON_BULB:
        {
            /* State is OFF */
            if(fsm_state == STATE_OFF)
            {
                /* ON THE BULB */
                array_of_func_Pointers[SWITCHON_BULB](fsm_event,  " HEY SWITCH ON THE BULB, HERE VERY DARK \n");
            }
            else       
            {
                if(fsm_state == STATE_ON)
                {               
                    printf(" \nHEY  ALREADY BULB is in ON STATE, SO No ACTION is TAKEN, RELAX \n");
                }
            }
        }
        break;
   
        default:
            printf("INVALID EVENT RECIEVED \n");
            break;
    }   
 }
 /*
  *  Main() function
  */
 int main()
 {
   
    int triggerEvent;
   
    do
    {
        printf("\n------------------------- \n");
        printf(" Enter the Event to be TRIGGER \n");
        printf(" Enter '0' to Switch Off the BULB \n");
        printf(" Enter '1' to Switch ON the BULB \n");
        printf(" Enter '10' to EXIT \n");
        scanf("%d", &triggerEvent);
        printf("--------------------------- \n");
       
        /* Call the Handler Function */
        FSM_Event_Handler_Function((FSM_EVENTS) triggerEvent );
       
    }while(triggerEvent != 10);
   
 }











1 comment:

  1. Hi , Mr. A.M.Sekhar Reddy
    Your explanation is very useful and helped me a lot.
    I have implemented a finite state machine using trasition table. I am using a microcontroller to measure the line voltage of Electricity power.
    The problem is some transition depend on time (eg if Vrms==220 for 5 seconds reconnect the load ), how could calculate the time and the microcontroller don't has real time clock? my transition table and the elements of table has only those attributes (Current_State,Event,Action,Next State).
    thank you
    minimedc@gmail.com

    ReplyDelete