Password
Door Lock
with Solenoid
A real, relay-controlled solenoid door lock using Arduino UNO, 4×4 keypad, I²C LCD, and a 7.4V Li-ion + MT3608 boost converter. Three-attempt lockout, auto-relock, animated LCD feedback.
How the System Works
The user enters a password on the keypad. Arduino compares it against the stored password using the Password library. On match, the relay de-energises to release the solenoid lock. Three wrong attempts trigger a 10-second lockout with alarm buzzer. Correct entry gives a 10-second unlock window before auto-relock.
Input
User presses digits on the 4×4 keypad. Each keypress shows * on LCD row 1.
Verify
Press D to submit. Password library compares entry to stored hash.
Actuate
Relay pin goes LOW → solenoid releases → door unlocks physically.
Auto-Relock
After 10 s countdown on LCD, relay returns HIGH and door locks again.
- 3 happy beeps from buzzer
- Relay → LOW (solenoid opens)
- LCD: "ACCESS GRANTED — DOOR OPEN"
- Countdown 10 s then auto-relock
- LCD: "DOOR LOCKED — See you soon!"
- Buzzer beeps for 3 seconds
- Relay stays HIGH (locked)
- LCD: "ACCESS DENIED — Attempts Left: N"
- After 3 failures: 10 s lockout + alarm
- LCD shows live countdown during lockout
Components Required
Eight components. The MT3608 boost converter is key — it steps the 7.4V Li-ion up to 12V needed by the solenoid lock.
| Component | Purpose | Buy |
|---|---|---|
| Arduino UNO | Main controller | Buy Now |
| MT3608 Boost Converter | 7.4V → 12V for solenoid | Buy Now |
| 16×2 LCD with I2C | SDA → A4, SCL → A5 | Buy Now |
| 4×4 Keypad | Pins D2–D9 | Buy Now |
| 5V Relay Module | Controls solenoid on D10 | Buy Now |
| Solenoid Lock | 12V electromagnetic latch | Buy Now |
| 7.4V Li-ion Battery | Powers MT3608 + Arduino | Buy Now |
| Jumper Wires | M-M, M-F assortment | Buy Now |
Pin Connections
Every wire in one place. The keypad occupies D2–D9, leaving D10 and D11 for relay and buzzer. The LCD uses the I²C bus on A4/A5 — no extra pins consumed.
| Component | Component Pin | Arduino Pin | Notes |
|---|---|---|---|
| 4×4 Keypad | Row 1–4 | D2, D3, D4, D5 | Row pins in order |
| 4×4 Keypad | Col 1–4 | D6, D7, D8, D9 | Column pins in order |
| 16×2 LCD (I²C) | SDA | A4 | I²C Data, addr 0x27 |
| 16×2 LCD (I²C) | SCL | A5 | I²C Clock |
| 16×2 LCD (I²C) | VCC | 5V | Arduino 5V rail |
| 16×2 LCD (I²C) | GND | GND | Common ground |
| 5V Relay Module | IN / Signal | D10 | HIGH = locked, LOW = open |
| 5V Relay Module | VCC | 5V | Arduino 5V rail |
| 5V Relay Module | GND | GND | Common ground |
| Active Buzzer | + (Positive) | D11 | Active buzzer, 5V logic |
| Active Buzzer | – (Negative) | GND | Common ground |
| MT3608 Boost | IN+ | 7.4V Bat+ | Battery positive |
| MT3608 Boost | IN– | GND (common) | Common ground rail |
| MT3608 Boost | OUT+ (12V) | Relay COM | 12V to relay common terminal |
| Solenoid Lock | + Wire | Relay NO | Relay Normally Open |
| Solenoid Lock | – Wire | GND (common) | Common ground rail |
| Arduino UNO | VIN | 7.4V Bat+ | Or use 5V from USB + separate 12V for solenoid |
Important: Set the MT3608 output to exactly 12V using the trim pot and a multimeter before connecting the solenoid. All grounds must share a common rail — Arduino GND, MT3608 IN–, and solenoid GND must all be joined together.
Keypad Key Functions
Only three special keys. All other keys (0–9, A, B, #) act as password characters.
Enter / Submit
Submits the entered password for verification.
Clear / Reset
Wipes all entered digits and returns to the entry screen.
Backspace
Deletes the last digit entered. Gives a short beep.
Password Digits
Each press appends a character. Shown as * on the LCD.
Assembly Steps
Set MT3608 Output Voltage
Connect 7.4V battery to MT3608 input. Use a multimeter on the output. Trim the onboard pot until output reads exactly 12V. Do this before wiring the solenoid.
Wire the Keypad
Connect keypad row pins R1–R4 to Arduino D2–D5. Column pins C1–C4 to D6–D9. Match the physical order on your keypad module.
Connect the I²C LCD
VCC → 5V, GND → GND, SDA → A4, SCL → A5. Default I²C address is 0x27. If display is blank, try 0x3F in the code.
Wire the Relay Module
Relay IN → D10, VCC → 5V, GND → GND. Connect MT3608 12V output to relay COM terminal. Solenoid + wire to relay NO (Normally Open) terminal.
Connect the Buzzer
Active buzzer positive → D11, negative → GND. Ensure it is an active buzzer (not passive) — it beeps with just a HIGH/LOW signal.
Common Ground Rail
Join Arduino GND, MT3608 IN–, relay GND, buzzer GND, and solenoid – wire all to the same ground rail. This is critical for proper operation.
Install Libraries & Upload Code
Install: Keypad (Mark Stanley), LiquidCrystal_I2C (Frank de Brabander), Password (Justin Shaw). Change the password string and PASSWORD_LEN in the code, then upload.
Power On & Test
Watch the welcome sequence on LCD. Enter your password and press D. Test wrong attempts to verify lockout. Confirm solenoid clicks on correct entry.
Full Tutorial Video
Complete wiring walkthrough, LCD animations, lockout demonstration, and solenoid operation in real-time.
Watch for exact wire routing — especially how the 12V solenoid power path runs through the relay. The video also shows MT3608 voltage adjustment and LCD I²C address troubleshooting.
Arduino Code
Change the password inside Password("1234") and update PASSWORD_LEN to match. Supports 4–8 digit passwords.
/*
* ========================================
* PASSWORD DOOR LOCK — SIMPLE CIRCUITS
* ========================================
* Components:
* - Arduino Uno
* - 4x4 Keypad → D2 to D9
* - 16x2 LCD I2C → A4 (SDA), A5 (SCL)
* - Relay Module → D10 (HIGH=locked, LOW=open)
* - Active Buzzer → D11
* - 7.4V Li-ion + MT3608 → 12V Solenoid
*
* Libraries needed:
* - Keypad (by Mark Stanley)
* - LiquidCrystal_I2C (by Frank de Brabander)
* - Password (by Justin Shaw)
*
* Keys:
* D = Enter / Submit
* C = Clear / Reset
* * = Backspace
* ========================================
*/
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Password.h>
// ─── PINS ───────────────────────────────────────────
#define RELAY_PIN 10
#define BUZZER_PIN 11
// ═══════════════════════════════════════════════════
// PASSWORD ← Change here
// ═══════════════════════════════════════════════════
Password password = Password("1234");
const byte PASSWORD_LEN = 4; // match length above (4–8)
// ─── SETTINGS ───────────────────────────────────────
const int MAX_ATTEMPTS = 3;
const long LOCKOUT_MS = 10000; // 10 sec lockout
const long UNLOCK_MS = 10000; // 10 sec auto-relock
const int WRONG_BEEP_MS = 160;
// ─── STATE ──────────────────────────────────────────
byte currentLen = 0;
int wrongAttempts = 0;
bool isLockedOut = false;
long lockoutStart = 0;
// ─── KEYPAD ─────────────────────────────────────────
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'D', 'C', 'B', 'A'},
{'#', '9', '6', '3'},
{'0', '8', '5', '2'},
{'*', '7', '4', '1'},
};
byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, 8, 9};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// ─── LCD ────────────────────────────────────────────
LiquidCrystal_I2C lcd(0x27, 16, 2); // try 0x3F if blank
// ─── CUSTOM LCD CHARACTERS ──────────────────────────
byte lockChar[8] = {0b01110,0b10001,0b10001,0b11111,0b11011,0b11011,0b11111,0b00000};
byte unlockChar[8] = {0b01110,0b10000,0b10000,0b11111,0b11011,0b11011,0b11111,0b00000};
byte noteChar[8] = {0b01111,0b01001,0b01001,0b01001,0b11001,0b11001,0b01110,0b00000};
byte starChar[8] = {0b00100,0b10101,0b01110,0b11111,0b01110,0b10101,0b00100,0b00000};
byte tickChar[8] = {0b00000,0b00001,0b00011,0b10110,0b11100,0b01000,0b00000,0b00000};
// ─── HELPERS ────────────────────────────────────────
int centerCol(int textLen) {
int col = (16 - textLen) / 2;
return (col < 0) ? 0 : col;
}
void printCenter(int row, String text) {
lcd.setCursor(0, row);
lcd.print(" ");
lcd.setCursor(centerCol(text.length()), row);
lcd.print(text);
}
int pwStartCol() {
int width = PASSWORD_LEN * 2 - 1;
return centerCol(width);
}
void drawPasswordRow() {
int col = pwStartCol();
lcd.setCursor(0, 1);
lcd.print(" ");
for (byte i = 0; i < PASSWORD_LEN; i++) {
lcd.setCursor(col + i * 2, 1);
lcd.print(i < currentLen ? '*' : '_');
}
}
// ═══════════════════════════════════════════════════
// SETUP
// ═══════════════════════════════════════════════════
void setup() {
pinMode(RELAY_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(RELAY_PIN, HIGH); // HIGH = locked
digitalWrite(BUZZER_PIN, LOW);
lcd.init();
lcd.backlight();
lcd.createChar(0, lockChar);
lcd.createChar(1, unlockChar);
lcd.createChar(2, noteChar);
lcd.createChar(3, starChar);
lcd.createChar(4, tickChar);
welcomeSequence();
showEnterPassword();
}
// ═══════════════════════════════════════════════════
// LOOP
// ═══════════════════════════════════════════════════
void loop() {
if (isLockedOut) {
long elapsed = millis() - lockoutStart;
if (elapsed >= LOCKOUT_MS) {
isLockedOut = false;
wrongAttempts = 0;
resetPW();
showEnterPassword();
} else {
int s = (LOCKOUT_MS - elapsed) / 1000 + 1;
lcd.setCursor(0, 1);
String line = " Wait: " + String(s) + "s ";
lcd.print(line.substring(0, 16));
}
return;
}
char key = keypad.getKey();
if (key == NO_KEY) return;
delay(60);
if (key == 'C') { resetPW(); showEnterPassword(); }
else if (key == '*') { if (currentLen > 0) { currentLen--; buzzOnce(60); drawPasswordRow(); } }
else if (key == 'D') { if (currentLen == 0) return; checkPassword(); }
else {
if (currentLen < PASSWORD_LEN) {
password.append(key);
currentLen++;
buzzOnce(160);
drawPasswordRow();
}
}
}
// ═══════════════════════════════════════════════════
// CHECK / GRANTED / DENIED
// ═══════════════════════════════════════════════════
void checkPassword() {
if (password.evaluate()) accessGranted();
else accessDenied();
}
void accessGranted() {
wrongAttempts = 0;
int col = pwStartCol();
for (byte i = currentLen; i < PASSWORD_LEN; i++) {
lcd.setCursor(col + i * 2, 1); lcd.print('*'); buzzOnce(50); delay(60);
}
for (int f = 0; f < 3; f++) {
lcd.setCursor(0, 1); lcd.print(" "); delay(120);
for (byte i = 0; i < PASSWORD_LEN; i++) { lcd.setCursor(col + i * 2, 1); lcd.print('*'); }
delay(120);
}
lcd.clear();
lcd.setCursor(0, 0); lcd.write(byte(1)); lcd.print(" ACCESS GRANTED");
lcd.setCursor(3, 1); lcd.write(byte(4)); lcd.print(" DOOR OPEN "); lcd.write(byte(4));
buzzOnce(100); delay(80); buzzOnce(100); delay(80); buzzOnce(300);
digitalWrite(RELAY_PIN, LOW);
for (int s = 10; s >= 1; s--) {
String line = "Locking in: " + String(s) + "s";
lcd.setCursor(0, 1); lcd.print(" ");
lcd.setCursor(centerCol(line.length()), 1); lcd.print(line); delay(1000);
}
digitalWrite(RELAY_PIN, HIGH);
lcd.clear();
lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.print(" DOOR LOCKED "); lcd.write(byte(0));
lcd.setCursor(centerCol(13), 1); lcd.print("See you soon!");
buzzOnce(200); delay(1500);
resetPW(); showEnterPassword();
}
void accessDenied() {
wrongAttempts++;
int left = MAX_ATTEMPTS - wrongAttempts;
for (int i = 0; i < 4; i++) {
lcd.clear(); lcd.setCursor(centerCol(14), 0); lcd.write(byte(0)); lcd.print(" WRONG!"); delay(90);
lcd.clear(); delay(70);
}
lcd.clear();
lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.print(" ACCESS DENIED ");
lcd.setCursor(0, 1);
if (left > 0) { String line = "Attempts Left: " + String(left); lcd.setCursor(centerCol(line.length()), 1); lcd.print(line); }
else { lcd.setCursor(centerCol(13), 1); lcd.print("Last Attempt!"); }
long beepStart = millis();
while (millis() - beepStart < 3000) { buzzOnce(WRONG_BEEP_MS); delay(WRONG_BEEP_MS); }
if (wrongAttempts >= MAX_ATTEMPTS) {
isLockedOut = true; lockoutStart = millis();
lcd.clear();
lcd.setCursor(0, 0); lcd.print("!! LOCKED OUT !!");
lcd.setCursor(centerCol(15), 1); lcd.print("Wait 10 seconds");
long alarmStart = millis();
while (millis() - alarmStart < 3000) { buzzOnce(150); delay(100); }
resetPW(); return;
}
resetPW(); showEnterPassword();
}
void showEnterPassword() {
lcd.clear();
lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.print(" Enter Password ");
drawPasswordRow();
}
void welcomeSequence() {
lcd.clear();
lcd.setCursor(0, 0); lcd.write(byte(2)); lcd.print(" SUBSCRIBE "); lcd.write(byte(2));
for (int i = 15; i >= 1; i--) {
lcd.setCursor(0, 1); lcd.print(" ");
lcd.setCursor(i, 1);
String s = "SIMPLE CIRCUITS";
int cv = 16 - i; if (cv > (int)s.length()) cv = s.length();
lcd.print(s.substring(0, cv)); delay(50);
}
delay(300);
buzzOnce(80); delay(100); buzzOnce(80); delay(100); buzzOnce(160); delay(300);
for (int i = 0; i < 3; i++) {
lcd.clear();
lcd.setCursor(0,0); lcd.write(byte(3)); lcd.setCursor(15,0); lcd.write(byte(3));
lcd.setCursor(centerCol(9), 0); lcd.print("SUBSCRIBE"); delay(130);
lcd.clear();
lcd.setCursor(1,0); lcd.write(byte(3)); lcd.setCursor(14,0); lcd.write(byte(3));
lcd.setCursor(centerCol(10), 0); lcd.print("SUBSCRIBE!"); delay(130);
}
lcd.clear(); lcd.setCursor(centerCol(10), 0); lcd.print("SUBSCRIBE!"); lcd.setCursor(1, 1); lcd.print("SIMPLE CIRCUITS");
buzzOnce(400); delay(800);
lcd.clear(); lcd.setCursor(centerCol(9), 0); lcd.print("SUBSCRIBE");
String brand = "SIMPLE CIRCUITS";
for (int i = 0; i < (int)brand.length(); i++) { lcd.setCursor(1 + i, 1); lcd.print(brand[i]); buzzOnce(30); delay(80); }
delay(500);
for (int i = 0; i < 3; i++) { lcd.noBacklight(); delay(150); lcd.backlight(); delay(150); }
buzzOnce(400); delay(400);
}
void resetPW() { password.reset(); currentLen = 0; }
void buzzOnce(int ms) { digitalWrite(BUZZER_PIN, HIGH); delay(ms); digitalWrite(BUZZER_PIN, LOW); delay(10); }
setup()
Relay starts HIGH (locked). Custom LCD characters loaded. Welcome sequence plays with typewriter animation and backlight flash.
loop()
Handles lockout countdown live on LCD. Polls keypad for D (submit), C (clear), * (backspace), or digit input with asterisk display.
accessGranted()
Fills and flashes asterisks, relay LOW for 10 s countdown, auto-relocks with lock icon and goodbye message.
accessDenied()
Shake animation on LCD, 3 s buzzer alarm, attempt counter. After 3 failures: 10 s siren lockout with live timer.
welcomeSequence()
Slide-in text, star bounce animation, typewriter brand reveal, backlight flash — runs once on boot.
To Change Password
Edit the string in Password("1234") and set PASSWORD_LEN to match. Supports 4–8 digits.
Design Your Own PCBs with Altium
For designing professional PCBs — like a custom PCBA for this door lock with all components on one board — I use Altium. It makes electronics design faster, cleaner, and production-ready.
Students get free access via Altium Student Lab — sign up with your university email for step-by-step PCB courses and industry certifications.
👉 Start designing with Altium →
Comments
Post a Comment