Загрузка данных


// =====================================================
//        СВЕТОФОР ДЛЯ МАШИН
// =====================================================

const int LED_RED = 13;
const int LED_YELLOW = 12;
const int LED_GREEN = 11;


// =====================================================
//        СВЕТОФОР ДЛЯ ПЕШЕХОДОВ
// =====================================================

const int PED_RED = 10;
const int PED_GREEN = 9;


// =====================================================
//        УЛЬТРАЗВУКОВОЙ ДАТЧИК HC-SR04
// =====================================================

const int TRIG_PIN = 7;
const int ECHO_PIN = 6;

// Расстояние, на котором срабатывает датчик
const int DETECT_DISTANCE = 20;  // сантиметры


// =====================================================
//                  ВРЕМЕНА
// =====================================================

// Желтый для машин
const int TIMEOUT_YELLOW = 1690;

// Мигание зеленого машин
const int TIMEOUT_FLASH_GREEN = 500;

// Сколько времени пешеходам горит зеленый
const int TIMEOUT_PEDESTRIAN = 5000;

// Небольшая пауза безопасности
const int SAFETY_DELAY = 500;


// Флаг.
// true  = датчик может запустить светофор
// false = уже срабатывал, ждем пока человек уберет руку
bool sensorReady = true;


// =====================================================
//                     SETUP
// =====================================================

void setup()
{
  // Светофор машин
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_YELLOW, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);

  // Светофор пешеходов
  pinMode(PED_RED, OUTPUT);
  pinMode(PED_GREEN, OUTPUT);

  // HC-SR04
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);


  // Начальное состояние:
  // машинам зеленый
  digitalWrite(LED_GREEN, HIGH);
  digitalWrite(LED_YELLOW, LOW);
  digitalWrite(LED_RED, LOW);

  // пешеходам красный
  digitalWrite(PED_RED, HIGH);
  digitalWrite(PED_GREEN, LOW);
}


// =====================================================
//        ФУНКЦИЯ ИЗМЕРЕНИЯ РАССТОЯНИЯ
// =====================================================

float getDistance()
{
  // На всякий случай выключаем TRIG
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);

  // Посылаем импульс 10 микросекунд
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Измеряем время возвращения сигнала
  // 30000 мкс - максимальное время ожидания
  long duration = pulseIn(ECHO_PIN, HIGH, 30000);

  // Если отражение не получено
  if (duration == 0)
  {
    return 999;
  }

  // Переводим время в сантиметры
  float distance = duration * 0.0343 / 2.0;

  return distance;
}


// =====================================================
//       ПЕРЕКЛЮЧЕНИЕ НА ПЕШЕХОДНЫЙ ЗЕЛЕНЫЙ
// =====================================================

void pedestrianCycle()
{
  // ---------------------------------------------------
  // 1. Машинам мигает зеленый
  // ---------------------------------------------------

  for (int i = 0; i < 3; i++)
  {
    digitalWrite(LED_GREEN, LOW);
    delay(TIMEOUT_FLASH_GREEN);

    digitalWrite(LED_GREEN, HIGH);
    delay(TIMEOUT_FLASH_GREEN);
  }


  // ---------------------------------------------------
  // 2. Выключаем зеленый машин
  //    Включаем желтый
  // ---------------------------------------------------

  digitalWrite(LED_GREEN, LOW);

  digitalWrite(LED_YELLOW, HIGH);
  delay(TIMEOUT_YELLOW);

  digitalWrite(LED_YELLOW, LOW);


  // ---------------------------------------------------
  // 3. Машинам красный
  // ---------------------------------------------------

  digitalWrite(LED_RED, HIGH);

  // Пешеходам пока еще красный
  delay(SAFETY_DELAY);


  // ---------------------------------------------------
  // 4. Пешеходам зеленый
  // ---------------------------------------------------

  digitalWrite(PED_RED, LOW);
  digitalWrite(PED_GREEN, HIGH);

  delay(TIMEOUT_PEDESTRIAN);


  // ---------------------------------------------------
  // 5. Пешеходам снова красный
  // ---------------------------------------------------

  digitalWrite(PED_GREEN, LOW);
  digitalWrite(PED_RED, HIGH);

  delay(SAFETY_DELAY);


  // ---------------------------------------------------
  // 6. Машинам красный + желтый
  // ---------------------------------------------------

  digitalWrite(LED_YELLOW, HIGH);
  delay(TIMEOUT_YELLOW);


  // ---------------------------------------------------
  // 7. Машинам снова зеленый
  // ---------------------------------------------------

  digitalWrite(LED_YELLOW, LOW);
  digitalWrite(LED_RED, LOW);

  digitalWrite(LED_GREEN, HIGH);
}


// =====================================================
//                       LOOP
// =====================================================

void loop()
{
  float distance = getDistance();


  // Если датчик готов и объект ближе 20 см
  if (sensorReady &&
      distance > 2 &&
      distance <= DETECT_DISTANCE)
  {
    // Запрещаем повторное срабатывание
    sensorReady = false;

    // Запускаем цикл светофора
    pedestrianCycle();
  }


  // Чтобы светофор снова мог сработать,
  // необходимо убрать руку от датчика.
  //
  // Используем 25 см вместо 20,
  // чтобы датчик не дергался на границе.

  if (!sensorReady && distance > 25)
  {
    sensorReady = true;
  }


  // Измеряем примерно 10 раз в секунду
  delay(100);
}