Общие сведения:
Модуль отпечатков пальцев ZFM-20 (Zhiantec Fingerprint Мodule) - позволяет создать систему контроля доступа, основанную на дактилоскопической идентификации.
Для создания системы контроля доступа, необходимо ознакомиться с такими функциями модуля как:
- Регистрация отпечатков пальцев в базе данных модуля.
- Удаление отпечатков пальцев из базы данных модуля.
- Поиск отпечатков пальцев в базе данных модуля.
- Сравнение текущего отпечатка пальца с отпечатками пальцев в базе данных модуля.
Все эти функции можно реализовать, используя библиотеку Adafruit_Fingerprint.
Подключение модуля отпечатков пальцев ZFM-20:
Модуль можно подключать к любым выводам поддерживающим прерывания PCINTx (В Arduino UNO данные прерывания поддерживают все выводы).
- В приведённых ниже примерах, модуль подключается к 2 и 3 выводу Arduino Uno:
- :ЖЕЛТЫЙ (ЗЕЛЁНЫЙ) провод модуля T (Transmit), подключается к линии Receive программного UART (вывод 2) arduino.
- БЕЛЫЙ провод модуля R (Receive), подключается к линии Transmit программного UART (вывод 3) arduino.
Примеры работы с модулем отпечатков пальцев:
Ниже приведённые скетчи, отличаются от стандартных примеров библиотеки Adafruit_Fingerprint, они модифицированы, проверены, откомментированы и перезаписаны в папку examples.
Все скетчи выводят информацию в монитор последовательного порта.
Обнаружение и вывод первых 10 отпечатков пальцев.
Скетч находится в файле examples/show_fingerprint_templates.ino
#include <Adafruit_Fingerprint.h> // подключаем библиотеку для работы с модулем отпечатков пальцев #include <SoftwareSerial.h> // подключаем библиотеку для работы с программным UART SoftwareSerial mySerial(2, 3); // объявляем объект mySerial для работы с библиотекой SoftwareSerial ИМЯ_ОБЪЕКТА( RX, TX ); // Можно указывать любые выводы, поддерживающие прерывание PCINTx Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); // объявляем объект finger для работы с библиотекой Adafruit_Fingerprint ИМЯ_ОБЪЕКТА = Adafruit_Fingerprint(ПАРАМЕТР); // ПАРАМЕТР - ссылка на объект для работы с UART к которому подключен модуль, например: &Serial1 void setup(){ while(!Serial); // Ожидание инициализации аппаратного UART delay(500); // Ожидание инициализации модуля отпечатков пальцев Serial.begin(9600); // Инициализация аппаратного UART на скорости 9600 Serial.println("Scan sensor..."); // Вывод сообщения "Поиск сенсора" finger.begin(9600); // Скорость по умолчанию 9600 или 57600 зависит от версии //finger.begin(57600); // Инициализация программного UART на скорости 57600 (скорость модуля по умолчанию) if(finger.verifyPassword()){Serial.println("Found sensor!");} // Если модуль отпечатков обнаружен, выводим сообщение "сенсор обнаружен" else{Serial.println("Did not find sensor :("); while(1); } // Если модуль отпечатков не обнаружен, выводим сообщение "сенсор не обнаружен" и входим в бесконечный цикл: while(1); uint8_t templateBuffer[256]; // Создание массива, для хранения пикселей модели (шаблона) отпечатка пальца int index; // Создание переменной, для хранения количества записанных элементов в массив templateBuffer uint32_t starttime; // Создание переменной, для хранения времени начала приёма пикселей по программному UART for (int id = 0; id < 10; id++){ // Проход по 10 идентификаторам if(finger.loadModel(id) == FINGERPRINT_OK) { Serial.print("template "); Serial.print(id); Serial.println(" loaded"); // Загрузка модели в буфер, если результат выполнения равен константе FINGERPRINT_OK (модель загружена), то проходим дальше if(finger.getModel() == FINGERPRINT_OK) { Serial.print("template "); Serial.print(id); Serial.println(" transferring"); // Получение модели из буфера, если результат выполнения равен константе FINGERPRINT_OK (передача инициирована), то проходим дальше index=0; starttime = millis(); // Обнуляем количество записанных элементов и обновляем время старта приёма данных while ((millis() - starttime) < 1000){ // Если с начала приёма данных прошло менее 1 секунды, то ... if (mySerial.available()){ // Если в буфере программного UART имеются данные для чтения, то ... if(index < 256){ // Если принято меньше 256 байт, то ... templateBuffer[index] = mySerial.read(); index++; // Сохраняем очередной байт, принятый по программному UART, в очередной элемент массива templateBuffer } } } Serial.print("template "); Serial.print(id); Serial.print(" array("); Serial.print(index); Serial.println(" bytes):"); for(int i=0; i<index; i++) { Serial.print("\t0x"); Serial.print(templateBuffer[i],HEX); if((i+1)%16==0) { Serial.println("");} } }else { Serial.print("template "); Serial.print(id); Serial.println(" not transferring");} }else { Serial.print("template "); Serial.print(id); Serial.println(" not found");} } } void loop(){}
Загрузите скетч в arduino uno, откройте монитор последовательного порта.
Вы увидите следующие строки:
Scan sensor...
Found sensor!
template 0 not found
template 1 not found
template 2 not found
template 3 not found
...
Если по указанному ID номеру будет обнаружен отпечаток пальца, то вместо надписи not found, будут выведены строки:
template 5 loaded
template 5 transferring
template 5 array(256 bytes):
массив шаблона отпечатка пальца
Если, во второй строке, вместо надписи Found sensor!, будет надпись Did not find sensor, значит Вы неправильно подключили модуль.
Сравнение текущего отпечатка пальца (приложенного к сканеру) с базой модуля.
Скетч находится в файле examples/fingerprint.ino
#include <Adafruit_Fingerprint.h> // подключаем библиотеку для работы с модулем отпечатков пальцев #include <SoftwareSerial.h> // подключаем библиотеку для работы с программным UART SoftwareSerial mySerial(2, 3); // объявляем объект mySerial для работы с библиотекой SoftwareSerial ИМЯ_ОБЪЕКТА( RX, TX ); // Можно указывать любые выводы, поддерживающие прерывание PCINTx Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); // объявляем объект finger для работы с библиотекой Adafruit_Fingerprint ИМЯ_ОБЪЕКТА = Adafruit_Fingerprint(ПАРАМЕТР); // ПАРАМЕТР - ссылка на объект для работы с UART к которому подключен модуль, например: &Serial1 void setup(){ while(!Serial); // Ожидание инициализации аппаратного UART delay(500); // Ожидание инициализации модуля отпечатков пальцев Serial.begin(9600); // Инициализация аппаратного UART на скорости 9600 Serial.println("Scan sensor..."); // Вывод сообщения "Поиск сенсора" finger.begin(9600); // Скорость по умолчанию 9600 или 57600 зависит от версии //finger.begin(57600); // Инициализация программного UART на скорости 57600 (скорость модуля по умолчанию) if(finger.verifyPassword()){Serial.println("Found sensor!");} // Если модуль отпечатков обнаружен, выводим сообщение "сенсор обнаружен" else{Serial.println("Did not find sensor :("); while(1); } // Если модуль отпечатков не обнаружен, выводим сообщение "сенсор не обнаружен" и входим в бесконечный цикл: while(1); Serial.println("Please put your finger on the scanner ..."); } void loop(){ if(finger.getImage() == FINGERPRINT_OK){ // Захватываем изображение, если результат выполнения равен константе FINGERPRINT_OK (корректная загрузка изображения), то проходим дальше if(finger.image2Tz() == FINGERPRINT_OK){ // Конвертируем полученное изображение, если результат выполнения равен константе FINGERPRINT_OK (изображение сконвертировано), то проходим дальше if(finger.fingerFastSearch() == FINGERPRINT_OK){ // Находим соответствие в базе данных отпечатков пальцев, если результат выполнения равен константе FINGERPRINT_OK (найдено соответствие), то проходим дальше Serial.print("Found ID="); Serial.print(finger.fingerID); Serial.print(", with confidence of "); Serial.println(finger.confidence); }}} delay(500); // Задержка перед следующим сканированием 0,5 сек (нет смысла запускать на полной скорости) }
Загрузите скетч в arduino uno, откройте монитор последовательного порта.
Вы увидите следующие строки:
Scan sensor...
Found sensor!
Please put your finger on the scanner ...
При этом сканер модуля будет мигать красным цветом. Приложите палец к сенсору. Если Отпечаток Вашего пальца имеется в базе модуля, то на мониторе отобразится надпись:
Found ID=5, with confidence of 73
где первое число (в нашем примере, это 5) соответствует ID номеру под которым записан совпавший отпечаток пальца, а последнее число (в нашем примере, это 73) означает уровень соответствия отпечатка приложенного пальца, отпечатку сохранённому в базе.
Если, во второй строке, вместо надписи Found sensor!, будет надпись Did not find sensor, значит Вы неправильно подключили модуль.
Удаление отпечатка пальца из базы отпечатков модуля.
Скетч находится в файле examples/delete.ino
#include <Adafruit_Fingerprint.h> // подключаем библиотеку для работы с модулем отпечатков пальцев #include <SoftwareSerial.h> // подключаем библиотеку для работы с программным UART uint8_t id; // идентификационный номер, под которым будет сохранён шаблон отпечатка пальца SoftwareSerial mySerial(2, 3); // объявляем объект mySerial для работы с библиотекой SoftwareSerial ИМЯ_ОБЪЕКТА( RX, TX ); // Можно указывать любые выводы, поддерживающие прерывание PCINTx Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); // объявляем объект finger для работы с библиотекой Adafruit_Fingerprint ИМЯ_ОБЪЕКТА = Adafruit_Fingerprint(ПАРАМЕТР); // ПАРАМЕТР - ссылка на объект для работы с UART к которому подключен модуль, например: &Serial1 void setup(){ while(!Serial); // Ожидание инициализации аппаратного UART delay(500); // Ожидание инициализации модуля отпечатков пальцев Serial.begin(9600); // Инициализация аппаратного UART на скорости 9600 Serial.println("Scan sensor..."); // Вывод сообщения "Поиск сенсора" finger.begin(9600); // Скорость по умолчанию 9600 или 57600 зависит от версии <span class="redactor-invisible-space"> //</span> finger.begin(57600); // Инициализация программного UART на скорости 57600 (скорость модуля по умолчанию) if(finger.verifyPassword()){Serial.println("Found sensor!");} // Если модуль отпечатков обнаружен, выводим сообщение "сенсор обнаружен" else{Serial.println("Did not find sensor :("); while(1); } // Если модуль отпечатков не обнаружен, выводим сообщение "сенсор не обнаружен" и входим в бесконечный цикл: while(1); } void loop(){ Serial.println("----------------------------------"); Serial.print ("Please enter ID number You want delete..."); // Вывод сообщения "Пожалуйста введите идентификационный номер который Вы хотите удалить" id = readnumber(); // Ожидание получения цифры, введённой с COM-порта Serial.print("Ok! ID="); Serial.println(id); // Вывод сообщения "Введён идентификационный номер" цифра deleteFingerprint(id); // Вызываем функцию удаления шаблона по его ID } // функция возвращает номер, введённый с COM-порта uint8_t readnumber(void){ int num = -1; // Переменная с номером, который требуется вернуть while(num<0){ // Вход в цикл, пока переменная num не станет >= 0 while(!Serial.available()); // Ожидание пока в буфере COM-порта нет появятся данные while(Serial.available()){ // Цикл пока в буфере COM-порта не закончатся данные char c = Serial.read(); // Присваиваем очередной символ из COM-порта в переменную c if(isdigit(c)){ // Если значение переменной с - цифра, то ... if(num<0){num=0;}else{num *= 10;} // Увеличиваем значение num на один порядок num += c - '0'; // Прибавляем к значению num цифру из переменной c } delay(5); // Задержка на 5мс, чтоб в буфер COM-порта успели догрузиться следующие символы (если таковые имеются) } } return num; // Возвращение введённого числа } // Функция удаляет отпечаток пальца по указанному ID uint8_t deleteFingerprint(uint8_t id){ int p = -1; // Переменная для получения результатов выполнения функций p = finger.deleteModel(id); // Удаляем шаблон отпечатка пальца из базы данных и возвращаем результат выполнения данной операции в переменную p switch(p){ // Проверка ответа ... case FINGERPRINT_OK: Serial.println("ID Deleted!"); break; // Шаблон отпечатка пальца корректно удалён case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); break; // Ошибка соединения case FINGERPRINT_BADLOCATION: Serial.println("Could not delete in that location"); break; // Не удалось сохранить в этом месте case FINGERPRINT_FLASHERR: Serial.println("Error writing to flash"); break; // Ошибка записи в flash память default: Serial.println("Unknown error :(\nPlease try again "); break; // Неизвестная ошибка } }
Загрузите скетч в arduino uno, откройте монитор последовательного порта.
Вы увидите следующие строки:
Scan sensor...
Found sensor!
----------------------------------
Please enter ID number You want delete...
Введите в монитор последовательного порта число (ID номер удаляемого отпечатка пальца) и нажмите Enter. На мониторе отобразится надпись:
ID Deleted!
Отпечаток хранящийся в базе сенсора под указанным ID, удалён из базы.
Если, во второй строке, вместо надписи Found sensor!, будет надпись Did not find sensor, значит Вы неправильно подключили модуль.
Регистрация отпечатка пальца в базе отпечатков модуля.
Скетч находится в файле examples/enroll.ino
#include <Adafruit_Fingerprint.h> // подключаем библиотеку для работы с модулем отпечатков пальцев #include <SoftwareSerial.h> // подключаем библиотеку для работы с программным UART uint8_t id; // идентификационный номер, под которым будет сохранён шаблон отпечатка пальца uint8_t getFingerprintEnroll(); SoftwareSerial mySerial(2, 3); // объявляем объект mySerial для работы с библиотекой SoftwareSerial ИМЯ_ОБЪЕКТА( RX, TX ); // Можно указывать любые выводы, поддерживающие прерывание PCINTx Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); // объявляем объект finger для работы с библиотекой Adafruit_Fingerprint ИМЯ_ОБЪЕКТА = Adafruit_Fingerprint(ПАРАМЕТР); // ПАРАМЕТР - ссылка на объект для работы с UART к которому подключен модуль, например: &Serial1 void setup(){ while(!Serial); // Ожидание инициализации аппаратного UART delay(500); // Ожидание инициализации модуля отпечатков пальцев Serial.begin(9600); // Инициализация аппаратного UART на скорости 9600 Serial.println("Scan sensor..."); // Вывод сообщения "Поиск сенсора" finger.begin(9600); // Скорость по умолчанию 9600 или 57600 зависит от версии // finger.begin(57600); // Инициализация программного UART на скорости 57600 (скорость модуля по умолчанию) if(finger.verifyPassword()){Serial.println("Found sensor!");} // Если модуль отпечатков обнаружен, выводим сообщение "сенсор обнаружен" else{Serial.println("Did not find sensor :("); while(1); } // Если модуль отпечатков не обнаружен, выводим сообщение "сенсор не обнаружен" и входим в бесконечный цикл: while(1); } void loop(){ Serial.println("----------------------------------"); Serial.print ("Please enter ID number You want save ... "); // Вывод сообщения "Пожалуйста введите идентификационный номер который Вы хотите сохранить" id = readnumber(); // Ожидание получения цифры, введённой с COM-порта Serial.print("Ok! ID="); Serial.println(id); // Вывод сообщения "Введён идентификационный номер" цифра while(!getFingerprintEnroll()); } // функция возвращает номер, введённый с COM-порта uint8_t readnumber(void){ int num = -1; // Переменная с номером, который требуется вернуть while(num<0){ // Вход в цикл, пока переменная num не станет >= 0 while(!Serial.available()); // Ожидание пока в буфере COM-порта нет появятся данные while(Serial.available()){ // Цикл пока в буфере COM-порта не закончатся данные char c = Serial.read(); // Присваиваем очередной символ из COM-порта в переменную c if(isdigit(c)){ // Если значение переменной с - цифра, то ... if(num<0){num=0;}else{num *= 10;} // Увеличиваем значение num на один порядок num += c - '0'; // Прибавляем к значению num цифру из переменной c } delay(5); // Задержка на 5мс, чтоб в буфер COM-порта успели догрузиться следующие символы (если таковые имеются) } } return num; // Возвращение введённого числа } uint8_t getFingerprintEnroll(){ int p; // Переменная для получения результатов выполнения функций //Загрузка первого изображения отпечатка пальца p = -1; Serial.print ("Please put your finger on the scanner ."); // Вывод сообщения "Пожалуйста положите Ваш палец на сканер" while(p != FINGERPRINT_OK){ // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_OK (корректная загрузка изображения) p = finger.getImage(); // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p switch(p){ // Проверка ответа ... case FINGERPRINT_OK: Serial.println(" Ok!"); break; // Изображение отпечатка пальца корректно загрузилось case FINGERPRINT_NOFINGER: Serial.print ("."); break; // Сканер не обнаружил отпечаток пальца case FINGERPRINT_PACKETRECIEVEERR: Serial.println(" Communication error :(\nPlease try again ");break; // Ошибка соединения case FINGERPRINT_IMAGEFAIL: Serial.println(" Imaging error :(\nPlease try again "); break; // Ошибка изображения default: Serial.println(" Unknown error :(\nPlease try again "); break; // Неизвестная ошибка } } //Конвертирование изображения первого отпечатка пальца p = finger.image2Tz(1); Serial.print ("Image converting: "); // Конвертируем первое изображение и возвращаем результат выполнения данной операции в переменную p switch(p){ // Проверка ответа ... case FINGERPRINT_OK: Serial.println("Ok!"); break; // Изображение сконвертировано case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy :("); return p; // Изображение слишком нечеткое case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error :("); return p; // Ошибка соединения case FINGERPRINT_FEATUREFAIL: Serial.println("No fingerprint on image :("); return p; // Ошибка конвертирования case FINGERPRINT_INVALIDIMAGE: Serial.println("No fingerprint on image :("); return p; // Ошибка изображения default: Serial.println("Unknown error :("); return p; // Неизвестная ошибка } //Просим убрать палец от сканера p = 0; Serial.print ("Please remove your finger from the scanner ..."); // Вывод сообщения "Пожалуйста уберите Ваш палец со сканера" delay(2000); while(p != FINGERPRINT_NOFINGER){ // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_NOFINGER (сканер не обнаружил отпечаток пальца) p=finger.getImage(); // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p } Serial.println(" Ok!"); //Загрузка второго изображения отпечатка пальца p = -1; Serial.print ("Place same finger again ."); // Вывод сообщения "Пожалуйста положите тот же палец еще раз" while(p != FINGERPRINT_OK){ // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_OK (корректная загрузка изображения) p = finger.getImage(); // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p switch(p){ // Проверка ответа ... case FINGERPRINT_OK: Serial.println(" Ok!"); break; // Изображение отпечатка пальца корректно загрузилось case FINGERPRINT_NOFINGER: Serial.print ("."); break; // Сканер не обнаружил отпечаток пальца case FINGERPRINT_PACKETRECIEVEERR: Serial.println(" Communication error :(\nPlease try again ");break; // Ошибка соединения case FINGERPRINT_IMAGEFAIL: Serial.println(" Imaging error :(\nPlease try again "); break; // Ошибка изображения default: Serial.println(" Unknown error :(\nPlease try again "); break; // Неизвестная ошибка } } //Конвертирование изображения второго отпечатка пальца p = finger.image2Tz(2); Serial.print ("Image converting: "); // Конвертируем второе изображение и возвращаем результат выполнения данной операции в переменную p switch(p){ // Проверка ответа ... case FINGERPRINT_OK: Serial.println("Ok!"); break; // Изображение сконвертировано case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy :("); return p; // Изображение слишком нечеткое case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error :("); return p; // Ошибка соединения case FINGERPRINT_FEATUREFAIL: Serial.println("No fingerprint on image :("); return p; // Ошибка конвертирования case FINGERPRINT_INVALIDIMAGE: Serial.println("No fingerprint on image :("); return p; // Ошибка изображения default: Serial.println("Unknown error :("); return p; // Неизвестная ошибка } //Создание модели (шаблона) отпечатка пальца, по двум изображениям p = finger.createModel(); Serial.print ("Creating model: "); // Создание модели (шаблона) отпечатка пальца, по двум изображениям if(p == FINGERPRINT_OK ){ Serial.println("Ok!"); }else // Модель (шаблон) отпечатка пальца создана if(p == FINGERPRINT_PACKETRECIEVEERR){ Serial.println("Communication error :("); return p;}else // Ошибка соединения if(p == FINGERPRINT_ENROLLMISMATCH ){ Serial.println("Fingerprints did not match :("); return p;}else // Отпечатки пальцев не совпадают { Serial.println("Unknown error :("); return p;} // Неизвестная ошибка //Сохранение, ранее созданной, модели (шаблона) отпечатка пальца, под определённым ранее, идентификационным номером p = finger.storeModel(id); Serial.print ("Saving model in ID="); Serial.print(id); Serial.print(": ");// Сохранение модели (шаблона) отпечатка пальца, по двум изображениям if(p == FINGERPRINT_OK ){ Serial.println("Ok!"); }else // Модель (шаблон) отпечатка пальца сохранена if(p == FINGERPRINT_PACKETRECIEVEERR){ Serial.println("Communication error"); return p;}else // Ошибка соединения if(p == FINGERPRINT_BADLOCATION ){ Serial.println("Could not store in that location"); return p;}else // Не удалось сохранить в этом месте if(p == FINGERPRINT_FLASHERR ){ Serial.println("Error writing to flash"); return p;}else // Ошибка записи в flash память { Serial.println("Unknown error"); return p;} // Неизвестная ошибка }
Загрузите скетч в arduino uno, откройте монитор последовательного порта.
Вы увидите следующие строки:
Scan sensor...
Found sensor!
----------------------------------
Please enter ID number You want save ...
Введите в монитор последовательного порта число (ID номер под которым требуется сохранить новый отпечаток пальца) и нажмите Enter. На мониторе отобразится надпись:
Please put your finger on the scanner ...
Приложите палец к сканеру модуля, после того как сканер считает изображение Вашего отпечатка пальца, на мониторе появятся еще две строки:
Image converting: Ok!
Please remove your finger from the scanner ...
Уберите палец от сканера, на мониторе появится надпись:
Place same finger again ...
Приложите тот же палец к сканеру модуля еще раз, на мониторе появятся следующие строки:
Image converting: Ok!
Creating model: Ok!
Saving model in ID=0: Ok!
Теперь отпечаток Вашего пальца сохранён в базе отпечатков модуля и будет участвовать в сравнении.
Если вместо Ok! появится надпись Error, значит первый отпечаток не соответствует второму, или плохо отсканирован, или пропало соединение и т.д., см комментарии к каждой ошибке.
Если, во второй строке, вместо надписи Found sensor!, будет надпись Did not find sensor, значит Вы неправильно подключили модуль.
Обсуждение