Arduino UNO Based Biometric Electronic Voting System with LCD Display and Fingerprint Authentication
Arduino UNO Based
Biometric Electronic Voting System
A secure digital polling machine with fingerprint authentication, real-time LCD display, servo gate control, buzzer feedback, and EEPROM vote storage — preventing duplicate and unauthorised voting.
01 / OverviewProject Overview
The Arduino UNO Based Biometric Electronic Voting System integrates fingerprint authentication, push-button voting, real-time LCD display, and buzzer feedback into a secure and intelligent digital polling solution.
At the core of the system is the Arduino UNO microcontroller, which manages voter authentication, vote counting, and result display. An Adafruit Fingerprint Sensor verifies voter identity before allowing access to voting buttons. Once authenticated, the voter selects their preferred candidate using dedicated push buttons.
The system features a 16×2 I2C LCD display that provides on-screen instructions, voter verification status, candidate names, and real-time vote counts. A buzzer gives audible confirmation after successful fingerprint verification and vote submission. A servo motor acts as a physical gate that opens only for authenticated voters. Vote counts are stored in EEPROM, so data is retained even after power loss.
This project demonstrates advanced embedded system concepts including serial communication with fingerprint modules, digital signal processing, real-time display management, and secure access control — all in a low-cost, practical prototype.
02 / WorkflowFunctional Workflow
-
1System Initialisation
Arduino initialises the LCD, fingerprint module, servo, and reads stored vote counts from EEPROM addresses 0, 1, and 2.
-
2Welcome Screen
LCD displays "Voting System by Finger Print" then transitions to the "Press Start to begin voting" prompt.
-
3Voter Presses Start
The start button (Pin 6) triggers the fingerprint scan sequence. LCD shows "Place Finger".
-
4Fingerprint Authentication
getFingerprintIDez()captures the image, converts it to a template, and performs a fast search against stored templates. -
5Authentication Result
On success: buzzer beeps, LCD shows "Allowed / Vote Now", servo opens the gate (0°). On failure: LCD shows "Fingerprint Not Found", buzzer beeps error pattern.
-
6Candidate Selection
Voter presses one of three candidate buttons (C1/C2/C3). Arduino increments the corresponding vote counter and writes it to EEPROM.
-
7Vote Confirmation & Gate Close
LCD confirms "Voted: Candidate X". Servo holds gate open for 5 seconds then closes (180°). LCD shows "Gate Closed".
03 / ComponentsKey Components
04 / CircuitCircuit Diagram
The diagram below shows all connections between components. Scroll horizontally on small screens. Colour-coded wires show signal type.
📋 Wiring Notes
- Fingerprint sensor VCC → 5V; TX → Arduino D2; RX → Arduino D3
- LCD: SDA → A4; SCL → A5 (hardware I2C on UNO)
- Servo signal → D5 (PWM); Servo VCC → 5V; Servo GND → GND
- Buzzer + → D8; Buzzer − → GND
- All buttons wired with INPUT_PULLUP — connect one leg to the pin, other to GND
- Use
SoftwareSerial(2,3)for fingerprint sensor to free hardware UART for debugging
Rendered from JSON — Components
Rendered from JSON — Connections
| From | To | Signal | Wire |
|---|
06 / TutorialStep-by-Step Tutorial
Follow these steps to build and program your biometric voting machine from scratch. Click each step to expand.
Collect all components: Arduino UNO, Adafruit fingerprint sensor (R307/R305), 16×2 I2C LCD, SG90 servo, active buzzer, 7 push buttons, breadboard, and jumper wires.
Open Arduino IDE and install these libraries via Sketch → Include Library → Manage Libraries:
Adafruit_Fingerprintby AdafruitLiquidCrystal_I2Cby Frank de BrabanderServo(built-in)EEPROM(built-in)SoftwareSerial(built-in)
Verify library versions — use Adafruit_Fingerprint v2.x or higher for fingerFastSearch() support.
The fingerprint sensor communicates via UART. Since we use SoftwareSerial to keep the hardware serial available for debugging:
- Fingerprint VCC → Arduino 5V
- Fingerprint GND → Arduino GND
- Fingerprint TX → Arduino D2 (SoftwareSerial RX)
- Fingerprint RX → Arduino D3 (SoftwareSerial TX)
In the code: SoftwareSerial fingerPrint(2, 3); — the first argument is RX, second is TX from Arduino's perspective.
Note: Some sensors require 3.3V — check your module's datasheet before connecting to 5V.
The I2C LCD reduces wiring significantly — only 4 wires needed:
- LCD VCC → 5V
- LCD GND → GND
- LCD SDA → Arduino A4
- LCD SCL → Arduino A5
Default I2C address is 0x27. If the display doesn't work, try 0x3F. Use an I2C scanner sketch to find the correct address.
In the code: LiquidCrystal_I2C lcd(0x27, 16, 2); followed by lcd.begin(16,2); — note this library uses begin() not init() in some versions.
Servo (SG90):
- Red wire → 5V | Brown wire → GND | Orange (signal) → D5
- Closed position = 180°, Open = 0°. Initialise with
myServo.write(180);in setup.
Buzzer:
- Positive (+) → D8 | Negative (−) → GND
- Active buzzer sounds when D8 goes HIGH. No additional resistor needed.
Push Buttons (all 7):
- One leg of each button → designated Arduino pin (see Pin Map above)
- Other leg → GND on breadboard
- Use
INPUT_PULLUPmode — button reads LOW when pressed - Pins: Start→D6, C1→D4, C2→A5, C3→A6, Enroll→A1, Delete→A0, Result→A4, Up→A2, Down→A3
Copy the full code from Section 07 below. Before uploading:
- Select Board: Arduino UNO and correct Port in Tools menu
- Click Upload (Ctrl+U)
- Open Serial Monitor at 9600 baud to see debug output
On power-up, LCD should show "Voting System / by Finger Print" then transition to "Finding Module". If it shows "Module Not Found", recheck fingerprint sensor wiring.
Troubleshooting:
- LCD blank: adjust contrast pot on the I2C backpack module
- Sensor not found: check TX/RX swap — they often need reversing
- Servo jitter: add a 100µF capacitor across the servo power lines
Before voting can begin, register voter fingerprints:
- Press the ENROLL button (A1) from the main screen
- LCD shows "Enroll Finger / Location: 0"
- Use UP (A2) / DOWN (A3) buttons to select the storage ID (0–24)
- Press DEL (A0) to confirm the selected location and begin capture
- LCD prompts "Place Finger" — place the finger firmly on the sensor
- After first scan: LCD shows "Remove Finger" — lift your finger
- Sensor captures a second scan and creates a combined template
- Template is stored in sensor memory at the selected ID
Repeat for each authorised voter. The sensor supports up to 127 fingerprints.
To delete a fingerprint: press DEL button from the main screen, select the ID, and confirm.
Voting Process:
- Voter presses START (D6) — LCD shows "Place Finger"
- Voter places finger on the sensor
- If matched: buzzer beeps once, LCD shows "Allowed / Vote Now", servo opens gate
- Voter presses C1, C2, or C3 button within 5 seconds
- LCD confirms "Voted: Candidate X", vote saved to EEPROM
- Servo closes automatically after 5 seconds
View Results:
- Press the RESULT button (A4) at any time
- LCD displays "Results: C1:X C2:Y C3:Z" for 5 seconds
- Counts are loaded from EEPROM on each boot — data is never lost
Reset votes: clear EEPROM addresses 0, 1, 2 manually with a separate sketch using EEPROM.write(addr, 0).
07 / CodeArduino Code
Upload the full sketch below via Arduino IDE. All five required libraries must be installed before compilation.
#include <Adafruit_Fingerprint.h> #include <LiquidCrystal_I2C.h> // I2C LCD library #include <SoftwareSerial.h> #include <Servo.h> #include <EEPROM.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD I2C address 0x27 SoftwareSerial fingerPrint(2, 3); // RX=2, TX=3 Servo myServo; Adafruit_Fingerprint finger = Adafruit_Fingerprint(&fingerPrint); // ── Button & pin definitions ──────────────────────────── #define enroll A1 #define del A0 #define up A2 #define down A3 #define startButton 6 // Start fingerprint scan #define resultbutton A4 #define candidate1 4 #define candidate2 A5 #define candidate3 A6 #define servoPin 5 #define buzzer 8 uint8_t id; int voteCount1, voteCount2, voteCount3; // ── Setup ─────────────────────────────────────────────── void setup() { delay(1000); myServo.attach(servoPin); myServo.write(180); // Gate closed initially pinMode(enroll, INPUT_PULLUP); pinMode(up, INPUT_PULLUP); pinMode(down, INPUT_PULLUP); pinMode(del, INPUT_PULLUP); pinMode(buzzer, OUTPUT); pinMode(candidate1, INPUT_PULLUP); pinMode(candidate2, INPUT_PULLUP); pinMode(candidate3, INPUT_PULLUP); pinMode(resultbutton,INPUT_PULLUP); pinMode(startButton, INPUT_PULLUP); lcd.begin(16, 2); lcd.print("Voting system"); lcd.setCursor(0, 1); lcd.print("by Finger Print"); delay(2000); lcd.clear(); finger.begin(57600); Serial.begin(9600); lcd.print("Finding Module"); delay(1000); if (finger.verifyPassword()) { Serial.println("Found fingerprint sensor!"); lcd.clear(); lcd.print("Module Found"); delay(1000); } else { lcd.clear(); lcd.print("Module Not Found"); lcd.setCursor(0, 1); lcd.print("Check Connections"); while (1); // Halt } // Load stored vote counts from EEPROM voteCount1 = EEPROM.read(0); voteCount2 = EEPROM.read(1); voteCount3 = EEPROM.read(2); } // ── Main Loop ─────────────────────────────────────────── void loop() { lcd.setCursor(0, 0); lcd.print("Press Start "); lcd.setCursor(0, 1); lcd.print("to begin voting"); if (digitalRead(startButton) == LOW) { lcd.clear(); lcd.print("Place Finger"); delay(2000); if (getFingerprintIDez() >= 0) { digitalWrite(buzzer, HIGH); delay(500); digitalWrite(buzzer, LOW); lcd.clear(); lcd.print("Allowed"); lcd.setCursor(0, 1); lcd.print("Vote Now"); handleVoting(); myServo.write(0); // Open gate delay(5000); myServo.write(180); // Close gate lcd.clear(); lcd.print("Gate Closed"); } delay(1000); } checkKeys(); delay(500); // Debounce delay } // ── Handle Voting ─────────────────────────────────────── void handleVoting() { lcd.clear(); lcd.print("Vote: C1 C2 C3"); while (true) { if (digitalRead(candidate1) == LOW) { voteCount1++; EEPROM.update(0, voteCount1); lcd.clear(); lcd.print("Voted: Candidate 1"); delay(2000); break; } else if (digitalRead(candidate2) == LOW) { voteCount2++; EEPROM.update(1, voteCount2); lcd.clear(); lcd.print("Voted: Candidate 2"); delay(2000); break; } else if (digitalRead(candidate3) == LOW) { voteCount3++; EEPROM.update(2, voteCount3); lcd.clear(); lcd.print("Voted: Candidate 3"); delay(2000); break; } } } // ── Show Results ──────────────────────────────────────── void showResults() { lcd.clear(); lcd.print("Results:"); lcd.setCursor(0, 1); lcd.print("C1:"); lcd.print(voteCount1); lcd.setCursor(6, 1); lcd.print("C2:"); lcd.print(voteCount2); lcd.setCursor(12, 1); lcd.print("C3:"); lcd.print(voteCount3); delay(5000); } // ── Check Admin Keys ──────────────────────────────────── void checkKeys() { if (digitalRead(enroll) == LOW) { lcd.clear(); lcd.print("Please Wait"); delay(1000); Enroll(); } else if (digitalRead(del) == LOW) { lcd.clear(); lcd.print("Please Wait"); delay(1000); delet(); } else if (digitalRead(resultbutton) == LOW) { showResults(); } } // ── Enroll Fingerprint ────────────────────────────────── void Enroll() { int count = 0; lcd.clear(); lcd.print("Enroll Finger"); lcd.setCursor(0, 1); lcd.print("Location:"); while (true) { lcd.setCursor(9, 1); lcd.print(count); if (digitalRead(up) == LOW) { count = (count + 1) % 25; delay(500); } else if (digitalRead(down) == LOW) { count = (count > 0) ? count - 1 : 24; delay(500); } else if (digitalRead(del) == LOW) { id = count; getFingerprintEnroll(); return; } else if (digitalRead(enroll) == LOW) { return; } } } // ── Delete Fingerprint ────────────────────────────────── void delet() { int count = 0; lcd.clear(); lcd.print("Delete Finger"); lcd.setCursor(0, 1); lcd.print("Location:"); while (true) { lcd.setCursor(9, 1); lcd.print(count); if (digitalRead(up) == LOW) { count = (count + 1) % 25; delay(500); } else if (digitalRead(down) == LOW) { count = (count > 0) ? count - 1 : 24; delay(500); } else if (digitalRead(del) == LOW) { id = count; finger.deleteModel(id); return; } else if (digitalRead(enroll) == LOW) { return; } } } // ── Capture & Store Fingerprint Template ──────────────── uint8_t getFingerprintEnroll() { int p; lcd.clear(); lcd.print("Finger ID:"); lcd.print(id); lcd.setCursor(0, 1); lcd.print("Place Finger"); while ((p = finger.getImage()) != FINGERPRINT_OK) { handleFingerprintErrors(p); } finger.image2Tz(1); lcd.clear(); lcd.print("Remove Finger"); delay(2000); p = finger.image2Tz(2); if (p == FINGERPRINT_OK && finger.createModel() == FINGERPRINT_OK) { finger.storeModel(id); } return p; } // ── Fast Fingerprint Match ────────────────────────────── int getFingerprintIDez() { if (finger.getImage() != FINGERPRINT_OK || finger.image2Tz() != FINGERPRINT_OK || finger.fingerFastSearch() != FINGERPRINT_OK) { lcd.clear(); lcd.print("Fingerprint Not Found"); digitalWrite(buzzer, HIGH); delay(1000); digitalWrite(buzzer, LOW); delay(2000); return -1; } return finger.fingerID; } // ── Fingerprint Error Handler ─────────────────────────── void handleFingerprintErrors(int errorCode) { lcd.clear(); if (errorCode == FINGERPRINT_NOFINGER) lcd.print("No Finger Detected"); else if (errorCode == FINGERPRINT_PACKETRECIEVEERR) lcd.print("Communication Error"); else if (errorCode == FINGERPRINT_IMAGEFAIL) lcd.print("Imaging Error"); delay(1000); }
08 / FeaturesTechnical Features
Biometric Authentication
Adafruit fingerprint sensor stores up to 127 unique templates. Fast search mode matches in under 1 second.
EEPROM Vote Persistence
Vote counts written to EEPROM with update() to minimise write cycles. Data survives power loss indefinitely.
16×2 I2C LCD Display
Provides real-time voter guidance, authentication status, and results display over just 2 wires (SDA/SCL).
Servo Gate Control
Physical access gate opens only for authenticated voters, held open for 5 seconds then auto-closes.
Dual-Mode Buzzer
Single beep confirms successful authentication. Extended beep signals fingerprint failure or error states.
Input Debouncing
Hardware INPUT_PULLUP with 500ms software debounce delay prevents false button triggers.
Anti-Duplicate Voting
Each voter must pass fingerprint authentication — the sensor rejects unregistered and repeat rapid attempts.
Admin Enroll & Delete
Dedicated enroll/delete buttons allow administrators to manage voter fingerprints without re-uploading code.
09 / ApplicationsApplications
This project demonstrates advanced embedded system concepts including serial communication with fingerprint modules, digital signal processing, real-time display management, and secure access control implementation — providing a scalable, practical prototype for biometric electronic voting.
Comments
Post a Comment