// Import Libraries
#include <Keypad.h> // Keypad
#include <LiquidCrystal_I2C.h> // I2C LCD
// Tone Library
#define TONE_USE_INT
#define TONE_PITCH 440
#include <TonePitch.h>
// Custom Library
#include "song.h"
// 4x4 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] = {6, 7, 8, 9};
byte colPins[COLS] = {2, 3, 4, 5};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// I2C_LCD Setup
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Components Setup
int BUZZER = 13;
int LED[2] = {A0, A1};
int RED_LED = LED[0], GREEN_LED = LED[1];
// Password
const String defaultPassword = "1234";
const int maxAttempts = 3;
// Other Variables
String username;
String password;
int attempts = 0;
unsigned long warningTimer = 0;
const unsigned long warningDuration = 5000;
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
WelcomeScreen();
}
void loop() {
EnterPin();
}
void center(String message, int lcdRow, bool animate){
int cursorPos;
cursorPos = 7 - (message.length() - 1) / 2;
lcd.setCursor(cursorPos, lcdRow);
if (animate == true) {
animation(message);
} else {
lcd.print(message);
}
}
void animation(String message){
for (byte i = 0; i < message.length(); i++) {
lcd.print(message[i]);
delay(200/5);
}
}
void WelcomeScreen(){
// center("Enter Username:", 0, true);
// while (Serial.available() == 0) {}
// username = Serial.readString();
// lcd.clear();
center("Welcome!", 0, false); center("Master", 1, true);
delay(2000);
}
void EnterPin(){
lcd.clear();
center("Enter PIN:", 0, true);
password = "";
lcd.setCursor(6, 1);
while (password.length() < 4) {
char key = keypad.getKey();
if (key) {
playNoteForKey(key);
lcd.setCursor(password.length(), 1);
lcd.print('*');
password += key;
}
}
checkPassword();
}
void checkPassword(){
if (password == defaultPassword) {
ACCESS_GRANTED();
delay(1000);
lcd.clear();
attempts = 0;
warningTimer = 0;
} else {
attempts++;
ACCESS_DENIED();
String current = String(attempts) + " Attempts";
center(current, 1, false);
incorrect();
delay(1000);
lcd.clear();
if (attempts >= maxAttempts) {
siren();
attempts = 0;
warningTimer = 0;
}
}
turn_off_LEDs();
}
void ACCESS_GRANTED() {
lcd.clear();
center("ACCESS GRANTED", 0, true);
song();
digitalWrite(GREEN_LED, HIGH);
}
void ACCESS_DENIED() {
lcd.clear();
center("ACCESS DENIED", 0, true);
digitalWrite(RED_LED, HIGH);
}
void playNoteForKey(char key) {
int note;
if (key == '#') {
note = NOTE_C7;
} else {
note = NOTE_C6;
}
tone(BUZZER, note);
delay(50);
noTone(BUZZER);
}
void siren() {
center("INTRUDER", 0, true);
center("ALERT!", 1, true);
unsigned long startTime = millis();
while (millis() - startTime < warningDuration) {
for (int hz = 440; hz < 1000; hz += 25) {
tone(BUZZER, hz, 50);
delay(15);
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
}
// Whoop down
for (int hz = 1000; hz > 440; hz -= 25) {
tone(BUZZER, hz, 50);
delay(15);
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
}
}
turn_off_LEDs();
noTone(BUZZER);
}
void song() {
int tempo1 = 170;
int wholenote1 = (60000 * 4) / tempo1;
int divider = 0, noteDuration = 0;
for (int thisNote = 0; thisNote < sizeof(notes) / sizeof(notes[0]); thisNote = thisNote + 2) {
divider = notes[thisNote + 1];
if (divider > 0) {
noteDuration = (wholenote1) / divider;
}
tone(BUZZER, notes[thisNote], noteDuration * 0.9);
delay(noteDuration);
noTone(BUZZER);
}
}
void incorrect() {
// Whoop up
for (int hz = 440; hz < 1000; hz += 25) {
tone(BUZZER, hz, 50);
delay(5);
}
// Whoop down
for (int hz = 1000; hz > 440; hz -= 25) {
tone(BUZZER, hz, 50);
delay(5);
}
}
void turn_off_LEDs() {
int no_of_LED = sizeof(LED) / sizeof(LED[0]);
for (int i = 0; i < no_of_LED; i++) {
digitalWrite(LED[i], LOW);
}
}