Arduino Door Lock with keypad + Solenoid / Relay and changeable code
Hi, and welcome to this tutorial, today I’m making a door lock project based on a Arduino board, keypad, LCD i²c screen, and I’ll use for the lock a solenoid and a relay, you can check my tutorial about the finger print door lock where I used a lock that uses a dc motor, so it depends on your locking system you’ll have to chose a wiring, codes and adapt them.
N.B: For a real project, I don’t recommend using a solenoid at all, but rather “hack” a lock that can be opened by both electronic and mechanic lock and adapt your project for it.
Hardware and parts
So for this project we will need those components, alongside some jump wires, and a power supply of 12V Sorry I didn’t add it here:
The Push Button is meant to open the lock from inside, you can remove it if you want, the resistor is for debounce.
I used 4×4 Keypad you can use 3×4 but you’ll need to modify somethings in the code like for confirmation I use ‘A’ you can change it to ‘*’ or ‘#’.
The solenoid is powered by 12V external power supply, and driven by the IRF510N MOSFET transistor.
The Transistor is used as a switch and it’s better to use an N-channel, the IRF510N is pretty popular when used with an Arduino, when you apply a 5V voltage across the Gate and the Source, the transistor becomes like a closed switch between the Drain and the Source, and it doesn’t need any resistor like bipolar ones.
And if there’s no voltage applied the transistor acts like an open switch, and this how we control the solenoid.
For the other example I’m using a 1 channel relay module, it works with 3.3V, and we control its input like controlling the transistor, the only difference is that they are inverted (we’ll see it in the code).
Algorithm flowchart
To make things easy to understand here’s the flowchart, it’s not completely detailed but it’s an overview of the code.
Wirings
Wiring 1: For the solenoid use
Wiring 2: For the relay use
N.B: You can use the relay to control any electric lock up to 250VAC, you can use it also to control the Solenoid…
Libraries
The only library I used is the LCD i²c NewLiquidCrystal: Download here
Keypad and EEPROM libraries are already installed.
Codes
Here you can download the codes I’ve created for the project: Download here code for solenoid and, Download here code for relay or check below
The codes are exactly the same the only thing is that you switch between (LOW and HIGH) to open the lock.
Just remember first time you must upload the code and change the passcode then uncomment some lines (read the code to find them (they’re in setup)) and reupload the code so it can read the passcode from the EEPROM.
IT’S DONE ONLY ONCE.
Code 1: Used with solenoid
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 |
/* This code works with 4x4 Keypad Matrix, LCD i²c, IRF510N transistor and a push button * It's a lock where the transistor drives a solenoid lock you can open either with correct code * or by the push button from inside * The code can be changed directly by the keypad and doesn't require uploading code again * Code is stored in EEPROM * Refer to http://www.surtrtech.com for more details */ #include <Keypad.h> #include <EEPROM.h> #include <LiquidCrystal_I2C.h> #define Solenoid 11 //Actually the Gate of the transistor that controls the solenoid #define O_Button 10 //Push Button #define I2C_ADDR 0x27 //I2C adress, you should use the code to scan the adress first (0x27) here #define BACKLIGHT_PIN 3 // Declaring LCD Pins #define En_pin 2 #define Rw_pin 1 #define Rs_pin 0 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7 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'} }; char keypressed; //Where the keys are stored it changes very often char code[]= {'6','6','0','1'}; //The default code, you can change it or make it a 'n' digits one char code_buff1[sizeof(code)]; //Where the new key is stored char code_buff2[sizeof(code)]; //Where the new key is stored again so it's compared to the previous one short a=0,i=0,s=0,j=0; //Variables used later byte rowPins[numRows] = {9,8,7,6}; //Rows 0 to 3 //if you modify your pins you should modify this too byte colPins[numCols]= {5,4,3,2}; //Columns 0 to 3 LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); void setup() { lcd.begin (16,2); lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); //Lighting backlight lcd.home (); lcd.print("Standby"); //What's written on the LCD you can change pinMode(Solenoid,OUTPUT); pinMode(O_Button,INPUT); // for(i=0 ; i<sizeof(code);i++){ //When you upload the code the first time keep it commented // EEPROM.get(i, code[i]); //Upload the code and change it to store it in the EEPROM // } //Then uncomment this for loop and reupload the code (It's done only once) } void loop() { keypressed = myKeypad.getKey(); //Constantly waiting for a key to be pressed if(keypressed == '*'){ // * to open the lock lcd.clear(); lcd.setCursor(0,0); lcd.print("Enter code"); //Message to show GetCode(); //Getting code function if(a==sizeof(code)) //The GetCode function assign a value to a (it's correct when it has the size of the code array) OpenDoor(); //Open lock function if code is correct else{ lcd.clear(); lcd.print("Wrong"); //Message to print when the code is wrong } delay(2000); lcd.clear(); lcd.print("Standby"); //Return to standby mode it's the message do display when waiting } if(keypressed == '#'){ //To change the code it calls the changecode function ChangeCode(); lcd.clear(); lcd.print("Standby"); //When done it returns to standby mode } if(digitalRead(O_Button)==HIGH){ //Opening by the push button digitalWrite(Solenoid,HIGH); delay(3000); //Opens for 3s you can change digitalWrite(Solenoid,LOW); } } void GetCode(){ //Getting code sequence i=0; //All variables set to 0 a=0; j=0; while(keypressed != 'A'){ //The user press A to confirm the code otherwise he can keep typing keypressed = myKeypad.getKey(); if(keypressed != NO_KEY && keypressed != 'A' ){ //If the char typed isn't A and neither "nothing" lcd.setCursor(j,1); //This to write "*" on the LCD whenever a key is pressed it's position is controlled by j lcd.print("*"); j++; if(keypressed == code[i]&& i<sizeof(code)){ //if the char typed is correct a and i increments to verify the next caracter a++; //Now I think maybe I should have use only a or i ... too lazy to test it -_-' i++; } else a--; //if the character typed is wrong a decrements and cannot equal the size of code [] } } keypressed = NO_KEY; } void ChangeCode(){ //Change code sequence lcd.clear(); lcd.print("Changing code"); delay(1000); lcd.clear(); lcd.print("Enter old code"); GetCode(); //verify the old code first so you can change it if(a==sizeof(code)){ //again verifying the a value lcd.clear(); lcd.print("Changing code"); GetNewCode1(); //Get the new code GetNewCode2(); //Get the new code again to confirm it s=0; for(i=0 ; i<sizeof(code) ; i++){ //Compare codes in array 1 and array 2 from two previous functions if(code_buff1[i]==code_buff2[i]) s++; //again this how we verifiy, increment s whenever codes are matching } if(s==sizeof(code)){ //Correct is always the size of the array for(i=0 ; i<sizeof(code) ; i++){ code[i]=code_buff2[i]; //the code array now receives the new code EEPROM.put(i, code[i]); //And stores it in the EEPROM } lcd.clear(); lcd.print("Code Changed"); delay(2000); } else{ //In case the new codes aren't matching lcd.clear(); lcd.print("Codes are not"); lcd.setCursor(0,1); lcd.print("matching !!"); delay(2000); } } else{ //In case the old code is wrong you can't change it lcd.clear(); lcd.print("Wrong"); delay(2000); } } void GetNewCode1(){ i=0; j=0; lcd.clear(); lcd.print("Enter new code"); //tell the user to enter the new code and press A lcd.setCursor(0,1); lcd.print("and press A"); delay(2000); lcd.clear(); lcd.setCursor(0,1); lcd.print("and press A"); //Press A keep showing while the top row print *** while(keypressed != 'A'){ //A to confirm and quits the loop keypressed = myKeypad.getKey(); if(keypressed != NO_KEY && keypressed != 'A' ){ lcd.setCursor(j,0); lcd.print("*"); //On the new code you can show * as I did or change it to keypressed to show the keys code_buff1[i]=keypressed; //Store caracters in the array i++; j++; } } keypressed = NO_KEY; } void GetNewCode2(){ //This is exactly like the GetNewCode1 function but this time the code is stored in another array i=0; j=0; lcd.clear(); lcd.print("Confirm code"); lcd.setCursor(0,1); lcd.print("and press A"); delay(3000); lcd.clear(); lcd.setCursor(0,1); lcd.print("and press A"); while(keypressed != 'A'){ keypressed = myKeypad.getKey(); if(keypressed != NO_KEY && keypressed != 'A' ){ lcd.setCursor(j,0); lcd.print("*"); code_buff2[i]=keypressed; i++; j++; } } keypressed = NO_KEY; } void OpenDoor(){ //Lock opening function open for 3s lcd.clear(); lcd.print("Welcome"); //With a message printed digitalWrite(Solenoid,HIGH); delay(3000); digitalWrite(Solenoid,LOW); } |
Code 2: Used with relay
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 |
/* This code works with 4x4 Keypad Matrix, LCD i²c, relay module and a push button * It's a lock where the relay can control a lock you can open either with correct code * or by the push button from inside * The code can be changed directly by the keypad and doesn't require uploading code again * Code is stored in EEPROM * Refer to http://www.surtrtech.com for more details */ #include <Keypad.h> #include <EEPROM.h> #include <LiquidCrystal_I2C.h> #define Relay 11 //Controls the Relay #define O_Button 10 //Push Button #define I2C_ADDR 0x27 //I2C adress, you should use the code to scan the adress first (0x27) here #define BACKLIGHT_PIN 3 // Declaring LCD Pins #define En_pin 2 #define Rw_pin 1 #define Rs_pin 0 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7 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'} }; char keypressed; //Where the keys are stored it changes very often char code[]= {'6','6','0','1'}; //The default code, you can change it or make it a 'n' digits one char code_buff1[sizeof(code)]; //Where the new key is stored char code_buff2[sizeof(code)]; //Where the new key is stored again so it's compared to the previous one short a=0,i=0,s=0,j=0; //Variables used later byte rowPins[numRows] = {9,8,7,6}; //Rows 0 to 3 //if you modify your pins you should modify this too byte colPins[numCols]= {5,4,3,2}; //Columns 0 to 3 LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); void setup() { lcd.begin (16,2); lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); //Lighting backlight lcd.home (); lcd.print("Standby"); //What's written on the LCD you can change pinMode(Relay,OUTPUT); pinMode(O_Button,INPUT); // for(i=0 ; i<sizeof(code);i++){ //When you upload the code the first time keep it commented // EEPROM.get(i, code[i]); //Upload the code and change it to store it in the EEPROM // } //Then uncomment this for loop and reupload the code (It's done only once) } void loop() { keypressed = myKeypad.getKey(); //Constantly waiting for a key to be pressed if(keypressed == '*'){ // * to open the lock lcd.clear(); lcd.setCursor(0,0); lcd.print("Enter code"); //Message to show GetCode(); //Getting code function if(a==sizeof(code)) //The GetCode function assign a value to a (it's correct when it has the size of the code array) OpenDoor(); //Open lock function if code is correct else{ lcd.clear(); lcd.print("Wrong"); //Message to print when the code is wrong } delay(2000); lcd.clear(); lcd.print("Standby"); //Return to standby mode it's the message do display when waiting } if(keypressed == '#'){ //To change the code it calls the changecode function ChangeCode(); lcd.clear(); lcd.print("Standby"); //When done it returns to standby mode } if(digitalRead(O_Button)==HIGH){ //Opening by the push button digitalWrite(Relay,LOW); delay(3000); //Opens for 3s you can change digitalWrite(Relay,HIGH); } } void GetCode(){ //Getting code sequence i=0; //All variables set to 0 a=0; j=0; while(keypressed != 'A'){ //The user press A to confirm the code otherwise he can keep typing keypressed = myKeypad.getKey(); if(keypressed != NO_KEY && keypressed != 'A' ){ //If the char typed isn't A and neither "nothing" lcd.setCursor(j,1); //This to write "*" on the LCD whenever a key is pressed it's position is controlled by j lcd.print("*"); j++; if(keypressed == code[i]&& i<sizeof(code)){ //if the char typed is correct a and i increments to verify the next caracter a++; //Now I think maybe I should have use only a or i ... too lazy to test it -_-' i++; } else a--; //if the character typed is wrong a decrements and cannot equal the size of code [] } } keypressed = NO_KEY; } void ChangeCode(){ //Change code sequence lcd.clear(); lcd.print("Changing code"); delay(1000); lcd.clear(); lcd.print("Enter old code"); GetCode(); //verify the old code first so you can change it if(a==sizeof(code)){ //again verifying the a value lcd.clear(); lcd.print("Changing code"); GetNewCode1(); //Get the new code GetNewCode2(); //Get the new code again to confirm it s=0; for(i=0 ; i<sizeof(code) ; i++){ //Compare codes in array 1 and array 2 from two previous functions if(code_buff1[i]==code_buff2[i]) s++; //again this how we verifiy, increment s whenever codes are matching } if(s==sizeof(code)){ //Correct is always the size of the array for(i=0 ; i<sizeof(code) ; i++){ code[i]=code_buff2[i]; //the code array now receives the new code EEPROM.put(i, code[i]); //And stores it in the EEPROM } lcd.clear(); lcd.print("Code Changed"); delay(2000); } else{ //In case the new codes aren't matching lcd.clear(); lcd.print("Codes are not"); lcd.setCursor(0,1); lcd.print("matching !!"); delay(2000); } } else{ //In case the old code is wrong you can't change it lcd.clear(); lcd.print("Wrong"); delay(2000); } } void GetNewCode1(){ i=0; j=0; lcd.clear(); lcd.print("Enter new code"); //tell the user to enter the new code and press A lcd.setCursor(0,1); lcd.print("and press A"); delay(2000); lcd.clear(); lcd.setCursor(0,1); lcd.print("and press A"); //Press A keep showing while the top row print *** while(keypressed != 'A'){ //A to confirm and quits the loop keypressed = myKeypad.getKey(); if(keypressed != NO_KEY && keypressed != 'A' ){ lcd.setCursor(j,0); lcd.print("*"); //On the new code you can show * as I did or change it to keypressed to show the keys code_buff1[i]=keypressed; //Store caracters in the array i++; j++; } } keypressed = NO_KEY; } void GetNewCode2(){ //This is exactly like the GetNewCode1 function but this time the code is stored in another array i=0; j=0; lcd.clear(); lcd.print("Confirm code"); lcd.setCursor(0,1); lcd.print("and press A"); delay(3000); lcd.clear(); lcd.setCursor(0,1); lcd.print("and press A"); while(keypressed != 'A'){ keypressed = myKeypad.getKey(); if(keypressed != NO_KEY && keypressed != 'A' ){ lcd.setCursor(j,0); lcd.print("*"); code_buff2[i]=keypressed; i++; j++; } } keypressed = NO_KEY; } void OpenDoor(){ //Lock opening function open for 3s lcd.clear(); lcd.print("Welcome"); //With a message printed digitalWrite(Relay,LOW); delay(3000); digitalWrite(Relay,HIGH); } |
Test
Well that was the test of the project, it’s the same for the solenoid or relay, and the push button opens from the inside if you want or you can remove it.
I hope it’s useful.
Categories
Yassine View All
Automation and Electrical Engineer, Electronics amateur trying to share my little projects.
How make it for 4 doorlock use relay 4 chanel with different passowrd ?
You can make 4 initial passcodes, and before you can change anyone of them you ask the user which one to changes ( you can do it by a switch case and test on the number entred 1-4, other than that is an error), then when getting the passcode you can compare it with the 4 codes and open the correspondant lock…
It just need some re arrangement, and add few lines.
I did this project too.How can I write the code that everyone has different passwords and these passwords are saved in EEPROM.Could you help me ?would you return to me?
You can add other codes arrays too, compare the input codes to them…
I want each password to belong to other users.When I enter A password, the door will open. When you enter B password, the door will open.I do not know how to do it.
Well this code contains the eeprom storage and the ability to change code… you better start with something that has only the code comparing, and instead of comparing the input to one code, you gonna try to compare it to both, and if one is correct the door will open.
Yassine I really need help for this. Can you help me ? I have a code of project (contain eeprom library). Can you do it for me?
Hello, I can help you if you already started something… It’s not a big deal.
the project code is ready but the door is opened with only one password.Can you add +4 password to eeprom memory.so there will be 5 passwords in total.Can you write your email address.I will send you project code.
What do you mean by adding 5 passcodes? Will they have the ability to be changed later through the keypad or not?
As I told you if you don’t need that just add the other codes arrays and inside the code compare the input to all of them, if one is correct it will open.
If you want to keep the ability to change the code, once the code is entered put a flag on that code previously stored and change it.
i was using your code with some changes. i dont know why i m unable to use the default password. it is always showing wrong password. just changed the display with oled
Hello, did you uncomment the “for loop that contains getting the code from the EEPROM”?
First you should upload the sketch as it is do not uncomment that line, then change the passcode from 6601 to anything 0000-9999 (if you want longer passcode change it from the program first).
Then when you change the passcode go back to the skech and uncomment those lines in the setup and reupload the sketch.
Explanation: What happens here is that everytime the Arduino starts it will go to the EEPROM and look for the correct passcode, the first time it will get unkown values stored there and can’t be used that’s why you comment those lines the first time then you change the code, chaning the code will store the new code in the EEPROM… and when you reupload the sketch with the uncommented lines the Arduino will look for the passcode in the EEPROM and will find what you stored there.
To sum up keep for loop commented, upload the sketch, change the passcode, uncomment the for loop and reupload the sketch.
Hey, I’m planning on using the circuit with the use of a solenoid for a safe locking mechanism. I was wondering, what would happen if the battery pack died while the door was locked? If I was able to access the Arduino board while it was locked would I be able to plug in a 12v supply to the Arduino board? or would this not activate the solenoid once the correct code is entered? any ideas.
The code is stored within the the EEPROM, when the Arduino resets it retrieves the New code that you’ve set and can open the door.
Of course always use an emergency power source unit.
can you use a IRF520NPBF mosfet instead of the 510
would you be able to let me know which items you used from the library for ‘keypad.h’ and ‘LiquidCrystal_I2C.h’.
hey there, I have managed to find the correct libraries but now I am having other issues with errors in the code at the moment i keep getting ”GetCode’ was not declared in this scope ‘and the same for ‘open door’. have I made a mistake? are you able to help me?
Did you change the name of the variables/functions? If yes, you should do so with the declarations too.
Hey Yassine, my code is working perfectly now, when the right code is entered the screen displays welcome and when the wrong code is entered the screen displays wrong. but there is something wrong with my circuit that i cant work out. it is the exact same as the circuit you have displayed in wiring one but when the screen displays welcome nothing happens to the solenoid and nothing happens when i push the button. what could be wrong? i checked the power and im getting 12v
i have the same circuit as wiring 1 but my solenoid stays on the whole time and will not react to the button or the keypad.
If you changed things in the original code or wiring, I’m sorry I cannot help, since I don’t know what you changed… just make sure the solenoid works properly by doing an individual test using transistor and the Arduino pin before you add anything else.
Can you explain the use of MOSFET in this project briefly?
Hello. I would like the screen to turn off. Press a key to light up. How can this be done? Can you help me with the code?
I am getting an error message which says
no matching function for call to ‘LiquidCrystal_I2C::LiquidCrystal_I2C(int, int, int, int, int, int, int, int)’
do you know what to do and also thank you so much.
Library problem.
Hi Yassine, Thanks for the awesome project. I have a push button with only NO CM and NC so i do not have the extra 3.3v wire leading to it. When the keypad goes into sleep it also puts the push button to sleep. Is there a way to work around this?