Introduction: UCL-Embedded - Arduino Door Lock

This project was created by Daniel Månsson [], Flemming Andersen [flem781a] and Mikkel Pavia [mikk24b9] as an exam project at the school University College Lillebælt.

As a part of one of our electives, during second semester, in automation engineering, we were tasked with creating an Arduino project.

As a student at our school, you get an RFID chip to allow you access to certain areas of the school as well as entrance to the school after opening hours - we wanted to create an add-on for existing door locks at home. The door lock will feature a keypad, an RFID reader, Bluetooth connectivity and a display.

The parts needed for attaching the servo to the deadbolt on the door were printed using a Ultimax 2+ 3D printer.

Step 1: Components

Here are the components we used for our setup, you can probably mix/match various models.
The following components can be purchased from various sellers, such as Aliexpress or eBay.

The components we used to success are as following:

  • Arduino MEGA (2560R3)
  • Servo (MG996R)
  • SD-card module (No model no.)
  • Real time Clock (DS3231)
  • Bluetooth (hc-05)
  • RFID (RC522)
  • Keypad 4*4 (membrane matrix)
  • LCD 16*2 (1602A)
  • RFID Tag
  • SD
  • Resistor (2k and 220)
  • Led (Green, Red)
  • Switch
  • Potentiometer
  • SD card fitting the module
  • Android Phone

A more complete list with both amounts, model and a links to a danish vendor is attached.

Step 2: How It Should Work

When first connected to power the door lock starts out by locking, then sits 'idle', awaiting any user input.

If the keypad is pressed, it starts checking up the pressed key against the stored password.
If a wrong key is pressed it increases the wrong counter.
When 4 digits have been pressed, it will check the wrong counter, if above '0' the LCD prints "Wrong Password" and the lock will stay locked.
If 4 digits have been pressed and the wrong counter is '0' the LCD prints "Password Accepted" and the lock unlocks.
if however pressing '#' or '*' during any of this it will reset the process & counter values.

If Bluetooth data is received, it reads the received data - if this data is '1' the lock unlocks, it also sends back "Unlocked" to the Bluetooth device(Android Phone)

The RFID module scans if there is any readable tags nearby, if there isn't it simply skips over. If there is a readable tag nearby - it reads the tags value and matches it up against our predefined tags, if it doesn't match it simply prints "Not Authorized" on the LCD. If the tag matches up, it prints "Welcome " and unlocks the door. It will also save the date and time including the tag holder's name to a text file on the SD card.

When the lock unlocks, it sets a step, this is used to check when the door opens/closes so the lock will engage again. It basically uses 3 steps to keep track of where it is, the operation is done with a simple switch currently.

Successfully unlocking will also lit a green led, just like a red led will be lit if it is currently locked.

We've attached a flowchart above that simplifies this.

Step 3: Wiring and Electrical Component Setup

We've made use of the Fritzing software to sketch up our wiring.
To make the Fritzing schematic easier to do, we also made up an IO/Arduino mega pin list - both of these are also included in our files.

In the electrical diagram above, you will find every necessary connection between the components including an overview of the wiring.

Since we're using quite a few wires and the double row at the bottom of the Arduino the wire points can be quite hard to see with this quality, we recommend downloading the picture and zooming in.

As you can see we're wiring only a few things to the breadboard, mostly power(5 V) and GND, this however doesn't reflect our real world test setup where we used the breadboard for holding most of the modules excluding SD Card and the keypad, this will also be shown in a later step.

Also do note that we're using a potentiometer to control the brightness of the LCD.

listing the 'larger' objects/modules from left to right: Servo, DS3231, HC-05, Breadboard+Arduino, RC522, SD card, LCD, Keypad.

In the Diagram above + leading wires are red for 5 V, brown for 3.3 V, -(GND) leading wires are blue.

Step 4: Programming the Arduino

So programming the Arduino itself - this is where the fun begins - we've attached 5 pictures above with different sections of the code. This is the code from our testing setup where we had a lot of troubleshooting serial prints in the code, they were a great help to see where we got stuck/what we did wrong.

The code has been compressed a bit to fit the pictures better.

The first picture above is what we're initializing and global variables:
Lines below:
1 initializing the software serial, including setting the pins so we don't have to use the HW serial.
4 initializing the real time clock module
7-9 defining pins including slave select pin for RFID module, and creating the instance.
12-13 defining the slave select pin for our SD card module, also setting the file variable
16-28 defining(mapping) the layout of the keypad, rows and columns, also setting the pins used.
31 defining the pins used for the LCD.
33-37 declaring the variables.
40 defining the servo motor.
43 our string variable containing the default password.
44-45 variables for LCD position and keypad presses.

The second picture above is programming the keypad:
3-4 are the variables used to track what is pressed on the keypad and also the 'key' password.
6-12 are printing the key pressed to the LCD, the delay makes the code wait a few seconds before the key pressed disappears on the LCD.
13-18 are simply what should happen if the '*' or '#' is pressed - in our case its a reset.
19-23 what happens if the pressed key matches our predefined password.
25-29 if the pressed key does not match our predefined password.
31-44 what happens if we reached the max length of our password (4 digits) and we've had wrong key presses.46-60 and at last if we've reached max length and there have been no wrong inputs

The third picture above is programming the Bluetooth:
2 here we check if there is any data coming from the Bluetooth on the serial port.
3 Since we're only handling a simple '1' from the Bluetooth the code here reads from the serial and puts it in our variable.

4-8 what happens if there was a '1' coming from the Bluetooth connection, here we also send back "Unlocked" to the Bluetooth serial.

The fourth picture above is programming the RFID:
4-5 we're checking if there is a card nearby.
8-9 reading the value from the card.
12-18 adding the RFID value to our string variable.
20-21 basically making the content of our variable uppercase.
22 we're checking if the variable matches our predefined.
24-25 selecting our slave, we need the SD card module.
27 we're opening the file on the SD card so its ready to receive printed data.
29-69 if our variable data matches either of our predefined, we print name on the LCD, and print both date&time and the name to our log on the SD card.
70-72 calling the function "setlocked" and setting it false - unlocking the lock.
74-78 if the tag value didn't match our predefined.

Fifth picture above is our function actually controlling the servo:
3 if setLocked(true) is called.
5-10 attaching the servo and giving it a position to go to, basically locking the door.
12 if setLocked(false) is called
13-20 attach the servo and give it a position to go to, unlocking the door.

Step 5: Programming the Android Phone

We've made use of the simple to use web based MIT App Inventor 2 for programming the Android phone.

Not having used App Inventor before, we found it pretty simple and straight forward to use - since its made like a puzzle. We did however follow various guides for basic functionality.

First picture is how our simple app ended up looking - as you can see on the right side there are two buttons, one of them being a list.
Clicking the Bluetooth banner at the top reveals a Bluetooth list for the phone, tapping HC-05 will connect your phone to the Arduino Bluetooth module.
Then there's the unlock button - it does what it says, unlocks the door, we've got no way of locking the door, since if you open it, it'll auto lock when closing.
The first line of text simply shows if you're connected or not - in the actual app this is either red or blue depending on connection.
The second shows the current state of the lock.

The second picture is our block design(puzzle) - what the app actually does.
Starting from the top left we're basically telling it what to do when the Bluetooth banner is clicked.
Second part is that we're wanting to connect to the selected device in the popup.
Third part is what we want to do when clicking the unlock button - we're simply sending 49, and since this is sent with ASCII the number '49' equals '1' - so we're actually sending a '1' to the Arduino.

Moving on to the right side of the picture we're using a clock timer to update (somewhat real time) the connection text, so if the connection is dropped so will the text show.
We're also using this clock to send out our locked/unlocked status, this does have a downside of throwing a "no connected Bluetooth device" when starting the app up, but we'd prefer this over incorrect status.

Step 6: 3D Printing

As explained earlier we made use of some 3D printed parts for attaching the servo to the deadbolt.
The printer we had access to was an Ultimaker 2+, using 0.4 mm black PLA.
The software we used was Fusion 360 to edit the designs and Cura to make it suitable for the Ultimaker.
It is pretty simple, consisting of two things, one being the deadlock attachment, and the second being the mount for the servo - there is included a hole for for an led and also if wanted, a square hole for a button for manual operation.

The deadbolt attachment took just over three hours to print, the servo mount/housing took just over 21 hours to print.

Credits to Hacker Shack for the 3D design for the deadbolt
and a link to his:

Step 7: Testing Setup

Since we were all sort of new to programming Arduino - and just cause it is a good idea to test things out first before soldering everything together and possibly putting it in a nice box, we've made use of the large breadboard for attaching most things together. This does however make it quite messy to look at with all the wiring.

After making sure that everything was working as we wanted, all there was left is fitting the servo to the 3D printer adapter and attaching the servo to the housing using screws.
You might have to use spacers to make it fit your deadbolt.

Since this was a project in our semester, we didn't actually solder things together since we'd like to use our parts for different projects later - it would however have made it much better looking, being able to remove a lot of the wiring.

Step 8: Testing Setup - Youtube

Step 9: Full Code

<p>//Libraries used<br>#include <LiquidCrystal.h> //LCD MODULE<br>#include <Keypad.h> //Keypad MODULE<br>#include< MFRC522.h> //RFID MODULE<br>#include <SPI.h> //RFID AND SD CARD MODULES<br>#include <SD.h> //SD CARD MODULE<br>#include <DS3231.h> //RTC MODULE<br>#include <Servo> //Servo MODULE<br>#include <SoftwareSerial.h> //Software Serial</p><p>SoftwareSerial mySerial(10, 11); //SoftSerial initialize. pin number RX, TX</p><p>//Realtime clock hardware interface initialize
DS3231  rtc(SDA, SCL);</p><p>//RFID pins same instance
#define SSRFID_PIN 53 //SS PIN for RFID   //SS PIN (Slave Select)
#define RSTRFID_PIN 47                    //RST PIN
MFRC522 mfrc522(SSRFID_PIN, RSTRFID_PIN); //instance</p><p>//SD Card
#define SSSD_PIN 54 //SS PIN (Slave Select)
File myFile;        //File being used</p><p>//KEYPAD Grid
const byte ROWS = 4; //keypad Rows
const byte COLS = 4; //keypad Columns
//layout af keypad
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
byte rowPins[ROWS] = {31, 33, 35, 37}; //pinout Rows
byte colPins[COLS] = {39, 41, 43, 45}; //pinout Columns</p><p>Keypad keyPad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);</p><p>//LCD RELATED
LiquidCrystal lcd(22, 23, 24, 25, 26, 27); //LCD pins</p><p>int redPin = 2;   //Red LED Pin (No Access)
int greenPin = 3; //Green LED Pin (Access Granted)
int doorPin = 5;  //Door Magnet (HIGH if door is closed)
int steps = 0;    //Step counter for door + locking control
int state = 0;    //Bluetooth state</p><p>//Servo (needed in setlocked function)
Servo servo_Motor;</p><p>String password = "1234"; //Keypad Default Password
int position = 0; // Variable for Cursor(LCD) and Password position(0-3  = 4)
int wrong = 0; // Variabel for wrong password</p><p>//RFID
//1A 83 57 D3 = Blue RFID Tag
//52 0B C6 1F = White Creditcard Tag</p><p>void setup() {
  Serial.begin(9600); //Start the Serial Function(to communicate over USB)
  rtc.begin();        //Start the Real Time Clock</p><p>  mySerial.begin(9600); //Bluetooth Serial</p><p>  pinMode(doorPin, INPUT_PULLUP);</p><p>  //SD CARD
  pinMode(46, OUTPUT);  //Changes pin 46 to output mode (SS pin)
  digitalWrite(46, HIGH); //Has to be high from startup since we're using RFID</p><p>  //RFID
  pinMode(53, OUTPUT);  //Changes pin 53 to output mode (SS pin)
  digitalWrite(53, LOW); //Has to be low from startup so RFID is used.
  SPI.begin();          //Start the SPI (Serial Peripheral Interface) for RFID&SDCard
  mfrc522.PCD_Init();   //Start the RFID</p><p>  if (!SD.begin(46)) {                     //Start the SD library and Card (! for invert)
    while (1);
  Serial.println("initialization done."); //Troubleshoot Serial</p><p>  lcd.begin(16, 2); //LCD Size
  servo_Motor.attach(6); //Attach Servo to pin 6(PWM)
  setLocked(true); //Locks the first time during setup
}</p><p>void loop() {</p><p>  lcd.clear(); //Clears the LCD
  lcd.print("Enter Password:"); //Prints on the LCD
  delay(100);</p><p>  //Keypad</p><p>  char pressed = keyPad.getKey(); //Variable for pressed on keypad
  String key[4];  //Variable</p><p>  if (pressed) //If keypad pressed
    lcd.clear(); //Clear LCD
    lcd.print("Enter Password:"); //Print LCD
    lcd.setCursor(position, 1);   //Sets the cursor to our variable on the "second row"
    lcd.print(pressed);           //Prints the pressed key
    if (pressed == '*' || pressed == '#') //If Star or Square is pressed
      position = 0;   //Reset position
      setLocked(true);//Set locked
      lcd.clear();    //Clear LCD
    else if (pressed == password[position]) //Else if the pressed key matches the password position
      key[position] = pressed; //Adds the pressed to the key variable
      position++; //adds 1 to position
    }</p><p>    else if (pressed != password[position] ) //Else if pressed key doesnt match password position
      wrong++; //Add 1 to wrong variable
      position ++; //Add 1 to position
    }</p><p>    if (position == 4) //If position = 4 (password is max 4)
      if ( wrong > 0) //if the wrong variable is above zero</p><p>      {
        wrong = 0; //Reset wrong variable
        position = 0; //Reset position variable
        lcd.clear(); //Clear LCD
        lcd.print("WRONG"); //print
        lcd.setCursor(5, 1); //sets cursor position LCD
        lcd.print("PASSWORD"); //print
        setLocked(true); //set locked
      }</p><p>      else if (position == 4 && wrong == 0) //If position is 4 and wrong variable is zero
        position = 0; //reset position variable
        wrong = 0;    //reset wrong variable
        lcd.setCursor(6, 1);
        lcd.print("Door Open");
        setLocked(false); //Unlocking
        steps = 1; //sets step to 1
      }</p><p>    }
  else if (mySerial.available() > 0) { // Checks whether data is comming from the serial port
    state =; // Reads the data from the serial port
    if (state == '1') {
      lcd.clear();    //Clear LCD
      lcd.print("Bluetooth Open"); //LCD print
      setLocked(false); //unlocking
      steps = 1; //sets steps so door autolock works
      mySerial.println("Unlocked"); // Send back the String "Unlocked"
  }</p><p>  //RFID</p><p>  else {
    //Wait for a card
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
    //Read Card value
    if ( ! mfrc522.PICC_ReadCardSerial()) {
    }</p><p>    String content = "";    //Variable for UID from tag
    for (byte i = 0; i < mfrc522.uid.size; i++) {
      content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
      content.concat(String(mfrc522.uid.uidByte[i], HEX));
    }</p><p>    //Compare RFID Tags and do XX</p><p>    content.toUpperCase();
    content = content.substring(1);
    if ((content == "1A 83 57 D3") || (content == "52 0B C6 1F")) { //If variable content matches either tag</p><p>      digitalWrite(53, HIGH); //SS Pin RFID HIGH to not use
      digitalWrite(46, LOW);  //SS pin SD Card LOW to use</p><p>      myFile ="log.txt", FILE_WRITE); //Opens the file on SDCARD</p><p>      if (content == "1A 83 57 D3") { //If variable matches
        lcd.setCursor(3, 0);
        lcd.print("Velkommen"); //Print welcome LCD
        lcd.setCursor(4, 1);
        lcd.print("Flemming"); //print name LCD
        //SD START
        myFile.print(rtc.getDateStr()); //Prints the RTC Date to SD card
        myFile.print(" ");              //Prints a space
        myFile.print(rtc.getTimeStr()); //Prints RTC Time HH/MM/SS
        myFile.print(" ");              //Prints a space
        myFile.println("Flemming");     //Prints the name entering
        myFile.close();                 //Closes the file opened on the SD Card
        digitalWrite(46, HIGH); //SS pin SD card High
        digitalWrite(53, LOW);  //SS pin RFID Low
      if (content == "52 0B C6 1F") {
        lcd.setCursor(3, 0);
        lcd.setCursor(4, 1);
        myFile.print(rtc.getDateStr()); //Prints the RTC Date to SD card
        myFile.print(" ");              //Prints a space
        myFile.print(rtc.getTimeStr()); //Prints RTC Time HH/MM/SS
        myFile.print(" ");              //Prints a space
        myFile.println("Mikkel");     //Prints the name entering
        myFile.close();                 //Closes the file opened on the SD Card
        digitalWrite(46, HIGH); //SS pin SD card High
        digitalWrite(53, LOW);  //SS pin RFID Low
      setLocked(false);  //Unlocking
      steps = 1; //Setting step 1</p><p>    }
    else { //If RFID Tag doesnt match
      lcd.clear();                 //Clear LCD
      lcd.print("Not Authorized"); //Print LCD
  }</p><p>  //Door Magnet, closed, open, closed (For relocking)</p><p>  while (steps > 0) { //If steps is above 0
    if ((steps == 1) && (digitalRead(doorPin) == HIGH )) {  //If step = 1 read the doorpin if high (closed) continue
      steps = 2;  //Set step 2
    if ((steps == 2) && (digitalRead(doorPin) == LOW)) { //if step = 2 read the doorpin if low (open)
      steps = 3; //set step 3
    if ((steps == 3) && (digitalRead(doorPin) == HIGH)) { //If step = 3 read the doorpin if high (closed) continue
      setLocked(true); //set locked
      lcd.clear();     //Clear LCD
      lcd.print("Enter Password:"); //LCD print
      mySerial.println("locked"); // Send back the String "locked"
      steps = 0;       //set steps = 0
} //loop end</p><p>void setLocked(int locked)  //function for the doorlock
  if (locked) //if locked is true, lock
    digitalWrite(redPin, HIGH); //Red on
    digitalWrite(greenPin, LOW); //Green off
    servo_Motor.attach(6); //attach servo to pin 6
    servo_Motor.write(150); //write Servo position
    servo_Motor.detach(); //deattach servo
  else //if locked is false, unlock
    digitalWrite(redPin, LOW); //Red off
    digitalWrite(greenPin, HIGH); //Green on
    servo_Motor.attach(6); //Attach Servo to pin 6
    servo_Motor.write(0); //write servo position
    servo_Motor.detach(); //Deattach Servo

Step 10: Final Thoughts

This turned out to be a fun little project for our second semester in automation.

The upside:
Fun and functional project, we've got to try out things like building a simple app using MIT App Inventor 2 and using the Ultimaker 3D printers, also fiddling around with all the wires on the breadboard, making the code actually work - it did give some insight to how text based programming works.

The downside:
Possibly not the most secure (there is none) smart lock - also that it doesn't leave the smallest of footprints - even the Arduino and breadboard is quite large.

Possible future upgrades:
Changes to the 3D design, both to make it leave less of a footprint and also to make room for the Arduino - this could include using a cogwheel function so the servo can sit on the side along with the Arduino.
Also soldering things together as said earlier, the wires are quite messy.

Adding some sort of security, to make it actually suitable for a front door.

Final comments:
Looking back at the project it did turn out great - so overall we are very satisfied with our results with the amount of time we were given.

Arduino Contest 2019

Participated in the
Arduino Contest 2019