Описание
В этом уроке мы разработаем систему контроля доступа в помещение, шкаф, ящик стола... Да куда угодно! В основе проекта электромеханический замок и RFID считыватель.
Видео
Нам понадобится
- Электромагнитный замок или Электромеханический замок
- RFID считыватель
- Piranha UNO (или другой контроллер)
- Trema Shield
- Силовой ключ N-канал или Р-канал
- Провод питания, DC (Папа)
- Коннектор power jack Мама с клемником
- Обжать провода считывателя (при необходимости) можно вот такими клемниками
Для работы со считывателем необходимо установить библиотеку Wiegand. При необходимости, ознакомьтесь с нашей инструкцией по установке библиотек в Arduino IDE.
Подключение
RFID считыватель | Piranha UNO |
D0 (зеленый провод) | 2 |
D1 (белый провод) | 3 |
ZUMMER (желтый провод) | 4 |
LED (коричневый провод) | 5 |
Vcc | + 12В |
GND | - 12В |
Силовой ключ | Piranha UNO |
G | GND |
V | Vcc |
S | 6 |
+Vin | +12В |
-Vin | -12В |
+Vout | + замка |
-Vout | - замка |
Скетч проекта
#include <Wiegand.h> // подключение библиотеки #include <EEPROM.h> // Подключаем библиотеку для работы с энергонезависимой памятью WIEGAND wg; // создание объекта считывателя #define INIT_ADDR 1023 // номер резервной ячейки (для EEPROM) #define INIT_KEY 50 // ключ первого запуска. 0-254, на выбор (для EEPROM) #define lock 6 // замок подключен к 6 пину #define led 5 // светодиод (встроенный с считыватель) - 4 пин #define zummer 4 // зуммер (встроенный в считыватель) - 5 пин ///////////////////НАСТРОЙКИ/////////////////////// const int openTime = 200; // время, мс, на которое открывается замок const int masterTime = 3000; // время, на которое активируется режим добавления новой метки const int zummerTime = 2000; // время работы светодиода и зуммера во время открытия замка long masterKey = 5687942; // идентификационный номер метки мастера (мастер позволяет добавлять новые метки) long keysArr[10] = {}; // массив ключей из 10 меток /////////////////////////////////////////////////// bool ledState = true; // установка флага для мигания светодиода long timeStart; // время, в которое сработала карта long timeMasterStart; // время, в которое запустился цикл добавления новой метки uint8_t k; // счётчик количества приложенных раз метки Мастер long printKey[10] = {}; // массив выводимых меток в монитор порта void setup() { // светодиод, зуммер, замок - выходы pinMode(lock, OUTPUT); pinMode(led, OUTPUT); pinMode(zummer, OUTPUT); digitalWrite(led, HIGH); // светодиод, зуммер, замок ВЫКЛючены (светодиод и зуммер включаются подачей минуса на пин) digitalWrite(zummer, HIGH); digitalWrite(lock, LOW); Serial.begin(9600); // Инициализация последовательного порта на скорости 9600 бод wg.begin(); // Инициализация считывателя if (EEPROM.read(INIT_ADDR) != INIT_KEY) { // первый запуск EEPROM.write(INIT_ADDR, INIT_KEY); // записываем ключ EEPROM.put(0, keysArr); // записываем массив ключей (обнуляем данные, которые могли остаться в памяти после других проектов) Serial.println ("Массив данных обновлён."); } else{ EEPROM.get(0, keysArr); // читаем ключи } } void loop(){ if(wg.available()){ long id = wg.getCode(); if (id == masterKey) Serial.print("Master "); Serial.print("id = "); Serial.println(id); // чтение идентификатора метки и отправка в монитор порта if (id == masterKey){ // если id карты - мастер. Добавляем новую метку в массив timeMasterStart = millis(); // фиксируем время начала выполнения функции master(); // запускаем функцию master() } else{ for (uint8_t i = 0; i < sizeof(keysArr)/sizeof(long); i++){ // проверяем все элементы массива номеров меток if (id == keysArr[i]) { // если считанный номер совпал с i-м элементом succes(); // открываем замок return; // заканчиваем перебор элементов } } reject(); // иначе отказ } } } void succes(){ // функция открытия замка digitalWrite(led, LOW); // ВКЛючаем светодиод и зуммер (для включения на них нужно подать "-") digitalWrite(zummer, LOW); digitalWrite(lock, HIGH); // открываем замок на время openTime delay(openTime); digitalWrite(lock, LOW); // заканчиваем подавать напряжение для открытия delay(zummerTime-openTime); digitalWrite(led, HIGH); // ВЫКЛючаем светодиод и зуммер digitalWrite(zummer, HIGH); } void master(){ // функция мастер while(timeMasterStart + masterTime > millis()){ // пока время нахождения в режиме Мастер не вышло if (timeStart + 100 < millis()){ // мигаем светодиодом каждые 100 мс timeStart = millis(); ledState = ! ledState; digitalWrite(led, ledState); } if(wg.available()){ long idNew = wg.getCode(); // считываем новую метку if (idNew != masterKey){ // если метка - не мастер for (uint8_t i = 0; i < sizeof(keysArr)/sizeof(long); i++){ // перебираем массив идентификаторов меток для поиска первого нуля, вместо котого можно её записать if (keysArr[i] == 0 || keysArr[i] == idNew) { // смотрим, записана ли метка, или мы осмотрели все записи и нашли первый 0 - свободное место, куда запишем метку keysArr[i] = idNew; // записываем в массив EEPROM.put(0, keysArr); // записываем массив в EEPROM Serial.print("Массив ключей изменён: "); // вывод в монитор порта всех номеров в массиве writeEEPROM(); // функция вывода массива в монитор порта succes(); // открываем замок digitalWrite(led, HIGH); // выключаем светодиод и зуммер digitalWrite(zummer, HIGH); break; } } } else if (idNew == masterKey){ // если метка - мастер k++; // увеличиваем счётчик - сколько раз подряд прикладывали метку мастер if (k >= 2){ // если два раза k=0; for (uint8_t p = 0; p < sizeof(keysArr)/sizeof(long); p++){ // очищаем массив и EEPROM keysArr[p] = 0; } EEPROM.put(0, keysArr); Serial.println("Массив ключей очищен!"); writeEEPROM(); // выводим в монитор порта массив меток } } } } digitalWrite(led, HIGH); // отключаем светодиод и зуммер digitalWrite(zummer, HIGH); k=0; } void reject(){ // функция отказа в открытии замка for (uint8_t n=0; n<=2; n++){ // повторяем три раза digitalWrite(led, LOW); // включаем зуммер и светодиод, ждём, выключаем digitalWrite(zummer, LOW); delay(100); digitalWrite(led, HIGH); digitalWrite(zummer, HIGH); delay(100); } } void writeEEPROM(){ // функция вывода в монитор порта массива ключей меток EEPROM.get(0, printKey); for (uint8_t j = 0; j < sizeof(printKey)/sizeof(long); j++){ Serial.print(printKey[j]); Serial.print("; "); } Serial.println(""); }
Описание работы
В начале скетча вы найдёте настройки, в том числе, номер карты-мастера, и массив из меток, изначально открывающих замок. Для того, чтобы узнать код метки (например для добавления мастера), запустите тестовый скетч. Полученный идентификатор впишите в переменную masterKey
Все добавленные метки помещаются в энергонезависимую память и остаются в ней даже при отключении питания.
Если что-то пошло не так, измените ключ первого запуска (INIT_KEY
) на любой другой в указанном в скетче диапазоне. Это позволит стереть все добавленные ранее ключи на программном уровне.
Вы можете не использовать метку Мастер. В таком случае, запишите в массив keysArr[]
номера меток, которые будут открывать замок. При необходимости, размер массива может быть увеличен.
Добавление новой метки
Для добавления новой метки, приложите метку Мастер к считывателю. С этого момента начинается отсчёт времени нахождения в режиме "Мастер" (задаётся переменной masterTime
).
Пока устройство находится в режиме "Мастер", приложите новую метку к считывателю. Она будет добавлена в массив меток.
Удаление всех меток
Для удаления всех добавленных меток приложите карту Мастер к считывателю три раза подряд. Произойдет удаление всех меток (кроме Мастера).
Обсуждение