Menu
CoddyTech

Конечный автомат светофора

Часть раздела Отсчёт времени без 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() занимает микросекунды, поэтому у платы остаётся время для других задач: здесь — светодиод состояния, который мигает всё это время, показывая, что контроллер работает.

challenge icon

Задание

Средне

Светодиод состояния на выводе 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, затем снова зелёный
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Отсчёт времени без delay

Потренируйтесь самостоятельно: Песочница Arduino