Smart Arduino Door Lock System With Voice Alert Coding Explanation

Copy the code by clicking the “Copy Icon” situated in the righ upper corner of the code block.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Servo.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>

#define maxPasswordLength 4
#define buzzerPin 12
#define servoPin A1
#define ledPin 13       // Use A0 (D14) for LED strip output
#define numPixels 1

SoftwareSerial mySerial(10, 11); // RX, TX for DFPlayer Mini
DFRobotDFPlayerMini dfPlayer;

LiquidCrystal_I2C lcd(0x27, 20, 4);
Servo myServo;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numPixels, ledPin, NEO_GRB + NEO_KHZ800);

// Keypad setup
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};  // Connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2};  // Connect to the column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

String currentPassword = "1234";
String inputPassword = "";
boolean settingPassword = false;
boolean confirmingPassword = false;

void setup() {
  pinMode(buzzerPin, OUTPUT);
  pinMode(ledPin, OUTPUT); // Set A0 as an output pin
  myServo.attach(servoPin);
  strip.begin();
  strip.show();
  
  lcd.init();
  lcd.backlight();
  
  mySerial.begin(9600);
  if (!dfPlayer.begin(mySerial)) {
    lcd.setCursor(0, 0);
    lcd.print("DFPlayer Error");
    while (true);
  }
  
  dfPlayer.volume(30);  // Set volume to a high level
  loadPassword();
}

void loop() {
  char key = keypad.getKey();  // Get the key pressed on the keypad

  if (key == 'B' && !settingPassword && !confirmingPassword) { // Press 'B' to set a new password
    settingPassword = true;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Enter Old Pass:");
    inputPassword = "";
    return;
  }

  if (settingPassword) {
    if (key == 'A') { // Press 'A' to confirm old password
      if (inputPassword == currentPassword) {
        confirmingPassword = true;
        settingPassword = false;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Enter New Pass:");
        inputPassword = "";
      } else {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Wrong Old Pass");
        blinkLED(255, 0, 0, 3, 200);
        beepBuzzer(3, 200);
        playAudio(1); // Play "Wrong Password" audio
        delay(2000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Enter Old Pass:");
        inputPassword = "";
      }
      return;
    }

    if (key == 'C') { // Press 'C' to clear input
      inputPassword = "";
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Enter Old Pass:");
    } else if (key == 'D') { // Press 'D' to delete the last character
      if (inputPassword.length() > 0) {
        inputPassword.remove(inputPassword.length() - 1);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Enter Old Pass:");
        lcd.setCursor(0, 1);
        lcd.print(inputPassword);
      }
    } else if (key != NO_KEY) { // Entering the old password
      if (inputPassword.length() < maxPasswordLength) {
        inputPassword += key;
        lcd.setCursor(0, 1);
        lcd.print(inputPassword);
      }
    }
    return;
  }

  if (confirmingPassword) {
    if (key == 'A') { // Press 'A' to confirm the new password
      if (inputPassword.length() == maxPasswordLength) {
        savePassword(inputPassword);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Password Saved");
        blinkLED(0, 255, 0, 3, 200);
        beepBuzzer(3, 200);
        playAudio(2); // Play "Password Saved" audio
        delay(2000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Enter Password:");
        confirmingPassword = false;
      } else {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Invalid Length");
        blinkLED(255, 0, 0, 3, 200);
        beepBuzzer(3, 200);
        playAudio(3); // Play "Invalid Length" audio
        delay(1000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Enter New Pass:");
        lcd.setCursor(0, 1);
        lcd.print(inputPassword);
      }
      return;
    }

    if (key == 'C') { // Press 'C' to clear the new password input
      inputPassword = "";
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Enter New Pass:");
    } else if (key == 'D') { // Press 'D' to delete the last character of the new password
      if (inputPassword.length() > 0) {
        inputPassword.remove(inputPassword.length() - 1);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Enter New Pass:");
        lcd.setCursor(0, 1);
        lcd.print(inputPassword);
      }
    } else if (key != NO_KEY) { // Entering the new password
      if (inputPassword.length() < maxPasswordLength) {
        inputPassword += key;
        lcd.setCursor(0, 1);
        lcd.print(inputPassword);
      }
    }
    return;
  }

  // Handle normal password entry
  if (key == 'A') { // Press 'A' to confirm the password
    checkPassword();
  } else if (key == 'C') { // Press 'C' to clear the input
    inputPassword = "";
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Enter Password:");
  } else if (key == 'D') { // Press 'D' to delete the last character
    if (inputPassword.length() > 0) {
      inputPassword.remove(inputPassword.length() - 1);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Enter Password:");
      lcd.setCursor(0, 1);
      lcd.print(inputPassword);
    }
  } else if (key != NO_KEY) { // Entering the password
    if (inputPassword.length() < maxPasswordLength) {
      inputPassword += key;
      lcd.setCursor(0, 1);
      lcd.print(inputPassword);
    }
  }
}

void checkPassword() {
  if (inputPassword == currentPassword) {
    myServo.write(90); // Unlock position
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Door Unlocked");
    blinkLED(0, 255, 0, 3, 200);
    beepBuzzer(3, 200);
    playAudio(4); // Play "Door Unlocked" audio
    delay(5000); // Keep the door unlocked for 5 seconds
    myServo.write(0); // Lock position
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Re-Locked");
    playAudio(5); // Play "Re-Locked" audio
    delay(2000);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Enter Password:");
  } else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Wrong Password");
    blinkLED(255, 0, 0, 3, 200);
    beepBuzzer(3, 200);
    playAudio(1); // Play "Wrong Password" audio
    delay(1000);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Enter Password:");
  }
  inputPassword = ""; // Clear the input after checking
}

void loadPassword() {
  char pwd[maxPasswordLength + 1];
  for (int i = 0; i < maxPasswordLength; i++) {
    pwd[i] = EEPROM.read(i);
  }
  pwd[maxPasswordLength] = '\0';
  currentPassword = String(pwd);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Password Loaded");
  delay(1000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Enter Password:");
}

void savePassword(String newPassword) {
  for (int i = 0; i < maxPasswordLength; i++) {
    EEPROM.write(i, newPassword[i]);
  }
  currentPassword = newPassword;
}


void blinkLED(int red, int green, int blue, int times, int delayTime) {
  for (int i = 0; i < times; i++) {
    strip.setPixelColor(0, strip.Color(red, green, blue));
    strip.show();
    delay(delayTime);
    strip.setPixelColor(0, strip.Color(0, 0, 0));
    strip.show();
    delay(delayTime);
  }
}

void beepBuzzer(int times, int delayTime) {
  for (int i = 0; i < times; i++) {
    digitalWrite(buzzerPin, HIGH);
    delay(delayTime);
    digitalWrite(buzzerPin, LOW);
    delay(delayTime);
  }
}

void playAudio(int trackNumber) {
  dfPlayer.play(trackNumber);
}

1. Library Inclusions

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Servo.h>
#include <EEPROM.h>
#include <Adafruit_NeoPixel.h>
#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>
  • Wire.h: I2C communication (used by the LCD).
  • LiquidCrystal_I2C.h: Controls the 20×4 LCD over I²C at address 0x27.
  • Keypad.h: Reads button presses from a 4×4 matrix keypad.
  • Servo.h: Drives the servo motor that physically locks/unlocks the door.
  • EEPROM.h: Stores and retrieves the 4-digit password in non-volatile memory.
  • Adafruit_NeoPixel.h: Controls the RGB LED strip (used here as a single-pixel indicator).
  • DFRobotDFPlayerMini.h + SoftwareSerial.h: Interface and communicate with the DFPlayer Mini MP3 module for audio feedback.

2. Configuration Constants & Pins

#define maxPasswordLength 4
#define buzzerPin 12
#define servoPin A1
#define ledPin 13
#define numPixels 1
  • maxPasswordLength: Password is exactly 4 digits.
  • buzzerPin: Piezo buzzer output.
  • servoPin: Analog pin A1 driving the lock servo.
  • ledPin: Pin for the NeoPixel data input.
  • numPixels: Only one RGB LED pixel in the strip.

3. Hardware Object Instantiations

SoftwareSerial mySerial(10, 11);            // RX, TX for DFPlayer
DFRobotDFPlayerMini dfPlayer; // DFPlayer instance

LiquidCrystal_I2C lcd(0x27, 20, 4); // 20×4 I2C LCD
Servo myServo; // Door servo
Adafruit_NeoPixel strip(numPixels, ledPin, NEO_GRB + NEO_KHZ800);
  • SoftwareSerial mySerial(10, 11): Creates a serial link to DFPlayer on pins 10(RX)/11(TX).
  • dfPlayer: Controls audio playback (error beeps, confirmations).
  • lcd: Text display to prompt user and show status.
  • myServo: Moves between locked (0°) and unlocked (90°).
  • strip: One-pixel NeoPixel for colored feedback (red/green).

4. Keypad Definition

const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'}, {'4','5','6','B'},
{'7','8','9','C'}, {'*','0','#','D'}
};
byte rowPins[ROWS] = {9,8,7,6}, colPins[COLS] = {5,4,3,2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
  • Defines a 4×4 layout.
  • Rows on pins 9–6, columns on 5–2.
  • Keys A, B, C, D serve as “confirm,” “set new password,” “clear,” and “delete” controls.

5. Password State Variables

String currentPassword = "1234";
String inputPassword = "";
boolean settingPassword = false;
boolean confirmingPassword = false;
  • currentPassword: Holds the active 4-digit code (loaded from EEPROM on startup).
  • inputPassword: Accumulates user keystrokes.
  • settingPassword / confirmingPassword: Track whether the sketch is in “change password” mode.

6. setup()

void setup() {
pinMode(buzzerPin, OUTPUT);
pinMode(ledPin, OUTPUT);
myServo.attach(servoPin);
strip.begin(); strip.show();

lcd.init(); lcd.backlight();

mySerial.begin(9600);
if (!dfPlayer.begin(mySerial)) { … } // Halt on DFPlayer error
dfPlayer.volume(30);

loadPassword(); // Read the saved password from EEPROM
}
  1. Pin modes for buzzer and LED.
  2. Attach servo and initialize NeoPixel.
  3. Initialize the LCD and DFPlayer audio module.
  4. Set volume on DFPlayer.
  5. Call loadPassword() to fetch the last-saved code and prompt “Enter Password:”.

7. loop(): Main Input Handler

  1. Read one key: char key = keypad.getKey();
  2. If user pressed ‘B’ (start password‐change), prompt “Enter Old Pass:” and set settingPassword = true.
  3. If in settingPassword:
    • ‘A’ → confirm old code, compare to currentPassword; on match, switch to confirmingPassword (enter new pass), else show error feedback.
    • ‘C’ → clear entry.
    • ‘D’ → backspace (delete last digit).
    • Any digit → append to inputPassword (up to 4 digits) and display.
  4. If in confirmingPassword (entering new pass):
    • ‘A’ → confirm new code; if length == 4 then savePassword(), feedback and return to normal mode; else show “Invalid Length.”
    • ‘C’/‘D’/digits** behave as clear, backspace, or append, similar to above.
  5. Normal password entry:
    • ‘A’ → call checkPassword() (unlock on match, error on mismatch).
    • ‘C’ → clear entry.
    • ‘D’ → delete last digit.
    • Digit → append to inputPassword.

8. checkPassword()

void checkPassword() {
if (inputPassword == currentPassword) {
// Unlock sequence
myServo.write(90);
lcd.print("Door Unlocked");
blinkLED(green), beepBuzzer, playAudio(track 4);
delay(5000);
myServo.write(0);
lcd.print("Re-Locked");
playAudio(track 5);
} else {
// Wrong password feedback
lcd.print("Wrong Password");
blinkLED(red), beepBuzzer, playAudio(track 1);
}
inputPassword = "";
lcd.print("Enter Password:");
}
  • Correct code:
    1. Rotate servo to 90° to unlock.
    2. Green LED blinks, buzzer beeps, plays “Unlocked” audio.
    3. Wait 5 s, relock (servo → 0°), play “Re-Locked” audio.
  • Incorrect code: Red blink + buzzer + “Wrong Password” audio.
  • Always reset inputPassword and prompt again.

9. EEPROM Persistence: loadPassword() & savePassword()

void loadPassword() {
for (int i=0; i<4; i++) pwd[i] = EEPROM.read(i);
currentPassword = String(pwd);
lcd.print("Password Loaded");
delay(1000);
lcd.print("Enter Password:");
}

void savePassword(String newPassword) {
for (int i=0; i<4; i++) EEPROM.write(i, newPassword[i]);
currentPassword = newPassword;
}
  • loadPassword(): Reads four bytes from EEPROM addresses 0–3, converts to a String, and shows a brief “Password Loaded” message.
  • savePassword(): Writes each character of the new 4-digit code to EEPROM and updates currentPassword.

10. Feedback Helpers

blinkLED(int red, int green, int blue, int times, int delayTime)

Cycles the single NeoPixel on/off in the specified RGB color for the given number of times.

beepBuzzer(int times, int delayTime)

Turns the buzzer on/off rapidly to produce audible beeps.

playAudio(int trackNumber)

Sends the play command to DFPlayer Mini to play pre-loaded MP3 tracks (e.g. “Wrong Password,” “Password Saved,” etc.).


How It All Fits

  1. Startup: Reads stored password, initializes all peripherals.
  2. Idle: Prompts “Enter Password:” on LCD.
  3. User Interaction: Keypad drives all state changes—entering passwords, switching to change-password mode, and confirming actions.
  4. Visual & Audio: Neopixel, buzzer, and MP3 tracks reinforce success/failure.
  5. Security: Password is stored in EEPROM so it survives power‐cycles, and the servo physically locks/unlocks a door mechanism.

Leave a Comment