Именованные состояния с enum
Часть раздела Отсчёт времени без delay путешествия по Arduino на Coddy. Урок 9 из 18.
Режимы с номерами 0, 1 и 2 работают, но if (mode == 2) не объясняет, что означает 2. enum присваивает каждому числу имя:
enum State { READY, RUNNING, DONE };
State state = READY;Первая строка создаёт новый тип State, единственными значениями которого являются READY, RUNNING и DONE. Внутри они по-прежнему представлены числами 0, 1 и 2, но имена поясняют, что означает каждое из них. Вторая строка создаёт переменную этого типа.
enum и switch хорошо сочетаются: для каждого состояния — свой case.
switch (state) {
case READY:
// что делает READY и когда переходит к следующему состоянию
break;
case RUNNING:
// ...
break;
}Чтобы перейти в новое состояние, присвой state новое значение и запомни, когда оно началось: state = DONE; stateStart = millis();. Затем каждое состояние отсчитывает своё время с помощью millis() - stateStart. Такой способ написания скетча называется конечным автоматом.
Задание
СреднеУ машины три состояния. Для вас уже написано READY: зелёный светодиод горит, а нажатие запускает машину. Добавьте два других случая:
RUNNING: горит жёлтый светодиод. Через 2000 мс выключите его и перейдите вDONE.DONE: горит красный светодиод. Через 1000 мс выключите его и вернитесь вREADY.
Сохраняйте stateStart при каждом изменении. Нажмите Run, нажмите кнопку, затем нажмите Check.
Попробуйте сами
const int buttonPin = 2;
const int greenLed = 10;
const int yellowLed = 11;
const int redLed = 12;
enum State { READY, RUNNING, DONE };
State state = READY;
unsigned long stateStart = 0; // когда началось текущее состояние
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(greenLed, OUTPUT);
pinMode(yellowLed, OUTPUT);
pinMode(redLed, OUTPUT);
}
void loop() {
unsigned long now = millis();
switch (state) {
case READY:
digitalWrite(greenLed, HIGH);
if (digitalRead(buttonPin) == LOW) {
digitalWrite(greenLed, LOW);
state = RUNNING;
stateStart = now;
}
break;
// добавьте ветку RUNNING: включите жёлтый светодиод; через 2000 мс выключите его и перейдите в DONE
// добавьте ветку DONE: включите красный светодиод; через 1000 мс выключите его и вернитесь в READY
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Отсчёт времени без delay
1millis()
Часы на millis()Время в unsigned longМигание без задержкиДва светодиода, две скоростиМигание и переключение кнопкойСвет по таймеру4Точное измерение времени
Измерение с помощью micros()Когда millis() переполняетсяСекундомер с кнопкой2Конечные автоматы
Запоминаем режимВыбор с помощью switchИменованные состояния с enumКонечный автомат светофораПереключаем режимы кнопкойПотренируйтесь самостоятельно: Песочница Arduino