Описание
В этом уроке мы разработаем систему контроля доступа в помещение, шкаф, ящик стола... Да куда угодно! В основе проекта электромеханический замок и 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).
Пока устройство находится в режиме "Мастер", приложите новую метку к считывателю. Она будет добавлена в массив меток.
Удаление всех меток
Для удаления всех добавленных меток приложите карту Мастер к считывателю три раза подряд. Произойдет удаление всех меток (кроме Мастера).

Обсуждение