Идея: реализуем стандартный алгоритм работы трёхсекционного светофора на Arduino Uno.
Дополнительные библиотеки не требуются.
#include <Arduino.h>
// ---------- Пины ----------
const uint8_t PIN_RED = 10;
const uint8_t PIN_YELLOW = 9;
const uint8_t PIN_GREEN = 8;
// ---------- Тайминги (мс) ----------
const uint32_t T_GREEN_STEADY = 7000; // Зелёный, перед миганием
const uint32_t T_GREEN_BLINK_TOTAL = 4000; // Мигание зелёного: 1 Гц, суммарно 4 с
const uint32_t BLINK_PERIOD = 1000; // 1 Гц
const uint32_t T_YELLOW = 3000; // Жёлтый строго 3 с
const uint32_t T_RED = 7000; // Красный
const uint32_t T_RED_YELLOW = 2000; // Красный+жёлтый
// ---------- Состояния ----------
enum Phase : uint8_t {
PH_GREEN = 0,
PH_GREEN_BLINK,
PH_YELLOW,
PH_RED,
PH_RED_YELLOW
};
Phase phase = PH_GREEN;
uint32_t phaseStart = 0;
// Для мигания зелёного
uint32_t blinkStart = 0;
bool greenOn = true;
// Управление огнями
void setLights(bool r, bool y, bool g) {
digitalWrite(PIN_RED, r ? HIGH : LOW);
digitalWrite(PIN_YELLOW, y ? HIGH : LOW);
digitalWrite(PIN_GREEN, g ? HIGH : LOW);
}
void setup() {
pinMode(PIN_RED, OUTPUT);
pinMode(PIN_YELLOW, OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
setLights(false, false, true);
phase = PH_GREEN;
phaseStart = millis();
}
void loop() {
const uint32_t now = millis();
const uint32_t elapsed = now - phaseStart;
switch (phase) {
case PH_GREEN:
if (elapsed >= T_GREEN_STEADY) {
phase = PH_GREEN_BLINK;
phaseStart = now;
blinkStart = now;
greenOn = true;
setLights(false, false, true);
}
break;
case PH_GREEN_BLINK: {
const uint32_t blinkElapsed = now - blinkStart;
if (blinkElapsed >= BLINK_PERIOD) {
blinkStart = now;
greenOn = !greenOn;
setLights(false, false, greenOn);
}
if (elapsed >= T_GREEN_BLINK_TOTAL) {
phase = PH_YELLOW;
phaseStart = now;
setLights(false, true, false);
}
} break;
case PH_YELLOW:
if (elapsed >= T_YELLOW) {
phase = PH_RED;
phaseStart = now;
setLights(true, false, false);
}
break;
case PH_RED:
if (elapsed >= T_RED) {
phase = PH_RED_YELLOW;
phaseStart = now;
setLights(true, true, false);
}
break;
case PH_RED_YELLOW:
if (elapsed >= T_RED_YELLOW) {
phase = PH_GREEN;
phaseStart = now;
setLights(false, false, true);
}
break;
}
}
Вторая часть урока не менее увлекательна, и позволяет менять режимы работы светофора, подключим к текущей схеме сенсорную кнопку, напишем обновленный код и проверим ее работу.
Часть 2 урока "Светофор"