Cycle Modes With a Button
Part of the Timing Without Delay section of Coddy's Arduino journey. Lesson 11 of 18.
Many gadgets have one button that steps through modes: a bike light goes off, on, blinking, fast blinking, then off again. That is a state machine where a press, not the clock, moves to the next state.
Put the step in its own function. A switch on the current mode sets the next one, and the last mode goes back to the first:
void nextMode() {
switch (mode) {
case OFF:
mode = ON;
Serial.println("ON");
break;
// ... and so on, until FAST goes back to OFF
}
}The sketch calls nextMode() once per press. The button is debounced the way you learned in the Inputs section: when the reading changes, act on it, then wait 20 ms for the contacts to settle. A second switch on mode sets the LED.
Challenge
MediumThe button and the LED are written for you. Write nextMode() so each press moves to the next mode and prints its name: OFF, ON, BLINK, FAST, then OFF again.
Press Run, press the button a few times, then Check.
Try it yourself
const int ledPin = 13;
const int buttonPin = 2;
enum Mode { OFF, ON, BLINK, FAST };
Mode mode = OFF;
bool wasPressed = false;
unsigned long blinkPrevious = 0;
int ledState = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
}
// Moves to the next mode and prints its name.
void nextMode() {
// one case per mode: set the next mode, print its name, break
}
// Switches the LED every interval ms.
void blinkEvery(unsigned long interval) {
unsigned long now = millis();
if (now - blinkPrevious >= interval) {
blinkPrevious = now;
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
void loop() {
// 1. a press (debounced) calls nextMode()
bool pressed = digitalRead(buttonPin) == LOW;
if (pressed != wasPressed) {
if (pressed) {
nextMode();
}
wasPressed = pressed;
delay(20); // let the contacts settle
}
// 2. the mode decides what the LED does
switch (mode) {
case OFF:
digitalWrite(ledPin, LOW);
break;
case ON:
digitalWrite(ledPin, HIGH);
break;
case BLINK:
blinkEvery(500);
break;
case FAST:
blinkEvery(100);
break;
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Timing Without Delay
Practice on your own: Arduino playground