Portable IoT Based Fingerprint Biometric Attendance System using NodeMCU
(Last Updated On: June 3, 2021)

Table of Contents:

Overview:

In this project, I will tell you how to build a Portable IoT based Fingerprint Biometric Attendance System using NodeMCU ESP8266 12E, 0.96” OLED Display & SFG R303a Fingerprint Sensor. The ESP8266 Wi-Fi Module will collect the fingerprint data from the multiple users and sends it over the internet to a website. The Enrolment of fingerprints is done on the server using any fingerprint sensor like R303, R305 or R307 that is available on the market and verification of the fingerprint will be done on the webserver while fingerprint templates are transmitted over the WiFi.

The website used in this project is developed using PHP, it has a database and records of attendance. By logging into the website, you can collect all the attendance records of each user including personal details as well as incoming & outgoing timing. The data can also be downloaded and exported to an excel sheet.

website_IoT Based Fingerprint Biometric Attendance SystemWebsite: a snapshot of Portable IoT Based Fingerprint Biometric Attendance System

The main drawback of conventional authentication technologies like RFID tags and authentication cards are can be transferred, if we use such type of methodologies users can easily manipulate the data,  biometric method of authentication is a prompt replacement for this. Biometrics such as fingerprints, Face Recognition, voice and ECG signals are unique human characters that cannot be tampered or replicated impossible to manipulate. This allow us to develop rugged real-time biometric system implementations.

Biometric Attendance systems are commonly used systems to mark the presence of students or employees in the schools and offices. This project has a wide scope in the modern era of schools, colleges, business organizations, offices where accurate attendance data is required. Biometric attendance system will make the process of taking very easy and reliable. Thus, by using the fingerprint sensor, the system will become more secure for both parties.

You can watch the following video tutorial for detailed information, or you can read the article written over here.

Required Components:

The following are the required components to proceed with IoT Based Biometric Fingerprint Attendance System. All the components can be purchased from Amazon. The purchase links are given below.
In this article, I am using SFG r303a module. Currently, this module is not in production. you can R305 or R307.

  1.  NodeMCU                             Buy from Amazon.
  2. R303/R305/R307 fingerprint sensor   Buy from Amazon (R303)/(R307)
  3. 0.96″ OLED display                  Buy from Amazon
  4. Li-Ion battery(18650)              Buy from Amazon
  5. TP4056 Li-Ion Battery charger       Buy from Amazon
  6. MT3608 Boost converter              Buy from Amazon 
  7. On/Off switch                       Buy from Amazon
  8. Breadboard                          Buy from Amazon
  9. Connecting wires                    Buy from Amazon

SFG R303 Fingerprint Identification Module

Introduction

This is a fingerprint sensor module with TTL UART interface for direct connections to microcontroller UART or to PC through MAX232 / USB-Serial adapter. The user can store the fingerprint data in the module and can configure it in 1:1 or 1: N mode for identifying the person.

The Fingerprint module can be directly interfaced with any microcontroller as well as Arduino Board. This optical biometric fingerprint reader with great features and can be embedded into a variety of end products like access control system, attendance system, safety deposit box, car door locking system.

Fingerprint sesnor

 

Operation Principle:

Fingerprint processing includes two parts: fingerprint enrollment and fingerprint matching (the matching can be 1:1 or 1:N).
When enrolling, the user needs to enter the finger two times. The system will process the two-time finger images, generate a template of the finger based on processing results and store the template. When matching, the user enters the finger through the optical sensor and system will generate a template of the finger and compare it with templates of the finger library. For 1:1 matching, the system will compare the live finger with specific template designated in the Module; for 1:N matching, or searching, the system will search the whole finger library for the matching finger. In both circumstances, system will return the matching result, success or failure.

Features

  1. Integrated image collecting and algorithm chip together, ALL-in-One
  2. The fingerprint reader can conduct secondary development, can be embedded into a variety of end products
  3. Low power consumption, low cost, small size, excellent performance
  4. Professional optical technology, precise module manufacturing techniques
  5. Good image processing capabilities can successfully capture image up to resolution 500 dpi

Specifications:

Specifications of Fingerprint sensor

For more information about SFG R303A Fingerprint sensor, check out this datasheet.

0.96″ I2C OLED Display:

This is a 0.96 inch blue OLED display module. The display module can be interfaced with any microcontroller using SPI/IIC protocols. It is having a resolution of 128×64. The package includes display board, display,4 pin male header pre-soldered to board.

OLED (Organic Light-Emitting Diode) is a self light-emitting technology composed of a thin, multi-layered organic film placed between an anode and cathode. In contrast to LCD technology, OLED does not require a backlight. OLED possesses high application potential for virtually all types of displays and is regarded as the ultimate technology for the next generation of flat-panel displays.

128x64-Blue-I2C-OLED-Display

 

Specifications:

  • OLED Driver IC: SSD1306
  • Resolution: 128 x 64
  • Visual Angle: >160°
  • Input Voltage: 3.3V ~ 6V
  • Compatible I/O Level: 3.3V, 5V
  • Mini Size: 2.7 x 2.8cm
  • Only Need 2 I/O Port to Control
  • Fully Compatible with Arduino
  • Working temperature: -30°C ~ 70°C
  • Module volume ( generous ): 27.0 x 27.0 x 4.1mm
  • Factory configured for SPI protocol (can be easily changed to IIC)

For more information about the SSD1306 OLED Display, check out this datasheet.

The Total process includes the following steps:
  1. Setting up the website
  2. Circuit Diagram and hardware connections
  3. Source code development
  4. Registration of the users.

Setting up the website:

The website used in this project can be configured as global/Local. You need to have a unique domain name and to set up a global website. if you have a website and a server you can simply download the biometricattendance.zip file and copy to the cPanel/website file manager and modify the connectDb.php and install.php files with your website credentials. but having website domain and hosting is will cost you more.

In case if you don’t wanna spend money on website management, then you can configure your website as local and use your own computer as a server to store the data locally in localhost.

For that, you can use any local server provider Xampp or Wamp. I have given both download links below you can choose either.

Download and install Xampp from the link here: Download XAMPP

Download and install Xampp from the link here: Download Wamp

I will use Xampp to demonstrate further process. Choose an appropriate file for your operating system. Xampp is available for Windows, Linux Mac.

Download Xampp

Once the file downloaded succesfully install the Xampp, the installation process is very easy, it is like normal software installation only.

After successful installation, simply download the biometricattendance.zip file and copy to the folder C:\xampp\htdocs in your computer. This folder is the location where all your website data will store.

Biometric attendance system

The website configuration process is a little bit longer, which is explained in the video. You can follow the video to completely set up the website.

Circuit Diagram: Portable IoT based Fingerprint Biometric Attendance System

The following circuit diagram shows how an OLED Display & Fingerprint Sensor is interfaced to NodeMCU ESP8266 12E Board.

Circuit Diagram_IoT Based Fingerprint Biometric Attendance System

The I2C pins of OLED Display, i.e SDA & SCL is connected to NodeMCU D1 & D2 pins respectively. Similarly, the fingerprint sensor is also connected to UART pins D5 & D6. The fingerprint sensor Tx and Rx wires color may vary. So connect it by finding appropriate color wires else the module won’t be detected by NodeMCU.

The R303a fingerprint sensor is supplied with 5V through Vin pins of NodeMCU. In my case, the sensor didn’t work at 3.3V. because sensor operating voltage is 3.6v to 6v Similarly, connect OLED Vcc pin to 3.3V of NodeMCU.

 

Circuit Diagram_IoT Based Fingerprint Biometric Attendance System - Copy

 

Source Code/Program 

The source code for the Portable IoT Based Fingerprint Biometric Attendance System using NodeMCU here.
In this source code, you need to do two modifications according to your WiFi Network connection and PC IP.

You have to make sure that the WiFi username and password are provided which is available in the range.

/* Set these to your desired credentials. */
const char *ssid = "Electronics_Innovation"; //ENTER YOUR WIFI SETTINGS
const char *password = "subscribe";

Also, change the IP Address if you are using Xampp or change the website domain name if you are using the global website as changed below.

String link = "http://192.168.43.205/biometricattendance/getdata.php"; //computer IP or the server domain

Add the following libraries via library manager or simply add the following zip files to Arduino libraries folder:
1. OLED GFX Library: Download
2. SSD1306 Library: Download
3. Adafruit Fingerprint Sensor Library: Download

/*
Developed by Electronics Innovation
Project: Portable IoT based Fingerprint Biometric Attendance System with NodeMCU.
Electronics Innovation - www.electronicsinnovation.com

GitHub - https://github.com/VeeruSubbuAmi
YouTube - http://bit.ly/Electronics_Innovation

Upload date: 18 September 2019

Libraries:
Adafruit GFX:- https://github.com/adafruit/Adafruit-GFX-Library
Adafruit SSD1306:- https://github.com/adafruit/Adafruit_SSD1306
Adafruit-Fingerprint-Sensor-Library:- https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library

This sketch is developed to capture fingerprint data to compare the existing data and mark attendance on the server over the Internet.

Note: 1)Connect the circuit as shown in the circuit diagram.
2) Download and install all the required libraries.
All the Links are given above.
*/
//*******************************libraries********************************
#include <SPI.h>
#include <Wire.h>
#include <ESP8266WiFi.h> // If you face any problem with this library vist here:
#include <SoftwareSerial.h> // https://youtu.be/oq3_xy2rCyk
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <Adafruit_GFX.h> //Library link:https://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h> //Library link:https://github.com/adafruit/Adafruit_SSD1306
#include <Adafruit_Fingerprint.h> //Library link:https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library
//************************************************************************
//Fingerprint scanner Pins
#define Finger_Rx 14 //D5
#define Finger_Tx 12 //D6
// Declaration for SSD1306 display connected using software I2C
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 0 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//************************************************************************
SoftwareSerial mySerial(Finger_Rx, Finger_Tx);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
//************************************************************************
/* Set these to your desired credentials. */
const char *ssid = "Electronics_Innovation"; //ENTER YOUR WIFI SETTINGS
const char *password = "subscribe";
//************************************************************************
String postData ; // post array that will be send to the website
String link = "http://192.168.43.205/biometricattendance/getdata.php"; //computer IP or the server domain
int FingerID = 0; // The Fingerprint ID from the scanner
uint8_t id;
//*************************Biometric Icons*********************************
#define Wifi_start_width 54
#define Wifi_start_height 49
const uint8_t PROGMEM Wifi_start_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x1f,0xf0,0x00,0x00,0x00
,0x00,0x03,0xff,0xff,0x80,0x00,0x00
,0x00,0x1f,0xf0,0x1f,0xf0,0x00,0x00
,0x00,0x7e,0x00,0x00,0xfc,0x00,0x00
,0x01,0xf0,0x00,0x00,0x1f,0x00,0x00
,0x03,0xc0,0x00,0x00,0x07,0xc0,0x00
,0x0f,0x00,0x00,0x00,0x01,0xe0,0x00
,0x1c,0x00,0x00,0x00,0x00,0x70,0x00
,0x38,0x00,0x07,0xc0,0x00,0x38,0x00
,0x70,0x00,0xff,0xfe,0x00,0x1e,0x00
,0xe0,0x03,0xfc,0x7f,0xc0,0x0e,0x00
,0x00,0x1f,0x80,0x03,0xf0,0x00,0x00
,0x00,0x3c,0x00,0x00,0x78,0x00,0x00
,0x00,0xf0,0x00,0x00,0x1c,0x00,0x00
,0x01,0xe0,0x00,0x00,0x0c,0x00,0x00
,0x03,0x80,0x00,0x00,0x00,0x00,0x00
,0x03,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x3f,0xf8,0x07,0x1e,0x00
,0x00,0x00,0xff,0xfe,0x1f,0xbf,0x80
,0x00,0x03,0xe0,0x04,0x7f,0xff,0xc0
,0x00,0x07,0x80,0x00,0xff,0xff,0xe0
,0x00,0x0e,0x00,0x00,0xff,0xff,0xe0
,0x00,0x0c,0x00,0x00,0x7f,0xff,0xc0
,0x00,0x00,0x00,0x00,0xfe,0x07,0xe0
,0x00,0x00,0x00,0x03,0xf8,0x03,0xf8
,0x00,0x00,0x07,0xe7,0xf9,0xf1,0xfc
,0x00,0x00,0x1f,0xe7,0xf1,0xf9,0xfc
,0x00,0x00,0x1f,0xe7,0xf3,0xf9,0xfc
,0x00,0x00,0x3f,0xe7,0xf3,0xf9,0xfc
,0x00,0x00,0x3f,0xe7,0xf1,0xf1,0xfc
,0x00,0x00,0x3f,0xe3,0xf8,0xe3,0xfc
,0x00,0x00,0x3f,0xf3,0xfc,0x07,0xf8
,0x00,0x00,0x1f,0xf0,0x7f,0x0f,0xc0
,0x00,0x00,0x0f,0xe0,0x7f,0xff,0xe0
,0x00,0x00,0x07,0xc0,0xff,0xff,0xe0
,0x00,0x00,0x00,0x00,0x7f,0xff,0xe0
,0x00,0x00,0x00,0x00,0x3f,0xff,0x80
,0x00,0x00,0x00,0x00,0x1f,0xbf,0x00
,0x00,0x00,0x00,0x00,0x03,0x18,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
#define Wifi_connected_width 63
#define Wifi_connected_height 49
const uint8_t PROGMEM Wifi_connected_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x03,0xff,0xff,0x80,0x00,0x00
,0x00,0x00,0x3f,0xff,0xff,0xf8,0x00,0x00
,0x00,0x01,0xff,0xff,0xff,0xff,0x00,0x00
,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0x00
,0x00,0x3f,0xff,0xc0,0x07,0xff,0xf8,0x00
,0x00,0xff,0xf8,0x00,0x00,0x3f,0xfe,0x00
,0x03,0xff,0x80,0x00,0x00,0x03,0xff,0x80
,0x07,0xfe,0x00,0x00,0x00,0x00,0xff,0xc0
,0x1f,0xf8,0x00,0x00,0x00,0x00,0x3f,0xf0
,0x3f,0xe0,0x01,0xff,0xff,0x00,0x0f,0xf8
,0x7f,0x80,0x0f,0xff,0xff,0xe0,0x03,0xfc
,0xff,0x00,0x7f,0xff,0xff,0xfc,0x01,0xfe
,0xfc,0x01,0xff,0xff,0xff,0xff,0x00,0x7e
,0x78,0x07,0xff,0xc0,0x07,0xff,0xc0,0x3c
,0x00,0x0f,0xfc,0x00,0x00,0x7f,0xe0,0x00
,0x00,0x1f,0xf0,0x00,0x00,0x1f,0xf0,0x00
,0x00,0x3f,0xc0,0x00,0x00,0x07,0xf8,0x00
,0x00,0x7f,0x00,0x01,0x00,0x01,0xfc,0x00
,0x00,0x7e,0x00,0x7f,0xfc,0x00,0xfc,0x00
,0x00,0x3c,0x03,0xff,0xff,0x80,0x78,0x00
,0x00,0x00,0x07,0xff,0xff,0xc0,0x00,0x00
,0x00,0x00,0x1f,0xff,0xff,0xf0,0x00,0x00
,0x00,0x00,0x3f,0xf0,0x1f,0xf8,0x00,0x00
,0x00,0x00,0x3f,0x80,0x03,0xf8,0x00,0x00
,0x00,0x00,0x3f,0x00,0x01,0xf8,0x00,0x00
,0x00,0x00,0x1c,0x00,0x00,0x70,0x00,0x00
,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x0f,0xe0,0x00,0x00,0x00
,0x00,0x00,0x00,0x1f,0xf0,0x00,0x00,0x00
,0x00,0x00,0x00,0x3f,0xf8,0x00,0x00,0x00
,0x00,0x00,0x00,0x3f,0xf8,0x00,0x00,0x00
,0x00,0x00,0x00,0x3f,0xf8,0x00,0x00,0x00
,0x00,0x00,0x00,0x3f,0xf8,0x00,0x00,0x00
,0x00,0x00,0x00,0x1f,0xf0,0x00,0x00,0x00
,0x00,0x00,0x00,0x0f,0xe0,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
#define FinPr_start_width 64
#define FinPr_start_height 64
const uint8_t PROGMEM FinPr_start_bits[] = {
0x00,0x00,0x00,0x1f,0xe0,0x00,0x00,0x00
,0x00,0x00,0x01,0xff,0xfe,0x00,0x00,0x00
,0x00,0x00,0x03,0xff,0xff,0x80,0x00,0x00
,0x00,0x00,0x0f,0xc0,0x0f,0xe0,0x00,0x00
,0x00,0x00,0x1f,0x00,0x01,0xf8,0x00,0x00
,0x00,0x00,0x3c,0x00,0x00,0x7c,0x00,0x00
,0x00,0x00,0x78,0x00,0x00,0x3e,0x00,0x00
,0x00,0x00,0xf0,0x3f,0xf8,0x0f,0x00,0x00
,0x00,0x01,0xe0,0xff,0xfe,0x07,0x80,0x00
,0x00,0x03,0xc3,0xff,0xff,0x03,0x80,0x00
,0x00,0x03,0x87,0xc0,0x07,0xc3,0xc0,0x00
,0x00,0x07,0x0f,0x00,0x03,0xe1,0xc0,0x00
,0x00,0x0f,0x0e,0x00,0x00,0xe0,0xe0,0x00
,0x00,0x0e,0x1c,0x00,0x00,0xf0,0xe0,0x00
,0x00,0x0c,0x3c,0x1f,0xe0,0x70,0xe0,0x00
,0x00,0x00,0x38,0x3f,0xf0,0x38,0x70,0x00
,0x00,0x00,0x78,0x78,0xf8,0x38,0x70,0x00
,0x00,0x00,0x70,0x70,0x3c,0x18,0x70,0x00
,0x00,0x00,0xe0,0xe0,0x1e,0x1c,0x70,0x00
,0x00,0x03,0xe1,0xe0,0x0e,0x1c,0x70,0x00
,0x00,0x0f,0xc1,0xc3,0x0e,0x1c,0x70,0x00
,0x00,0x3f,0x03,0xc3,0x8e,0x1c,0x70,0x00
,0x00,0x3e,0x03,0x87,0x0e,0x1c,0x70,0x00
,0x00,0x30,0x07,0x07,0x0e,0x18,0xe0,0x00
,0x00,0x00,0x0e,0x0e,0x0e,0x38,0xe0,0x00
,0x00,0x00,0x3e,0x1e,0x1e,0x38,0xe0,0x00
,0x00,0x00,0xf8,0x1c,0x1c,0x38,0xe0,0x00
,0x00,0x03,0xf0,0x38,0x3c,0x38,0xe0,0x00
,0x00,0x3f,0xc0,0xf8,0x78,0x38,0xe0,0x00
,0x00,0x7f,0x01,0xf0,0x70,0x38,0xf0,0x00
,0x00,0x78,0x03,0xe0,0xe0,0x38,0x70,0x00
,0x00,0x00,0x0f,0x81,0xe0,0x38,0x7c,0x00
,0x00,0x00,0x3f,0x03,0xc0,0x38,0x3e,0x00
,0x00,0x00,0xfc,0x0f,0x80,0x38,0x1e,0x00
,0x00,0x07,0xf0,0x1f,0x1c,0x1c,0x04,0x00
,0x00,0x3f,0xc0,0x3e,0x3f,0x1e,0x00,0x00
,0x00,0x7f,0x00,0xf8,0x7f,0x0f,0x00,0x00
,0x00,0x38,0x01,0xf0,0xf7,0x07,0xc0,0x00
,0x00,0x00,0x07,0xe1,0xe3,0x83,0xf8,0x00
,0x00,0x00,0x3f,0x87,0xc3,0xc0,0xfc,0x00
,0x00,0x01,0xfe,0x0f,0x81,0xe0,0x3c,0x00
,0x00,0x0f,0xf8,0x1f,0x00,0xf0,0x00,0x00
,0x00,0x1f,0xc0,0x7c,0x00,0x7c,0x00,0x00
,0x00,0x1e,0x01,0xf8,0x00,0x3f,0x00,0x00
,0x00,0x00,0x07,0xe0,0x78,0x0f,0xc0,0x00
,0x00,0x00,0x3f,0x81,0xfe,0x07,0xf0,0x00
,0x00,0x01,0xfe,0x07,0xff,0x01,0xf0,0x00
,0x00,0x07,0xf8,0x0f,0x87,0x80,0x30,0x00
,0x00,0x07,0xc0,0x3f,0x03,0xe0,0x00,0x00
,0x00,0x06,0x00,0xfc,0x01,0xf8,0x00,0x00
,0x00,0x00,0x03,0xf0,0x00,0x7e,0x00,0x00
,0x00,0x00,0x0f,0xc0,0x00,0x3f,0x80,0x00
,0x00,0x00,0x7f,0x00,0xf8,0x0f,0x80,0x00
,0x00,0x00,0xfc,0x03,0xfe,0x01,0x80,0x00
,0x00,0x00,0xf0,0x1f,0xff,0x80,0x00,0x00
,0x00,0x00,0x00,0x7f,0x07,0xe0,0x00,0x00
,0x00,0x00,0x00,0xfc,0x03,0xf8,0x00,0x00
,0x00,0x00,0x03,0xf0,0x00,0x78,0x00,0x00
,0x00,0x00,0x0f,0xc0,0x00,0x18,0x00,0x00
,0x00,0x00,0x0f,0x01,0xf8,0x00,0x00,0x00
,0x00,0x00,0x00,0x07,0xfe,0x00,0x00,0x00
,0x00,0x00,0x00,0x1f,0xfe,0x00,0x00,0x00
,0x00,0x00,0x00,0x1e,0x0e,0x00,0x00,0x00
,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00
};
//---------------------------------------------------------------
#define FinPr_valid_width 64
#define FinPr_valid_height 64
const uint8_t PROGMEM FinPr_valid_bits[] = {
0x00,0x00,0x03,0xfe,0x00,0x00,0x00,0x00
,0x00,0x00,0x1f,0xff,0xe0,0x00,0x00,0x00
,0x00,0x00,0x7f,0xff,0xf8,0x00,0x00,0x00
,0x00,0x00,0xfc,0x00,0xfe,0x00,0x00,0x00
,0x00,0x03,0xe0,0x00,0x1f,0x00,0x00,0x00
,0x00,0x07,0xc0,0x00,0x07,0x80,0x00,0x00
,0x00,0x0f,0x80,0x00,0x03,0xe0,0x00,0x00
,0x00,0x0e,0x03,0xff,0x01,0xe0,0x00,0x00
,0x00,0x1c,0x1f,0xff,0xe0,0xf0,0x00,0x00
,0x00,0x3c,0x3f,0xff,0xf0,0x78,0x00,0x00
,0x00,0x78,0x7c,0x00,0xf8,0x3c,0x00,0x00
,0x00,0x70,0xf0,0x00,0x3c,0x1c,0x00,0x00
,0x00,0xe1,0xe0,0x00,0x1e,0x1c,0x00,0x00
,0x00,0xe1,0xc0,0x00,0x0f,0x0e,0x00,0x00
,0x00,0xc3,0x81,0xfc,0x07,0x0e,0x00,0x00
,0x00,0x03,0x83,0xff,0x07,0x8e,0x00,0x00
,0x00,0x07,0x07,0x8f,0x83,0x87,0x00,0x00
,0x00,0x0f,0x0f,0x03,0xc3,0x87,0x00,0x00
,0x00,0x1e,0x0e,0x01,0xc3,0x87,0x00,0x00
,0x00,0x3c,0x1c,0x00,0xe1,0x87,0x00,0x00
,0x00,0xf8,0x1c,0x30,0xe1,0x87,0x00,0x00
,0x07,0xf0,0x38,0x70,0xe1,0x86,0x00,0x00
,0x07,0xc0,0x78,0x70,0xe3,0x8e,0x00,0x00
,0x02,0x00,0xf0,0xf0,0xe3,0x8e,0x00,0x00
,0x00,0x01,0xe0,0xe0,0xe3,0x8e,0x00,0x00
,0x00,0x03,0xc1,0xe1,0xc3,0x8e,0x00,0x00
,0x00,0x0f,0x83,0xc3,0xc3,0x8e,0x00,0x00
,0x00,0x7f,0x07,0x83,0x83,0x0e,0x00,0x00
,0x07,0xfc,0x0f,0x07,0x83,0x0e,0x00,0x00
,0x07,0xf0,0x1e,0x0f,0x03,0x0e,0x00,0x00
,0x07,0x80,0x7c,0x1e,0x03,0x07,0x00,0x00
,0x00,0x00,0xf8,0x3c,0x03,0x87,0x80,0x00
,0x00,0x03,0xf0,0x78,0x03,0x83,0xc0,0x00
,0x00,0x1f,0xc0,0xf0,0x02,0x00,0x00,0x00
,0x00,0xff,0x01,0xe1,0xc0,0x0c,0x00,0x00
,0x07,0xfc,0x03,0xc3,0xe1,0xff,0xc0,0x00
,0x07,0xe0,0x0f,0x87,0xc7,0xff,0xf0,0x00
,0x07,0x00,0x3f,0x0f,0x0f,0xff,0xfc,0x00
,0x00,0x00,0x7c,0x3e,0x3f,0xff,0xfe,0x00
,0x00,0x03,0xf8,0x7c,0x3f,0xff,0xff,0x00
,0x00,0x1f,0xe0,0xf0,0x7f,0xff,0xff,0x80
,0x00,0xff,0x83,0xe0,0xff,0xff,0xff,0x80
,0x01,0xfc,0x07,0xc1,0xff,0xff,0xe3,0xc0
,0x01,0xe0,0x1f,0x01,0xff,0xff,0xc3,0xc0
,0x00,0x00,0xfe,0x01,0xff,0xff,0x87,0xe0
,0x00,0x03,0xf8,0x13,0xff,0xff,0x0f,0xe0
,0x00,0x1f,0xe0,0x73,0xff,0xfe,0x1f,0xe0
,0x00,0x7f,0x81,0xf3,0xff,0xfc,0x1f,0xe0
,0x00,0xfc,0x03,0xe3,0xef,0xf8,0x3f,0xe0
,0x00,0x60,0x0f,0xc3,0xc7,0xf0,0x7f,0xe0
,0x00,0x00,0x3f,0x03,0xc3,0xe0,0xff,0xe0
,0x00,0x00,0xfc,0x03,0xc1,0xc1,0xff,0xe0
,0x00,0x07,0xf0,0x13,0xe0,0x83,0xff,0xe0
,0x00,0x0f,0xc0,0x7b,0xf8,0x07,0xff,0xe0
,0x00,0x0f,0x01,0xf9,0xfc,0x0f,0xff,0xc0
,0x00,0x00,0x07,0xf1,0xfe,0x1f,0xff,0xc0
,0x00,0x00,0x1f,0xc0,0xff,0x3f,0xff,0x80
,0x00,0x00,0x7e,0x00,0xff,0xff,0xff,0x80
,0x00,0x00,0xfc,0x00,0x7f,0xff,0xff,0x00
,0x00,0x00,0xf0,0x1f,0x3f,0xff,0xfe,0x00
,0x00,0x00,0x00,0x7f,0x1f,0xff,0xfc,0x00
,0x00,0x00,0x01,0xff,0x8f,0xff,0xf8,0x00
,0x00,0x00,0x03,0xe0,0xe3,0xff,0xe0,0x00
,0x00,0x00,0x01,0x80,0x00,0x7f,0x00,0x00
};
//---------------------------------------------------------------
#define FinPr_invalid_width 64
#define FinPr_invalid_height 64
const uint8_t PROGMEM FinPr_invalid_bits[] = {
0x00,0x00,0x03,0xfe,0x00,0x00,0x00,0x00
,0x00,0x00,0x1f,0xff,0xe0,0x00,0x00,0x00
,0x00,0x00,0x7f,0xff,0xf8,0x00,0x00,0x00
,0x00,0x00,0xfc,0x00,0xfe,0x00,0x00,0x00
,0x00,0x03,0xe0,0x00,0x1f,0x00,0x00,0x00
,0x00,0x07,0xc0,0x00,0x07,0x80,0x00,0x00
,0x00,0x0f,0x80,0x00,0x03,0xe0,0x00,0x00
,0x00,0x0e,0x03,0xff,0x01,0xe0,0x00,0x00
,0x00,0x1c,0x1f,0xff,0xe0,0xf0,0x00,0x00
,0x00,0x3c,0x3f,0xff,0xf0,0x78,0x00,0x00
,0x00,0x78,0x7c,0x00,0xf8,0x3c,0x00,0x00
,0x00,0x70,0xf0,0x00,0x3c,0x1c,0x00,0x00
,0x00,0xe1,0xe0,0x00,0x1e,0x1c,0x00,0x00
,0x00,0xe1,0xc0,0x00,0x0f,0x0e,0x00,0x00
,0x00,0xc3,0x81,0xfc,0x07,0x0e,0x00,0x00
,0x00,0x03,0x83,0xff,0x07,0x8e,0x00,0x00
,0x00,0x07,0x07,0x8f,0x83,0x87,0x00,0x00
,0x00,0x0f,0x0f,0x03,0xc3,0x87,0x00,0x00
,0x00,0x1e,0x0e,0x01,0xc3,0x87,0x00,0x00
,0x00,0x3c,0x1c,0x00,0xe1,0x87,0x00,0x00
,0x00,0xf8,0x1c,0x30,0xe1,0x87,0x00,0x00
,0x07,0xf0,0x38,0x70,0xe1,0x86,0x00,0x00
,0x07,0xc0,0x78,0x70,0xe3,0x8e,0x00,0x00
,0x02,0x00,0xf0,0xf0,0xe3,0x8e,0x00,0x00
,0x00,0x01,0xe0,0xe0,0xe3,0x8e,0x00,0x00
,0x00,0x03,0xc1,0xe1,0xc3,0x8e,0x00,0x00
,0x00,0x0f,0x83,0xc3,0xc3,0x8e,0x00,0x00
,0x00,0x7f,0x07,0x83,0x83,0x0e,0x00,0x00
,0x07,0xfc,0x0f,0x07,0x83,0x0e,0x00,0x00
,0x07,0xf0,0x1e,0x0f,0x03,0x0e,0x00,0x00
,0x07,0x80,0x7c,0x1e,0x03,0x07,0x00,0x00
,0x00,0x00,0xf8,0x3c,0x03,0x87,0x80,0x00
,0x00,0x03,0xf0,0x78,0x03,0x83,0xc0,0x00
,0x00,0x1f,0xc0,0xf0,0x02,0x00,0x00,0x00
,0x00,0xff,0x01,0xe1,0xc0,0x00,0x00,0x00
,0x07,0xfc,0x03,0xc3,0xe1,0xff,0xc0,0x00
,0x07,0xe0,0x0f,0x87,0xc7,0xff,0xf0,0x00
,0x07,0x00,0x3f,0x0f,0x0f,0xff,0xf8,0x00
,0x00,0x00,0x7c,0x3e,0x1f,0xff,0xfe,0x00
,0x00,0x03,0xf8,0x7c,0x3f,0xff,0xff,0x00
,0x00,0x1f,0xe0,0xf0,0x7f,0xff,0xff,0x00
,0x00,0xff,0x83,0xe0,0xfe,0xff,0xbf,0x80
,0x01,0xfc,0x07,0xc0,0xfc,0x7f,0x1f,0xc0
,0x01,0xe0,0x1f,0x01,0xf8,0x3e,0x0f,0xc0
,0x00,0x00,0xfe,0x01,0xf8,0x1c,0x07,0xe0
,0x00,0x03,0xf8,0x13,0xf8,0x00,0x0f,0xe0
,0x00,0x1f,0xe0,0x73,0xfc,0x00,0x1f,0xe0
,0x00,0x7f,0x81,0xf3,0xfe,0x00,0x3f,0xe0
,0x00,0xfc,0x03,0xe3,0xff,0x00,0x7f,0xe0
,0x00,0x60,0x0f,0xc3,0xff,0x80,0xff,0xe0
,0x00,0x00,0x3f,0x03,0xff,0x00,0x7f,0xe0
,0x00,0x00,0xfc,0x03,0xfe,0x00,0x3f,0xe0
,0x00,0x07,0xf0,0x13,0xfc,0x00,0x1f,0xe0
,0x00,0x0f,0xc0,0x79,0xf8,0x08,0x0f,0xe0
,0x00,0x0f,0x01,0xf9,0xf8,0x1c,0x0f,0xc0
,0x00,0x00,0x07,0xf1,0xfc,0x3e,0x1f,0xc0
,0x00,0x00,0x1f,0xc0,0xfe,0x7f,0x3f,0x80
,0x00,0x00,0x7e,0x00,0xff,0xff,0xff,0x80
,0x00,0x00,0xfc,0x00,0x7f,0xff,0xff,0x00
,0x00,0x00,0xf0,0x1f,0x3f,0xff,0xfe,0x00
,0x00,0x00,0x00,0x7f,0x1f,0xff,0xfc,0x00
,0x00,0x00,0x01,0xff,0x8f,0xff,0xf8,0x00
,0x00,0x00,0x03,0xe0,0xe3,0xff,0xe0,0x00
,0x00,0x00,0x01,0x80,0x00,0x7f,0x00,0x00
};
//---------------------------------------------------------------
#define FinPr_failed_width 64
#define FinPr_failed_height 64
const uint8_t PROGMEM FinPr_failed_bits[] = {
0x00,0x00,0x3f,0xe0,0x00,0x00,0x00,0x00
,0x00,0x01,0xff,0xfe,0x00,0x00,0x00,0x00
,0x00,0x0f,0xc0,0x1f,0x80,0x00,0x00,0x00
,0x00,0x1e,0x00,0x03,0xc0,0x00,0x00,0x00
,0x00,0x78,0x00,0x00,0xf0,0x00,0x00,0x00
,0x00,0xe0,0x00,0x00,0x38,0x00,0x00,0x00
,0x01,0xc0,0x00,0x00,0x1c,0x00,0x00,0x00
,0x03,0x80,0x00,0x00,0x0e,0x00,0x00,0x00
,0x07,0x00,0x7f,0xe0,0x07,0x00,0x00,0x00
,0x06,0x01,0xff,0xf8,0x03,0x00,0x00,0x00
,0x0c,0x03,0xc0,0x3c,0x03,0x80,0x00,0x00
,0x1c,0x0f,0x00,0x0e,0x01,0x80,0x00,0x00
,0x18,0x0c,0x00,0x03,0x00,0xc0,0x00,0x00
,0x18,0x18,0x00,0x01,0x80,0xc0,0x00,0x00
,0x30,0x38,0x00,0x01,0xc0,0xe0,0x00,0x00
,0x30,0x30,0x0f,0x00,0xc0,0x60,0x00,0x00
,0x30,0x30,0x3f,0xc0,0xe0,0x60,0x00,0x00
,0x70,0x60,0x78,0xe0,0x60,0x60,0x00,0x00
,0x60,0x60,0x60,0x60,0x60,0x70,0x00,0x00
,0x60,0x60,0x60,0x60,0x60,0x30,0x00,0x00
,0x60,0x60,0x60,0x60,0x30,0x30,0x00,0x00
,0x60,0x60,0x60,0x30,0x30,0x20,0x00,0x00
,0x60,0x60,0x60,0x30,0x30,0x01,0xe0,0x00
,0x60,0x60,0x60,0x30,0x30,0x0f,0xfc,0x00
,0x60,0x60,0x60,0x30,0x30,0x3f,0xff,0x00
,0x60,0x60,0x60,0x30,0x18,0x78,0x03,0x80
,0x60,0x60,0x60,0x30,0x1c,0x60,0x01,0x80
,0x60,0x60,0x30,0x38,0x0c,0xc0,0x00,0xc0
,0x00,0x60,0x30,0x18,0x00,0xc0,0x00,0xc0
,0x00,0x60,0x30,0x18,0x00,0xc0,0x00,0xc0
,0x00,0xe0,0x30,0x0c,0x01,0xc0,0x00,0xe0
,0x00,0xc0,0x18,0x0e,0x01,0xc0,0x00,0xe0
,0x60,0xc0,0x18,0x07,0x01,0xc0,0x00,0xe0
,0x01,0xc0,0x1c,0x03,0x81,0xc0,0x00,0xe0
,0x01,0x80,0x0c,0x01,0xc1,0xc0,0x00,0xe0
,0x03,0x80,0x0e,0x00,0xf1,0xc0,0x00,0xe0
,0x0f,0x00,0x06,0x00,0x01,0xc0,0x00,0xe0
,0x3e,0x01,0x03,0x00,0x01,0xc0,0x00,0xe0
,0x30,0x03,0x83,0x80,0x1f,0xff,0xff,0xfe
,0x00,0x03,0x81,0xc0,0x3f,0xff,0xff,0xff
,0x00,0x07,0xc0,0xe0,0x30,0x00,0x00,0x03
,0x00,0x0e,0xc0,0x78,0x30,0x00,0x00,0x03
,0x00,0x3c,0x60,0x1e,0x30,0x00,0x00,0x03
,0x00,0x78,0x70,0x0f,0x30,0x00,0x00,0x03
,0x03,0xe0,0x38,0x03,0x30,0x00,0x00,0x03
,0x07,0x80,0x1c,0x00,0x30,0x00,0x00,0x03
,0xc0,0x00,0x0f,0x00,0x30,0x00,0x00,0x03
,0xc0,0x00,0x03,0x80,0x30,0x01,0xe0,0x03
,0x00,0x18,0x01,0xe0,0x30,0x03,0xf0,0x03
,0x00,0x18,0x00,0x7c,0x30,0x07,0x38,0x03
,0x00,0x0c,0x00,0x1f,0x30,0x06,0x18,0x03
,0x18,0x0e,0x00,0x07,0x30,0x06,0x18,0x03
,0x0c,0x07,0x80,0x00,0x30,0x07,0x38,0x03
,0x0e,0x03,0xc0,0x00,0x30,0x03,0x30,0x03
,0x07,0x00,0xf0,0x00,0x30,0x03,0x30,0x03
,0x03,0x00,0x7e,0x00,0x30,0x03,0x30,0x03
,0x01,0x80,0x1f,0xc0,0x30,0x03,0x30,0x03
,0x01,0xc0,0x03,0xe1,0x30,0x07,0xf8,0x03
,0x00,0xf0,0x00,0x01,0x30,0x03,0xf0,0x03
,0x00,0x38,0x00,0x00,0x30,0x00,0x00,0x03
,0x00,0x1e,0x00,0x00,0x30,0x00,0x00,0x03
,0x00,0x07,0xc0,0x00,0x30,0x00,0x00,0x03
,0x00,0x01,0xff,0x80,0x3f,0xff,0xff,0xff
,0x00,0x00,0x3f,0x80,0x1f,0xff,0xff,0xfe
};
//---------------------------------------------------------------
#define FinPr_scan_width 64
#define FinPr_scan_height 64
const uint8_t PROGMEM FinPr_scan_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x1f,0xf8,0x00,0x00,0x00
,0x00,0x00,0x00,0x7f,0xff,0x00,0x00,0x00
,0x00,0x00,0x01,0xfc,0x7f,0xc0,0x00,0x00
,0x00,0x00,0x03,0xc0,0x03,0xe0,0x00,0x00
,0x00,0x00,0x07,0x80,0x00,0xf0,0x00,0x00
,0x00,0x00,0x0e,0x00,0x00,0x3c,0x00,0x00
,0x00,0x00,0x1c,0x1f,0xfc,0x1c,0x00,0x00
,0x00,0x00,0x38,0x7f,0xfe,0x0e,0x00,0x00
,0x00,0x00,0x78,0xf8,0x0f,0x87,0x00,0x00
,0x00,0x00,0x71,0xe0,0x03,0xc7,0x00,0x00
,0x00,0x00,0xe3,0x80,0x01,0xc3,0x80,0x00
,0x00,0x00,0xc3,0x83,0xc0,0xe3,0x80,0x00
,0x00,0x00,0xc7,0x0f,0xf0,0x71,0x80,0x00
,0x00,0x00,0x06,0x1f,0xf8,0x71,0xc0,0x00
,0x00,0x00,0x0e,0x1c,0x3c,0x31,0xc0,0x00
,0x00,0x00,0x1c,0x38,0x1c,0x31,0xc0,0x00
,0x00,0x00,0x38,0x70,0x0e,0x39,0xc0,0x00
,0x00,0x01,0xf0,0x71,0x8e,0x39,0xc0,0x00
,0x00,0x03,0xe0,0xe1,0x86,0x31,0xc0,0x00
,0x00,0x03,0x81,0xe3,0x8e,0x31,0x80,0x00
,0x00,0x00,0x03,0xc3,0x8e,0x33,0x80,0x00
,0x00,0x00,0x07,0x87,0x0c,0x73,0x80,0x00
,0x00,0x00,0x1f,0x0e,0x1c,0x73,0x80,0x00
,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xfe
,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xfe
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x03,0xf0,0x1e,0x3e,0x1c,0x00,0x00
,0x00,0x03,0x80,0x7c,0x77,0x0f,0x00,0x00
,0x00,0x00,0x01,0xf0,0xe3,0x07,0xc0,0x00
,0x00,0x00,0x07,0xe3,0xc3,0x81,0xf0,0x00
,0x00,0x00,0x3f,0x87,0x81,0xc0,0x60,0x00
,0x00,0x01,0xfc,0x1f,0x00,0xf0,0x00,0x00
,0x00,0x01,0xe0,0x3c,0x00,0x7c,0x00,0x00
,0x00,0x00,0x00,0xf8,0x78,0x1f,0x00,0x00
,0x00,0x00,0x07,0xe0,0xfc,0x0f,0xc0,0x00
,0x00,0x00,0x3f,0x83,0xef,0x03,0xc0,0x00
,0x00,0x00,0xfc,0x0f,0x87,0x80,0x00,0x00
,0x00,0x00,0x70,0x1f,0x03,0xe0,0x00,0x00
,0x00,0x00,0x00,0x7c,0x00,0xf8,0x00,0x00
,0x00,0x00,0x01,0xf0,0x00,0x3e,0x00,0x00
,0x00,0x00,0x0f,0xc0,0xf8,0x0f,0x00,0x00
,0x00,0x00,0x1f,0x03,0xfe,0x02,0x00,0x00
,0x00,0x00,0x0c,0x0f,0x8f,0x80,0x00,0x00
,0x00,0x00,0x00,0x3f,0x03,0xe0,0x00,0x00
,0x00,0x00,0x00,0xf8,0x00,0xf0,0x00,0x00
,0x00,0x00,0x01,0xe0,0x00,0x30,0x00,0x00
,0x00,0x00,0x01,0xc0,0xf8,0x00,0x00,0x00
,0x00,0x00,0x00,0x07,0xfe,0x00,0x00,0x00
,0x00,0x00,0x00,0x0f,0x8e,0x00,0x00,0x00
,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
//************************************************************************
void setup() {

Serial.begin(115200);

//-----------initiate OLED display-------------

// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
// you can delet these three lines if you don't want to get the Adfruit logo appear
display.display();
delay(2000); // Pause for 2 seconds
display.clearDisplay();

//---------------------------------------------

connectToWiFi();

//---------------------------------------------

// set the data rate for the sensor serial port
finger.begin(57600);
Serial.println("\n\nAdafruit finger detect test");

if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!");
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();
} else {
Serial.println("Did not find fingerprint sensor :(");
display.clearDisplay();
display.drawBitmap( 32, 0, FinPr_failed_bits, FinPr_failed_width, FinPr_failed_height, WHITE);
display.display();
while (1) { delay(1); }
}
//---------------------------------------------

finger.getTemplateCount();
Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");
Serial.println("Waiting for valid finger...");

//------------*test the connection*------------

//SendFingerprintID( FingerID );

}
//************************************************************************
void loop() {

//check if there's a connection to WiFi or not
if(WiFi.status() != WL_CONNECTED){
connectToWiFi();
}
//---------------------------------------------
//If there no fingerprint has been scanned return -1 or -2 if there an error or 0 if there nothing, The ID start form 1 to 127
FingerID = getFingerprintID(); // Get the Fingerprint ID from the Scanner
delay(50); //don't need to run this at full speed.

//---------------------------------------------

DisplayFingerprintID();

//---------------------------------------------

ChecktoAddID();

//---------------------------------------------

ChecktoDeleteID();

//---------------------------------------------
}
//************Display the fingerprint ID state on the OLED*************
void DisplayFingerprintID(){
//Fingerprint has been detected
if (FingerID > 0){
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();

SendFingerprintID( FingerID ); // Send the Fingerprint ID to the website.

}
//---------------------------------------------
//No finger detected
else if (FingerID == 0){
display.clearDisplay();
display.drawBitmap( 32, 0, FinPr_start_bits, FinPr_start_width, FinPr_start_height, WHITE);
display.display();
}
//---------------------------------------------
//Didn't find a match
else if (FingerID == -1){
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_invalid_bits, FinPr_invalid_width, FinPr_invalid_height, WHITE);
display.display();
}
//---------------------------------------------
//Didn't find the scanner or there an error
else if (FingerID == -2){
display.clearDisplay();
display.drawBitmap( 32, 0, FinPr_failed_bits, FinPr_failed_width, FinPr_failed_height, WHITE);
display.display();
}
}
//************send the fingerprint ID to the website*************
void SendFingerprintID( int finger ){

HTTPClient http; //Declare object of class HTTPClient
//Post Data
postData = "FingerID=" + String(finger); // Add the Fingerprint ID to the Post array in order to send it
// Post methode

http.begin(link); //initiate HTTP request, put your Website URL or Your Computer IP
http.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Specify content-type header

int httpCode = http.POST(postData); //Send the request
String payload = http.getString(); //Get the response payload

Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
Serial.println(postData); //Post Data
Serial.println(finger); //Print fingerprint ID

if (payload.substring(0, 5) == "login") {
String user_name = payload.substring(5);
// Serial.println(user_name);

display.clearDisplay();
display.setTextSize(2); // Normal 2:2 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(15,0); // Start at top-left corner
display.print(F("Welcome"));
display.setCursor(0,20);
display.print(user_name);
display.display();
}
else if (payload.substring(0, 6) == "logout") {
String user_name = payload.substring(6);
// Serial.println(user_name);

display.clearDisplay();
display.setTextSize(2); // Normal 2:2 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(10,0); // Start at top-left corner
display.print(F("Good Bye"));
display.setCursor(0,20);
display.print(user_name);
display.display();
}
delay(1000);

postData = "";
http.end(); //Close connection
}
//********************Get the Fingerprint ID******************
int getFingerprintID() {
uint8_t p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
//Serial.println("Image taken");
break;
case FINGERPRINT_NOFINGER:
//Serial.println("No finger detected");
return 0;
case FINGERPRINT_PACKETRECIEVEERR:
//Serial.println("Communication error");
return -2;
case FINGERPRINT_IMAGEFAIL:
//Serial.println("Imaging error");
return -2;
default:
//Serial.println("Unknown error");
return -2;
}
// OK success!
p = finger.image2Tz();
switch (p) {
case FINGERPRINT_OK:
//Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
//Serial.println("Image too messy");
return -1;
case FINGERPRINT_PACKETRECIEVEERR:
//Serial.println("Communication error");
return -2;
case FINGERPRINT_FEATUREFAIL:
//Serial.println("Could not find fingerprint features");
return -2;
case FINGERPRINT_INVALIDIMAGE:
//Serial.println("Could not find fingerprint features");
return -2;
default:
//Serial.println("Unknown error");
return -2;
}
// OK converted!
p = finger.fingerFastSearch();
if (p == FINGERPRINT_OK) {
//Serial.println("Found a print match!");
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
//Serial.println("Communication error");
return -2;
} else if (p == FINGERPRINT_NOTFOUND) {
//Serial.println("Did not find a match");
return -1;
} else {
//Serial.println("Unknown error");
return -2;
}
// found a match!
//Serial.print("Found ID #"); Serial.print(finger.fingerID);
//Serial.print(" with confidence of "); Serial.println(finger.confidence);

return finger.fingerID;
}
//******************Check if there a Fingerprint ID to delete******************
void ChecktoDeleteID(){

HTTPClient http; //Declare object of class HTTPClient
//Post Data
postData = "DeleteID=check"; // Add the Fingerprint ID to the Post array in order to send it
// Post methode

http.begin(link); //initiate HTTP request, put your Website URL or Your Computer IP
http.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Specify content-type header

int httpCode = http.POST(postData); //Send the request
String payload = http.getString(); //Get the response payload

if (payload.substring(0, 6) == "del-id") {
String del_id = payload.substring(6);
Serial.println(del_id);
deleteFingerprint( del_id.toInt() );
}

http.end(); //Close connection
}
//******************Delete Finpgerprint ID*****************
uint8_t deleteFingerprint( int id) {
uint8_t p = -1;

p = finger.deleteModel(id);

if (p == FINGERPRINT_OK) {
//Serial.println("Deleted!");
display.clearDisplay();
display.setTextSize(2); // Normal 2:2 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("Deleted!\n"));
display.display();
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
//Serial.println("Communication error");
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("Communication error!\n"));
display.display();
return p;
} else if (p == FINGERPRINT_BADLOCATION) {
//Serial.println("Could not delete in that location");
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("Could not delete in that location!\n"));
display.display();
return p;
} else if (p == FINGERPRINT_FLASHERR) {
//Serial.println("Error writing to flash");
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("Error writing to flash!\n"));
display.display();
return p;
} else {
//Serial.print("Unknown error: 0x"); Serial.println(p, HEX);
display.clearDisplay();
display.setTextSize(2); // Normal 2:2 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("Unknown error:\n"));
display.display();
return p;
}
}
//******************Check if there a Fingerprint ID to add******************
void ChecktoAddID(){

HTTPClient http; //Declare object of class HTTPClient
//Post Data
postData = "Get_Fingerid=get_id"; // Add the Fingerprint ID to the Post array in order to send it
// Post methode

http.begin(link); //initiate HTTP request, put your Website URL or Your Computer IP
http.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Specify content-type header

int httpCode = http.POST(postData); //Send the request
String payload = http.getString(); //Get the response payload

if (payload.substring(0, 6) == "add-id") {
String add_id = payload.substring(6);
Serial.println(add_id);
id = add_id.toInt();
getFingerprintEnroll();
}
http.end(); //Close connection
}
//******************Enroll a Finpgerprint ID*****************
uint8_t getFingerprintEnroll() {

int p = -1;
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_scan_bits, FinPr_scan_width, FinPr_scan_height, WHITE);
display.display();
while (p != FINGERPRINT_OK) {
p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
//Serial.println("Image taken");
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();
break;
case FINGERPRINT_NOFINGER:
//Serial.println(".");
display.setTextSize(1); // Normal 2:2 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("scanning"));
display.display();
break;
case FINGERPRINT_PACKETRECIEVEERR:
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_invalid_bits, FinPr_invalid_width, FinPr_invalid_height, WHITE);
display.display();
break;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
break;
default:
Serial.println("Unknown error");
break;
}
}

// OK success!

p = finger.image2Tz(1);
switch (p) {
case FINGERPRINT_OK:
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();
break;
case FINGERPRINT_IMAGEMESS:
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_invalid_bits, FinPr_invalid_width, FinPr_invalid_height, WHITE);
display.display();
return p;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return p;
case FINGERPRINT_FEATUREFAIL:
Serial.println("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return p;
default:
Serial.println("Unknown error");
return p;
}
display.clearDisplay();
display.setTextSize(2); // Normal 2:2 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("Remove"));
display.setCursor(0,20);
display.print(F("finger"));
display.display();
//Serial.println("Remove finger");
delay(2000);
p = 0;
while (p != FINGERPRINT_NOFINGER) {
p = finger.getImage();
}
Serial.print("ID "); Serial.println(id);
p = -1;
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_scan_bits, FinPr_scan_width, FinPr_scan_height, WHITE);
display.display();
while (p != FINGERPRINT_OK) {
p = finger.getImage();
switch (p) {
case FINGERPRINT_OK:
//Serial.println("Image taken");
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();
break;
case FINGERPRINT_NOFINGER:
//Serial.println(".");
display.setTextSize(1); // Normal 2:2 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("scanning"));
display.display();
break;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
break;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
break;
default:
Serial.println("Unknown error");
break;
}
}

// OK success!

p = finger.image2Tz(2);
switch (p) {
case FINGERPRINT_OK:
//Serial.println("Image converted");
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();
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("Could not find fingerprint features");
return p;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return p;
default:
Serial.println("Unknown error");
return p;
}

// OK converted!
Serial.print("Creating model for #"); Serial.println(id);

p = finger.createModel();
if (p == FINGERPRINT_OK) {
//Serial.println("Prints matched!");
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();
} 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;
}

Serial.print("ID "); Serial.println(id);
p = finger.storeModel(id);
if (p == FINGERPRINT_OK) {
//Serial.println("Stored!");
display.clearDisplay();
display.drawBitmap( 34, 0, FinPr_valid_bits, FinPr_valid_width, FinPr_valid_height, WHITE);
display.display();
confirmAdding();
} 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 {
Serial.println("Unknown error");
return p;
}
}
//******************Check if there a Fingerprint ID to add******************
void confirmAdding(){

HTTPClient http; //Declare object of class HTTPClient
//Post Data
postData = "confirm_id=" + String(id); // Add the Fingerprint ID to the Post array in order to send it
// Post methode

http.begin(link); //initiate HTTP request, put your Website URL or Your Computer IP
http.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Specify content-type header

int httpCode = http.POST(postData); //Send the request
String payload = http.getString(); //Get the response payload

display.clearDisplay();
display.setTextSize(1.5); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(payload);
display.display();
delay(1000);
Serial.println(payload);

http.end(); //Close connection
}
//********************connect to the WiFi******************
void connectToWiFi(){
WiFi.mode(WIFI_OFF); //Prevents reconnection issue (taking too long to connect)
delay(1000);
WiFi.mode(WIFI_STA);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);

display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.print(F("Connecting to \n"));
display.setCursor(0, 50);
display.setTextSize(2);
display.print(ssid);
display.drawBitmap( 73, 10, Wifi_start_bits, Wifi_start_width, Wifi_start_height, WHITE);
display.display();

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Connected");

display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(8, 0); // Start at top-left corner
display.print(F("Connected \n"));
display.drawBitmap( 33, 15, Wifi_connected_bits, Wifi_connected_width, Wifi_connected_height, WHITE);
display.display();

Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP

}
//=======================================================================

 

Registration of users:

Once the Program successfully uploaded to the NodeMCU, It will boot up with the Adafruit logo and then ModeMCU will try to establish the connection between the WiFi router which is provided in the program.  Once it gets Connected it will display Connected. The same log can be seen on the Serial Monitor as well as in OLED Display.

IoT based fingerprint biometric project boot up

So now you can start the registration process of the user on the website using the following link: http://localhost/biometricattendance/ManageUsers.php

IoT Based Fingerprint Biometric Attendance System_Manage users

The whole process of registration is explained very well in the video. You can follow the video for the complete registration process. The user fingerprint is taken twice i.e as mentioned in the datasheet and stored in EEPROM of Fingerprint Sensor. It is to be noted that only 127 fingerprints can be stored in this R303/R305/R307 module.

IoT Based Fingerprint Biometric Attendance System_User_registration1Pic: User registration Step1_ScanningIoT Based Fingerprint Biometric Attendance System_User_registration2Pic: User registration Step1_Remove finger

IoT Based Fingerprint Biometric Attendance System_User_registration3Pic: User registration Step1_Fingerprint has been added.

Authentication of Users:

So once the User registration process is completed, you can start scanning and marking the attendance. If a registered user scans his/her finger for the first time on that day, It will display the welcome message as follows.

IoT Based Fingerprint Biometric Attendance System_Welcome Jarvis

If a registered user scans his/her finger for the second time on that day, It will display the goodbye message as follows.

IoT Based Fingerprint Biometric Attendance System_good byeJarvis

In case if the fingerprint is not matched or an unregistered candidate tries to authenticate it will display an error message as shown in the figure below.

IoT Based Fingerprint Biometric Attendance System_ErroMessage

Finally, you can access the entire Attendance data of the Students/Employee on the website by simply selecting the particular date as shown below, You can also download the same data in excel format by clicking on the Export to Excel button.

IoT Based Fingerprint Biometric Attendance System_ErroMessage_Attendance data

 

Realtime implementation of Portable IoT based Fingerprint Biometric Attendance System:

I wanted to take this project to the next level i.e Real-Time implementation, This includes additions circuitry and mechanical parts like Battery, Battery management system, Boost converter and a casing. but there will be no change in the Firmware(Source code)

Since R303a Fingerprint sensor will not work on 3.3v we need to have 5V supply, on the other hand, we should have rechargeable battery i.e Li-ion battery whose voltage is not sufficient to drive the R303a Fingerprint sensor. So I decided to add one boost converter(MT3608) to the circuitry to get 5v.

After these modifications circuit will be like this.

Realtime implementation circuit.

Realtime_Implemetation circuitFInal Circuit: Portable IoT based Fingerprint Biometric Attendance System

I made one casing with the wooden stripers to keep all the circuitry in that just have a look at this. I showed this process in the video you can experience it there.

The dimensions for this box are 7x8x5 (cm), I cut down some area on the front part to accommodate the Fingerprint sensor and OLED display.

Final results:

Portable IoT Based Fingerprint Biometric Attendance System using NodeMCU

Final product: Portable IoT based Fingerprint Biometric Attendance System

You can follow the video to understanding the whole process like how to add, update and remove the users from the database, how to access the attendance data, how to export the attendance data to the excel. This video will help you through the journey of making Portable IoT Based Fingerprint Biometric Attendance System using NodeMCU.

Video Tutorial & Explanation : Portable IoT based Fingerprint Biometric Attendance System

By Veeru

15 thoughts on “Portable IoT Based Fingerprint Biometric Attendance System using NodeMCU”
  1. thank you for your great work …can you give me the link to downlaod the webinterface(the data base) please. i need it for my graduation project

    1. Same here. The code shows error in the http.begin(link) which says it is an obsolete api. They tell to use begin(wificlient, link) instead

  2. We are unable to do the connection we are using R307 finger sensor model which has 6 pin but in your fingerprint sensor has 4 pin. Please help we are making this as a final year project

  3. Sir unable to do connection I am using R307 finger sensor which has only 6 pin .
    Plz help sir I am making this as final year project. Dead line is really very near.

Leave a Reply