Создаем светофор на базе Ардуино Уно

Урок по созданию светофора на основе контроллера Ардуино, который научит понимать временные последовательности и будет работать как реальный светофор.

Последовательность работы светодиодов, выполненная на основе Arduino Uno, имитирует четырехстороннее пересечение, т.е. классический перекресток, где пересекаются две улицы одна из которых с менее интенсивным трафиком чем вторая. Этот урок по созданию светофора также поможет детям изучить последовательность сигналов дорожного трафика, чтобы они могли научиться пересекать перекрестки и понимать их поведение в реальной жизни.

Комплектующие

Начинаем с деталей для нашего проекта светофора:

  • 1x - Ардуино Уно (большинство плат Arduino должны подойти)
  • 2x - красные светодиоды
  • 2x - желтые (янтарные) светодиоды
  • 2x - зеленые светодиоды
  • 6x - резисторы 330 Ом

Дополнительно нам нужны провода-перемычки для соединения всех деталей схемы проекта.

Схема соединений

Для того, чтобы собрать наш Ардуино светофор нам нужно соединить плату Уно и светодиоды согласно схеме выше.

Как работает Ардуино светофор?

Это действительно простая концепция светофора, и приведенная ниже таблица помогает её объяснить. В коде используются инструкции loop и delay для того, чтобы реализовать время включения для каждого из светодиодов.

В примере светофора Ардуино, условно, две улицы. Каждая из них имеет разный объемы трафика (количество проезжающих машин), поэтому есть более длинный зеленый свет (с более коротким красным светом).

Трафик по одной из улиц (второй столбец) очень активный. Зеленый свет для  этой улицы продолжается 12 секунд. На второй улице (третий столбец) гораздо меньше машин, поэтому нашему гипотетическому городу нужен зеленый свет на менее активной улице короче по времени. Зеленый свет составит 1/3 от времени зеленого сигнала светофора на основной улице, т.е. получается 4-секундный зеленый свет.

Поскольку главный светофор переключается с зеленого на желтый и потом на красный, второй светофор ненадолго сохраняет свой красный свет в случае, если есть зазевавшиеся водители, которые пытаются проехать через перекресток. Не забывайте об этом интервале "перекрытия" красного света, если вы когда-либо будете создавать систему светофоров для какого-либо перекрестка вашего города.

Когда проходят 4 секунды зеленого света на второй улице мы делаем еще один период "перекрытия" красным светом, после чего цикл сигналов светофора Ардуино возобновляется.

Скетч (код) для Ардуино

Ниже приводим код нашего светофора, который необходимо загрузить в ардуину. Вы можете либо скачать .ino файл, либо скопировать код целиком и вставить в редактор Arduino IDE.

//===============================================================================
//  Постоянные
//===============================================================================
const int TRAFFIC_LIGHT_STYLE   = 1;  // Используется для выбора стиля светофора
const int GREEN_LIGHT           = 12; // Время зеленого света в секундах
const int AMBER_LIGHT           = 3;  // Время янтарного (желтого) света в секундах
const int DEAD_LIGHT            = 2;  // Время "перекрытия" в секундах
const int RED_AMBER_LIGHT       = 1;  // Красный/Янтарный свет в секундах

// Выходы:
int greenBusyBunnyLane      = 30;  
int amberBusyBunnyLane      = 32;  
int redBusyBunnyLane        = 34;  

int greenBusyBunnyLaneGnd   = 31;  
int amberBusyBunnyLaneGnd   = 33;  
int redBusyBunnyLaneGnd     = 35;  

int greenLazyTortoiseAve    = 48;  
int amberLazyTortoiseAve    = 50;   
int redLazyTortoiseAve      = 52;  

int greenLazyTortoiseAveGnd = 49; 
int amberLazyTortoiseAveGnd = 51; 
int redLazyTortoiseAveGnd   = 53;  

//===============================================================================
//  Инициализация
//===============================================================================
void setup() 
{
  // Установка соответствующих выходов светодиодов для первой улицы
  pinMode(greenBusyBunnyLane, OUTPUT);
  pinMode(amberBusyBunnyLane, OUTPUT);
  pinMode(redBusyBunnyLane, OUTPUT);
  
  pinMode(greenBusyBunnyLaneGnd, OUTPUT);
  pinMode(amberBusyBunnyLaneGnd, OUTPUT);
  pinMode(redBusyBunnyLaneGnd, OUTPUT);  
  
  // Установка соответствующих выходов светодиодов для второй улицы
  pinMode(greenLazyTortoiseAve, OUTPUT);
  pinMode(amberLazyTortoiseAve, OUTPUT);
  pinMode(redLazyTortoiseAve, OUTPUT);
  
  pinMode(greenLazyTortoiseAveGnd, OUTPUT);
  pinMode(amberLazyTortoiseAveGnd, OUTPUT);
  pinMode(redLazyTortoiseAveGnd, OUTPUT);  
  
  digitalWrite(greenBusyBunnyLane,LOW);
  digitalWrite(amberBusyBunnyLane,LOW);
  digitalWrite(redBusyBunnyLane,LOW);
  
  digitalWrite(greenBusyBunnyLaneGnd,LOW);
  digitalWrite(amberBusyBunnyLaneGnd,LOW);
  digitalWrite(redBusyBunnyLaneGnd,LOW);  
  
  digitalWrite(greenLazyTortoiseAve,LOW);
  digitalWrite(amberLazyTortoiseAve,LOW);
  digitalWrite(redLazyTortoiseAve,LOW);
  
  digitalWrite(greenLazyTortoiseAveGnd,LOW);
  digitalWrite(amberLazyTortoiseAveGnd,LOW);
  digitalWrite(redLazyTortoiseAveGnd,LOW);  
}
//===============================================================================
//  Главный блок
//===============================================================================
void loop() 
{

  switch (TRAFFIC_LIGHT_STYLE)
  {
    case 0:
      usaTrafficLight();
      break;
      
    case 1:
      ukTrafficLight();
      break;
      
    default:
      break;
  }
}

void usaTrafficLight() 
{  
 
  for (int seconds = 0; seconds < GREEN_LIGHT; seconds++)
  {
    digitalWrite(greenBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }
    digitalWrite(greenBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);
  
  for (int seconds = 0; seconds < AMBER_LIGHT; seconds++)
  {
    digitalWrite(amberBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(amberBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);  
  
  for (int seconds = 0; seconds < DEAD_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);  
    
  for (int seconds = 0; seconds < (GREEN_LIGHT / 3); seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(greenLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(greenLazyTortoiseAve,LOW);  
    
  // Lazy Tortoise Ave now goes into amber light.
  for (int seconds = 0; seconds < AMBER_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(amberLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(amberLazyTortoiseAve,LOW);  
  
  // Once again, a dead zone
  for (int seconds = 0; seconds < DEAD_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);  
  
}

void ukTrafficLight() 
{  
  for (int seconds = 0; seconds < GREEN_LIGHT; seconds++)
  {
    digitalWrite(greenBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }
    digitalWrite(greenBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);
  
  for (int seconds = 0; seconds < AMBER_LIGHT; seconds++)
  {
    digitalWrite(amberBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(amberBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);  
  
  for (int seconds = 0; seconds < DEAD_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);  
    
  for (int seconds = 0; seconds < RED_AMBER_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    digitalWrite(amberLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);
    digitalWrite(amberLazyTortoiseAve,LOW);
    
  for (int seconds = 0; seconds < (GREEN_LIGHT / 3); seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(greenLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(greenLazyTortoiseAve,LOW);  
    
  for (int seconds = 0; seconds < AMBER_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(amberLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(amberLazyTortoiseAve,LOW);  
  
  for (int seconds = 0; seconds < DEAD_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);  
 
  for (int seconds = 0; seconds < RED_AMBER_LIGHT; seconds++)
  {
    digitalWrite(redBusyBunnyLane,HIGH);
    digitalWrite(amberBusyBunnyLane,HIGH);
    digitalWrite(redLazyTortoiseAve,HIGH);
    delay(1000);
  }  
    digitalWrite(redBusyBunnyLane,LOW);
    digitalWrite(amberBusyBunnyLane,LOW);
    digitalWrite(redLazyTortoiseAve,LOW);  
   
}

Честно скажем, что у нас получился довольно простой и устаревший Ардуино светофор. Современные светофоры сегодня достаточно «умны» - они могут обнаруживать транспортные средства, корректировать свое время и даже делать перерывы для пешеходных переходов. Всегда есть возможность для улучшения!

Ардуино+