Advanced Robot Behaviors and State Machines
A state machine is a way to organize robot behavior by breaking it down into different "states" or modes. Think of it like the different modes your phone can be in: silent mode, vibrate mode, or ring mode. Your phone behaves differently in each state, and it switches between states based on what you do.
For robots, states might be: "searching for objects," "following a line," "avoiding obstacles," or "returning home." The robot does different things in each state and switches states based on what its sensors detect.
State machines are everywhere in technology:
Start by listing all the different things your robot needs to do. For example, a simple exploring robot might have:
Next, decide when the robot should switch from one state to another. These are called "transitions":
// Example state transitions for exploring robot: EXPLORING → AVOIDING: when obstacle detected AVOIDING → EXPLORING: when path is clear EXPLORING → STUCK: when same position for too long STUCK → EXPLORING: after backup maneuver complete ANY STATE → RETURNING: when battery is low
Write the code for what the robot should do in each state:
// Simple state machine structure
enum RobotState {
EXPLORING,
AVOIDING,
STUCK,
RETURNING
};
RobotState currentState = EXPLORING;
void loop() {
switch (currentState) {
case EXPLORING:
exploreMode();
break;
case AVOIDING:
avoidMode();
break;
case STUCK:
stuckMode();
break;
case RETURNING:
returnMode();
break;
}
} Here's a complete example of a robot that explores, avoids obstacles, and returns home when the battery is low:
#include <Servo.h>
// Robot states
enum RobotState {
EXPLORING,
AVOIDING,
STUCK,
RETURNING,
CHARGING
};
RobotState currentState = EXPLORING;
unsigned long stateStartTime = 0;
unsigned long lastPositionTime = 0;
float lastX = 0, lastY = 0;
void setup() {
Serial.begin(9600);
initializeRobot();
stateStartTime = millis();
Serial.println("Robot starting in EXPLORING state");
}
void loop() {
// Check for state transitions first
checkStateTransitions();
// Execute current state behavior
switch (currentState) {
case EXPLORING:
exploreMode();
break;
case AVOIDING:
avoidMode();
break;
case STUCK:
stuckMode();
break;
case RETURNING:
returnMode();
break;
case CHARGING:
chargingMode();
break;
}
delay(100); // Small delay for stability
} The key to good state machines is clear transition logic:
void checkStateTransitions() {
float batteryLevel = getBatteryLevel();
float distance = getUltrasonicDistance();
bool isStuck = checkIfStuck();
// Battery low - always return home
if (batteryLevel < 20 && currentState != RETURNING && currentState != CHARGING) {
changeState(RETURNING);
return;
}
// State-specific transitions
switch (currentState) {
case EXPLORING:
if (distance < 20) { // Obstacle detected
changeState(AVOIDING);
} else if (isStuck) { // Haven't moved in a while
changeState(STUCK);
}
break;
case AVOIDING:
if (distance > 30) { // Path is clear
changeState(EXPLORING);
}
break;
case STUCK:
if (millis() - stateStartTime > 3000) { // Been stuck for 3 seconds
changeState(EXPLORING);
}
break;
case RETURNING:
if (isAtHome()) {
changeState(CHARGING);
}
break;
}
} Each state has its own function that defines what the robot does:
void exploreMode() {
// Move forward slowly and scan for interesting things
moveForward(100); // Slow speed for exploration
// Occasionally turn to explore different directions
if (millis() - stateStartTime > 5000) {
turnRandom();
stateStartTime = millis();
}
}
void avoidMode() {
// Stop and turn away from obstacle
stopMotors();
delay(500);
// Turn right or left based on which side is clearer
if (scanLeft() > scanRight()) {
turnLeft();
} else {
turnRight();
}
delay(1000); // Turn for 1 second
}
void stuckMode() {
// Back up and turn to get unstuck
moveBackward(150);
delay(1000);
// Turn a random amount
if (random(2) == 0) {
turnLeft();
} else {
turnRight();
}
delay(random(1000, 3000)); // Turn for 1-3 seconds
}
void returnMode() {
// Navigate back to starting position using GPS or dead reckoning
navigateToHome();
}
void chargingMode() {
// Stop all movement and wait
stopMotors();
Serial.println("Charging... Press reset to restart exploration");
} Create an autonomous "pet" robot that exhibits lifelike behaviors using state machines. Your robot pet will explore, play, rest, and interact with its environment just like a real pet!