Introduction: Modular Arduino-powered Fingerprint Door Lock

There is nothing more frustrating than forgetting your dorm/apartment key and realizing it much later in front of your dorm/apartment door. Well if you have 30$ and a few hours to spare, you don't have to worry about forgetting your key ever again.

This Fingerprint door lock is made out of four main 3D printed parts that can be put together with a few screws. It can attach to a regular door handle with 2 screws( without damaging it), or can be edited(Editable Tinkercad files will be provided) to attach to different door handles. A servo is attached to the key with a nut and bolt. It has a reed switch so the door will be locked when it's closed. It has a button on the inside handle so the lock can be opened from the inside, and a fingerprint reader outside of the door. The door also can be opened with a key without using the fingerprint reader(does not work for all locks). And since the door lock is holding the handle a little bit loose, the door handle can move freely.

You can use a keypad, RFID scanner, combination, or something you created to unlock the door. I'll provide some links later in the steps so you can integrate other projects to it.

Step 1: The Idea

Last year while in summer school, I was staying in a quad dorm room, I got up a little bit early and found out my class was canceled. So I decided to take a shower(showers are outside the room in the hall). When I was back, the door was locked. I realized that my roommates had left the room since they all had morning classes. And there I was standing in front of the door only with a towel. No key ,no phone, no nothing.( for my luck the janitor on that floor had a master key so I got in).

later that year after I got home I decided to make a keypad door lock for my room

and the result was this mess:

http://imgur.com/AdtjTl4

Since this was my own room I hot glued most of the components onto the door. It was working very well however there were many problems with it. Since it was driving a deadbolt lock behind the door, In the case of a Power outage or a failure there was no way of unlocking the door from the outside.

When I saw the dorm Hack Contest the first thing that came to my mind was to revive this project. I thought of a way to attach the locking mechanism to the door and rotating the key itself. And since I have a 3d printer now, prototyping was much easier.

The idea was to create a door lock that can attach to any door and key without damaging the door.

Step 2: Tools & Parts

Here are the main parts I used in this project:

Arduino nano clone - 2.65$

9g Servo ( more powerful servo recomended) - 0.93$

Fingerprint sensor - 25.04$ ( I could not get it from Adafruit because they do not ship to my country)

buzzer (optional) - 0.38$

magnetic door reed switch - 2.95$

2x 1000ohm resistor

A push button

Tools:

  • Jumper cables for prototyping
  • 10x M3 bolts and nuts
  • A 3d printer
  • Soldering iron
  • Soldering proto-board

Step 3: Designing and Printing the Parts

here are the parts that I designed for a regular door handle and lock, you can edit the base by clicking ungroup. You can adjust the height of the base so it will match your lock:

Note:

while printing the base don't forget to generate support !

The Base

Other Parts

Step 4: Prototype Assembly (Electronics)

You should test your project before soldering anything permanently, and the best way to do that is by using jumper cables.

You can use other sensors instead of the Fingerprint Scanner, here are some examples.

Detecting a secret knock - https://www.instructables.com/id/Secret-Knock-Detec...

Combination Lock - https://www.instructables.com/id/Arduino-Combinatio...

Bluetooth lock (smartphone) - https://www.instructables.com/id/Arduino-Android-Ba...

If you encounter any problem please feel free to ask!

Step 5: The Code

How does it work?

The Arduino is reading the button,fingerprint sensor and reed switch constantly.

The door will stay locked if; (servo at 180 degrees)

  • The magnet is LOW.
  • The button is HIGH (pull-up resistor)
  • The reading from the fingerprint function equals to -1

The door will unlock if; (servo at 20 degrees)

  • The fingerprint sensor gets an ID
  • the button is pressed (reading LOW)

Setup

  1. download the Adafruit fingerprint library from here: https://github.com/adafruit/Adafruit-Fingerprint-S...
  2. Connect the arduino to your computer and upload the enroll.ino sketch from file > Examples > Adafruit Fingerprint Scanner
  3. Follow the guide and enroll your finger print to the scanner. The sacnner will store your fingerprint
  4. Now you can upload the project sketch and test it!

Note:

The servo will detach after completing its turn.(servo.detach()) This way the door can be unlocked with a key from the other side without damaging to the servo.

Here is the code:

https://github.com/gocivici/door-lock

/*************************************************** <br>  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



  These displays use TTL Serial to communicate, 2 pins are required to 
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!


  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution


  Edited by Görkem Bozkurt
 ****************************************************/


#include <Servo.h>
#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>
Servo myservo;
int getFingerprintIDez();
boolean lock = false;
int pos = 0;
int buzzer = 6;
int buttonPin = 7;
int magnet = 4;
boolean doorStatus = false;
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
SoftwareSerial mySerial(2, 3);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);


// On Leonardo/Micro or others with hardware serial, use those! #0 is green wire, #1 is white
//Adafruit_Fingerprint finger = Adafruit_Fingerprint(&Serial1);


void setup()  
{
  
  while (!Serial);  // For Yun/Leo/Micro/Zero/...
  pinMode(buzzer, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(magnet,INPUT);
  Serial.begin(9600);
  Serial.println("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);
  }
  Serial.println("Waiting for valid finger...");
}


void loop(){
//Serial.println(digitalRead(magnet));// test for magnet readings.


  if(doorStatus){
    if(digitalRead(magnet)==LOW){
      delay(1000);
      
      sweepc();//rotate servo from 20 to 180 degrees.
      doorStatus=false;
    }else{
      sweepcc();//rotate servo from 180 to 20 degrees.
      }
  }
  
  if(getFingerprintIDez()>=0||digitalRead(buttonPin)==LOW){
    digitalWrite(buzzer, HIGH);
    delay(200);
    digitalWrite(buzzer, LOW);
    doorStatus=true;
    
    sweepcc();
    
    delay(1000);
    }
  delay(50);            //don't need 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); 
}


// 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 sweepc(){
  if(lock==false){
  myservo.attach(5);
  for (pos = 20; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  lock=true;
  myservo.detach();
  }
  }
 void sweepcc(){
 if(lock){
  myservo.attach(5);
 for (pos = 180; pos >= 20; pos -= 1) { // goes from 180 degrees to 20 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);
 }
 lock = false;
 myservo.detach();
 }
 }

Step 6: Final Assembly

Notes
  • Before starting assembly, test your servo with the lock. If the servo is weak for the lock try another, more powerful servo.
  • Soldering is not necessary you can use a small breadboard to wire all the components
  • You can power the Arduino with USB or external power source. I'm currently using USB connected to a charger.

Step 7: Troubleshooting

-The servo can not unlock or lock the door

The lock can be hard to turn. The 9g servo can be weak for your lock. You can use a bigger more powerful servo to drive the lock.

-The lock slips off from the handle

You can put some ziplock in front and back of the handle to prevent it from sliding.

Step 8: What's Next

There are a lot of things to improve on this project, some of them are,

  • Battery power for emergency usage
  • A stepper could be better instead of a servo
  • Opening the door with a pebble watch using particle photon
  • A small OLED screen displaying the accuracy of the fingerprint scanner
  • A small interface to store new fingerprints ( Currently you have to program the fingerprint scanner for new prints manually)

If you have any feedback for this project I'd really like to hear them, all questions are welcome!

You can also contact me at gocivici@gmail.com.