HUM: FINGERPRINT SENSOR

Fingerprint sensor

You are a beginner with Dasduino. Or electronics? A specific module caught your eye, but you do not know how to use it? Do not worry, HUM is here for you! How to Use Module (HUM) is a blog tutorials series by soldered where you will find all you need in order to begin working with your favorite module. Tutorials include technical characteristics, work principles, instructions on how to connect the module with Dasduino and the basic code. Everything else is left to your imagination.

INTRODUCTION

In this tutorial, we will learn about the fingerprint sensor which is used in numerous applications, usually when a specific user needs to log in. As we already know, most smartphones have fingerprint unlocking, and many rooms are secured from an unauthorized entry using this sensor. The sensor is used in various security systems because it uses a fingerprint that is unique to everyone. In order to protect something important, from now on, you will be able to do it with a very high level of security using this sensor. To find out how, let’s start with learning a bit more about the sensor itself.

HOW DOES IT WORK?

In order for us to do something useful with the fingerprint sensor, we will first get acquainted with the way this sensor works. The sensor is optical, which means that it recognizes a fingerprint with the help of light, and in addition to the optical, it also has a capacitive sensor (used on mobile devices) and an ultrasonic one. The optical fingerprint sensor is an older technology and therefore simpler than the others, but precisely because of its simplicity of operation, it is great for various projects.
It is known that on the finger we have protrusions and indentations that are unique to each person and that is the fingerprint. To detect indentations and protrusions, the fingerprint sensor uses LEDs as lighting and a photodetector to receive reflected light rays. Of course, the sensor does not only have one diode and a photodetector but inside it, there are numerous photodetectors placed in the matrix, as well as a prism and a lens so that it can receive reflected light more accurately. In the image, we see the principle on which the sensor works and which has been previously explained.

Of course, within the sensor, we also have a controller that controls the diodes and photodetectors and analyzes the received signals. In order to be able to recognize the fingerprint, the controller has a database of stored fingerprints in its memory and compares them with the current fingerprint, and if it is stored in the database, it signifies to which extent they match.

 

HOW TO CONNECT?

The sensor uses serial communication to exchange data with the microcontroller and it is easy to connect. The sensor has a 6-pin cable, but only 4 pins are used for connection (2 for power supply and 2 for communication). We connect the RX pin to D3, and we connect the TX from the sensor to D2 on the Dasduino. For the power supply, we use 3.3V as indicated on the sensor.
For easier sensor connection, we use an adapter that switches pins from the PicoBlade header to the standard header, so that we can connect it to the microcontroller. The adapter can be found on the link.

ARDUINO CODE

To work with the sensor, it is necessary to download and install the library from the link. Of course, if you don’t know how to install the library there is a tutorial explaining the installation process.
In the part where the mode of operation is explained, you will find mentioned the base of fingerprints that are stored inside of the sensor’s memory. Of course, when we buy a brand new sensor, there are no fingerprints stored, so it is necessary to add new fingerprints, and we can have up to 200 stored fingerprints, which is a lot.
To save the new fingerprint to the database, it is necessary to transfer the given code to the microcontroller, open the Serial monitor, and follow the instructions that are displayed. Each fingerprint is saved under the identification number that we choose when saving the fingerprint to the database, and it is necessary to remember it because the sensor will return that number when we scan a certain fingerprint that is in the database.

//including the library to work with the fingerprint sensor
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//we connect (RX, TX)( D2(RX) from the Croduino to the TX sensor, and D3(TX) from the Croduino to the RX sensor
//Adafruit_Fingerprint library constructor, to which we transmit the Serial port on which we have connected the sensor (in our case, it is the Software serial port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
//variable to which we save the ID under which the user wants to save a new fingerprint
uint8_t id;
void setup()
{
 Serial.begin(9600);//serial communication initialization (speed 9600 baud) for displaying messages on the Serial monitor
 delay(100);//100 ms pause
 Serial.println("\Entering the new fingerprint");
 
 finger.begin(57600);//sensor communication initialization
 
 //checking the sensor's password which is set in the library (can be changed in the code)
 //if the password is correct (if we haven't changed it, it will be correct), displaying that the sensor is found (if we have checked the password, it means that the communication with the sensor is successful)
 if (finger.verifyPassword()) {
 Serial.println("Fingerprint sensor found!");
 } else {//if the password is incorrect or the sensor is not found, displaying a message on the Serial monitor, staying in the infinite while loop
 Serial.println("Fingerprint sensor not found");
 while (1) while (1) { delay(1); }
 }
}
//function that reads the number from the Serial monitor and returns the same number
uint8_t readnumber(void) {
 uint8_t num = 0;
 
 while (num == 0) {
 while (! Serial.available());
 num = Serial.parseInt();
 }
 return num;
}
void loop()
{
 Serial.println("\Ready for adding the fingerprint!");
 Serial.println("Enter the ID#(from 1 to 127) under which you want to save the new fingerprint...");
 id = readnumber();
 if (id == 0) {//if the entered number is 0, we return to the beginning, and request re-entering the number
 return;
 }
 Serial.print("Entering the ID #");
 Serial.println(id);
 //calling the function that enters a new fingerprint 
 while (! getFingerprintEnroll() );
}
uint8_t getFingerprintEnroll() {
 int p = -1;
 Serial.print("waiting for the new fingerprint with the ID #"); Serial.println(id);
 //until we get an accurate fingerprint, we repeat the process of imaging
 while (p != FINGERPRINT_OK) {
 p = finger.getImage();// taking the image from the fingerprint sensor and to the p variable, we save the return value
 //according to the p variable value, displaying the corresponding message of what the sensor has made, i.e. whether there was an error
 switch (p) {
 case FINGERPRINT_OK:
 Serial.println("Image done");
 break;
 case FINGERPRINT_NOFINGER:
 Serial.println(".");
 delay(100);//pause for the . not to be displayed constantly
 break;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Communication error");
 break;
 case FINGERPRINT_IMAGEFAIL:
 Serial.println("Image error");
 break;
 default:
 Serial.println("Unknown error");
 break;
 }
 }
 p = finger.image2Tz(1);//we convert the saved image to another format that can be stored in the memory
 switch (p) {
 //according to the p variable value, displaying whether the conversion was successful or there was an error
 case FINGERPRINT_OK:
 Serial.println("Image converted");
 break;
 case FINGERPRINT_IMAGEMESS:
 Serial.println("Image invalid");
 return p;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Communication error");
 return p;
 case FINGERPRINT_FEATUREFAIL:
 Serial.println("Impossible to find features of the fingerprint");
 return p;
 case FINGERPRINT_INVALIDIMAGE:
 Serial.println("Impossible to find features of the fingerprint");
 return p;
 default:
 Serial.println("Unknown error");
 return p;
 }
 //the user must remove his finger from the sensor and then place it back again in order to confirm the fingerprint
 Serial.println("Remove the finger from the sensor");
 delay(2000);
 p = 0;
 while (p != FINGERPRINT_NOFINGER) {
 p = finger.getImage();
 }
 Serial.print("ID "); Serial.println(id);
 p = -1;
 Serial.println("Place the same finger back to the sensor");
 //when the user places his finger back, we repeeat the imaging and conversion of the image, and display messages about whether there are errors like in the previous case
 while (p != FINGERPRINT_OK) {
 p = finger.getImage();
 switch (p) {
 case FINGERPRINT_OK:
 Serial.println("Image done");
 break;
 case FINGERPRINT_NOFINGER:
 Serial.print(".");
 delay(100);//pause for the . not to be displayed constantly
 break;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Communication error");
 break;
 case FINGERPRINT_IMAGEFAIL:
 Serial.println("Image error");
 break;
 default:
 Serial.println("Unknown error");
 break;
 }
 }
 p = finger.image2Tz(2);
 switch (p) {
 case FINGERPRINT_OK:
 Serial.println("Image converted");
 break;
 case FINGERPRINT_IMAGEMESS:
 Serial.println("Image invalid");
 return p;
 case FINGERPRINT_PACKETRECIEVEERR:
 Serial.println("Communication error");
 return p;
 case FINGERPRINT_FEATUREFAIL:
 Serial.println("Impossible to find features of the fingerprint");
 return p;
 case FINGERPRINT_INVALIDIMAGE:
 Serial.println("Impossible to find features of the fingerprint");
 return p;
 default:
 Serial.println("Unknown error");
 return p;
 }
 
 //for the user, displaying that image processing is done and that the fingerprint model is being made
 Serial.print("Making the model for #"); Serial.println(id);
 
 p = finger.createModel();//function we call for making the model of the fingerprint
 //checking the return value of the function, to know what has been made
 if (p == FINGERPRINT_OK) {
 Serial.println("Fingerprints match!");
 } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
 Serial.println("Communication error");
 return p;
 } else if (p == FINGERPRINT_ENROLLMISMATCH) {
 Serial.println("Fingerprints do not match!");
 return p;
 } else {
 Serial.println("Unknown error");
 return p;
 }
 //if the fingerprints match, we save the fingerprint model to the sensor's memory
 Serial.print("ID "); Serial.println(id);
 p = finger.storeModel(id);//function for saving the model to the sensor's memory which returns wheter saving was successful or not
 //displaying message depending on the return value of the saving function
 if (p == FINGERPRINT_OK) {
 Serial.println("Saved!\n");
 } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
 Serial.println("Communication error");
 return p;
 } else if (p == FINGERPRINT_BADLOCATION) {
 Serial.println("Impossible to save at this location (try another ID)");
 return p;
 } else if (p == FINGERPRINT_FLASHERR) {
 Serial.println("Error while saving to memory");
 return p;
 } else {
 Serial.println("Unknown error");
 return p;
 }
}

Now that we have the fingerprints in the database, let’s test how the sensor works, and for that, we need another code given in the example. In this code, when the sensor reads a fingerprint that is in the database, it returns the identification number that we assigned to a particular fingerprint when we were saving the fingerprints to the database.

//including the library to work with the fingerprint sensor
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//we connect (RX, TX)( D2(RX) from the Croduino to the TX sensor, and D3(TX) from the Croduino to the RX sensor
//Adafruit_Fingerprint library constructor, to which we transmit the Serial port on which we have connected the sensor (in our case, it is the Software serial port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
void setup()
{
 Serial.begin(9600);//serial communication initialization (speed 9600 baud) for displaying messages on the Serial monitor
 delay(100);//100 ms pause
 
 Serial.println("\nFingerprint sensor_reading");
 finger.begin(57600);//sensor communication initialization
 delay(5);
 //checking the sensor's password which is set in the library (can be changed in the code)
 //if the password is correct (if we haven't changed it, it will be correct), displaying that the sensor is found (if we have checked the password, it means that the communication with the sensor is successful)
 if (finger.verifyPassword()) {
 Serial.println("Fingerprint sensor found!");
 } else {//if the password is incorrect or the sensor is not found, displaying message on the Serial monitor, staying in the infinite while loop
 Serial.println("Fingerprint sensor not found");
 while (1) { delay(1); }
 }
 finger.getTemplateCount();//function for collecting data on the number of saved fingerprints
 //displaying colors of the saved fingerprints to the Serial monitor 
 Serial.print("Senzor ima "); Serial.print(finger.templateCount); Serial.println(" spremljenih otisaka");
 Serial.println("Place your finger for check...");
}
void loop()
{
 getFingerprintIDez();//function in which we read the fingerprint, if the finger is placed on the sensor
 delay(50);
}
//function in which we read the print and which returns -1 if there was an error or the ID of the fingerprint in case it matches with some of the saved fingerprints
int getFingerprintIDez() {
 uint8_t p = finger.getImage();
 if (p != FINGERPRINT_OK) return -1;
 p = finger.image2Tz();
 if (p != FINGERPRINT_OK) return -1;
 p = finger.fingerFastSearch();
 if (p != FINGERPRINT_OK) return -1;
 
 Serial.print("ID found #");
 Serial.print(finger.fingerID); //displaying the fingerprint ID
 Serial.print(" s pouzdanjem ");
 Serial.println(finger.confidence);//displaying how reliable the read fingerprint is in comparison to another from the database
 return finger.fingerID; //function returns the fingerprint ID
}

We will most likely have to remove a certain fingerprint from the database, and that is very easy to do with this sensor. It is necessary to transfer the given code to the microcontroller, open the Serial monitor, and then enter the ID of the fingerprint we want to remove and it will be removed.

//including the library to work with the fingerprint sensor
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//we connect (RX, TX)( D2(RX) from the Croduino to the TX sensor, and D3(TX) from the Croduino to the RX sensor
//Adafruit_Fingerprint library constructor, to which we transmit the Serial port on which we have connected the sensor (in our case, it is the Software serial port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
void setup()
{
 Serial.begin(9600);//serial communication initialization (speed 9600 baud) for displaying messages on the Serial monitor
 delay(100);//100 ms pause
 
 Serial.println("\nDeleting saved fingerprints");
 finger.begin(57600);//sensor communication initialization
//checking the sensor's password which is set in the library (can be changed in the code)
//if the password is correct (if we haven't changed it, it will be correct), displaying that the sensor is found (if we have checked the password, it means that the communication with the sensor is successful)
 if (finger.verifyPassword()) {
 Serial.println("Fingerprint sensor found!");
 } else {//if the password is incorrect or the sensor is not found, displaying message on the Serial monitor, staying in the infinite while loop
 Serial.println("Fingerprint sensor not found");
 while (1) while (1) { delay(1); }
 }
}
//function that reads the number from the Serial monitor and returns the same number
uint8_t readnumber(void) {
 uint8_t num = 0;
 
 while (num == 0) {
 while (! Serial.available());
 num = Serial.parseInt();
 }
 return num;
}
void loop()
{
 Serial.println("Enter the ID # of the fingerprint (from 1 to 127) you want to delete...");
 uint8_t id = readnumber();//to the id variable, we save the number that the readnumber function returns when it's reading the number from the Serial monitor
 if (id == 0) {//if the id is 0, return to the beginning and wait for entering the number again
 return;
 }
 Serial.print("Deleting the ID #");
 Serial.println(id);//displaying the ID that is to be deleted
 
 deleteFingerprint(id);//calling the function for fingerprint deletion
}
//function for deleting fingerprints
uint8_t deleteFingerprint(uint8_t id) {
 uint8_t p = -1;
 
 p = finger.deleteModel(id);//brišemo otisak s predanim ID brojem, a funkcija nam vraća rezultat brisanja
 //displaying a message about what has happened, depending on what the previous function has returned (successful deletion or error)
 if (p == FINGERPRINT_OK) {
 Serial.println("Deleted!");
 } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
 Serial.println("Communication error");
 return p;
 } else if (p == FINGERPRINT_BADLOCATION) {
 Serial.println("Impossible to delete at this location ");
 return p;
 } else if (p == FINGERPRINT_FLASHERR) {
 Serial.println("Error while writing in the memory");
 return p;
 } else {
 Serial.print("Unknown error: 0x"); Serial.println(p, HEX);
 return p;
 }
}

The last example of the code is used to delete the entire database of fingerprints if we no longer want to use the sensor, or it is necessary to delete all saved fingerprints for another reason. With this code, we can do it in a few steps.

//including the library to work with the fingerprint sensor
#include <Adafruit_Fingerprint.h>
SoftwareSerial mySerial(2, 3);//we connect (RX, TX)( D2(RX) from the Croduino to the TX sensor, and D3(TX) from the Croduino to the RX sensor
//Adafruit_Fingerprint library constructor, to which we transmit the Serial port on which we have connected the sensor (in our case, it is the Software serial port)
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
void setup()
{
 Serial.begin(9600);//serial communication initialization (speed 9600 baud) for displaying messages on the Serial monitor
 delay(100);//100 ms pause
 
 Serial.println("\n Deleting all saved fingerprints!");
 Serial.println("Press Y to continue.");
//waiting until the user enters Y to the Serial monitor
 while (1) {
 if (Serial.available() && (Serial.read() == 'Y')) {
 break;
 }
 }
 finger.begin(57600);//sensor communication initialization
 delay(5);
 //checking the sensor's password which is set in the library (can be changed in the code)
 //if the password is correct (if we haven't changed it, it will be correct), displaying that the sensor is found (if we have checked the password, it means that the communication with the sensor is successful)
 if (finger.verifyPassword()) {
 Serial.println("Fingerprint sensor found!");
 } else {//if the password is incorrect or the sensor is not found, displaying message on the Serial monitor, staying in the infinite while loop
 Serial.println("Fingerprint sensor not found");
 while (1) { delay(1); }
 }
 //function for deleting all sensor databases
 finger.emptyDatabase();
Serial.println("Fingerprints deleted!");
Serial.println("Database is empty");
}
void loop() {
}