Biometric Safe

There are 3 components to the Biometric Safe: The biometric fingerprint scanner, the keypad, and the safe itself. The scanner and keypad are both powered by an arduino. The safe will hold and be opened by the scanner and keypad.

Engineer

Giulia C

Area of Interest

Electrical/ Computer Engineering

School

Livermore High School

Grade

Incoming Senior

Third Milestone

My third milestone was assembling all of the components into the chest. I measured and cut a piece of cardboard to act as a sort of shelf to hold everything. I added a 6V battery pack to power the Arduino. I screwed down the battery and Arduino into the cardboard so it won’t shift when opening the chest. To access the fingerprint scanner and keypad from the outside I cut two holes into the right hand side of the chest. I cut a few holes into the cardboard shelf to attach the servo motor and to string the servo wires through to the Arduino. I stapled a zip tie on the inside of the chest so that it lines up with the paperclip on the servo. This acts as the locking mechanism.

Second Milestone

My second milestone was combining the fingerprint sensor with the keypad and motor. When you put your fingerprint on the fingerprint sensor it recognizes your ID, prints your information on the serial monitor, and then starts the keypad code so you can enter the four digit code. Once you put in the right code on the keypad it turns the motor 90 degrees. If you put in the wrong code it turns back. To set up the fingerprint scanner you enroll as many fingerprints as you want. It takes your print and converts it into an image, saving it as your ID. This is separate code from my combined code, so it is completed beforehand. The fingerprint scanner is set to scan for a finger every second. When you scan your finger to unlock the keypad it converts your finger to an image again and then compares it to the IDs it has saved. Once it finds a match, it tells the keypad to start recognizing button strokes. Some issues I ran into for this milestone was understanding the code for the fingerprint scanner and combining it with my existing keypad code. The fingerprint scanner code used a complicated library that made understanding certain unnamed parts difficult. When I combined the fingerprint scanner and keypad code the keypad stopped working. As I was troubleshooting I learned about and added more booleans to make it run smoother. In the end the only issue was the position of a delay. For my next milestone I plan to attach all of the components to the safe.

Code for Fingerprint Sensor and Keypad
#include <Adafruit_Fingerprint.h>
#include <Servo.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

bool fingerTF = false;

Servo myservo;
int angle = 0;

unsigned long previousTime = 0;
long interval = 5000;

#define Password_Length 5

char Data[Password_Length]; 
char Master[Password_Length] = "1234"; 
byte data_count = 0, master_count = 0;
bool Pass_is_good;
char customKey;

const byte ROWS = 4;
const byte COLS = 4;

char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {11, 10, 9, 8};
byte colPins[COLS] = {7, 6, 5, 4};

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x21, 16, 2);

#if defined(__AVR__) || defined(ESP8266)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 3);

#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial1

#endif


Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

void setup(){
lcd.init(); 
lcd.backlight(); 
Serial.begin(9600);
myservo.attach(12);

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);
delay(5);
if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!");
} else {
Serial.println("Did not find fingerprint sensor :(");
while (1) { delay(1); }
}

Serial.println(F("Reading sensor parameters"));
finger.getParameters();
Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX);
Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX);
Serial.print(F("Capacity: ")); Serial.println(finger.capacity);
Serial.print(F("Security level: ")); Serial.println(finger.security_level);
Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX);
Serial.print(F("Packet len: ")); Serial.println(finger.packet_len);
Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate);

finger.getTemplateCount();

if (finger.templateCount == 0) {
Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
} 
else {
Serial.println("Waiting for valid finger...");
Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");
} 

}

void loop(){


if (!fingerTF){
fingerTF = getFingerprintID();
delay(1000); //time delay for fingerprint falsh
}
else{


char customKey = customKeypad.getKey();

lcd.setCursor(0,0);
lcd.print("Enter Password:");

customKey = customKeypad.getKey();
if (customKey){
Serial.println(customKey);
Data[data_count] = customKey; 
lcd.setCursor(data_count,1); 
lcd.print(Data[data_count]); 
data_count++; 
}

if(data_count == Password_Length-1){
lcd.clear();

if(!strcmp(Data, Master)){
lcd.print("Correct");

myservo.write(0);
delay(1000);

}
else{
lcd.print("Incorrect");

myservo.write(90);
delay(1000);

}

lcd.clear();
clearData(); 
}
}

}

bool 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 false;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return false;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error");
return false;
default:
Serial.println("Unknown error");
return false;
}

// OK success!

p = finger.image2Tz();
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
Serial.println("Image too messy");
return false;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error");
return false;
case FINGERPRINT_FEATUREFAIL:
Serial.println("Could not find fingerprint features");
return false;
case FINGERPRINT_INVALIDIMAGE:
Serial.println("Could not find fingerprint features");
return false;
default:
Serial.println("Unknown error");
return false;
}

// OK converted!
p = finger.fingerSearch();
if (p == FINGERPRINT_OK) {
Serial.println("Found a print match!");
} else if (p == FINGERPRINT_PACKETRECIEVEERR) {
Serial.println("Communication error");
return false;
} else if (p == FINGERPRINT_NOTFOUND) {
Serial.println("Did not find a match");
return false;
} else {
Serial.println("Unknown error");
return false;
}

// found a match!
Serial.print("Found ID #"+ finger.fingerID);
Serial.println(" with confidence of "+ finger.confidence);
Serial.println("Enter Code");
bool fingerTF = true;
// return finger.fingerID;

return true;

}

// 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("Found ID #"); Serial.print(finger.fingerID); 
Serial.print(" with confidence of "); Serial.println(finger.confidence);

return finger.fingerID; 
}

void clearData(){
while(data_count !=0){
Data[data_count--] = 0; 
}
return;
}

First Milestone

My first milestone was getting the keypad to work with a servo motor. When you input in the correct four digit pass code onto the keypad it sends a signal to the arduino telling the motor to turn 90 degrees. If you put in the wrong passcode it will move back to its original position. This represents the unlocking and locking of the safe. I also added a green and red LED to signal if the passcode was correct or incorrect. Another addition I made was a timer that starts counting down if the data count is less than four. This was so that if someone, for example, put only three numbers in, the keypad would reset after 5 seconds so they can then put in the correct passcode more easily. Some issues I ran into were figuring out a good way to wire the breadboard, understanding the keypad coding and library, and adding the timer to reset the keypad input.

Code for Keypad
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Servo.h>

Servo myservo;
int angle = 0;
int lightOutput = 11;
int lightOutput2 = 10;

unsigned long previousTime = 0;
long interval = 10000;

#define Password_Length 5

char Data[Password_Length]; 
char Master[Password_Length] = "9511"; 
byte data_count = 0, master_count = 0;
bool Pass_is_good;
char customKey;

const byte ROWS = 4;
const byte COLS = 4;

char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {11, 10, 9, 8};
byte colPins[COLS] = {7, 6, 5, 4};

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x21, 16, 2);

void setup(){
lcd.init(); 
lcd.backlight(); 
myservo.attach(12);
pinMode(lightOutput, OUTPUT);
pinMode(lightOutput2, OUTPUT);
Serial.begin(9600);
}

void loop(){

unsigned long currentTime = millis();
if (currentTime - previousTime > interval){
previousTime = currentTime;
lcd.clear();
clearData();
delay(150);

}

char customKey = customKeypad.getKey();

lcd.setCursor(0,0);
lcd.print("Enter Password:");

customKey = customKeypad.getKey();
if (customKey){
Serial.println(customKey);
Data[data_count] = customKey; 
lcd.setCursor(data_count,1); 
lcd.print(Data[data_count]); 
data_count++; 
}

if(data_count == Password_Length-1){
lcd.clear();

if(!strcmp(Data, Master)){
lcd.print("Correct");
delay(500);
digitalWrite(lightOutput, HIGH);
myservo.write(0);
delay(1000);
digitalWrite(lightOutput, LOW);

}
else{
lcd.print("Incorrect");
digitalWrite(lightOutput2, HIGH);
myservo.write(90);
delay(1000);
digitalWrite(lightOutput2, LOW);
}

lcd.clear();
clearData(); 
}

}

void clearData(){
while(data_count !=0){
Data[data_count--] = 0; 
}
return;
}

Starter Project

Start typing and press Enter to search

Bluestamp Engineering
BlueStamp and COVID-19 Summer 2020 was fully remote and a huge success! We hope to offer both remote and in person programming for 2021! More Information