A state machine helps your Arduino program handle different situations clearly and in order. It makes your code easier to read and control.
0
0
State machine design for Arduino
Introduction
When your Arduino needs to do different things based on button presses.
When you want to control a device with multiple steps, like a traffic light.
When you want to manage modes, like sleep mode and active mode.
When you want to avoid messy if-else code and keep things organized.
Syntax
Arduino
enum State {
STATE1,
STATE2,
STATE3
};
State currentState = STATE1;
void loop() {
switch (currentState) {
case STATE1:
// do something
if (condition) currentState = STATE2;
break;
case STATE2:
// do something else
if (condition) currentState = STATE3;
break;
case STATE3:
// do another thing
if (condition) currentState = STATE1;
break;
}
}Use enum to name your states clearly.
Use a switch statement inside loop() to handle each state.
Examples
Simple two-state machine to toggle an LED on and off with a button.
Arduino
enum State { OFF, ON };
State currentState = OFF;
void loop() {
switch (currentState) {
case OFF:
// turn LED off
if (buttonPressed) currentState = ON;
break;
case ON:
// turn LED on
if (buttonPressed) currentState = OFF;
break;
}
}Traffic light example cycling through states with timing.
Arduino
enum State { RED, GREEN, YELLOW };
State currentState = RED;
unsigned long lastChange = 0;
void loop() {
unsigned long now = millis();
switch (currentState) {
case RED:
if (now - lastChange > 5000) {
currentState = GREEN;
lastChange = now;
}
break;
case GREEN:
if (now - lastChange > 5000) {
currentState = YELLOW;
lastChange = now;
}
break;
case YELLOW:
if (now - lastChange > 2000) {
currentState = RED;
lastChange = now;
}
break;
}
}Sample Program
This program uses a state machine to blink the built-in LED on pin 13. It starts in IDLE state. When you send the letter 'b' over the serial monitor, it starts blinking the LED on and off every 500 milliseconds. The serial prints show the current state.
Arduino
#include <Arduino.h> enum State { IDLE, BLINK_ON, BLINK_OFF }; State currentState = IDLE; const int ledPin = 13; unsigned long lastChange = 0; const unsigned long interval = 500; void setup() { pinMode(ledPin, OUTPUT); Serial.begin(9600); } void loop() { unsigned long now = millis(); switch (currentState) { case IDLE: digitalWrite(ledPin, LOW); Serial.println("State: IDLE"); if (Serial.available()) { char c = Serial.read(); if (c == 'b') { currentState = BLINK_ON; lastChange = now; } } break; case BLINK_ON: digitalWrite(ledPin, HIGH); Serial.println("State: BLINK_ON"); if (now - lastChange >= interval) { currentState = BLINK_OFF; lastChange = now; } break; case BLINK_OFF: digitalWrite(ledPin, LOW); Serial.println("State: BLINK_OFF"); if (now - lastChange >= interval) { currentState = BLINK_ON; lastChange = now; } break; } }
OutputSuccess
Important Notes
Use millis() for timing instead of delay() to keep the program responsive.
Keep states simple and focused on one task each.
Use descriptive names for states to make your code easier to understand.
Summary
A state machine helps organize your Arduino program into clear steps.
Use enum and switch to manage states easily.
State machines make your code easier to read, debug, and extend.