#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 = 4; // Changed to 4 for 6-digit pin
byte pin_rows[ROW_NUM] = {9, 8, 7, 6};
byte pin_column[COLUMN_NUM] = {5, 4, 3, 2}; // Added one more column for 6-digit pin
char keys[ROW_NUM][COLUMN_NUM] = {
{'1','2','3','A'}, // Added 'A' for the additional column
{'4','5','6','B'}, // Added 'B' for the additional column
{'7','8','9','C'}, // Added 'C' for the additional column
{'*','0','#','D'} // Added 'D' for the additional column
};
int currTry;
int leftTry;
int maxTry = 4;
int ledRed = 12;
int ledGreen = 13;
char key;
boolean statusLocked = true;
boolean instance = false;
boolean isSuccessful = false;
String storePassword;
unsigned long buzzerStartTime = 0; // Variable to store the start time of buzzer
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("WELCOME");
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("SISA INPUT");
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("TERBUKA!");
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("TERKUNCI!!");
warning();
}
}
void warning() { // when max attempt is used
unsigned long currentTime = millis(); // Get the current time
while (true) {
digitalWrite(ledGreen, HIGH);
digitalWrite(ledRed, HIGH);
invalid();
if (millis() - currentTime >= 4000) { // Check if 4 seconds have passed
noTone(SPEAKER_PIN); // Stop the buzzer after 4 seconds
break;
}
}
key = keypad.getKey();
if (key == '*') {
currTry = 0; // resets the value of current try
}
}
String passwordInpt() { // prompts the user to input 6-digit password
lcd.setCursor(5, 1);
lcd.print("[______]"); // Changed to accommodate 6 characters
lcd.setCursor(6, 1);
String result = "";
while (result.length() < 6) { // Changed to read 6 characters
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();
}