Originally published by Sep 16, 2016
Tired of being locked out when you lose or forget your keys? Well, I have the perfect solution for you! Today we will build an Arduino RFID door lock. I wanted to find an easy and secure way to lock a door, without having to buy an expensive locking device. We will learn about radio frequency identification (RFID) and make use of wireless communication.
“RFID stands for Radio-Frequency IDentification. […] The RFID device serves the same purpose as a bar code or a magnetic strip on the back of a credit card or ATM card; it provides a unique identifier for that object. And, just as a bar code or magnetic strip must be scanned to get the information, the RFID device must be scanned to retrieve the identifying information.” – ©Technovelgy – where science meets fiction.
RFID is used in this project to read data from the RFID tags and send the information to the non-volatile memory of the MCU. The ID read from the tags is compared with the stored information, and if it matches, then the door unlocks/opens.
The LCD has 16 pins which is too much for an Arduino Nano, that’s why it’s important to have an I2C adapter. This allows running the display from only 2 signal pins on the Arduino. It is helpful because of the small number of pins that will have to be controlled from the MCU.
Figure 1: LCD pins
The LCDs have a parallel interface, meaning that the MCU has to manipulate several interface pins at the same time to control the display. The table below gives a description for each of the pins:
Figure 2: Pin specification
First, we will make the connections between LCD and I2C. To do that, we need an I2C LCD display adapter (LCD1602). The adapter converts the 16 x 2 character LCD display into a serial I2C LCD that can be controlled via Arduino by just 2 wires.
Figure 3: Connections between Arduino and LCD
Next, we’ll add library “<LiquidCrystal_I2C.h>” in Arduino IDE. The library allows us to connect the LCD to the Arduino. The built-in LiquidCrystal_I2C library makes it easy to display characters on the LCD.
You can download the LiquidCrystal_I2C.h here.
Please follow the steps below to install a new library into your Arduino IDE.
1) First, download the files from Github. (I’ll be downloading Keypad library.)
2) Zip (.zip) each folder.
3) Copy the .zip files to your Arduino folder.
4) Open Arduino and add Keypad.zip: : Sketch menu > Include Library > Add .ZIP Library.
5) Add keypad library: Sketch menu > Include Library > Keypad.
1 2 3 4 5 6 7 8 9 10 11 |
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16 chars and 2 line display void setup() { lcd.begin();// initialize the LCD lcd.backlight();// Turn on the blacklight and print a message. lcd.backlight(); lcd.print("Hello, world!"); } void loop() { } |
Figure 4: LCD connected to Arduino Nano
Now, on to the keypad! We will connect the keypad in order to display the numbers on the LCD that we input from the keypad.
Keypad.h is a library which allows the Arduino to read a matrix type keypad.
I used a 4×4 keypad in this tutorial.
The table shows the connection between the Arduino board and the keypad. The keypad pins are connected to Arduino’s digital output pins. Pin D6 was used for the buzzer because it was a PWM pin.
Keypad pin | Arduino pin |
1 | D2 |
2 | D3 |
3 | D4 |
4 | D5 |
5 | A0 |
6 | D7 |
7 | D8 |
Figure 5: Connection between Arduino, LCD, and Keypad
Figure 6: LCD and Keypad connected to Arduino
Next, we will add the RFID. In this case, the RFID board uses a SPI communication protocol, where the Arduino will be acting as a master and the RFID reader as a slave. The card reader and the tags are designed to communicate using a frequency equal to 13.56MHz.
This is an important step because it helps us to read data from the card and it will decide if the ID corresponds to the information stored in the EEPROM. If it matches, it will give us access and display “Unlocked”. Otherwise, the LCD will display “Blocked”.
Figure 7: Connection between Arduino, LCD, and RFID
Figure 8: Arduino, LCD, and RFID
Next step is to add a buzzer and 2 LEDs to simulate a controlled access system. Please review the wire diagram below (Figure 9). The buzzer is set so that it buzzes whenever we gain access (unlocked). The red LED is always on when it is locked, but the green LED will come on when it is unlocked.
In order to protect the modules, I decided to 3D print the housing box/case. If you don’t have a 3D printer, you can just use a plastic case that allows you to fit all of the components inside. This is very helpful because the modules will be placed inside and the only parts outside of the box will be the LEDs, keypad, and LCD.
Figure 9: Wire diagram showing connection between Nano, LCD, Keypad, RFID, and buzzer
For this project, I wanted to create a custom case to house all of the components neatly and keep them free of damage.
I have designed a box using SketchUp, which has a user-friendly interface with simple buttons like Eraser, Lines, and Tape Measure Tool.
The dimensions of the box is 120x125x37 mm.
If you’re not familiar with Sketchup, I recommend you go through some SketchUp tutorials here.
Figure 10: Housing case (top view)
Figure 11: Housing case (bottom view)
When I designed the box, I took these dimensions into consideration:
After I measured the dimensions of the components, I designed a box that’s rather compact. Feel free to change the design to your preference.
Figure 12: Complete housing case with modules placed inside
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
#include <SPI.h> #include <MFRC522.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <Keypad.h> #include <EEPROM.h> int relPin; int state=0; byte COD[10]; byte AUX[10]; int k=0; String accessCode="*123456#"; String codpairing="*654321#"; //NFC #define RST_PIN 9 #define SS_PIN 10 MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance #define NEW_UID {0xDE, 0xAD, 0xBE, 0xEF} MFRC522::MIFARE_Key key; //LCD LiquidCrystal_I2C lcd(0x27,16,2); //KEYPAD const byte numRows= 4; //number of rows on the keypad const byte numCols= 4; //number of columns on the keypad char keymap[numRows][numCols]= { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; //Code that shows the the keypad connections to the arduino terminals byte rowPins[numRows] = {2,3,4,5}; //Rows 0 to 3 byte colPins[numCols] = {A0,7,8,9}; //Columns 0 to 3 //initializes an instance of the Keypad class Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); void setup() { pinMode(A0,OUTPUT); digitalWrite(A0,HIGH); pinMode(A3,OUTPUT); digitalWrite(A3,HIGH); pinMode(A1,OUTPUT); digitalWrite(A1,HIGH); pinMode(A2,OUTPUT); digitalWrite(A2,LOW); //NFC Serial.begin(9600); // Initialize serial communications with the PC while (!Serial); // Do nothing if no serial port is opened SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card for (byte i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; } lcd.begin(); lcd.backlight(); lcd.setCursor(0,0); lcd.clear(); lcd.print( "BLOCKED" ); } void readNFC(){ // This function will read the code stored on for (byte i =0; i<(mfrc522.uid.size); i++) { // the UID COD[i]=mfrc522.uid.uidByte[i]; } Serial.print("COD"); Serial.print(COD[0]); Serial.print(COD[1]); Serial.print(COD[2]); Serial.print(COD[3]); } void pairNFC(){ Serial.println("COD in pair"); Serial.print(COD[0]); Serial.print(COD[1]); Serial.print(COD[2]); Serial.print(COD[3]); long r=0; int c=0; for(int i=1;i<=EEPROM.read(0);i++){ //The UID cannot be stored on switch(i%4){ // one variable, it was needed to be case 1 :{AUX[0]=EEPROM.read(i); break;} // split case 2 :{AUX[1]=EEPROM.read(i); break;} case 3 :{AUX[2]=EEPROM.read(i); break;} case 0 :{AUX[3]=EEPROM.read(i); break;} } if((i)%4==0) {Serial.println(r); if( AUX[0]==COD[0] && AUX[1]==COD[1] && AUX[2]==COD[2] && AUX[3]==COD[3] ){ //Verify if the code is in EEPROM lcd.clear(); lcd.setCursor(0,0); lcd.print("CODE ALREADY IN"); lcd.setCursor(0,1); lcd.print("SYSTEM"); delay(2000); c=1; break;} } } if(c==0){int aux2=EEPROM.read(0); Serial.println("CODE PAIRED"); Serial.print(COD[0]); Serial.print(COD[1]); Serial.print(COD[2]); Serial.print(COD[3]); EEPROM.write(aux2+1,COD[0]); //Writing code in EEPROM EEPROM.write(aux2+2,COD[1]); EEPROM.write(aux2+3,COD[2]); EEPROM.write(aux2+4,COD[3]); aux2=aux2+4; // Position for a new code Serial.println("aux2"); Serial.println(aux2); EEPROM.write(0,0); EEPROM.write(0,aux2); lcd.clear(); lcd.setCursor(0,0); lcd.print("CODE PAIRED"); delay(2000); } } boolean validationNFC(){ boolean c=false; for(int i=1;i<=EEPROM.read(0);i++){ //Read the EEPROM switch(i%4){ case 1 :{AUX[0]=EEPROM.read(i); break;} case 2 :{AUX[1]=EEPROM.read(i); break;} case 3 :{AUX[2]=EEPROM.read(i); break;} case 0 :{AUX[3]=EEPROM.read(i); break;} } if((i)%4==0) { if( AUX[0]==COD[0] && AUX[1]==COD[1] && AUX[2]==COD[2] && AUX[3]==COD[3]) c=true; //Verify if the code is in EEPROM and make flag=true; } } return c; } int compareCODE(String a) //We type a code on keypad and this will be compared { //with the accessCode; if(a.equals(accessCode)) return 1; else if(a.equals(codpairing)) return 2; else return 0; } String takeCode(char x) //Will display on the LCD the code typed { char vec[10]; vec[0]=x; lcd.setCursor(0,0); lcd.clear(); lcd.print('X'); for(int i=1;i<8;i++) {vec[i]=myKeypad.waitForKey(); //Waits for 8 keys to be pressed and after that lcd.print('X');} //is taking the decision vec[8]=NULL; String str(vec); return str; } void loop() { switch(state){ case 0: { mfrc522.PCD_Init(); if ( mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial() ){ readNFC(); //It will read the card and it will search for UID in its if(validationNFC()) //memory { state=1; lcd.clear(); lcd.setCursor(0,0); lcd.print( "VALID NFC CODE" ); //The door will be opened delay(1000); return; } else{ lcd.clear(); lcd.setCursor(0,0); lcd.print( "INVALID NFC CODE" ) //If the code was wrongblocked delay(1000); lcd.setCursor(0,0); lcd.clear(); lcd.print( "BLOCKED" ); return; } } char c=myKeypad.getKey(); if(c != NO_KEY){ String codcurent=takeCode(c); int A=compareCODE(codcurent); if(A==0){ //A is a variable that stores the current code lcd.clear(); lcd.print("INVALID CODE"); delay(2000); lcd.setCursor(0,0); lcd.clear(); lcd.print("BLOCKED"); return; } if(A==1){ lcd.setCursor(0,0); lcd.clear(); lcd.print( "VALID CODE " ); delay(2000); state = 1; Return; } if(A==2); { state=2; lcd.clear(); lcd.setCursor(0,0); lcd.print( " Pairing..." ); delay(2000); return;} } break; } case 1:{ lcd.clear(); lcd.setCursor(0,0); lcd.print( "UNLOCKED" ); digitalWrite(A3,LOW); digitalWrite(A1,LOW); //The red LED will be off digitalWrite(A2,HIGH); //The green LED will be on tone(6,3000,5010); //The buzzer will make a sound delay(5000); //After 5 seconds the system will be blocked digitalWrite(A3,HIGH); digitalWrite(A1,HIGH); digitalWrite(A2,LOW); state=0; lcd.setCursor(0,0); lcd.clear(); lcd.print( "BLOCKED" ); return; } case 2:{ mfrc522.PCD_Init(); if ( mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial() ){ readNFC(); pairNFC(); state=0; delay(2000); lcd.clear(); lcd.setCursor(0,0); lcd.print( "BLOCKED" ); } break; } } } |
So, we managed to build a low-cost Arduino RFID door lock. It was an interesting project for me because I made it for my personal use. Moreover, building such a device will provide you not only the satisfaction of doing something useful, but also a lot of knowledge and an initiation in the first steps of custom electronics. Dealing with a wide range of boards will be definitely very challenging. The project presents a lot of interesting tasks, such as:
Click here to see Part 2 of this article, where we enable unlocking from a smartphone! Check out our Arduino projects section for other fun and challenging Arduino projects!
Want to learn more about how to make the most of your Arduino projects? Explore some of our in-depth Arduino guides: