Конечный автомат светофора
Часть раздела Отсчёт времени без delay путешествия по Arduino на Coddy. Урок 10 из 18.
Светофор — это конечный автомат: он всегда находится в одном состоянии (зелёный, жёлтый или красный), каждое состояние длится заданное время и определяет, какое состояние будет следующим:
- GREEN: горит зелёный; через 2 s перейти в YELLOW
- YELLOW: горит жёлтый; через 1 s перейти в RED
- RED: горит красный; через 2 s перейти в GREEN
Каждая строка становится одним case:
case GREEN:
setLights(HIGH, LOW, LOW);
if (now - lightStart >= 2000) {
light = YELLOW;
lightStart = now;
}
break;С delay(2000) светофор тоже работал бы, но ничего другого не могло бы выполняться. С millis() каждый проход через loop() занимает микросекунды, поэтому у платы остаётся время для других задач: здесь — светодиод состояния, который мигает всё это время, показывая, что контроллер работает.
Задание
СреднеСветодиод состояния на выводе 13 уже мигает, а enum и lightStart готовы. Напиши программу для светофора с помощью switch (light), добавив по одному case для каждого сигнала:
- зелёный — 2 с, жёлтый — 1 с, красный — 2 с, затем снова зелёный
- за раз горит только один светодиод, используй
setLights() - не используй
delay(), чтобы светодиод состояния продолжал мигать
Нажми Run, затем Check.
Попробуйте сами
const int greenLed = 10;
const int yellowLed = 11;
const int redLed = 12;
const int statusLed = 13; // собственный светодиод платы
enum Light { GREEN, YELLOW, RED };
Light light = GREEN;
unsigned long lightStart = 0; // когда загорелся текущий сигнал
unsigned long statusPrevious = 0;
int statusState = LOW;
void setup() {
pinMode(greenLed, OUTPUT);
pinMode(yellowLed, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(statusLed, OUTPUT);
}
void setLights(int green, int yellow, int red) {
digitalWrite(greenLed, green);
digitalWrite(yellowLed, yellow);
digitalWrite(redLed, red);
}
void loop() {
unsigned long now = millis();
// индикаторный светодиод переключается каждые 250 ms, показывая, что контроллер работает
if (now - statusPrevious >= 250) {
statusPrevious = now;
if (statusState == LOW) {
statusState = HIGH;
} else {
statusState = LOW;
}
digitalWrite(statusLed, statusState);
}
// светофор: switch (light) с отдельным case для каждого сигнала
// зелёный 2 s, жёлтый 1 s, красный 2 s, затем снова зелёный
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Отсчёт времени без delay
1millis()
Часы на millis()Время в unsigned longМигание без задержкиДва светодиода, две скоростиМигание и переключение кнопкойСвет по таймеру4Точное измерение времени
Измерение с помощью micros()Когда millis() переполняетсяСекундомер с кнопкой2Конечные автоматы
Запоминаем режимВыбор с помощью switchИменованные состояния с enumКонечный автомат светофораПереключаем режимы кнопкойПотренируйтесь самостоятельно: Песочница Arduino