#15 Эксперимент “Турникет метро”
Сегодня мы разберём принцип работы одного простого, но полезного датчика – оптопары. В готовом виде оптопару можно купить практически в любом магазине радиоэлектроники.
Различные виды оптопар | ||
Несмотря на то, что в нашем базовом наборе данного датчика нет, его совсем несложно сконструировать самостоятельно, ведь он состоит лишь из двух компонентов: светодиода (или любого другого источника света) и фоторезистора. Принцип действия датчика очень прост:
- светодиод располагается рядом с фоторезистором и постоянно находится во включенном состоянии;
- фоторезистор, в свою очередь, постоянно регистрирует сигнал некоторого уровня, который зависит от яркости установленного светодиода;
- если между светодиодом и фоторезистором появляется некое препятствие, то уровень сигнала на фоторезисторе падает;
- благодаря этому падению сигнала мы можем определить момент, когда оптопара “определила” препятствие.
“Магазинные” версии оптопар выпускаются в корпусе, который частично прикрывает светодиод и фоторезистор, что позволяет датчику “спрятаться” от внешних источников света, т.е. делает его работу более стабильной. В нашем случае, оптопара будет собрана в открытом виде, а значит нам придётся вручную проверить уровень сигнала, который будет поступать с фоторезистора для случаев когда оптопара работает в штатном режиме, и когда оптопара “определит” препятствие.
СБОРКА УСТРОЙСТВА НА МАКЕТНОЙ ПЛАТЕ
Нам понадобятся следующие компоненты:
- Arduino Uno;
- USB-кабель для подключения к компьютеру;
- Беспаечная макетная плата;
- Модуль RFID-RC522;
- Чип и карта для этого модуля;
- Сервопривод;
- 2 светодиода жёлтого цвета;
- 1 светодиод красного цвета;
- 1 светодиод зелёного цвета;
- 2 фоторезистора;
- 4 резистора номиналом 220 Ом;
- 2 резистора номиналом 10 кОм;
- 7 соединительных проводов типа “папа-мама” различных цветов;
- 11 соединительных проводов типа “папа-папа” различных цветов.
Соберите устройство по следующей схеме:
Схема устройства на макетной плате |
Обратите внимание:
- Для питания модуля RFID мы используем пин 3,3 В;
- Помните о порядке подключения проводов сервопривода к пинам Arduino (коричневый – GND, красный – 5V, оранжевый – pin 8);
- Перед подключением жёлтых светодиодов и фоторезисторов загните их головки под 90º таким образом, чтоб при установке на плату, они как-бы “смотрели” друг на друга;
- В нашей схеме светодиоды подключены напрямую к пину +5V, а значит мы не сможем ими управлять и они будут светить постоянно;
- После сборки схемы убедитесь, что соединительные провода не перекрывают светодиоды, направленные на фоторезисторы. При необходимости немного подогните мешающие провода.
ПРОГРАММИРОВАНИЕ
Для начала нужно понять по какому принципу работают оптопары. Для этого напишем простенький скетч, который будет отправлять в монитор последовательного порта данные с фоторезисторов:
int opt1; // переменная для хранения значения сигнала с 1-го фоторезистора int opt2; // переменная для хранения значения сигнала с 2-го фоторезистора void setup() { Serial.begin(9600); } void loop() { opt1=analogRead(A0); // получаем сигналы с фоторезисторов и... opt2=analogRead(A1); // помещаем их в переменные Serial.print(opt1); // выводим сигнал с 1-й оптопары Serial.print(" "); // разделяем сигналы пробелом Serial.println(opt2); // выводим сигнал со 2-й оптопары и переходим на следующую строку }
Загрузите скетч в Arduino. После загрузки, запустите монитор последовательного порта или Serial Projector и зафиксируйте сигнал, который посылают наши оптопары в штатном состоянии.
Помните! В вашем случае данные могут быть другими! Используйте данные полученные в ходе работы именно вашей схемы!
Далее, возьмите ручку или карандаш и расположите это препятствие так, чтобы преградить поток света, который попадает на фоторезисторы наших оптопар с жёлтых светодиодов. Зафиксируйте полученные значения в мониторе порта.
Давайте внесём эти данные в нашу программу в качестве констант (т.е. постоянных) и попробуем написать алгоритм, который будет зажигать зелёный светодиод в случае, если 1-я оптопара обнаружила препятствие, и красный, если 2-я оптопара обнаружила препятствие. При этом, мы немного занизим значение констант, которые будут хранить наш штатный сигнал и немного завысим значение констант, которые будут хранить сигнал обнаружения препятствия. Это нужно для более стабильной работы нашего устройства, а конкретно: для избежания случайных срабатываний при незначительных изменениях освещённости:
const int opt1_max=750; // объявляем константы для хранения штатного сигнала... const int opt2_max=740; // и сигнала препятствия с оптопар const int opt1_min=550; const int opt2_min=400; int opt1; // переменная для хранения значения сигнала с 1-го фоторезистора int opt2; // переменная для хранения значения сигнала с 2-го фоторезистора void setup() { Serial.begin(9600); pinMode(6, OUTPUT); // объявляем пины со светодиодами на выход pinMode(7, OUTPUT); } void loop() { opt1=analogRead(A0); // получаем сигналы с фоторезисторов и... opt2=analogRead(A1); // помещаем их в переменные Serial.print(opt1); // выводим сигнал с 1-й оптопары Serial.print(" "); // разделяем сигналы пробелом Serial.println(opt2); // выводим сигнал со 2-й оптопары и переходим на следующую строку if (opt1<=opt1_min) // если с оптопары пришёл сигнал меньший или равный сигналу препятствия {digitalWrite(6, HIGH);} // зажигаем зелёный светодиод if (opt1>=opt1_max) // если с оптопары пришёл сигнал больший или равный штатному сигналу {digitalWrite(6, LOW);} // тушим зелёный светодиод if (opt2<=opt2_min) // повторяем для 2-й оптопары... {digitalWrite(7, HIGH);} if (opt2>=opt2_max) {digitalWrite(7, LOW);} }
Загрузите скетч в Arduino и протестируйте работу программы. Для этого проведите ручку или карандаш между светодиодами и фоторезисторами оптопар. При этом, зелёный и красный светодиоды должны зажигаться и гаснуть. Если этого не происходит, то повторите измерение штатного сигнала и сигнала препятствия, пришедших с оптопар и подкорректируйте значения констант. Теперь давайте разберёмся с принципом работы турникета метро. В турникете, как и в нашей схеме, установлены две оптопары. Они могут определять не только наличие препятствия, но и направление движения этого препятствия. Делают они это по следующему алгоритму:
- Если с 1-й оптопары пришёл сигнал препятствия, то программа устанавливает триггер для этого события и начинает ждать пока препятствие не возникнет на 2-й оптопаре. Если это произошло, то система регистрирует движение в направлении от первой оптопары ко второй;
- Если же сигнал пришёл сначала от второй оптопары, то программа устанавливает другой триггер, соответствующий этому событию и ждёт сигнала с первой оптопары. Если после этого с первой оптопары пришёл сигнал о препятствии, то система регистрирует движение в обратном направлении.
Этот алгоритм позволяет установить разные события с учётом направления движения, например беспрепятственно выпускать людей, которые выходят из метро и требовать предъявления жетона, для людей входящих в метро. Давайте попробуем реализовать этот алгоритм. В нашем случае:
- Если будет зафиксировано движение от первой оптопары ко второй, то программа должна зажечь зелёный светодиод и погасить красный;
- Если же будет зафиксировано движение в обратном направлении, то программа должна зажечь красный светодиод, погасив при этом зелёный.
Реализуем такую программу:
const int opt1_max=750; // объявляем константы для хранения штатного сигнала... const int opt2_max=740; // и сигнала препятствия с оптопар const int opt1_min=550; const int opt2_min=400; int opt1; // переменная для хранения значения сигнала с 1-го фоторезистора int opt2; // переменная для хранения значения сигнала с 2-го фоторезистора bool trig1=false; // триггеры для фиксации срабатываний первой и второй оптопар bool trig2=false; void setup() { Serial.begin(9600); pinMode(6, OUTPUT); // объявляем пины со светодиодами на выход pinMode(7, OUTPUT); } void loop() { opt1=analogRead(A0); // получаем сигналы с фоторезисторов и... opt2=analogRead(A1); // помещаем их в переменные Serial.print(opt1); // выводим сигнал с 1-й оптопары Serial.print(" "); // разделяем сигналы пробелом Serial.println(opt2); // выводим сигнал со 2-й оптопары и переходим на следующую строку if (opt1<=opt1_min) // если с 1-й оптопары пришёл сигнал меньший или равный сигналу препятствия {trig1=true;} // устанавливаем 1-й тригер if (opt2<=opt2_min) // если со 2-й оптопары пришёл сигнал меньший или равный сигналу препятствия {trig2=true;} // устанавливаем 2-й тригер if ((opt2<=opt2_min) && trig2==true) // если сработала 2-я оптопара и 1-й триггер был установлен, то... { digitalWrite(6, HIGH); // зажигаем зелёный светодиод digitalWrite(7, LOW); // гасим красный светодиод trig1=false; // сбрасываем 1-й триггер } if ((opt1<=opt1_min) && trig2==true) // если сработала 1-я оптопара и 2-й триггер был установлен, то... { digitalWrite(6, LOW); // гасим зелёный светодиод digitalWrite(7, HIGH); // зажигаем красный светодиод trig2=false; // сбрасываем 2-й триггер } }
Загрузите программу в Arduino и протестируйте её работу, проводя ручкой или карандашом то в одном направлении, то в другом мимо фоторезисторов наших оптопар.
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОГО ВЫПОЛНЕНИЯ
Задание 1:
Измените программу таким образом, чтобы фиксации оптопарами движения от слева-направо, программа поворачивала сервопривод на угол 90º. А через 3 секунды возвращала его в первоначальное положение в 0º. При этом, вместе с поворотом сервопривода на 90º должен загораться красный светодиод, а при повороте в положение 0º, красный светодиод должен гаснуть. Если же движение происходит справа-налево, то программа не должна никак на это реагировать. В таком-штатном режиме должен гореть лишь зелёный светодиод. Этот алгоритм будет более точно описывать работу турникета.
Задание 2:
Дополните предыдущую программу таким образом, чтобы после закрытия турникета, он не возвращался обратно в открытое состояние сам по себе. Сделайте так, чтобы открыть наш турникет можно было только приложив к RFID-считывателю карту. При этом, турникет должен по прежнему пропускать всех, кто движется в направлении справа-налево.
Задание 3*:
Дополните задание №2 таким образом, чтобы наша программа считала количество “людей”, прошедших через турникет. При этом, это должно происходить в двух переменных-счётчиках. Один счётчик для “людей”, движущихся слева-направо. Другой – для “людей”, которые движутся справа-налево. Данные о количестве прошедших “людей” должны выводиться в монитор порта.