Fingerprint Based Biometric Voting Machine Using Arduino

Fingerprint Based Biometric Voting Machine Using Arduino

We all are aware of the existing electronic voting machine where the user has to press a button to cast the vote. But these machines have been criticized for tempering since the beginning. So the government is planning to introduce a fingerprint based voting machine where users can cast the vote based on his/her fingerprint impression. This system will not only remove the possibility of duplicate votes but also prevent any kind of manipulation. 

So in this project, we are going to build a prototype of a Biometric voting machine using the Arduino Uno, TFT display, and Fingerprint Sensor. 

We previously used R305 Fingerprint Sensor with NodeMCU to build a Biometric based Attendance System but here we will use the advanced GT-511C3 fingerprint sensor with Arduino.

 

Components Required 

  • Arduino Uno
  • 2.4” TFT LCD Display Shield
  • GT-511C3 Fingerprint Sensor

This 2.4 inch TFT display is previously used with Arduino to build IoT Based Restaurant Menu Ordering System.

 

Circuit Diagram

The circuit diagram for the Biometric Voting Machine using Arduino is given below:

Biometric Voting Machine Circuit Diagram

Circuit Diagram for this project is very simple as we are only connecting the TFT display and fingerprint sensor module with Arduino Uno. VCC and GND pins of the fingerprint sensor are connected to 5V and GND pins of Arduino while TX and RX pins are connected to digital pin 11 & 12 of Arduino Uno.

 

The 2.4” TFT LCD screen is an Arduino Shield and can be directly mounted on Arduino Uno, as shown in the below image. TFT display has 28 pins that perfectly fit into Arduino Uno, so I had to solder the fingerprint sensor on the backside of Arduino.

 

Code Explanation

The complete code for this Fingerprint Voting System Project using Arduino is given at the end of the article; here we are explaining some important functions of the code.

 

The code uses the SPFD5408Software Serial, and FPS_GT511C3 libraries. SPFD5408 library is the modified version of the original Adafruit Library. These library files can be downloaded from the links given below:

 

After downloading and adding these libraries to Arduino IDE, start the code by including the needed libraries files.

#include <SPFD5408_Adafruit_GFX.h>    
#include <SPFD5408_Adafruit_TFTLCD.h> 
#include <SPFD5408_TouchScreen.h>
#include "FPS_GT511C3.h"
#include "SoftwareSerial.h"
#include<EEPROM.h>

 

After that, define the calibration values for the X and Y-axis. These are the default values given in the library. If your TFT display touch is not working properly, then you can calibrate it again and change these calibration values with new ones.

#define TS_MINX 125
#define TS_MINY 85
#define TS_MAXX 965
#define TS_MAXY 905

 

In the next line, define the Arduino Uno pins where the fingerprint sensor is connected. The transmitter pin of the fingerprint sensor is connected to pin 11 and the receiver is connected to pin 12 of Arduino.

FPS_GT511C3 fps(11, 12); 

 

After including the libraries and defining some important parameters, we can get into the programming part. There are three sections involved in this program. One is creating a UI of a voting machine, second is getting the touchpoints for buttons & detecting the buttons based on the touch, and finally calculating the results and save them into Arduino’s memory. 

 

1. Creating UI

I have created a simple UI with three buttons and the name of the project. The TFT display library allows you to draw Lines, Rectangle, Circles, Chars, Strings, and a lot more of any preferred colour and size. Here two rectangular buttons are created using fillRoundRect and drawRoundRect functions. Syntax for tft.drawRoundRect function is given below:

tft.drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color)

Where: 
x0= X co-ordinate of the starting point of rectangular
y0= Y coordinate of the starting point of rectangular
w = Width of the rectangular
h = Height of the Rectangular
radius= Radius of the round corner
color = Colour of the Rect. 

 

void drawHome()
{
  tft.fillScreen(WHITE);
  tft.drawRoundRect(0, 0, 319, 240, 8, WHITE); //Page border
  tft.fillRoundRect(10, 70, 220, 50, 8, GOLD);
  tft.drawRoundRect(10, 70, 220, 50, 8, WHITE); //Vote
  tft.fillRoundRect(10, 160, 220, 50, 8, GOLD);
  tft.drawRoundRect(10, 160, 220, 50, 8, WHITE); //Enroll
  tft.fillRoundRect(10, 250, 220, 50, 8, GOLD); //Result
  tft.drawRoundRect(10, 250, 220, 50, 8, WHITE);
  tft.setCursor(65, 5);
  tft.setTextSize(3);
  tft.setTextColor(CYAN);
  tft.print("Voting");
  tft.setCursor(57, 29);
  tft.print("Machine");
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(25, 82);
  tft.print("Candidate 1");
  tft.setCursor(25, 172);
  tft.print("Candidate 2");
  tft.setCursor(25, 262);
  tft.print("Candidate 3");
}

 

2. Getting the TouchPoints and Detecting Buttons

Now in the second section of the code, we will detect the button touchpoints and then use these points to predict the button. ts.getPoint() function is used to detect the user touch on TFT display. ts.getPoint gives the Raw ADC values for the touched area. These RAW ADC values are then converted to Pixel Co-ordinates using the map function.

TSPoint p = ts.getPoint();
if (p.z > ts.pressureThreshhold)
    {
      p.x = map(p.x, TS_MAXX, TS_MINX, 0, 320);
      p.y = map(p.y, TS_MAXY, TS_MINY, 0, 240);
      //Serial.print("X:");  
      //Serial.print(p.x);
      //Serial.print("Y:");
      //Serial.print(p.y);

 

Now, since we know the X and Y coordinates for each button, we can predict where the user has touched by using the ‘if’ statement.

  if (p.x > 70 && p.x < 120 && p.y > 10 && p.y < 220 
      && p.z > MINPRESSURE && p.z < MAXPRESSURE)
    {
      Serial.println("Candidate 1");

 

When a voter presses the candidate button, he will be asked to scan the finger on the fingerprint sensor. If finger ID is authorized, then the voter is allowed to vote. If any Non-registered user wants to vote, then the fingerprint module will not detect its ID into the system and the display will show ‘Sorry You Can’t Vote ’.

if (fps.IsPressFinger())
      {
        fps.CaptureFinger(false);
        int id = fps.Identify1_N();
        if (id <200) 
        {
         msg = "Candidate 1";
          vote1++;
          EEPROM.write(0, vote1);
          tft.setCursor(42, 170);
          tft.print("Thank You");
          delay(3000);
          drawHome();

 

3. Result

The last step is getting the vote count from EEPROM memory and comparing the votes of all three candidates. A Candidate with the highest votes wins. The Result can only be accessed from serial monitor and will not be displayed on the TFT screen.

  vote1=EEPROM.read(0);
  vote2=EEPROM.read(1);
  vote3=EEPROM.read(2);
  if(vote)
    {
     if((vote1 > vote2 && vote1 > vote3))
       {
        Serial.print("Can1 Wins");
        delay(2000);
        }

 

Testing the Fingerprint Voting System using Arduino

To test the project, connect the Arduino Uno to the laptop and upload the below given code. Once the code is uploaded the TFT display should display the candidate’s name. When someone taps on a candidate name, the machine will ask to scan the fingerprint scanner. If the fingerprint is valid, then the user vote will be counted, but in case, the pattern doesn’t match with the records of the database, access to cast a vote will be denied. The total number of votes for each candidate will be stored in EEPROM and a candidate having the highest number of votes will win.

Fingerprint Based Biometric Voting Machine Using Arduino

The complete code and a working video are given below. If you have any questions related to this project, you can leave them in the comment section below.

Code

#include <SPFD5408_Adafruit_GFX.h>    // Core graphics library
#include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library
#include <SPFD5408_TouchScreen.h>
#include "FPS_GT511C3.h"
#include "SoftwareSerial.h"
#include<EEPROM.h>
int vote1, vote2, vote3;
String msg  ;
#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin
#define TS_MINX 125
#define TS_MINY 85
#define TS_MAXX 965
#define TS_MAXY 905
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4
#define REDBAR_MINX 80
#define GREENBAR_MINX 130
#define BLUEBAR_MINX 180
#define BAR_MINY 30
#define BAR_HEIGHT 250
#define BAR_WIDTH 30
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
#define BLACK   0x0000
int BLUE = tft.color565(50, 50, 255);
#define DARKBLUE 0x0010
#define VIOLET 0x8888
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define GREY   tft.color565(64, 64, 64);
#define GOLD 0xFEA0
#define BROWN 0xA145
#define SILVER 0xC618
#define LIME 0x07E0
FPS_GT511C3 fps(11, 12); // (Arduino SS_RX = pin 4, Arduino SS_TX = pin 5)
void drawHome()
{
  tft.fillScreen(WHITE);
  tft.drawRoundRect(0, 0, 319, 240, 8, WHITE);   //Page border
  tft.fillRoundRect(10, 70, 220, 50, 8, GOLD);
  tft.drawRoundRect(10, 70, 220, 50, 8, WHITE);  //Vote
  tft.fillRoundRect(10, 160, 220, 50, 8, GOLD);
  tft.drawRoundRect(10, 160, 220, 50, 8, WHITE);  //Enroll
  tft.fillRoundRect(10, 250, 220, 50, 8, GOLD);   //Result
  tft.drawRoundRect(10, 250, 220, 50, 8, WHITE);
  tft.setCursor(65, 5);
  tft.setTextSize(3);
  tft.setTextColor(CYAN);
  tft.print("Voting");
  tft.setCursor(57, 29);
  tft.print("Machine");
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(25, 82);
  tft.print("Candidate 1");
  tft.setCursor(25, 172);
  tft.print("Candidate 2");
  tft.setCursor(25, 262);
  tft.print("Candidate 3");
}
int oldcolor, currentcolor, currentpcolour;
void setup(void) {
  tft.reset();
  tft.begin(tft.readID());
  tft.setRotation(2);
  Serial.begin(9600); 
  Serial.println();
  Serial.print("reading id...");
  delay(500);
  //Serial.println(tft.readID(), HEX);
  tft.fillScreen(BLACK);
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(50, 140);
  tft.print("Loading...");
  for (int i; i < 250; i++)
  {
    tft.fillRect(BAR_MINY - 10, BLUEBAR_MINX, i, 10, RED);
    delay(0.000000000000000000000000000000000000000000000000001);
  }
  tft.fillScreen(BLACK);
  drawHome();
  pinMode(13, OUTPUT);
  result();
}
#define MINPRESSURE 10
#define MAXPRESSURE 1000
void loop()
{
  digitalWrite(13, HIGH);
  digitalWrite(13, LOW);
  TSPoint p = ts.getPoint();
  // if sharing pins, you'll need to fix the directions of the touchscreen pins
  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);
  if (p.z > ts.pressureThreshhold)
    {
      p.x = map(p.x, TS_MAXX, TS_MINX, 0, 320);
      p.y = map(p.y, TS_MAXY, TS_MINY, 0, 240);
      //Serial.print("X:");  // I used this to get the accurate touch points for X and Y axis
      //Serial.print(p.x);
      //Serial.print("\n");
      //Serial.print("Y:");
      //Serial.print(p.y);
      
     if (p.x > 70 && p.x < 120 && p.y > 10 && p.y < 220  && p.z > MINPRESSURE && p.z < MAXPRESSURE)
      {
       Serial.println("Candidate 1");
       fps.Open();         //send serial command to initialize fps
       fps.SetLED(true);   //turn on LED so fps can see fingerprint
       screen();
       delay(3000);
       if (fps.IsPressFinger())
      {
        fps.CaptureFinger(false);
        int id = fps.Identify1_N();
        if (id < 200) 
        {
          msg = "Candidate 1";
          Serial.println(msg);
          vote1++;
          EEPROM.write(0, vote1);
          Serial.print("Verified ID:");
          Serial.println(id);
         // delay(2000);
          tft.setCursor(42, 170);
          tft.print("Thank You");
          delay(3000);
          drawHome();
        }
       else  
       {
        screen1();
      }
      }
       }
      if (p.x > 160 && p.x < 210 && p.y > 10 && p.y < 230)
      {
       Serial.println("Candidate 2");
       fps.Open();         //send serial command to initialize fps
       fps.SetLED(true);   //turn on LED so fps can see fingerprint
       screen();
       delay(3000);
       if (fps.IsPressFinger())
      {
        fps.CaptureFinger(false);
        int id = fps.Identify1_N();
        if (id <200) 
        {
          msg = "Candidate 2";
          Serial.println(msg);
          vote2++;
          EEPROM.write(1, vote2);
          Serial.print("Verified ID:");
          Serial.println(id);
         // delay(2000);
          tft.setCursor(42, 170);
          tft.print("Thank You");
          delay(3000);
          drawHome();
        }
       else
       {
        screen1();
       }
      }
      }
      if (p.x > 260 && p.x < 300 && p.y > 10 && p.y < 220)
      {
       Serial.println("Candidate 3");
       fps.Open();         //send serial command to initialize fps
       fps.SetLED(true);   //turn on LED so fps can see fingerprint
       screen();
       delay(3000);
       if (fps.IsPressFinger())
      {
        fps.CaptureFinger(false);
        int id = fps.Identify1_N();
        if (id <200) 
        {
          msg = "Candidate 3";
          Serial.println(msg);
          vote3++;
          EEPROM.write(2, vote3);
          Serial.print("Verified ID:");
          Serial.println(id);
        //  delay(2000);
          tft.setCursor(42, 170);
          tft.print("Thank You");
          delay(3000);
          drawHome();
        }
       else
       {
        screen1();
       }
      }
      }
    }
  } 
void screen()
{
  tft.fillScreen(BLACK);
  tft.setTextSize(3);
  tft.setTextColor(WHITE);
  tft.setCursor(20, 40);
  tft.print("Please Scan");
  tft.setCursor(20, 90);
  tft.print("Your Finger");
  Serial.println("Please press finger");
}
void screen1()
{
  Serial.println("Finger not found");
  tft.fillScreen(BLACK);
  tft.setCursor(20, 40);
  tft.print("Sorry You");
  tft.setCursor(20, 90);
  tft.print("Can't Vote");
  delay(3000);
  drawHome();
}
void result()

  vote1=EEPROM.read(0);
  vote2=EEPROM.read(1);
  vote3=EEPROM.read(2);
  int vote=vote1+vote2+vote3;
  Serial.println(vote1);
  Serial.println(vote2);
  Serial.println(vote3);
 if(vote)
           {
            if((vote1 > vote2 && vote1 > vote3))
            {
             Serial.print("Candidate 1 Wins");
             delay(2000);
            }
            else if(vote2 > vote1 && vote2 > vote3)
            {
             Serial.print("Candidate 2 Wins");
             delay(2000);
            }
            else if((vote3 > vote1 && vote3 > vote2))
            {
             Serial.print("Candidate 3 Wins");
             delay(2000);
            }
           else
           {
             Serial.print("Tie Up Or");
             Serial.print("No Result");
             delay(1000);
           }
          }      
           else 
           {
             Serial.print("No Voting....");
             delay(1000);
           }
  }

Video