Так как у меня нет машины, то мне не нужно везде носить с собой ключи. Из-за этого оказывалось, что я несколько раз оказывался без ключей вне дома и мне приходилось ждать, пока кто-либо из родственников вернётся домой и впустит меня, и в какой-то момент я решил, что нужно что-то с этим сделать и сконструировал самодельный гаражный замок.
В этом проекте я расскажу, как сделать замок с отпечатком пальца на входную дверь.
Содержание статьи
Шаг 1: Материалы
Вот список необходимых материалов и инструментов.
Электроника:
- Сканер отпечатков пальцев (и коннектор JST)
- Набор LCD (c ATmega328)
- ATtiny85
- NPN-транзистор
- Динамик-пищалка
- Провод для спикера
- Кейс (в шаге 9 будут файлы для 3Д-печати)
- Медная плёнка
- Регулятор напряжения 5V
- Батарейка 9V
- Коннектор для батарейки 9V
- SPDT-выключатель
Для удобства я приложу готовый вишлист на сайте Sparkfun.
Инструмент:
- Паяльник и припой
- Изолента
- Провода и джамперы
- Кусачки / стриппер
- Плата прототипирования
- Разные резисторы
- Винты
- Дрель
- Несколько светодиодов для тестирования
- Плата FTDI 5V
- Пистолет с горячим клеем
- Доступ к 3Д-принтеру
- Опционально: сокет для интегральных схем (8-пиновый для ATtiny и 28-пиновый для ATmega)
- Опционально: еще одна плата Ардуино / конденсатор 10uF (подробности в шаге 5)
Шаг 2: Схема устройства
Приобретённый в Sparkfun LCD-набор шёл с ATmega328, управляющей дисплеем. ATmega328 достаточно мощна и может быть использована не только для управления дисплеем, но и для других задач. Ввиду этого мы можем использовать её вместо Ардуино для коммуникации со сканером отпечатков пальцев и отправки команд на ATtiny85, управления дисплеем и пищалкой.
Чтобы биометрический дверной замок не работал всё время, я встроил в него выключатель, срабатывающий в тот момент, когда кейс закрывается. Если кейс закрыт — питание на девайс не подается, и мы экономим ресурсы батарейки.
Важная заметка: Сканнер отпечатков пальцев работает при напряжении 3.3V, так что я рекомендую использовать разделитель напряжения, который будет преобразовывать сигналы от ATmega к 3.2V. Разделитель напряжения состоит из резистора на 560 Ом между D10 / вторым пином сканера и резистором на 1 КОм между GND / вторым пином сканера.
Распиновка LCD:
- D10 — пин 1 сканера (черный провод)
- D11 — пин 2 сканера (через разделитель напряжения)
- D12 — ATtiny85
- D13 — Пищалка
Распиновка ATtiny85:
- Пин 5 (0 в коде программы) — вход с ATmega
- Пин 3 (4 в коде программы) — транзистор / желтый светодиод
- Пин 7 (2 в коде программы) — светодиод индикации
Заметка: к пину 5 на ATtiny рекомендуется подключить подтягивающий резистор
Шаг 3: Собираем компоненты из LCD-набора
Название шага говорит само за себя: handy-dandy quick start/assembly guide
Шаг 4: Собираем схему на плате прототипирования
Размещение компонентов на плате остается за вами, просто старайтесь припаивать провода так, чтобы они смотрели в одну сторону и не заламывались.
После сборки я покрыл верх и низ платы горячим клеем — это закрепило и изолировало элементы схемы. Горячий клей не повредит микросхему.
Как и с основной платой, припаяйте все к плате ATtiny и нанесите горячий клей для закрепления и изоляции компонентов. Регулятор напряжения может очень сильно греться, поэтому будет хорошей идеей не наносить горячий клей на него и поверхности, располагающиеся рядом с ним. Также лучше не покрывать горячим клеем плату ATtiny, ведь вы можете захотеть снять и перепрограммировать её.
Шаг 5: Программирование ATmega328
Как уже говорилось в шаге 2, у ATmega328 достаточно сильный процессор и достаточно пинов для управления LCD, в то время как он управляет другими дополнительными компонентами. Чтобы добиться этого, нужно запрограммировать чип.
Если у вас есть Arduino Uno или Duemilanove, вы можете просто снять с них чип и заменить его тем, который шел в наборе. Либо вы можете найти плату FTDI Basic Breakout (5V) и припаять насадки к её стороне (смотрите картинки в шаге 3)
Также вам нужно будет залить код в режиме «Duemilanove w/ ATmega328».
Код внизу — рабочая программа для проверки работоспособности девайса.
#include "LiquidCrystal.h" LiquidCrystal lcd(2,3,4,5,6,7,8); void setup() { pinMode(9, OUTPUT); //подсветка pinMode(13, OUTPUT); //пищалка lcd.begin(16, 2); //16 знаков в ширину, 2 в высоту digitalWrite(9, HIGH); //включаем подсветку lcd.print(" Hello world! "); //центрируйте текст при помощи пробелов delay(2000); } void loop() { //пищалка включается и выключается, её состояние отображается на дисплее lcd.clear(); lcd.print(" Buzzer is on "); tone(13, 262, 1000); delay(1000); lcd.clear(); lcd.print(" Buzzer is off "); delay(1000); }
Файлы
Шаг 6: Настраиваем сканер отпечатков пальцев
Для коммуникации со сканером я использовал эту библиотеку. Прямая ссылка на скачивание здесь.
Для проверки работоспособности кода загрузите эту программу проверки «миганием».
У сканера отпечатков есть своя встроенная память для хранения данных. Так что после того, как вы убедитесь, что сканер работает, загрузите эту программу, чтобы добавить ваш отпечаток в базу данных под id #0. Откройте последовательную консоль и просто следуйте инструкциям.
Программа мигания светодиода для проверки сканера
/* Этот простой код включит и выключит светодиод. Он используется для того, чтобы понять, работает ли коммуникация. */ #include "FPS_GT511C3.h" #include "SoftwareSerial.h" //Настройка железа - сканер пальцев соединён с: //цифровым пином 10(arduino rx, fps tx) //цифроывм пином 11(arduino tx - резистор 560ohm fps tx - резистор 1000ohm - GND) //это понижает 5v tx примерно до 3.2v и мы не сожжем наш сканер FPS_GT511C3 fps(10, 11); void setup(){ Serial.begin(9600); fps.UseSerialDebug = true; // вы сможете увидеть сообщения на последовательном дебаг-экране fps.Open(); } void loop(){ // тест мигания светодиодов для сканера fps.SetLED(true); // включает LED внутри сканера delay(1000); fps.SetLED(false);// выключает LED внутри сканера delay(1000); }
Программа регистрации данных в сканер
#include "FPS_GT511C3.h" #include "SoftwareSerial.h" //Настройка железа - сканер пальцев соединён с: //цифровым пином 10(arduino rx, fps tx) //цифроывм пином 11(arduino tx - резистор 560ohm fps tx - резистор 1000ohm - GND) //это понижает 5v tx примерно до 3.2v и мы не сожжем наш сканер FPS_GT511C3 fps(10, 11); void setup(){ Serial.begin(9600); delay(100); fps.Open(); fps.SetLED(true); Enroll(); } void Enroll(){ // Тест регистрации // поиск открытого id int enrollid = 0; fps.EnrollStart(enrollid); // регистрация Serial.print("Press finger to Enroll #"); Serial.println(enrollid); while(fps.IsPressFinger() == false) delay(100); bool bret = fps.CaptureFinger(true); int iret = 0; if (bret != false) { Serial.println("Remove finger"); fps.Enroll1(); while(fps.IsPressFinger() == true) delay(100); Serial.println("Press same finger again"); while(fps.IsPressFinger() == false) delay(100); bret = fps.CaptureFinger(true); if (bret != false) { Serial.println("Remove finger"); fps.Enroll2(); while(fps.IsPressFinger() == true) delay(100); Serial.println("Press same finger yet again"); while(fps.IsPressFinger() == false) delay(100); bret = fps.CaptureFinger(true); if (bret != false) { Serial.println("Remove finger"); iret = fps.Enroll3(); if (iret == 0) { Serial.println("Enrolling Successfull"); } else { Serial.print("Enrolling Failed with error code:"); Serial.println(iret); } } else Serial.println("Failed to capture third finger"); } else Serial.println("Failed to capture second finger"); } else Serial.println("Failed to capture first finger"); } void loop(){ delay(100000); }
Файлы
Шаг 7: Программируем ATtiny85
ATtiny85 — это что-то типа дешевого Ардуино, собранного в одном чипе. ATtiny85 может быть запрограммирована другим Ардуино, включая ATmega328, который есть в нашем наборе LCD. В проекте он используется для запуска очень простых команд: проверить сигнал с ATmega и открыть ворота, если сигнал правильный.
Чтобы запрограммировать его, подключите всё согласно приложенным фотографиям. Затем скачайте необходимые файлы и следуйте этой инструкции.
После загрузки кода, пин 13 на Ардуино (встроенный светодиод) должен загореться, оповещая, что код загружен.
Итоговый код:
//Получает краткий сигнал от основного модуля для закрытия реле void setup(){ pinMode(2,OUTPUT); //LEd индикации через резистор на 10K pinMode(4,OUTPUT); //пин странзистора, открывающий гараж pinMode(0,INPUT); //ввод delay(500); //даём девайсу время для старта digitalWrite(2, HIGH); //LED индикации } void loop(){ if(digitalRead(0)){ //простой паттерн для переключения транзистора delay(125); if(digitalRead(0)==false){ delay(55); //ждём, так как таймер ATtiny не идеален if(digitalRead(0)){ delay(55); if(digitalRead(0)==false){ delay(55); if(digitalRead(0)){ delay(55); if(digitalRead(0)==false){ digitalWrite(4, HIGH); //транзистор "нажимает" кнопку delay(1000); digitalWrite(4,LOW); digitalWrite(2,LOW); delay(1000); digitalWrite(2, HIGH); } } } } } } }
Файлы
Шаг 8: Итоговый код
Ниже приложена программа для Ардуино, которую я написал с использованием библиотек сканера и дисплея. Чтобы было понятно, что происходит в каждой части программы, я постарался закомментировать всё наилучшим образом. После загрузки этого кода всё должно заработать и всё что останется сделать — интегрировать систему в дверь.
Предупреждение: если библиотека сканера не работает, то попробуйте использовать старую версию IDE Ардуино.
Код для ATmega238:
#include "LiquidCrystal.h" //библиотека дисплея #include "FPS_GT511C3.h" //библиотека fps (сканера отпечатков) #include "SoftwareSerial.h" //используется библиотекой сканера //Настраиваем пины дисплея и сканера LiquidCrystal lcd(2, 3, 4, 5, 6, 7, 8); //распиновка дисплея FPS_GT511C3 fps(10, 11); //RX, TX boolean isFinger = false; //true если библиотека fps засечет палец на сканере //выходные пины const int buzzerPin = 13; const int backlightPin = 9; const int attinyPin = 12; const String idNames[] = { "self","Bro", "Ryan", "Mom", "Dad", "Auntie", "Grandma", "Zeide", "Person", "person", "Thumb"}; void setup(){ //настраиваем выходы pinMode(buzzerPin, OUTPUT); pinMode(backlightPin, OUTPUT); pinMode(attinyPin, OUTPUT); //для отладки //Serial.begin(9600); fps.UseSerialDebug = false; //становится true для отладки fps через последовательный порт //инициализация библиотек lcd.begin(16,2); digitalWrite(backlightPin, HIGH); //подсветка LCD fps.Open(); fps.SetLED(true); //светодиод на fps //звук загрузки for(int i=0; i<30; i++){ tone(buzzerPin, 50+10*i, 30); delay(30); } tone(buzzerPin, 350); //вывод стартового сообщения lcd.print("Put your finger "); //команда вывода на экран lcd.setCursor(0, 1); //устанавливаем курсор на нулевую колонку первой строки lcd.print(" on the scanner "); delay(150); noTone(buzzerPin); //останавливаем стартовый звук } void loop(){ //сканируем и распознаём отпечаток, когда приложен палец waitForFinger(); lcd.clear(); //очищаем экран и устанавливаем курсов в положение 0,0 fps.CaptureFinger(false); //захватываем отпечаток для идентификации int id = fps.Identify1_N(); //идентифицируем отпечаток и сохраняем id if(id <= 10){ lcd.print(" Access granted "); //сообщение об успехе lcd.setCursor(0,1); //выводим на экран имя когда дверь открывается String message = " Hey " + idNames[id] + "!"; lcd.print(message); tone(buzzerPin, 262, 1000); delay(1500); //отправляем сигнал для открытия двери digitalWrite(attinyPin, HIGH); //первый импульс синхронизирует задержку (10ms) delay(5); digitalWrite(attinyPin, LOW); delay(3); digitalWrite(attinyPin, HIGH); //следующие два - открывают дверь delay(15); digitalWrite(attinyPin, LOW); delay(5); digitalWrite(attinyPin, HIGH); delay(10); digitalWrite(attinyPin, LOW); delay(1000); lcd.clear(); lcd.print("Don't forget to "); lcd.setCursor(0,1); lcd.print(" shut me off! "); delay(2000); waitForFinger(); //нажмите чтобы продолжить запись while(true){ //сохраняет новый отпечаток //выводит сообщение на экран lcd.clear(); lcd.print(centerText("So you want to")); lcd.setCursor(0,1); lcd.print(centerText("scan a new one?")); delay(2000); //Скопировано и слегка модифицировано из примера регистрации данных: int enrollid = 11; //выбираете какой id переписатьсоздать //отпустите палец, когда хотите записать id/имя, напечатанное на экране waitForFinger(); //ждёт, когда будет нажат fps while(enrollid==11){ for (int i = 1; i1){ lcd.print(i); enrollid = i-1; break; } } } //предупреждение, если в данном слоте уже есть данные if(fps.CheckEnrolled(enrollid)){ lcd.clear(); lcd.print(" Warning! ID #"); lcd.print(enrollid); lcd.setCursor(0,1); lcd.print(" has data. OK? "); delay(2500); waitForFinger(); //ждёт, когда будет нажат fps fps.DeleteID(enrollid); //удаляет данные delay(100); } //Enroll fps.EnrollStart(enrollid); lcd.clear(); lcd.print("Place finger to "); lcd.setCursor(0,1); lcd.print("enroll #"); lcd.print(enrollid); //выводит id, который был добавлен waitForFinger(); //ждёт, когда будет нажат fps //захватывает отпечаток и сохраняет его в память трижды для точности данных bool bret = fps.CaptureFinger(true); //картинка высокого качества для записи int iret = 0; //в случае ошибки if (bret != false){ //первая регистрация lcd.clear(); lcd.print(" Remove finger "); fps.Enroll1(); while(fps.IsPressFinger() == true) delay(100); //ждёт пока уберут палец lcd.clear(); lcd.print(" Press again "); waitForFinger(); //ждёт, когда будет нажат fps bret = fps.CaptureFinger(true); if (bret != false){ //вторая регистрация lcd.clear(); lcd.print(" Remove finger "); fps.Enroll2(); while(fps.IsPressFinger() == true) delay(100); lcd.clear(); lcd.print("Press yet again "); waitForFinger(); bret = fps.CaptureFinger(true); if (bret != false){ //третья регистрация iret = fps.Enroll3(); if (iret == 0){ //проверяет, были ли какие-нибудь ошибки lcd.clear(); lcd.print(" Success! "); delay(2000); beep(); //выключает Ардуино } else{ //запускает этот код в случае любой ошибки lcd.clear(); lcd.print("Fail. Try again "); delay(1000); } } lcd.clear(); lcd.print(" Failed 3rd "); //ошибка на третьей записи delay(1000); } lcd.clear(); lcd.print(" Failed 2nd "); //ошибка на второй записи delay(1000); } lcd.clear(); lcd.print(" Failed 1st "); //ошибка на первой записи delay(1000); } } else{ lcd.print("Fingerprint is"); //если отпечаток не распознан lcd.setCursor(0,1); lcd.print(" unverified "); delay(2000); lcd.clear(); lcd.print("Please try again"); lcd.setCursor(0,1); lcd.print("Use your pointer"); //pointer - указательный палец (можете использовать любой и заменить это слово) delay(500); } delay(250); } void beep(){ //издаёт звуки, чтобы кто-нибудь закрыл кейс lcd.clear(); lcd.print("Please close the"); lcd.setCursor(0,1); lcd.print(" case! "); for(int i=0;i=80 && !fps.IsPressFinger()){ beep(); } } timer = 0; //обнуляет таймер как только функция завершится } String centerText(String s) { //центрует текст на дисплее, чтобы он лучше смотрелся while(16-s.length()>1){ //если текст нуждается в центровке s = " " + s + " "; //равномерно добавляет пробелы с обеих сторон } return s; }
Файлы
Шаг 9: Напечатанный на 3Д-принтере кейс
Чтобы включить модуль, нужно захлопнуть кейс, запустив выключатель. Как видно на фото выключатель должен подключаться к общему контакту и нормально замкнутому контакту (NC). Приклейте всё к кейсу при помощи горячего клея. Спозиционируйте выключатель с небольшим смещением, чтобы он надавливался более легко.
Файлы
Шаг 10: Подготовка гаража
Чтобы открывать гараж, я подключил ATtiny85 к кнопке, которая открывала гараж до этого. Вместо физического соединения, ATtiny использует в качестве «кнопки» NPN-транзистор.
Провода нужно измерить и отрезать по нужной длине, оставив немного длины про запас. Затем нужно припаять провода от кнопки к модулю сканера. Затем всё нужно хорошо изолировать.
Чтобы ATtiny внутри гаража получал сигналы от ATmega, находящегося снаружи гаража, я пропустил сквозь стену 3 провода (питание, землю и сигнальный). В гараже была деревянная стойка, через которую я и проделал отверстие.
Наконец, можно привинтить кейс и запустить устройство!
Шаг 11: Тестирование
Этот шаг будет самым весёлым. Используйте встроенную функцию добавления данных, чтобы ваши семья/друзья могли открывать гараж. Затем вы можете создать персональные сообщения для каждого из них! Посмотрите видео для визуального объяснения функционала девайса.
Шаг 12: Делаем устройство портативным
Сканер отпечатков и экран могут быть встроены в коробку или сундук, ведь они работают от батареек. Я временно снял модуль с гаража и совместил его с сервоприводом, чтобы открыватьзакрывать свой сундук при помощи пальца.
Заметка: я обнаружил, что 9V батарейки не хватало для одновременной работы девайса и сервопривода, поэтому заменил её на 6 батареек AA. Также хочу заметить, что дизайн моего замка был разработан в ознакомительных целях. Чтобы сделать его более безопасным, я бы рекомендовал использовать более жесткий корпус.