Общие положения
Движение на Х-образном перекрёстке регулируется светофором, в данном случае с дополнительными секциями. Вы можете почитать подробнее информацию о сборке светофора, его настройке, особенностях питания и настройке расстояния передачи ИК-сигнала.
Схема установки знака на трассе:
В данном случае светофор имеет дополнительные секции.
Центр светофора должен находиться в 15 см от линии трассы, образующих перекрёсток, а сам светофор — располагаться под углом 45° относительно линии движения автомобиля.
Угол распространения ИК-данных составляет около 80°, а дальность передачи ИК-данных настраивается поворотом крестовины резистора на обратной стороне платы основания.
Алгоритм работы светофора
Алгоритм работы светофоров:
Движение на данном перекрёстке в любых направлениях можно организовать за 4 фазы работы светофоров, но мы предлагаем алгоритм, при котором светофоры работают за 8 фаз. В предложенном алгоритме каждый светофор разрешает движение: только прямо, только направо, прямо и налево, во всех направлениях.
Для удобства описания работы назовём левую часть дороги — «A», нижнюю — «B», правую — «C», верхнюю — «D». Тогда светофоры перекрёстка разрешают движение следующим образом:
- В 1 фазе: между дорогами «A» и «B» в обоих направлениях, дополнительно от «B» к «C» и «D»;
- В 8 фазе: между дорогами «B» и «C» в обоих направлениях, дополнительно от «C» к «A» и «D»;
- В 4 фазе: между дорогами «C» и «D» в обоих направлениях, дополнительно от «D» к «A» и «B»;
- В 5 фазе: между дорогами «D» и «A» в обоих направлениях, дополнительно от «A» к «B» и «C»;
- В 6 фазе: между дорогами «A» и «C» в обоих направлениях, дополнительно от «A» к «B»;
- В 7 фазе: между дорогами «A» и «C» в обоих направлениях, дополнительно от «C» к «D»;
- В 2 фазе: между дорогами «B» и «D» в обоих направлениях, дополнительно от «B» к «C»;
- В 3 фазе: между дорогами «B» и «D» в обоих направлениях, дополнительно от «D» к «A».
Реализуется данный алгоритм следующим образом:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Подробнее о переключении от зелёного к красному и от красного к зелёному Вы можете почитать по ссылке.
Адресация на шине I2C
Мы уже говорили о том, что все наши знаки и светофоры являются устройствами, работающими по шине I2C. Это значит, что они подключаются параллельно к одной шине, и для того, чтобы они могли взаимодействовать с контроллером, каждое устройство должно иметь свой уникальный адрес в пределах этой шины. Поэтому при подключении двух и более устройств необходимо убедиться, что они имеют разные адреса.
Смена адреса устройства
Подключите светофор, у которого хотите сменить адрес, к шине I2C, и загрузите следующий скетч. После этого адрес светофора изменится и сохранится в его энергонезависимой памяти. Повторите то же самое с другими светофорами, заменив записываемый адрес.
Установите светофорам адреса 0x0A, 0x0B, 0x0C, 0x0D.
Для установки адресов воспользуйтесь скетчем из меню Arduino IDE:
Файл / Примеры / iarduino I2C Track (модуль трассы) / NewAddress
Схема включения
После установки адресов I2C для каждого светофора, соедините их с помощью I2C Hub'а и подключите к контроллеру. Подробнее о питании контроллера и светофоров Вы можете почитать в статье.
Скетч
#include <iarduino_I2C_Track.h> // Подключаем библиотеку для работы с модулем трассы iarduino_I2C_Track tl_A(0x0A); // Создаём объект tl_A для работы с первым светофором, указав его адрес на шине I2C (0x0A) iarduino_I2C_Track tl_B(0x0B); // Создаём объект tl_B для работы со вторым светофором, указав его адрес на шине I2C (0x0B) iarduino_I2C_Track tl_C(0x0C); // Создаём объект tl_C для работы с третьим светофором, указав его адрес на шине I2C (0x0C) iarduino_I2C_Track tl_D(0x0D); // Создаём объект tl_D для работы с четвёртым светофором, указав его адрес на шине I2C (0x0D) // void setup(){ // tl_A.begin(MODUL_TLIGHT, TRACK_LFR, SECTION_LR); // Инициируем работу с четырьмя светофорами, tl_B.begin(MODUL_TLIGHT, TRACK_LFR, SECTION_LR); // указав, что на перекрёстках есть дорога tl_C.begin(MODUL_TLIGHT, TRACK_LFR, SECTION_LR); // налево, прямо и направо (TRACK_LFR), и каждый tl_D.begin(MODUL_TLIGHT, TRACK_LFR, SECTION_LR); // светофор оснащён стрелками налево и направо (SECTION_LR) tl_A.irProtocol(IR_IARDUINO); // Указываем протокол передачи данных по ИК-каналу: «IARDUINO» tl_B.irProtocol(IR_IARDUINO); // Указываем протокол передачи данных по ИК-каналу: «IARDUINO» tl_C.irProtocol(IR_IARDUINO); // Указываем протокол передачи данных по ИК-каналу: «IARDUINO» tl_D.irProtocol(IR_IARDUINO); // Указываем протокол передачи данных по ИК-каналу: «IARDUINO» tl_A.irAutoSend(); // Указываем модулю постоянно отправлять информацию о состоянии светофора по ИК-каналу с интервалами по умолчанию ±50% tl_B.irAutoSend(); // Указываем модулю постоянно отправлять информацию о состоянии светофора по ИК-каналу с интервалами по умолчанию ±50% tl_C.irAutoSend(); // Указываем модулю постоянно отправлять информацию о состоянии светофора по ИК-каналу с интервалами по умолчанию ±50% tl_D.irAutoSend(); // Указываем модулю постоянно отправлять информацию о состоянии светофора по ИК-каналу с интервалами по умолчанию ±50% tl_A.timing(3); // Указываем время свечения жёлтого (и мигающего зелёного) сигнала светофора = 3 сек tl_B.timing(3); // Указываем время свечения жёлтого (и мигающего зелёного) сигнала светофора = 3 сек tl_C.timing(3); // Указываем время свечения жёлтого (и мигающего зелёного) сигнала светофора = 3 сек tl_D.timing(3); // Указываем время свечения жёлтого (и мигающего зелёного) сигнала светофора = 3 сек // Определяем начальное состояние: // tl_A.set(TL_FORWARD_OFF); // Запрещаем движение прямо на светофоре «A» tl_B.set(TL_FORWARD_OFF, TL_RIGHT_ON); // Запрещаем движение прямо на светофоре «B», но разрешаем поворот направо tl_D.set(TL_FORWARD_OFF); // Запрещаем движение прямо на светофоре «D» } // // void loop(){ // // ================================== // ============================================================================= // Фаза 1: // Было: «A» X-X-X , «B» X-X-> , «C» <-^-> , «D» X-X-X // Станет: «A» X-X-> , «B» <-^-> , «C» X-X-X , «D» X-X-X // Нужно: «A» — включить стрелку направо, «B» — переключить на зелёный и включить стрелку налево, «C» — переключить на красный и отключить обе стрелки, «D» — оставить без изменений // ----------------1----------------- // tl_C.set(TL_FORWARD_OFF, TL_LEFT_OFF, TL_RIGHT_OFF); // Запрещаем движение в прямом направлении и оба поворота на светофоре «C» delay(3000); // В течение 3 секунд на светофоре «C» будут мигать отключаемые стрелки и основной зелёный // ----------------2----------------- // tl_B.set(TL_FORWARD_ON ); // Разрешаем движение в прямом направлении светофора «B» delay(3000); // В течение 3 секунд на светофоре «B» будет светиться красный с жёлтым // ----------------3----------------- // tl_A.set(TL_RIGHT_ON); // Разрешаем поворот направо на светофоре «A». Стрелка включается сразу tl_B.set(TL_LEFT_ON); // Разрешаем поворот налево на светофоре «B». Стрелка включается сразу delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= // Фаза 2: // Было: «A» X-X-> , «B» <-^-> , «C» X-X-X , «D» X-X-X // Станет: «A» X-X-X , «B» X-^-> , «C» X-X-X , «D» X-^-X // Нужно: «A» — отключить стрелку направо, «B» — отключить стрелку налево, «C» — оставить без изменений, «D» — переключить на зелёный // ----------------1----------------- // tl_A.set(TL_RIGHT_OFF); // Запрещаем поворот направо на светофоре «A» tl_B.set(TL_LEFT_OFF); // Запрещаем поворот налево на светофоре «B» delay(3000); // В течение 3 секунд на светофорах «A» и «B» будут мигать отключаемые стрелки // ----------------2----------------- // tl_D.set(TL_FORWARD_ON ); // Разрешаем движение в прямом направлении светофора «D» delay(3000); // В течение 3 секунд на светофоре «D» будет светиться красный с жёлтым // ----------------3----------------- // delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= // Фаза 3: // Было: «A» X-X-X , «B» X-^-> , «C» X-X-X , «D» X-^-X // Станет: «A» X-X-X , «B» X-^-X , «C» X-X-X , «D» X-^-> // Нужно: «A» — оставить без изменений, «B» — отключить стрелку направо, «C» — оставить без изменений, «D» — включить стрелку направо // ----------------1----------------- // tl_B.set(TL_RIGHT_OFF); // Запрещаем поворот направо на светофоре «B» delay(3000); // В течение 3 секунд на светофоре «B» будет мигать отключаемая стрелка // ----------------2----------------- // delay(3000); // В данной фазе нет переключений светофоров на разрешающий сигнал в прямом направлении // ----------------3----------------- // tl_D.set(TL_RIGHT_ON); // Разрешаем поворот направо на светофоре «D». Стрелка включается сразу delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= // Фаза 4: // Было: «A» X-X-X , «B» X-^-X , «C» X-X-X , «D» X-^-> // Станет: «A» X-X-X , «B» X-X-X , «C» X-X-> , «D» <-^-> // Нужно: «A» — оставить без изменений, «B» — переключить на красный, «C» — включить стрелку направо, «D» — включить стрелку налево // ----------------1----------------- // tl_B.set(TL_FORWARD_OFF); // Запрещаем движение в прямом направлении на светофоре «B» delay(3000); // В течение 3 секунд на светофоре «B» будет мигать зелёный // ----------------2----------------- // delay(3000); // В данной фазе нет переключений светофоров на разрешающий сигнал в прямом направлении // ----------------3----------------- // tl_C.set(TL_RIGHT_ON); // Разрешаем поворот направо на светофоре «C». Стрелка включается сразу tl_D.set(TL_LEFT_ON); // Разрешаем поворот налево на светофоре «D». Стрелка включается сразу delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= // Фаза 5: // Было: «A» X-X-X , «B» X-X-X , «C» X-X-> , «D» <-^-> // Станет: «A» <-^-> , «B» X-X-X , «C» X-X-X , «D» X-X-> // Нужно: «A» — переключить на зелёный и включить обе стрелки, «B» — оставить без изменений, «C» — отключить стрелку направо, «D» — переключить на красный и отключить стрелку налево // ----------------1----------------- // tl_C.set(TL_RIGHT_OFF); // Запрещаем поворот направо на светофоре «C» tl_D.set(TL_FORWARD_OFF, TL_LEFT_OFF); // Запрещаем движение в прямом направлении и поворот налево на светофоре «D» delay(3000); // В течение 3 секунд на светофорах «C» и «D» будут мигать отключаемые зелёные сигналы // ----------------2----------------- // tl_A.set(TL_FORWARD_ON ); // Разрешаем движение в прямом направлении светофора «A» delay(3000); // В течение 3 секунд на светофоре «A» будет светиться красный с жёлтым // ----------------3----------------- // tl_A.set(TL_LEFT_ON, TL_RIGHT_ON); // Разрешаем повороты налево и направо на светофоре «A». Стрелки включатся сразу delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= // Фаза 6: // Было: «A» <-^-> , «B» X-X-X , «C» X-X-X , «D» X-X-> // Станет: «A» X-^-> , «B» X-X-X , «C» X-^-X , «D» X-X-X // Нужно: «A» — отключить стрелку налево, «B» — оставить без изменений, «C» — переключить на зелёный, «D» — отключить стрелку направо // ----------------1----------------- // tl_A.set(TL_LEFT_OFF); // Запрещаем поворот налево на светофоре «A» tl_D.set(TL_RIGHT_OFF); // Запрещаем поворот направо на светофоре «D» delay(3000); // В течение 3 секунд на светофорах «A» и «D» будут мигать отключаемые стрелки // ----------------2----------------- // tl_C.set(TL_FORWARD_ON ); // Разрешаем движение в прямом направлении светофора «C» delay(3000); // В течение 3 секунд на светофоре «C» будет светиться красный с жёлтым // ----------------3----------------- // delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= // Фаза 7: // Было: «A» X-^-> , «B» X-X-X , «C» X-^-X , «D» X-X-X // Станет: «A» X-^-X , «B» X-X-X , «C» X-^-> , «D» X-X-X // Нужно: «A» — отключить стрелку направо, «B» — оставить без изменений, «C» — включить стрелку направо, «D» — оставить без изменений // ----------------1----------------- // tl_A.set(TL_RIGHT_OFF); // Запрещаем поворот направо на светофоре «A» delay(3000); // В течение 3 секунд на светофоре «A» будет мигать отключаемая стрелка // ----------------2----------------- // delay(3000); // В данной фазе нет переключений светофоров на разрешающий сигнал в прямом направлении // ----------------3----------------- // tl_C.set(TL_RIGHT_ON); // Разрешаем поворот направо на светофоре «C». Стрелка включается сразу delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= // Фаза 8: // Было: «A» X-^-X , «B» X-X-X , «C» X-^-> , «D» X-X-X // Станет: «A» X-X-X , «B» X-X-> , «C» <-^-> , «D» X-X-X // Нужно: «A» — переключить на красный, «B» — включить стрелку направо, «C» — включить стрелку налево, «D» — оставить без изменений // ----------------1----------------- // tl_A.set(TL_FORWARD_OFF); // Запрещаем движение в прямом направлении на светофоре «A» delay(3000); // В течение 3 секунд на светофоре «A» будет мигать зелёный // ----------------2----------------- // delay(3000); // В данной фазе нет переключений светофоров на разрешающий сигнал в прямом направлении // ----------------3----------------- // tl_B.set(TL_RIGHT_ON); // Разрешаем поворот направо на светофоре «B». Стрелка включается сразу tl_C.set(TL_LEFT_ON); // Разрешаем поворот налево на светофоре «C». Стрелка включается сразу delay(10000); // Ждём 10 секунд, пока едут машины // ================================== // ============================================================================= } //
В коде setup()
выполняются следующие действия:
- Обращением к функции
begin()
мы указываем, что каждый модуль является светофоромMODUL_TLIGHT
, который регулирует перекрёсток с дорогами налево, прямо и направоTRACK_LFR
и оснащён двумя секциями поворотовSECTION_LR
. - Обращением к функции
irProtocol()
мы указываем ИК-протокол передачи данных. В скетче используетсяIR_IARDUINO
. - Обращением к функции
irAutoSend()
мы заставляем модуль самостоятельно постоянно отправлять данные о состоянии светофора по ИК-каналу. - Обращением к функции
timing()
мы указали длительность свечения жёлтого и мигающего зелёного, равной 3 секундам. Это требуется, так как в полуавтоматическом режиме модуль включает эти цвета без нашего участия. - В конце кода
setup()
выполнено обращение к функцииset()
для установки цветов, необходимых для корректной работы циклаloop()
при его первом проходе.
Код loop()
разделён на 8 фаз, в которых выполняются по три действия:
- Действие №1 — запрет движения для любых направлений:
- Вызов функции
set()
для светофоров, которым требуется запретить движение прямоTL_FORWARD_OFF
, налевоTL_LEFT_OFF
, направоTL_RIGHT_OFF
. - Задержка
delay()
на время свечения мигающего зелёного сигнала. - Действие №2 — разрешение движения в прямом направлении:
- Вызов функции
set()
для светофоров, которым требуется разрешить движение прямоTL_FORWARD_ON
. - Задержка
delay()
на время свечения жёлтого сигнала. - Действие №3 — включение секций поворотов:
- Вызов функции
set()
для светофоров, которым требуется разрешить движение налевоTL_LEFT_ON
, направоTL_RIGHT_ON
(стрелки поворотов включаются сразу, без задержек). - После выполнения всех действий на светофорах перекрёстка установлены требуемые сигналы. Осталось приостановить выполнение скетча функцией
delay()
на желаемую длительность текущей фазы движения машин.
Обратите внимание на то, что в 3,4,7,8 фазах нет команд на разрешение движения в прямом направлении, но задержка delay()
осталась. Благодаря этой задержке, выполняется сразу два условия: запрет движения налево и направо завершится за 1 цикл свечения жёлтого сигнала, до того, как осуществится включение других секций поворотов. Включение секций поворотов совпадёт с включением красного или основного зелёного сигналов светофоров.
Обсуждение