Общие сведения:
Модуль отпечатков пальцев 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, значит Вы неправильно подключили модуль.

Обсуждение