Skip to main content

МНОГОРЕЖИМНЫЙ СВЕТОФОР 🚦

БАЗОВАЯ РЕАЛИЗАЦИЯ

Логика работы:

Основные режимы:
- НОРМАЛЬНЫЙ: стандартные циклы (красный → зеленый → желтый)
- НОЧНОЙ: мигающий желтый для экономии энергии
- АВАРИЙНЫЙ: мигающий красный при экстренной ситуации
- ПИКОВЫЙ: укороченные циклы для интенсивного движения

Управление:
Потенциометр → выбор режима (4 позиции)
Кнопка → экстренное переключение в аварийный режим

Компоненты:

  • ✅ Светодиоды: красный (x2), желтый (x2), зеленый (x2) - для 2 направлений
  • ✅ Потенциометр 10кОм
  • ✅ Кнопка тактовая (экстренная)
  • ✅ Резисторы: 220 Ом (6 шт), 10кОм (1 шт)
  • ✅ Arduino Uno + макетка
  • ✅ ✅ Дополнительно: LCD дисплей для отображения режима

Схема подключения:

Светодиоды (Направление 1):
  Красный1 → pin 2 → резистор → GND
  Желтый1 → pin 3 → резистор → GND
  Зеленый1 → pin 4 → резистор → GND

Светодиоды (Направление 2):
  Красный2 → pin 5 → резистор → GND  
  Желтый2 → pin 6 → резистор → GND
  Зеленый2 → pin 7 → резистор → GND

Потенциометр (режимы):
  GND → GND, Сигнал → A0, VCC → 5V

Кнопка (экстренная):
  один вывод → 5V
  другой вывод → pin 8 + резистор 10кОм → GND

ЛОГИКА РАБОТЫ 🔄

Псевдокод для обсуждения:

// ИЕРАРХИЯ СОСТОЯНИЙ:
ГЛАВНЫЙ_РЕЖИМ = [НОРМАЛЬНЫЙ, НОЧНОЙ, АВАРИЙНЫЙ, ПИКОВЫЙ]
СОСТОЯНИЕ_СВЕТОФОРА = [КРАСНЫЙ, КРАСНЫЙ_ЖЕЛТЫЙ, ЗЕЛЕНЫЙ, ЖЕЛТЫЙ]

// ОСНОВНОЙ ЦИКЛ:
определяем_текущий_режим_из_потенциометра()

обрабатываем_экстренную_кнопку() // имеет высший приоритет!

в_зависимости_от_режима:
  случай НОРМАЛЬНЫЙ:
    выполняем_стандартный_цикл_светофора()
    
  случай НОЧНОЙ:
    мигаем_желтым_с_интервалом()
    
  случай АВАРИЙНЫЙ:
    мигаем_красным_с_интервалом()
    
  случай ПИКОВЫЙ:
    выполняем_укороченный_цикл_светофора()

ДЕТАЛЬНАЯ РЕАЛИЗАЦИЯ АЛГОРИТМОВ

Структура данных состояний:

enum MainMode { MODE_NORMAL, MODE_NIGHT, MODE_EMERGENCY, MODE_PEAK };
enum TrafficState { STATE_RED, STATE_RED_YELLOW, STATE_GREEN, STATE_YELLOW };

struct TrafficSystem {
  MainMode currentMode;
  TrafficState currentState;
  unsigned long stateStartTime;
  bool emergencyRequested;
  int modeFromPot; // запомненный режим до экстренной ситуации
};

TrafficSystem system;

Управление режимами:

void updateMainMode() {
  int potValue = analogRead(POT_PIN);
  int newMode = map(potValue, 0, 1023, 0, 3);
  
  // Если не в аварийном режиме - разрешаем смену
  if (system.currentMode != MODE_EMERGENCY) {
    system.currentMode = (MainMode)newMode;
  } else {
    // В аварийном режиме запоминаем выбранный режим для восстановления
    system.modeFromPot = newMode;
  }
}

Обработка экстренной кнопки:

void handleEmergencyButton() {
  if (digitalRead(EMERGENCY_BUTTON_PIN) == LOW) {
    delay(50); // антидребезг
    if (digitalRead(EMERGENCY_BUTTON_PIN) == LOW) {
      
      if (system.currentMode != MODE_EMERGENCY) {
        // Входим в аварийный режим
        system.modeFromPot = system.currentMode;
        system.currentMode = MODE_EMERGENCY;
        system.emergencyRequested = true;
      } else {
        // Выходим из аварийного режима
        system.currentMode = (MainMode)system.modeFromPot;
        system.emergencyRequested = false;
      }
      
      // Ждем отпускания кнопки
      while (digitalRead(EMERGENCY_BUTTON_PIN) == LOW) {
        delay(10);
      }
    }
  }
}

Реализация режимов светофора:

void runNormalMode() {
  unsigned long currentTime = millis();
  unsigned long stateDuration = getStateDuration(system.currentState);
  
  if (currentTime - system.stateStartTime > stateDuration) {
    // Переход к следующему состоянию
    switch(system.currentState) {
      case STATE_RED:
        system.currentState = STATE_RED_YELLOW;
        break;
      case STATE_RED_YELLOW:
        system.currentState = STATE_GREEN;
        break;
      case STATE_GREEN:
        system.currentState = STATE_YELLOW;
        break;
      case STATE_YELLOW:
        system.currentState = STATE_RED;
        break;
    }
    system.stateStartTime = currentTime;
  }
  
  updateLights();
}

void runNightMode() {
  // Мигающий желтый - оба направления
  unsigned long currentTime = millis();
  bool yellowOn = ((currentTime / 500) % 2) == 0; // мигание каждые 500ms
  
  digitalWrite(YELLOW1_PIN, yellowOn ? HIGH : LOW);
  digitalWrite(YELLOW2_PIN, yellowOn ? HIGH : LOW);
  digitalWrite(RED1_PIN, LOW);
  digitalWrite(GREEN1_PIN, LOW);
  digitalWrite(RED2_PIN, LOW);
  digitalWrite(GREEN2_PIN, LOW);
}

void runEmergencyMode() {
  // Мигающий красный - оба направления
  unsigned long currentTime = millis();
  bool redOn = ((currentTime / 500) % 2) == 0; // мигание каждые 500ms
  
  digitalWrite(RED1_PIN, redOn ? HIGH : LOW);
  digitalWrite(RED2_PIN, redOn ? HIGH : LOW);
  digitalWrite(YELLOW1_PIN, LOW);
  digitalWrite(GREEN1_PIN, LOW);
  digitalWrite(YELLOW2_PIN, LOW);
  digitalWrite(GREEN2_PIN, LOW);
}

Функция длительностей состояний:

unsigned long getStateDuration(TrafficState state) {
  switch(state) {
    case STATE_RED:
      return (system.currentMode == MODE_PEAK) ? 5000 : 10000; // 5сек в пике, 10сек норма
    case STATE_RED_YELLOW:
      return 2000; // всегда 2 секунды
    case STATE_GREEN:
      return (system.currentMode == MODE_PEAK) ? 5000 : 15000; // 5сек в пике, 15сек норма
    case STATE_YELLOW:
      return 3000; // всегда 3 секунды
    default:
      return 5000;
  }
}

УСЛОЖНЕНИЯ И ВАРИАЦИИ 🎛️

1. Режим “Согласованные светофоры”:

// Несколько светофоров работают согласованно
void coordinatedMode() {
  // Светофор 1: зеленый, когда светофор 2: красный
  if (system.currentState == STATE_GREEN) {
    setLightsDirection1(GREEN);
    setLightsDirection2(RED);
  } else {
    setLightsDirection1(RED);
    setLightsDirection2(GREEN);
  }
}

2. Адаптивный режим по датчикам:

// Добавляем датчики движения для адаптивного управления
void adaptiveMode() {
  int carsDirection1 = countCars(CAR_SENSOR_1);
  int carsDirection2 = countCars(CAR_SENSOR_2);
  
  // Динамически调整 длительность зеленого света
  if (carsDirection1 > carsDirection2 * 2) {
    greenDurationDirection1 = 20000; // больше машин - дольше зеленый
    greenDurationDirection2 = 5000;
  } else {
    greenDurationDirection1 = 10000;
    greenDurationDirection2 = 10000;
  }
}

3. Режим “Пешеходный переход”:

// Добавляем пешеходную кнопку и режим
void pedestrianMode() {
  if (pedestrianButtonPressed) {
    // Прерываем текущий цикл для пешеходов
    system.currentState = STATE_PEDESTRIAN;
    system.stateStartTime = millis();
    
    // Красный для машин, зеленый для пешеходов
    setAllCarLights(RED);
    setPedestrianLight(GREEN);
  }
}

ОЛИМПИАДНАЯ СВЯЗЬ 🏆

СВЯЗЬ С РЕАЛЬНЫМИ ОЛИМПИАДНЫМИ ЗАДАНИЯМИ:

// Аналогично системе контроля стаканов из 7-8 классов:
"Устройство должно иметь multiple состояния и режимы работы"

// Аналогично визуализатору битовых операций из 9-11 классов:
"Сложные конечные автоматы с приоритетами событий и временными ограничениями"

Критерии успеха в олимпиадах:

  • Четкая иерархия состояний - понятная структура автомата
  • Корректные приоритеты - экстренные события обрабатываются правильно
  • Стабильные временные циклы - нет дрифта времени
  • Восстановление состояния - система возвращается к прерванным процессам

Типичные олимпиадные ошибки:

  • Глобальные переменные вместо структур - трудно отслеживать состояние
  • Отсутствие антидребезга - multiple срабатывания кнопок
  • Жесткие тайминги - вместо millis() используют delay()
  • Путаница в приоритетах - события обрабатываются в неправильном порядке

МЕТОДИЧЕСКИЕ СОВЕТЫ 👨‍🏫

Поэтапная реализация:

// ЭТАП 1: Простой светофор с 3 состояниями
runBasicTrafficLight();

// ЭТАП 2: Добавляем второй направление
runTwoDirectionTrafficLight();

// ЭТАП 3: Вводим главные режимы
updateMainMode();
switch(system.currentMode) {
  case MODE_NORMAL: runNormalMode(); break;
  case MODE_NIGHT: runNightMode(); break;
}

// ЭТАП 4: Добавляем экстренные прерывания
handleEmergencyButton();
if (system.emergencyRequested) {
  runEmergencyMode();
}

Визуализация для понимания:

🎯 Иерархия состояний:

ГЛАВНЫЙ РЕЖИМ → ПОДСОСТОЯНИЯ
├── НОРМАЛЬНЫЙ → [КРАСНЫЙ] → [КРАСНЫЙ+ЖЕЛТЫЙ] → [ЗЕЛЕНЫЙ] → [ЖЕЛТЫЙ]
├── НОЧНОЙ → [МИГАЮЩИЙ_ЖЕЛТЫЙ]
├── АВАРИЙНЫЙ → [МИГАЮЩИЙ_КРАСНЫЙ] 
└── ПИКОВЫЙ → [КОРОТКИЙ_КРАСНЫЙ] → [КОРОТКИЙ_ЗЕЛЕНЫЙ]

🎮 Управление:
Потенциометр: Выбор главного режима (4 позиции)
Кнопка: Экстренное переключение (высший приоритет)

Практические упражнения:

Упражнение 1: “Диаграмма состояний”

  • Нарисовать полную диаграмму состояний системы
  • Определить все возможные переходы между состояниями
  • Выявить “зависшие” состояния и циклы

Упражнение 2: “Тестирование переходов”

  • Протестировать все возможные переходы между режимами
  • Проверить приоритеты экстренных событий
  • Убедиться в корректном восстановлении состояний

Упражнение 3: “Расширение автомата”

  • Добавить новые режимы (строительный, праздничный)
  • Реализовать сложные переходы с условиями
  • Создать систему логирования изменений состояний

Диагностика проблем:

  • Система “зависает” в состоянии → проверьте условия выхода из состояний
  • Некорректные переходы → убедитесь в правильности проверки времени
  • Кнопка не работает в аварийном режиме → проверьте приоритеты обработки
  • Мерцание светодиодов → оптимизируйте временные интервалы

Критерии оценки проекта:

  • 4 балла - стабильная работа 4 основных режимов
  • +2 балла - корректная обработка экстренных прерываний
  • +2 балла - сложная иерархия состояний с временными ограничениями
  • +2 балла - дополнительные режимы и диагностика

РЕАЛЬНОЕ ПРИМЕНЕНИЕ 🏙️

Где это используется:

  • Умные транспортные системы - адаптивное управление светофорами
  • Промышленная автоматика - сложные технологические процессы
  • Медицинское оборудование - многорежимные устройства жизнеобеспечения
  • Авионика - системы управления полетом с multiple режимами

Профессиональные аналоги:

  • SCADA системы - управление сложными производственными процессами
  • Автопилоты - многорежимные системы навигации
  • Сетевые коммутаторы - сложные конечные автоматы маршрутизации
  • Банкоматы - многоуровневые автоматы обработки транзакций