Це модель сигналів для автомобілів. Збираємо три незалежні гілки LED і повторюємо кнопку з уроку 2.
Перед зміною схеми від’єднай живлення. У Wokwi зупини симуляцію. Справжню схему перевір разом з учителем перед підключенням USB.
Урок 05-02 · Крок 2 / 10
П’ять станів світлофора
Зелений. Горить щонайменше 5 секунд. Без натискання залишається зеленим.
Зелений блимає. Тричі: 0,5 с вимкнений і 0,5 с увімкнений. Разом 3 секунди.
Жовтий. Горить 2 секунди.
Червоний. Горить 5 секунд.
Червоний і жовтий. Горять разом 1 секунду, потім знову зелений.
Коротке натискання запам’ятовується. Якщо натиснути на другій секунді зеленого, блимання почнеться на п’ятій секунді, жовтий — на восьмій. Якщо натиснути після п’ятої — блимання почнеться майже одразу.
Натискання під час інших кольорів не додають нових циклів.
Урок 05-02 · Крок 3 / 10
Окремий резистор для кожного LED
На макетній платі отвори a–e одного номера з’єднані. Різні номери — окремі контактні групи.
Червоний LED: анод A → 4a, катод C → 3a. Резистор 220 Ом → 4c–10c.
Жовтий: A → 13a, C → 12a. Резистор → 13c–19c.
Зелений: A → 22a, C → 21a. Резистор → 22c–28c.
Довга ніжка нового LED зазвичай є анодом. Плаский край корпусу позначає катод. Резистор не має полярності.
У Wokwi деталі стоять у цих самих отворах. Резистори розташовані в рядку c; кожен з’єднує дві різні контактні групи.
Урок 05-02 · Крок 4 / 10
Три виходи та спільний GND
D8 → 10d: струм іде через резистор до червоного LED.
D9 → 19d: живить жовту гілку.
D10 → 28d: живить зелену гілку.
GND Uno → нижня шина −. Від 3e, 12e та 21e проведи по короткому чорному дроту до цієї шини.
Так усі три катоди мають спільний GND. Початок кожної гілки під’єднаний до окремого виходу Arduino. Не з’єднуй між собою D8, D9 та D10: кожен вихід керує своїм кольором.
Урок 05-02 · Крок 5 / 10
Натискання з’єднує D2 з GND
Постав кнопку ліворуч через центральну канавку: ніжки в 6e, 8e, 6j та 8j. У Wokwi вона повернута на 90°. Перевір, які контакти з’єднані без натискання, за уроком 2 або мультиметром на знеструмленій схемі.
D2 → 8j: ця група з’єднана з контактом кнопки 1.r у 8j.
6j → нижня шина −: це контакт 2.r іншої внутрішньої групи.
У цій схемі використовуємо 1.r і 2.r. 1.l та 1.r уже з’єднані всередині, тому між ними натискання нічого не змінить.
З INPUT_PULLUP відпущена кнопка дає HIGH, натиснута — LOW. Додатковий резистор для кнопки не потрібний.
Урок 05-02 · Крок 6 / 10
Коли змінюється сигнал
void updatePhase(unsigned long now) {
unsigned long elapsed = now - phaseStartedAt; // Тривалість поточного стану.
if (phase == GREEN && crossingRequested && elapsed >= GREEN_MS) { // Можна завершити зелений.
phase = BLINK; // Спершу три блимання зеленого.
} else if (phase == BLINK && elapsed >= BLINK_MS) { // Три блимання завершились.
phase = YELLOW; // Після них вмикаємо жовтий.
} else if (phase == YELLOW && elapsed >= YELLOW_MS) { // Жовтий завершився.
phase = RED; // Вмикаємо червоний.
} else if (phase == RED && elapsed >= RED_MS) { // Час переходу завершився.
phase = READY; // Червоний разом із жовтим.
} else if (phase == READY && elapsed >= READY_MS) { // Повертаємо рух.
phase = GREEN; // Знову зелений.
crossingRequested = false; // Старий запит виконано.
} else { // Час зміни ще не настав.
return; // Залишаємо поточний стан.
}
phaseStartedAt = now; // Запам’ятовуємо початок нового стану.
}
phase зберігає один із п’яти станів: GREEN, BLINK, YELLOW, RED або READY. crossingRequested означає, що пішохід натиснув кнопку. elapsed — час від початку поточного стану.
У кожному рядку if перевіряємо стан і час. Якщо переходити ще рано, return завершує тільки цю функцію. Після переходу запам’ятовуємо новий час у phaseStartedAt.
Урок 05-02 · Крок 7 / 10
Три дії в loop()
void loop() {
unsigned long now = millis(); // Один показ часу для всіх дій цього оберту.
readButton(now); // Читаємо кнопку та запам’ятовуємо новий запит.
updatePhase(now); // Перемикаємо стан, якщо настав його час.
showLights(now - phaseStartedAt); // Показуємо кольори та оновлюємо блимання.
}
readButton(now) приймає зміну кнопки лише після 30 мс стабільного читання. Нове натискання на зеленому зберігає запит; утримання не створює нових запитів.
updatePhase(now) визначає, чи час перейти до наступного сигналу.
showLights(now - phaseStartedAt) встановлює виходи відповідно до поточного стану.
У showLights змінна flashOn чергується між false і true кожні 500 мс. Вираз (elapsed / HALF_BLINK_MS) % 2 дає 0, 1, 0, 1…: 0 — темно, 1 — світло. Стан BLINK триває 3 секунди, тому зелений блимає тричі.
Довгих delay немає: усі три функції швидко завершуються, і loop знову читає кнопку. Повний код кожної функції є в блоці «Код і файли».