Monday, March 1, 2021

Fingerprint-based attendance logger with SMS feedback

Parenting a teenager is quite a difficult and tiring task. At this age, they are no longer babies to be kept under continuous observation. On the other hand, they’re not mature enough to be trusted with themselves. Many teenagers go to school alone, but their parents are always worried. ‘Has my daughter reached safely at school safely?’ ‘Is my son bunking classes and hanging out with friends?’ Parents’ minds are often occupied with such questions. Keeping their tension in mind, in this tutorial, we will make a fingerprint-based attendance logger. It will keep a record of students’ attendance and also send an SMS to their parents’ mobiles every time they enter and leave school.

Working principle:

This project works in the following steps:

  1. At first, the system will enrol the fingerprints of all students one by one according to their roll numbers.
  2. When a fingerprint matches with an enrolled fingerprint, an LCD shows the student’s roll number.  
  3. The time of entry and exit is determined by an RTC.
  4. The time will be recorded on a microSD card.

5.      The parents will receive an SMS on their mobiles every time their children reach and leave the campus.

Components needed:

 

Component’s  name

Quantity

Website link

Sanguino TSB

1

http://bit.ly/2Pws2VS

Fingerprint Recognition Module (ZFM60)

1

http://bit.ly/2yysk4E

SIM900A kit

1

http://bit.ly/2CJ1uK4

Power distribution board

1

http://bit.ly/2RjSjUp

3-wire LCD

1

http://bit.ly/2SoTGTd

MicroSD card storage board

1

http://bit.ly/2wL0KCM

Team Micro SD HC Card 32GB Class 10

1

http://bit.ly/2Av3eFl

 PCF 8563 RTC Board

1

http://bit.ly/2O9EpSP

Breadboard

1

http://bit.ly/2IjyUPg

12V 700mA Power Adapter

1

http://bit.ly/2IbMpog

Male to male jumper

4

http://bit.ly/2IkA1hy

Male to female jumper

20

http://bit.ly/2rIu6w2

Soldering iron

1

http://bit.ly/2tpXpF3

Solder lead mini

1

http://bit.ly/2K496f8

Sim card

1

 

What is Sanguino TSB, and why did we choose it for this project?

                             


Sanguino TSB is am Arduino board equivalent to Arduino UNO-R3. Whatever you can do with Arduino UNO R3, can be done with Sanguino. Sanguino has some benefits over Arduino UNO.  Unlike Arduino UNO, it has both male and female headers. All the names of the pins are printed on the board for the User’s convenience.  Sanguino TSB’s SRAM, EEPROM, Flash memory are double of  Arduino UNO.  Sanguino has 2 pairs of USART pins. Tx0, Rx0, Tx1, RX1. The fingerprint scanner and GSM module used in this experiment both use the USART communication protocol. So, it’s not possible to connect these two with an Arduino UNO by hardware serial. At least one had to be connected by software serial. Software serial has some limitations including allowable baud rate only up to 115200, chances of missing bits etc. Keeping this in mind, Sanguino TSB seemed to be the best for this project. It can be implemented with Arduino Mega also, but that will add a bit more to the cost.

 

Circuit connection:

 

Step 1- Soldering the fingerprint scanner: Following is the pinout of the fingerprint scanner. 4 male to male jumpers must be soldered with the wires as shown in the picture below:




Step 2: Complete the following connection between Sanguino and Fingerprint scanner.



Sanguino TSB

Fingerprint Recognition Module (ZFM60)

VCC

VCC

GND

GND

TX

RX1

RX

TX1


 

Step 3- Connecting the SIM900A module: Following is the pinout of SIM900A.



To power up SIM900A, we will use a 12V Adapter and power distribution board. The power distribution board steps down the voltage to 5V and keeps the output voltage constant.

Complete the following connection among SIM900A, power distribution board and Sanguino TSB.



SIM900A

Power distribution board

Sanguino TSB

VCC

5V

GND

GND

GND


Power up the power distribution board with 12V adapter.    


    

Step 4- Connecting the 3-wire LCD: Now connect the 3-wire LCD with Sanguino TSB.


 


Sanguino TSB

3-wire LCD

VCC

VCC

GND

GND

12

DATA

13

Clock

3

Latch


Step 5- Connecting the RTC: The PCF 8563 RTC module has an inbuilt battery. So, there is no need to add any extra battery to power it up. Complete the following connection between PCF 8563 RTC and Sanguino TSB.



Sanguino TSB

PCF 8563 RTC Board

VCC

VCC

GND

GND

SCL

SCL

SDA

SDA


Step 6-Connecting the microSD card holder: Insert the microSD card inside the microSD card holder and complete the following connection.



Sanguino TSB

MicroSD card storage board

VCC

VCC

GND

GND

MISO

MISO

MOSI

MOSI

SCK

SCLK

SS

CS


Finally, power up the sanguino TSB with your computer’s USB PORT.

The whole circuit will look like this:



Now it’s time for coding.

The coding must be done in multiple steps.

 

a)      Library installation: Before starting to code, the following libraries must be installed.

 

b)      Board installation: If you’re using Sanguino TSB for the first time, you have to install the board by following this user manual.

c)       Fingerprint enrollment: To enrol fingerprints, upload the following code to Sanguino TSB

#include <Adafruit_Fingerprint.h>

uint8_t id;

unsigned char studentname[50];

int i=0;

 

 

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&Serial1);

 

void setup() 

{

  Serial.begin(9600);

  Serial.println("fingertest");

 

  // set the data rate for the sensor serial port

  finger.begin(57600);

 

  if (finger.verifyPassword()) {

    Serial.println("Found fingerprint sensor!");

  } else {

    Serial.println("Did not find fingerprint sensor :(");

    while (1);

  }

}

 

uint8_t readnumber(void) {

  uint8_t num = 0;

 

  while (num == 0) {

    while (! Serial.available());

    num = Serial.parseInt();

  }

  return num;

}

 

 

 

 

void loop()                     // run over and over again

{

  Serial.println("Type in the ID # you want to save this finger as...");

//  int id = 0;

//  while (true) {

//    while (! Serial.available());

//    char c = Serial.read();

//    if (! isdigit(c)) break;

//    id *= 10;

//    id += c - '0';

//

//  if (id == 0) {// ID #0 not allowed, try again!

//     return;

//  }

//  }

  id = readnumber();

  if (id == 0) {// ID #0 not allowed, try again!

     return;

  }

  Serial.print("Enrolling ID #");

  Serial.println(id);

 

  while (!  getFingerprintEnroll(id) );

}

 

uint8_t getFingerprintEnroll(int id) {

  int p = -1;

  Serial.println("Waiting for valid finger to enroll");

  while (p != FINGERPRINT_OK) {

    p = finger.getImage();

    switch (p) {

    case FINGERPRINT_OK:

      Serial.println("Image taken");

      break;

    case FINGERPRINT_NOFINGER:

      Serial.println(".");

      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(1);

  switch (p) {

    case FINGERPRINT_OK:

      Serial.println("Image converted");

      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;

  }

 

  Serial.println("Remove finger");

  delay(2000);

  p = 0;

  while (p != FINGERPRINT_NOFINGER) {

    p = finger.getImage();

  }

 

  p = -1;

  Serial.println("Place same finger again");

  while (p != FINGERPRINT_OK) {

    p = finger.getImage();

    switch (p) {

    case FINGERPRINT_OK:

      Serial.println("Image taken");

      break;

    case FINGERPRINT_NOFINGER:

      Serial.print(".");

      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");

      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!

  p = finger.createModel();

  if (p == FINGERPRINT_OK) {

    Serial.println("Prints matched!");

  } 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!");

  } 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;

  }  

}


 

d)    Setting RTC: Before using the PCF 8563 RTC board, its time should be set. Set the time of PCF 8563 RTC board  with the following code. You have to change the parameters according to the date of your project’s implementation. 

#include <PCF8563.h>
 
PCF8563 pcf;
 
void setup() {
  Serial.begin(9600);
  pcf.init();//initialize the clock
 
  pcf.stopClock();//stop the clock
 
  //set time to to 31/3/2018 17:33:0
 
  pcf.setYear(18);//set year
  pcf.setMonth(10);//set month
  pcf.setDay(28);//set dat
  pcf.setHour(13);//set hour
  pcf.setMinut(13);//set minut
  pcf.setSecond(0);//set second
 
  pcf.startClock();//start the clock
}
 
void loop() {
  
}

 

Main code: Upload the following code to Sanguino TSB.  Your project will be ready.

/***************************************************

  This is an example sketch for our optical Fingerprint sensor

 

  Designed specifically to work with the Adafruit BMP085 Breakout

  ----> http://www.adafruit.com/products/751

 

   ****************************************************/

#include <SPI.h>

#include <SD.h>

#include <PCF8563.h>

#include <LiquidCrystal_SR.h>

#include <Adafruit_Fingerprint.h>

LiquidCrystal_SR lcd(12, 13, 3);

            //  DATA CLOCK LATCH

 

//SH_CP->CLOCK->13

//ST_CP->LATCH->3

//DS->DATA->12

 

 

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&Serial1);

const int pinCS = 4;

int count1=0,count2=0,count3=0;

File myFile;

PCF8563 pcf;

 

void setup()  

{

  lcd.begin(16, 2);

  lcd.clear(); // clear the screen

 

  Serial.begin(9600);

  pcf.init();//initialize the clock

  pinMode(pinCS, OUTPUT);

  if (SD.begin(4))

  {

    Serial.println("fingerprint sensor.");

    

     

    

     

    Serial.println("SD card is ready to use.");

  } else

  {

    Serial.println("SD card initialization failed");

    return;

  }

  

 

   while (!Serial);  // For Yun/Leo/Micro/Zero/...

  delay(100);

  Serial.println("\n\nAdafruit finger detect test");

 

  // set the data rate for the sensor serial port

  finger.begin(57600);

  

  if (finger.verifyPassword()) {

    Serial.println("Found fingerprint sensor!");

  } else {

    Serial.println("Did not find fingerprint sensor :(");

    while (1) { delay(1); }

  }

 

  finger.getTemplateCount();

  Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");

  Serial.println("Waiting for valid finger...");

  lcd.setCursor(0, 0); // put cursor at colon 0 and row 0

  lcd.print("Press finger");

 

  

}

 

void loop()                     // run over and over again

{

  getFingerprintIDez();

  delay(50);            //don't ned to run this at full speed.

  

}

 

uint8_t 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 p;

    case FINGERPRINT_PACKETRECIEVEERR:

      Serial.println("Communication error");

      return p;

    case FINGERPRINT_IMAGEFAIL:

      Serial.println("Imaging error");

      return p;

    default:

      Serial.println("Unknown error");

      return p;

  }

 

  // OK success!

 

  p = finger.image2Tz();

  switch (p) {

    case FINGERPRINT_OK:

      Serial.println("Image converted");

      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!

  p = finger.fingerFastSearch();

  if (p == FINGERPRINT_OK) {

    Serial.println("Found a print match!");

  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {

    Serial.println("Communication error");

    return p;

  } else if (p == FINGERPRINT_NOTFOUND) {

    Serial.println("Did not find a match");

    return p;

  } else {

    Serial.println("Unknown error");

    return p;

  }   

  

  // found a match!

  

  Serial.print("Found ID #"); Serial.print(finger.fingerID);

  

  Serial.print(" with confidence of"); Serial.println(finger.confidence);

 

  return finger.fingerID;

  

}

 

// returns -1 if failed, otherwise returns ID #

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;

  

  // found a match!

  Serial.print("\r");

  delay(500);

  Serial.print("AT+CMGF=1\r");

  delay(500);

  if(finger.fingerID==1)

  {

  count1++;  

  Serial.print("AT+CMGS=\"+8801---------\"\r"); //Number to which you want to send the sms

  delay(250);

  

  if(count1%2==0)

  {

  Serial.print("Roll#1 has left class\r"); //The text of the message to be sent

  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("Goodbye Roll  #");

  lcd.print(finger.fingerID);

  delay(2000);

  lcd.clear(); // clear the screen

  lcd.print("Press finger");

  }

  else

  {

   Serial.print("Roll#1 has reached class \r");  

   lcd.clear();

   lcd.setCursor(0,0);

   lcd.print("Welcome roll #");

   lcd.print(finger.fingerID);

   delay(2000);

   lcd.clear(); // clear the screen

   lcd.print("Press finger");

  }

  delay(250);

  Serial.write(0x1A);

  myFile = SD.open("finger.txt", FILE_WRITE);

  if(count1%2==0)

  {

   myFile.print("Roll#1 left class at\r");

  }

  else

  {

   myFile.print("Roll#1 entered at\r");

  }

  myFile.print(" ");

  Time nowTime = pcf.getTime();//get current time

  myFile.print(nowTime.day);

  myFile.print("/");

  myFile.print(nowTime.month);

  myFile.print("/");

  myFile.print(nowTime.year);

  myFile.print(" ");

  myFile.print(nowTime.hour);

  myFile.print(":");

  myFile.print(nowTime.minute);

  myFile.print(":");

  myFile.println(nowTime.second);

  myFile.println();

  myFile.close();

  //myFile.println();

  

  

  }

 

  else if(finger.fingerID==2)

  {

  //similar to if(finger.fingerID==1), just change the mobile number and use the cariable count2

  

  

  }

 

  else if(finger.fingerID==3)

  {

  //similar to if(finger.fingerID==1), just change the mobile number and use the cariable count3. Similar loops can be written for total 152 fingerprints.

  }

  

  

  

 

  Serial.print("Found ID #"); Serial.print(finger.fingerID);

 

  Serial.print(" with confidence of "); Serial.println(finger.confidence);

  

  return finger.fingerID;

  

  

}

Attention: SIM 900A should be disconnected from the circuit at the time of uploading codes.

 

 

 

At the time of entering the class, students will give their fingerprints. If the given fingerprint matches with the enrolled fingerprint, a welcome message with the roll number of the student will appear on the LCD. His/her parent will receive an SMS immediately which confirms his/her arrival at the school.

Similarly, at the time of leaving the class, when a fingerprint matches, a goodbye message will appear on the LCD screen. The parent will receive an SMS and be notified. 



 

A file named finger.txt will be created in the microSD card. The times of entry and exit will be recorded. From this file, the school authority will get information regarding students’ attendance.