Introduction to State Machines in C : Embedded Systems

 

Table of Contents

  1. Introduction
  2. Types of State Machine
    1. Finite State Machine (FSM)
    2. Mealy Machine
    3. Moore Machine
    4. Hierarchical State Machine
    5. Harel Statechart
  3. State Machine Usage in Embedded System
    1. Control logic
    2. User interface
    3. Sensor data acquisition
  4. FSM Code Example
  5. Summary

Introduction

A state machine is a model used to represent the behavior of a system, which can be a software system, an electronic system, or any other type of system. It is composed of a set of states, each representing a specific condition or mode of the system, and a set of transitions between those states that determine how the system behaves. State machines are commonly used in the design and implementation of software systems, particularly in embedded systems, where they can help manage complex logic and control the behavior of a system in response to various events and inputs. They can be implemented using various programming languages and tools, and they are widely used in real-time systems, control systems, and user interface design.

1. Types of State Machine

   1. Finite State Machine (FSM) :

A Finite State Machine (FSM) is a specific type of state machine that has a finite number of states and transitions between them. In an FSM, the system is always in one of a finite set of states, and the transitions between states are triggered by specific events or inputs. FSMs are widely used in the design and implementation of hardware systems, such as digital circuits and microcontrollers, as well as in software systems, particularly in areas such as natural language processing and game development.

2. Mealy Machine :

In a Mealy machine, the output of the machine depends not only on the current state but also on the input. The output is generated as soon as a transition occurs. The state transition table includes both input and output values, so the output is produced as the machine moves from one state to another. This type of state machine is useful in applications where the output depends on the current input as well as the current state. One example is a vending machine that displays the product information as soon as the user selects a particular item.

3. Moore Machine :

In a Moore machine, the output depends only on the current state, and not on the input. The output is generated only when the machine enters a new state, and not during the transition. The state transition table only includes input values, and the output is associated with each state. This type of state machine is useful in applications where the output depends only on the current state. One example is a traffic light system where the color of the light changes based on the current state.

4. Hierarchical State Machine :

Hierarchical state machines consist of multiple state machines, where each machine represents a subsystem or module of the overall system. Each subsystem has its own set of states and transitions, and can have its own sub-state machines. This type of state machine is useful in modeling complex systems that can be broken down into smaller subsystems. One example is an airplane control system where each subsystem, such as the engine, navigation, and landing gear, has its own set of states and transitions.

5. Harel Statechart :

A Harel statechart is a type of hierarchical state machine that includes the concept of concurrency. It is used to model systems with multiple parallel processes or events that can occur simultaneously. In a Harel statechart, each state can have multiple concurrent sub-states, and each sub-state can have its own set of transitions and events. This type of state machine is useful in modeling complex systems with multiple parallel processes or events, such as a real-time control system.

2. State Machine Usage in Embedded System

State machines are very commonly used in embedded systems to model and control the behavior of the system. In embedded systems, the state machine is often used to represent the system's control logic or user interface.

Here are some examples of how state machines are used in embedded systems:

1. Control logic:

In many embedded systems, the control logic is modeled using a state machine. The control logic can be used to manage the system's power modes, handle interrupts, and perform other critical system functions. For example, a state machine can be used to control the power management of a battery-operated device, such as a mobile phone or a smartwatch. The state machine can manage the device's power consumption by transitioning between different power modes based on the device's activity level and battery level.

2. User interface:

Another common use of state machines in embedded systems is to model the user interface. The user interface can be modeled as a state machine with states representing different screens, menus, or modes of operation. For example, a state machine can be used to control the display of a digital thermometer, with states representing the different temperature ranges, and transitions between the states representing the changes in the temperature.

3. Sensor data acquisition:

In many embedded systems, state machines are used to acquire and process data from sensors. The state machine can be used to control the data acquisition process and ensure that the data is properly processed and stored. For example, a state machine can be used to acquire and process data from a temperature sensor, with states representing the different stages of the data acquisition process, such as data collection, filtering, and storage.

3. FSM Code Example

#include 
#include 
enum transmitter_fsm { trInit = 0, tTimerStarted, tTimerEnded, tIfButtonPressed }; enum receiver_fsm { rInit = 0, rTimerStarted, rTimerEnded, rIfButtonPressedDetected }; bool button_pressed = false; void *rfTransmitter(void *vargp) { enum transmitter_fsm state = trInit; time_t sec; uint8_t timeout_for_tx_seconds = 4; clock_t time_stamp; bool if_button_pressed = true; while (1) { switch (state) { case trInit: time_stamp = 0; if (button_pressed == false) state = tTimerStarted; break; case tTimerStarted: time_stamp = time(NULL); state = tTimerEnded; break; case tTimerEnded: if ((time(NULL) - time_stamp) == timeout_for_tx_seconds) { state = tIfButtonPressed; } break; case tIfButtonPressed: if (if_button_pressed == true) { button_pressed = true; printf("button_pressed_from_transmitter\n"); } state = trInit; break; } } }
void *rfReceiver(void *vargp) { enum receiver_fsm state = rInit; time_t sec; uint8_t timeout_for_rx_seconds = 1; clock_t time_stamp; while (1) { switch (state) { case rInit: time_stamp = 0; if (button_pressed == false) state = rTimerStarted; break; case rTimerStarted: time_stamp = time(NULL); state = rTimerEnded; break; case rTimerEnded: if ((time(NULL) - time_stamp) == timeout_for_rx_seconds) { state = rIfButtonPressedDetected; } break; case rIfButtonPressedDetected: if (button_pressed == true) { button_pressed = false; printf("button_pressed_detected\n"); } state = rInit; break; } } } int main() { pthread_t thread_id, thread_id1; printf("Before Thread\n"); pthread_create(&thread_id, NULL, rfTransmitter, NULL); pthread_create(&thread_id1, NULL, rfReceiver, NULL); pthread_join(thread_id, NULL); pthread_join(thread_id1, NULL); while (1); }

4. Summary

  1. State machines are a powerful tool for modeling and controlling complex systems, especially in embedded systems.
  2. They provide a structured approach to designing and implementing control logic, which can improve system reliability, predictability, and testability.
  3. State machines require careful planning and design, and can be difficult to modify or troubleshoot.
  4. Despite the challenges, state machines are essential in managing system complexity and controlling system behavior in modern embedded systems design and implementation.