#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Servo.h>
#include "pitches.h"
#define SPEAKER_PIN 11
#define SERVO_PIN 2
#define SERVO_LOCKED_POS 0 // position of the servo motor when in locked status
#define SERVO_UNLOCKED_POS 90 // position of the servo motor when in unlocked status
Servo lockServo;
LiquidCrystal_I2C lcd(0x27,20,4);
const int ROW_NUM = 4;
const int COLUMN_NUM = 3;
byte pin_rows[ROW_NUM] = {9, 8, 7, 6};
byte pin_column[COLUMN_NUM] = {5, 4, 3};
char keys[ROW_NUM][COLUMN_NUM] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
int currTry;
int leftTry;
int maxTry = 3;
int ledRed = 12;
int ledGreen = 13;
char key;
boolean statusLocked = true;
boolean instance = false;
boolean isSuccessful = false;
String storePassword;
Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
void startScreen() { // displays the initial screen
while(statusLocked){
lockServo.write(SERVO_LOCKED_POS);
lcd.setCursor(4, 0);
lcd.print("LOCKED!");
lcd.setCursor(1, 1);
lcd.print("'#' to Unlock");
ledStatus();
key = keypad.getKey();
if (key){
if (checkKeyLocked(key) && instance == false){ // true when used on the first run
createPass();
}
if (checkKeyLocked(key) && instance == true){ // true when used on the consecutive runs
locked();
}
}
}
}
// create new one time password when used for the first time
void createPass(){
while(statusLocked){ // while door lock is still in locked status
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter new pass:");
String newPass = passwordInpt();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Confirm new pass");
String confirmPass = passwordInpt();
if (newPass.equals(confirmPass)) { // confirm if confirmPass and newPass is equal/same
instance = true;
storePassword = newPass;
lcd.clear();
success();
startScreen();
}
else {
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("Password");
lcd.setCursor(4, 1);
lcd.print("Mismatch!");
invalid();
delay(2000);
lcd.clear();
startScreen();
}
}
}
void locked(){
while(statusLocked){ // while door lock is still in locked status
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter password:");
String tempPass = passwordInpt(); // store input to tempPass
if (tempPass == storePassword) {
lcd.clear();
success();
unlocked();
}
else {
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("Password");
lcd.setCursor(3, 1);
lcd.print("Incorrect!");
invalid();
check_first();
currTry +=1;
leftTry = maxTry - currTry;
delay(500);
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Attempt/s left:");
lcd.setCursor(7, 1);
lcd.print(leftTry);
check_second();
delay(500);
lcd.clear();
startScreen();
}
}
}
void unlocked() {
isSuccessful = true;
statusLocked = false; // change statusLocked flag into false
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("UNLOCKED!");
lockServo.write(SERVO_UNLOCKED_POS); // re-position servo motor
ledStatus();
delay(3000); // automatically locks after 3 seconds
statusLocked = true; // change back again to true
lcd.clear();
startScreen();
}
void ledStatus() { // change LED values depending statusLocked flag
if (statusLocked == true){
digitalWrite(ledRed, HIGH);
digitalWrite(ledGreen, LOW);
}
else{
digitalWrite(ledGreen, HIGH);
digitalWrite(ledRed, LOW);
}
}
void invalid() { // performs a combination of tone when invalid
tone(SPEAKER_PIN,NOTE_G4);
delay(100);
tone(SPEAKER_PIN,NOTE_C4);
delay(100);
noTone(SPEAKER_PIN);
}
void success() { // performs a combination of tone when successful
tone(SPEAKER_PIN, 650, 750);
delay(100);
tone(SPEAKER_PIN, 900, 1000);
delay(100);
tone(SPEAKER_PIN, 650, 750);
delay(100);
tone(SPEAKER_PIN, 900, 1000);
noTone(SPEAKER_PIN);
}
void check_first() { // first part of checking
if (isSuccessful) {
currTry = 0;
}
isSuccessful = false;
}
void check_second() { // second part of checking
if (leftTry == 0){
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Intruder Alert!!");
warning();
}
}
void warning() { // when max attempt is used
while(true){
digitalWrite(ledGreen, HIGH);
digitalWrite(ledRed, HIGH);
invalid();
key = keypad.getKey();
if (key == '*'){
currTry = 0; // resets the value of current try
break; // stop the alarm
}
}
}
String passwordInpt() { // prompts the user to input 4-digit password
lcd.setCursor(5, 1);
lcd.print("[____]");
lcd.setCursor(6, 1);
String result = "";
while (result.length() < 4) {
char key = keypad.getKey();
if (key >= '0' && key <= '9') {
lcd.print('*');
result += key;
}
}
return result;
}
boolean checkKeyLocked(char input){ // checks if key == '#'
if(input != '#'){
return false;
}
else{
return true;
}
}
void setup() {
lcd.init();
lcd.backlight();
lcd.home();
lockServo.attach(SERVO_PIN);
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(ledRed, OUTPUT);
pinMode(ledGreen, OUTPUT);
Serial.begin(9600);
statusLocked = true; // statusLocked is set true on default
}
void loop() {
startScreen();
}