Burglar Alarm System with Keypad

By Paul , 8 September 2025
/*
 * Burglar Alarm System with Keypad
 * Arduino Uno + 20x4 LCD (I2C) + 4x4 Keypad + Buzzer
 * 
 * Features:
 * - Arm/Disarm with passcode
 * - Entry delay
 * - Motion sensor support
 * - LCD status display
 * - Buzzer alarm
 */

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

// LCD Configuration (I2C address 0x27, 20 columns, 4 rows)
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Keypad Configuration
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};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// Pin Definitions
const int BUZZER_PIN = 10;
const int MOTION_SENSOR_PIN = 11;
const int LED_ARMED = 12;
const int LED_DISARMED = 13;

// System Variables
String correctPassword = "1234";  // Default password
String enteredPassword = "";
bool systemArmed = false;
bool alarmTriggered = false;
unsigned long entryDelayStart = 0;
unsigned long alarmStartTime = 0;
const unsigned long ENTRY_DELAY = 10000;  // 10 seconds
const unsigned long ALARM_DURATION = 30000; // 30 seconds

// System States
enum SystemState {
  DISARMED,
  ARMING,
  ARMED,
  ENTRY_DELAY,
  ALARM_ACTIVE
};

SystemState currentState = DISARMED;

void setup() {
  Serial.begin(9600);
  
  // Initialize LCD
  lcd.init();
  lcd.backlight();
  
  // Initialize pins
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(MOTION_SENSOR_PIN, INPUT);
  pinMode(LED_ARMED, OUTPUT);
  pinMode(LED_DISARMED, OUTPUT);
  
  // Initial state
  digitalWrite(LED_DISARMED, HIGH);
  digitalWrite(LED_ARMED, LOW);
  
  // Welcome message
  displayWelcome();
  delay(2000);
  updateDisplay();
}

void loop() {
  char key = keypad.getKey();
  bool motionDetected = digitalRead(MOTION_SENSOR_PIN);
  
  // Handle keypad input
  if (key) {
    handleKeyInput(key);
  }
  
  // Handle motion detection
  if (motionDetected && currentState == ARMED) {
    startEntryDelay();
  }
  
  // Handle state machine
  handleStateMachine();
  
  // Update display every second
  static unsigned long lastDisplayUpdate = 0;
  if (millis() - lastDisplayUpdate > 1000) {
    updateDisplay();
    lastDisplayUpdate = millis();
  }
}

void handleKeyInput(char key) {
  if (key == '#') {
    // Enter key - process password
    if (enteredPassword == correctPassword) {
      if (currentState == DISARMED) {
        armSystem();
      } else {
        disarmSystem();
      }
    } else {
      wrongPassword();
    }
    enteredPassword = "";
  } else if (key == '*') {
    // Clear key
    enteredPassword = "";
    lcd.setCursor(0, 3);
    lcd.print("                    ");
  } else if (key == 'A') {
    // Change password
    changePassword();
  } else if (key == 'B') {
    // Emergency disarm (could require admin code)
    emergencyDisarm();
  } else {
    // Add digit to password
    if (enteredPassword.length() < 8) {
      enteredPassword += key;
      displayPasswordInput();
    }
  }
}

void handleStateMachine() {
  switch (currentState) {
    case ENTRY_DELAY:
      if (millis() - entryDelayStart > ENTRY_DELAY) {
        triggerAlarm();
      }
      break;
      
    case ALARM_ACTIVE:
      // Flash LEDs and sound buzzer
      static unsigned long lastBeep = 0;
      if (millis() - lastBeep > 500) {
        digitalWrite(BUZZER_PIN, !digitalRead(BUZZER_PIN));
        digitalWrite(LED_ARMED, !digitalRead(LED_ARMED));
        lastBeep = millis();
      }
      
      // Auto-stop alarm after duration
      if (millis() - alarmStartTime > ALARM_DURATION) {
        currentState = ARMED;
        digitalWrite(BUZZER_PIN, LOW);
        digitalWrite(LED_ARMED, HIGH);
      }
      break;
  }
}

void armSystem() {
  currentState = ARMED;
  systemArmed = true;
  digitalWrite(LED_ARMED, HIGH);
  digitalWrite(LED_DISARMED, LOW);
  
  lcd.clear();
  lcd.setCursor(6, 1);
  lcd.print("SYSTEM ARMED");
  lcd.setCursor(4, 2);
  lcd.print("Motion Protected");
  
  // Confirmation beep
  digitalWrite(BUZZER_PIN, HIGH);
  delay(100);
  digitalWrite(BUZZER_PIN, LOW);
  
  delay(2000);
}

void disarmSystem() {
  currentState = DISARMED;
  systemArmed = false;
  alarmTriggered = false;
  digitalWrite(LED_ARMED, LOW);
  digitalWrite(LED_DISARMED, HIGH);
  digitalWrite(BUZZER_PIN, LOW);
  
  lcd.clear();
  lcd.setCursor(5, 1);
  lcd.print("SYSTEM DISARMED");
  lcd.setCursor(7, 2);
  lcd.print("Welcome Home");
  
  // Confirmation beeps
  for (int i = 0; i < 2; i++) {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
    delay(100);
  }
  
  delay(2000);
}

void startEntryDelay() {
  currentState = ENTRY_DELAY;
  entryDelayStart = millis();
  
  lcd.clear();
  lcd.setCursor(5, 1);
  lcd.print("ENTRY DETECTED");
  lcd.setCursor(2, 2);
  lcd.print("Enter Code or Alarm!");
}

void triggerAlarm() {
  currentState = ALARM_ACTIVE;
  alarmTriggered = true;
  alarmStartTime = millis();
  
  lcd.clear();
  lcd.setCursor(7, 1);
  lcd.print("ALARM!");
  lcd.setCursor(4, 2);
  lcd.print("INTRUDER ALERT");
}

void wrongPassword() {
  lcd.clear();
  lcd.setCursor(5, 1);
  lcd.print("WRONG PASSWORD");
  lcd.setCursor(6, 2);
  lcd.print("Try Again");
  
  // Error beep
  for (int i = 0; i < 3; i++) {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(200);
    digitalWrite(BUZZER_PIN, LOW);
    delay(200);
  }
  
  delay(2000);
}

void changePassword() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("CHANGE PASSWORD");
  lcd.setCursor(0, 1);
  lcd.print("Enter current code:");
  
  String currentCode = "";
  while (true) {
    char key = keypad.getKey();
    if (key) {
      if (key == '#') {
        if (currentCode == correctPassword) {
          // Get new password
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Enter new code:");
          
          String newCode = "";
          while (true) {
            char newKey = keypad.getKey();
            if (newKey) {
              if (newKey == '#') {
                if (newCode.length() >= 4) {
                  correctPassword = newCode;
                  lcd.clear();
                  lcd.setCursor(4, 1);
                  lcd.print("CODE CHANGED");
                  delay(2000);
                  return;
                }
              } else if (newKey == '*') {
                return; // Cancel
              } else {
                newCode += newKey;
                lcd.setCursor(newCode.length() - 1, 1);
                lcd.print("*");
              }
            }
          }
        } else {
          wrongPassword();
          return;
        }
      } else if (key == '*') {
        return; // Cancel
      } else {
        currentCode += key;
        lcd.setCursor(currentCode.length() - 1, 2);
        lcd.print("*");
      }
    }
  }
}

void emergencyDisarm() {
  disarmSystem();
  lcd.clear();
  lcd.setCursor(3, 1);
  lcd.print("EMERGENCY DISARM");
  delay(2000);
}

void displayWelcome() {
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("SECURITY SYSTEM");
  lcd.setCursor(6, 1);
  lcd.print("v1.0");
  lcd.setCursor(3, 2);
  lcd.print("Initializing...");
}

void updateDisplay() {
  if (currentState == ENTRY_DELAY) {
    // Show countdown
    unsigned long remaining = (ENTRY_DELAY - (millis() - entryDelayStart)) / 1000;
    lcd.setCursor(0, 3);
    lcd.print("Time left: ");
    lcd.print(remaining);
    lcd.print(" sec   ");
    return;
  }
  
  if (currentState == ALARM_ACTIVE) {
    return; // Don't update during alarm
  }
  
  lcd.clear();
  
  // Status line
  lcd.setCursor(0, 0);
  if (systemArmed) {
    lcd.print("Status: ARMED      ");
  } else {
    lcd.print("Status: DISARMED   ");
  }
  
  // Instructions
  lcd.setCursor(0, 1);
  lcd.print("Enter code + #");
  lcd.setCursor(0, 2);
  lcd.print("A=Change  B=Emergency");
  
  // Show entered password
  if (enteredPassword.length() > 0) {
    displayPasswordInput();
  }
}

void displayPasswordInput() {
  lcd.setCursor(0, 3);
  lcd.print("Code: ");
  for (int i = 0; i < enteredPassword.length(); i++) {
    lcd.print("*");
  }
  // Clear remaining characters
  for (int i = enteredPassword.length(); i < 8; i++) {
    lcd.print(" ");
  }
}

void calibratePiezoSensor() {
  lcd.clear();
  lcd.setCursor(2, 1);
  lcd.print("Calibrating Piezo");
  lcd.setCursor(4, 2);
  lcd.print("Please wait...");
  
  // Take baseline readings
  long total = 0;
  for (int i = 0; i < 50; i++) {
    total += analogRead(PIEZO_SENSOR_PIN);
    delay(20);
  }
  piezoBaseline = total / 50;
  
  lcd.clear();
  lcd.setCursor(3, 1);
  lcd.print("Calibration Done");
  lcd.setCursor(2, 2);
  lcd.print("Baseline: ");
  lcd.print(piezoBaseline);
  delay(2000);
}

bool checkPiezoSensor() {
  if (millis() - lastPiezoTrigger < PIEZO_COOLDOWN) {
    return false;  // Still in cooldown period
  }
  
  int reading = analogRead(PIEZO_SENSOR_PIN);
  int difference = abs(reading - piezoBaseline);
  
  if (difference > piezoThreshold) {
    lastPiezoTrigger = millis();
    return true;
  }
  return false;
}

void adjustSensitivity() {
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("PIEZO SENSITIVITY");
  lcd.setCursor(0, 1);
  lcd.print("Current: ");
  lcd.print(piezoThreshold);
  lcd.setCursor(0, 2);
  lcd.print("1-9=Set  #=Save  *=Exit");
  
  while (true) {
    char key = keypad.getKey();
    if (key) {
      if (key >= '1' && key <= '9') {
        piezoThreshold = (key - '0') * 20;  // 20-180 range
        lcd.setCursor(9, 1);
        lcd.print("   ");  // Clear old value
        lcd.setCursor(9, 1);
        lcd.print(piezoThreshold);
      } else if (key == '#') {
        lcd.clear();
        lcd.setCursor(4, 1);
        lcd.print("SENSITIVITY SET");
        lcd.setCursor(6, 2);
        lcd.print("Value: ");
        lcd.print(piezoThreshold);
        delay(2000);
        return;
      } else if (key == '*') {
        return;  // Exit without saving
      }
    }
  }
}

void testSensors() {
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("SENSOR TEST");
  lcd.setCursor(0, 1);
  lcd.print("PIR: ");
  lcd.setCursor(0, 2);
  lcd.print("Piezo: ");
  lcd.setCursor(0, 3);
  lcd.print("Press * to exit");
  
  while (true) {
    char key = keypad.getKey();
    if (key == '*') {
      return;
    }
    
    // Test PIR sensor
    bool pirState = digitalRead(PIR_SENSOR_PIN);
    lcd.setCursor(5, 1);
    if (pirState) {
      lcd.print("MOTION  ");
    } else {
      lcd.print("CLEAR   ");
    }
    
    // Test Piezo sensor
    int piezoReading = analogRead(PIEZO_SENSOR_PIN);
    int difference = abs(piezoReading - piezoBaseline);
    lcd.setCursor(7, 2);
    lcd.print("   ");  // Clear old reading
    lcd.setCursor(7, 2);
    lcd.print(difference);
    
    if (difference > piezoThreshold) {
      lcd.setCursor(11, 2);
      lcd.print("TRIGGER");
    } else {
      lcd.setCursor(11, 2);
      lcd.print("       ");
    }
    
    delay(100);
  }
}

Comments1

Paul

3 months 1 week ago

Required Components:

  • Arduino Uno
  • 20x4 LCD with I2C backpack (address 0x27)
  • 4x4 Matrix Keypad
  • Buzzer (active or passive)
  • PIR Motion Sensor
  • 2 LEDs (red for armed, green for disarmed)
  • 2 x 220Ω resistors (for LEDs)
  • Jumper wires
  • Breadboard

Wiring Connections:

LCD (I2C):

  • VCC → 5V
  • GND → GND
  • SDA → A4
  • SCL → A5

4x4 Keypad:

  • Row pins: 9, 8, 7, 6
  • Column pins: 5, 4, 3, 2

Other Components:

  • Buzzer → Pin 10
  • PIR Motion Sensor → Pin 11
  • LED Armed (Red) → Pin 12 + 220Ω resistor → GND
  • LED Disarmed (Green) → Pin 13 + 220Ω resistor → GND

Required Libraries:

Install these libraries in Arduino IDE:

  • LiquidCrystal_I2C by Frank de Brabander
  • Keypad by Mark Stanley

Features:

  • Default passcode: 1234
  • Arm/Disarm: Enter code + #
  • Change password: Press A, enter current code, then new code
  • Emergency disarm: Press B
  • Entry delay: 10 seconds when motion detected
  • Auto alarm shutoff: 30 seconds
  • Clear input: Press *

Usage:

  1. System starts disarmed (green LED on)
  2. Enter passcode + # to arm (red LED on)
  3. Motion detection starts 10-second entry delay
  4. Enter correct code to disarm, or alarm sounds
  5. Use 'A' to change password, 'B' for emergency disarm

The system includes visual feedback on the LCD, audio alerts via buzzer, and LED status indicators. The motion sensor will trigger the entry delay when the system is armed, giving you time to disarm before the alarm sounds.