В этом посте вы узнаете, как создать контроллер светофора, работающий на основе плотности потока автомобилей с использованием Arduino. Основная идея этого проекта заключается в том, что, если датчик не видит движения с какой-либо стороны, то и разрешающего сигнала с этой стороны не будет. Система пропустит этот сигнал и перейдет к следующему.
Arduino является основной частью этого проекта, и он будет использоваться для считывания сигнала с ультразвукового датчика HC-SR04 и расчета расстояния. Это расстояние скажет нам, находится ли какое-либо транспортное средство рядом с датчиком или нет, и в соответствии с этими данными будет регулироваться поток автомобилей.
Основная задача состояла в том, чтобы избежать использования задержки, потому что мы должны постоянно считывать данные с ультразвуковых датчиков, а также одновременно мы должны контролировать сигналы, которые требуют использования функции задержки.
Таким образом, мы использовали библиотеку timerone, которая используется для периодического измерения периода времени в микросекундах, и в конце каждого периода будет вызываться функция прерывания. В этой функции мы будем читать данные с датчиков, а в функции цикла мы будем контролировать сигналы трафика.
Работа контроллера светофора на основе плотности потока автомобилей с использованием Arduino
Работа контроллера делится на три этапа
- Если на всех направлениях присутствует трафик, то система будет работать нормально, переключая сигналы один за другим.
- Если с какой-то стороны нет трафика, система пропустит этот сигнал и перейдет к следующему. Например, если датчик 2, 3 не регистрирует наличие авто, система пропускает транспортные средства по сигналу 1. Затем после сигнала 1 система перейдет к сигналу 4, пропуская сигналы 2 и 3.
- Если на всех 4 сигналах отсутствует трафик, система остановится на текущем сигнале и перейдет к следующему сигналу, только если на любом другом сигнале будет трафик.
Необходимые детали для умного светофора
Для данного проекта необходимы следующие компоненты:
- Arduino Mega 2560
- 4 х HC-SR04 — ультразвуковые датчики
- 4 красных светодиода
- 4 зеленых светодиода
- 4 желтых светодиода
- Резисторы 12 х 220 Ом
- Соединительные кабели
- макетная плата
Схема управления светофором
Четыре ультразвуковых датчика соединены с Arduino. Arduino считывает данные с этих датчиков и рассчитает расстояние. Этот датчик может измерять расстояние от 2 до 400 см.
Ультразвуковой датчик излучает ультразвуковую волну и отраженное от объекта эхо принимается датчиком. Чтобы генерировать волну, нам нужно будет установить триггер на 10 мкс, который отправит звуковой импульс с 8 циклами на частоте 40 кГц, который посылается в сторону объекта, и после отражения сигнала возникает эхо. Затем эхо скажет нам время, когда волна пришла обратно к датчику (микросекунды). Затем мы преобразуем это время в пройденное расстояние, используя формулу S = V * T.
Подробнее: Ультразвуковой датчик HC-SR04 взаимодействует с Arduino
Светодиоды подключены к Arduino через резисторы 220 Ом. Необходимо использовать резистор со светодиодом. Резистор ограничивает ток, протекающий через светодиод. Если вы не будете использовать его, светодиод сгорит. Вы можете использовать резистор от 100 Ом до 10 кОм со светодиодом. Чем больше значение сопротивления, тем меньше будет проходить ток.
Описание кода
Прежде всего, мы включили библиотеку timerone. Эта библиотека используется для повторного измерения периода времени в микросекундах, и в конце каждого периода будет вызываться функция прерывания.
Мы использовали эту библиотеку, потому что мы хотим считывать сигналы с датчиков и управлять светодиодами одновременно. Библиотека позволит нам вызывать функцию, в которой мы будем непрерывно считывать данные с датчиков, а в функции цикла мы будем управлять сигналами светофора.
1 |
#include<TimerOne.h> |
В функции setup мы использовали функцию Timer1.initialize (микросекунды). Эта функция должна быть вызвана, прежде чем использовать любой из других методов библиотеки timerone. «Микросекунды» — это период времени, который занимает таймер. Здесь можно указать период таймера. Период по умолчанию составляет 1 секунду.
1 |
Timer1.initialize(100000); |
Timer1.attachInterrupt (softInterr) вызывает функцию каждый раз, когда заканчивается период таймера. Мы установили период таймера на 100000, поэтому наша функция будет вызываться через 100 миллисекунд.
1 |
Timer1.attachInterrupt(softInterr); |
В функции цикла проверяется, есть ли какие-либо транспортные средства под расстоянием 5 см или нет. Если будет автомобиль, то будет вызвана функция для включения разрешающего сигнала в данном направлении.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void loop() { // If there are vehicles at signal 1 if(S1<t) { signal1Function(); } // If there are vehicles at signal 2 if(S2<t) { signal2Function(); } // If there are vehicles at signal 3 if(S3<t) { signal3Function(); } // If there are vehicles at signal 4 if(S4<t) { signal4Function(); } } |
Softinterr () — это функция прерывания, которая будет вызываться через каждые 100 миллисекунд. В этой функции мы считали с ультразвуковых датчиков и рассчитали расстояние.
1 2 3 4 5 6 7 8 9 10 |
void softInterr() { // Reading from first ultrasonic sensor digitalWrite(triggerpin1, LOW); delayMicroseconds(2); digitalWrite(triggerpin1, HIGH); delayMicroseconds(10); digitalWrite(triggerpin1, LOW); time = pulseIn(echopin1, HIGH); S1= time*0.034/2; |
Код
Код Arduino для контроллера светофора на основе плотности трафика выглядит следующим образом
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
#include<TimerOne.h> int signal1[] = {23, 25, 27}; int signal2[] = {46, 48, 50}; int signal3[] = {13, 12, 11}; int signal4[] = {10, 9, 8}; int redDelay = 5000; int yellowDelay = 2000; volatile int triggerpin1 = 31; volatile int echopin1 = 29; volatile int triggerpin2 = 44; volatile int echopin2 = 42; volatile int triggerpin3 = 7; volatile int echopin3 = 6; volatile int triggerpin4 = 5; volatile int echopin4 = 4; volatile long time; // Variable for storing the time traveled volatile int S1, S2, S3, S4; // Variables for storing the distance covered int t = 5; // distance under which it will look for vehicles. void setup(){ Serial.begin(115200); Timer1.initialize(100000); //Begin using the timer. This function must be called first. "microseconds" is the period of time the timer takes. Timer1.attachInterrupt(softInterr); //Run a function each time the timer period finishes. // Declaring LED pins as output for(int i=0; i<3; i++){ pinMode(signal1[i], OUTPUT); pinMode(signal2[i], OUTPUT); pinMode(signal3[i], OUTPUT); pinMode(signal4[i], OUTPUT); } // Declaring ultrasonic sensor pins as output pinMode(triggerpin1, OUTPUT); pinMode(echopin1, INPUT); pinMode(triggerpin2, OUTPUT); pinMode(echopin2, INPUT); pinMode(triggerpin3, OUTPUT); pinMode(echopin3, INPUT); pinMode(triggerpin4, OUTPUT); pinMode(echopin4, INPUT); } void loop() { // If there are vehicles at signal 1 if(S1<t) { signal1Function(); } // If there are vehicles at signal 2 if(S2<t) { signal2Function(); } // If there are vehicles at signal 3 if(S3<t) { signal3Function(); } // If there are vehicles at signal 4 if(S4<t) { signal4Function(); } } // This is interrupt function and it will run each time the timer period finishes. The timer period is set at 100 milli seconds. void softInterr() { // Reading from first ultrasonic sensor digitalWrite(triggerpin1, LOW); delayMicroseconds(2); digitalWrite(triggerpin1, HIGH); delayMicroseconds(10); digitalWrite(triggerpin1, LOW); time = pulseIn(echopin1, HIGH); S1= time*0.034/2; // Reading from second ultrasonic sensor digitalWrite(triggerpin2, LOW); delayMicroseconds(2); digitalWrite(triggerpin2, HIGH); delayMicroseconds(10); digitalWrite(triggerpin2, LOW); time = pulseIn(echopin2, HIGH); S2= time*0.034/2; // Reading from third ultrasonic sensor digitalWrite(triggerpin3, LOW); delayMicroseconds(2); digitalWrite(triggerpin3, HIGH); delayMicroseconds(10); digitalWrite(triggerpin3, LOW); time = pulseIn(echopin3, HIGH); S3= time*0.034/2; // Reading from fourth ultrasonic sensor digitalWrite(triggerpin4, LOW); delayMicroseconds(2); digitalWrite(triggerpin4, HIGH); delayMicroseconds(10); digitalWrite(triggerpin4, LOW); time = pulseIn(echopin4, HIGH); S4= time*0.034/2; // Print distance values on serial monitor for debugging Serial.print("S1: "); Serial.print(S1); Serial.print(" S2: "); Serial.print(S2); Serial.print(" S3: "); Serial.print(S3); Serial.print(" S4: "); Serial.println(S4); } void signal1Function() { Serial.println("1"); low(); // Make RED LED LOW and make Green HIGH for 5 seconds digitalWrite(signal1[0], LOW); digitalWrite(signal1[2], HIGH); delay(redDelay); // if there are vehicels at other signals if(S2<t || S3<t || S4<t) { // Make Green LED LOW and make yellow LED HIGH for 2 seconds digitalWrite(signal1[2], LOW); digitalWrite(signal1[1], HIGH); delay(yellowDelay); } } void signal2Function() { Serial.println("2"); low(); digitalWrite(signal2[0], LOW); digitalWrite(signal2[2], HIGH); delay(redDelay); if(S1<t || S3<t || S4<t) { digitalWrite(signal2[2], LOW); digitalWrite(signal2[1], HIGH); delay(yellowDelay); } } void signal3Function() { Serial.println("3"); low(); digitalWrite(signal3[0], LOW); digitalWrite(signal3[2], HIGH); delay(redDelay); if(S1<t || S2<t || S4<t) { digitalWrite(signal3[2], LOW); digitalWrite(signal3[1], HIGH); delay(yellowDelay); } } void signal4Function() { Serial.println("4"); low(); digitalWrite(signal4[0], LOW); digitalWrite(signal4[2], HIGH); delay(redDelay); if(S1<t || S2<t || S3<t) { digitalWrite(signal4[2], LOW); digitalWrite(signal4[1], HIGH); delay(yellowDelay); } } // Function to make all LED's LOW except RED one's. void low() { for(int i=1; i<3; i++) { digitalWrite(signal1[i], LOW); digitalWrite(signal2[i], LOW); digitalWrite(signal3[i], LOW); digitalWrite(signal4[i], LOW); } for(int i=0; i<1; i++) { digitalWrite(signal1[i], HIGH); digitalWrite(signal2[i], HIGH); digitalWrite(signal3[i], HIGH); digitalWrite(signal4[i], HIGH); } } |