How to Create a State Machine in Arduino: Simple Guide
To create a
state machine in Arduino, define states using an enum and use a switch statement inside loop() to handle each state. Change states by updating the state variable based on conditions or events.Syntax
Use an enum to list all possible states. Declare a variable to hold the current state. Inside the loop(), use a switch statement to run code for each state. Change the state variable to move between states.
- enum State: Defines all states.
- State currentState: Holds current state.
- switch(currentState): Runs code for each state.
- currentState = NEW_STATE; Changes state.
arduino
enum State {
STATE_ONE,
STATE_TWO,
STATE_THREE
};
State currentState = STATE_ONE;
void setup() {
// Initialize things here
}
void loop() {
switch (currentState) {
case STATE_ONE:
// Code for state one
// Change state when needed
// currentState = STATE_TWO;
break;
case STATE_TWO:
// Code for state two
// currentState = STATE_THREE;
break;
case STATE_THREE:
// Code for state three
// currentState = STATE_ONE;
break;
}
}Example
This example shows a simple state machine that turns an LED on and off every second using three states: LED_OFF, LED_ON, and WAIT.
arduino
enum State {
LED_OFF,
LED_ON,
WAIT
};
State currentState = LED_OFF;
const int ledPin = 13;
unsigned long previousMillis = 0;
const unsigned long interval = 1000; // 1 second
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
switch (currentState) {
case LED_OFF:
digitalWrite(ledPin, LOW);
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
currentState = LED_ON;
}
break;
case LED_ON:
digitalWrite(ledPin, HIGH);
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
currentState = LED_OFF;
}
break;
case WAIT:
// Not used in this example
break;
}
}Output
The LED on pin 13 turns ON for 1 second, then OFF for 1 second, repeating continuously.
Common Pitfalls
Common mistakes when creating state machines in Arduino include:
- Not updating the state variable, causing the machine to get stuck in one state.
- Using delay() inside states, which blocks the program and stops state changes.
- Not handling all states in the
switch, leading to unexpected behavior. - Forgetting to initialize variables like timers, causing timing errors.
Always use non-blocking code like millis() for timing and ensure every state can transition properly.
arduino
/* Wrong: Using delay() blocks state changes */ void loop() { switch (currentState) { case LED_OFF: digitalWrite(ledPin, LOW); delay(1000); // Blocks everything currentState = LED_ON; break; case LED_ON: digitalWrite(ledPin, HIGH); delay(1000); // Blocks everything currentState = LED_OFF; break; } } /* Right: Use millis() for non-blocking timing */ unsigned long previousMillis = 0; const unsigned long interval = 1000; void loop() { unsigned long currentMillis = millis(); switch (currentState) { case LED_OFF: digitalWrite(ledPin, LOW); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; currentState = LED_ON; } break; case LED_ON: digitalWrite(ledPin, HIGH); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; currentState = LED_OFF; } break; } }
Quick Reference
Tips for creating state machines in Arduino:
- Use
enumfor clear state names. - Use a
switchstatement to handle states. - Use
millis()for timing, avoiddelay(). - Always update the state variable to move between states.
- Keep state code short and focused on one task.
Key Takeaways
Define states with an enum and track the current state with a variable.
Use a switch statement inside loop() to run code for each state.
Avoid delay(); use millis() for non-blocking timing in state transitions.
Always update the state variable to move between states.
Keep state code simple and handle all possible states.