A state machine helps your Arduino program handle different situations clearly and in order. It makes your code easier to read and control.
State machine design for 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.
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;
}
}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;
}
}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.
#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; } }
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.
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.
Practice
Solution
Step 1: Understand the concept of state machines
A state machine breaks a program into distinct states or steps to manage behavior clearly.Step 2: Identify the main benefit in Arduino context
This organization helps make the code easier to read, debug, and extend.Final Answer:
To organize the program into clear, manageable steps -> Option AQuick Check:
State machine purpose = organize steps [OK]
- Thinking state machines speed up the processor
- Confusing power saving with state management
- Assuming state machines connect multiple boards
enum?Solution
Step 1: Recall enum syntax in Arduino (C++)
The correct syntax uses curly braces and commas to list states without assignment or semicolons.Step 2: Check each option for syntax errors
enum State {START, RUNNING, STOPPED}; uses correct syntax: enum State {START, RUNNING, STOPPED}; Options B, C, and D have incorrect assignment, semicolons, or parentheses.Final Answer:
enum State {START, RUNNING, STOPPED}; -> Option AQuick Check:
Correct enum syntax = enum State {START, RUNNING, STOPPED}; [OK]
- Using '=' sign after enum name
- Separating states with semicolons instead of commas
- Using parentheses instead of braces
enum State {IDLE, PROCESS, DONE};
State currentState = IDLE;
void setup() {
Serial.begin(9600);
switch(currentState) {
case IDLE:
Serial.println("Waiting");
break;
case PROCESS:
Serial.println("Working");
break;
case DONE:
Serial.println("Finished");
break;
}
}Solution
Step 1: Identify the initial state value
The variable currentState is set to IDLE before setup() runs.Step 2: Follow the switch-case logic
Switch checks currentState; since it is IDLE, it prints "Waiting" to Serial Monitor.Final Answer:
Waiting -> Option CQuick Check:
State IDLE prints "Waiting" [OK]
- Assuming PROCESS or DONE prints without state change
- Thinking setup() runs multiple times
- Ignoring break statements in switch
enum State {START, RUNNING, STOPPED};
State currentState = START;
void loop() {
switch(currentState) {
case START:
Serial.println("Start");
currentState = RUNNING
break;
case RUNNING:
Serial.println("Running");
break;
case STOPPED:
Serial.println("Stopped");
break;
}
}Solution
Step 1: Check syntax line by line
Look at the line: currentState = RUNNING without a semicolon at the end.Step 2: Identify the error type
Missing semicolon causes a compile error. Other parts are correct or not critical for this snippet.Final Answer:
Missing semicolon after currentState = RUNNING -> Option DQuick Check:
Missing semicolon = syntax error [OK]
- Ignoring missing semicolon errors
- Assuming enum declaration is wrong
- Forgetting to initialize Serial in setup()
loop()?Solution
Step 1: Understand state machine cycling
Using a switch-case on currentState allows clear, readable transitions between states.Step 2: Evaluate each option's suitability
Use a switch on currentState and set currentState to the next state in each case correctly updates currentState to the next state inside each case. Use if statements comparing currentState to integers 0,1,2 and increment currentState by 1 uses integers but lacks clarity and safe cycling. Use a while loop inside loop() to cycle states infinitely with while loop inside loop() blocks Arduino's main loop. Use delay() to wait and then reset currentState to RED always resets state always to RED, not cycling properly.Final Answer:
Use a switch on currentState and set currentState to the next state in each case -> Option BQuick Check:
Switch-case for cycling states = Use a switch on currentState and set currentState to the next state in each case [OK]
- Using while loops inside loop() causing freezes
- Resetting state without cycling
- Using integers without clear state names
Ready to prove it?
Pass the test and this pattern moves unknown
