#include <Wire.h> // Include the Wire library for I2C communication
#include <LiquidCrystal_I2C.h> // Include the library for LCD 1602 with I2C interface
#include <Keypad.h>
#include <Servo.h>
/* Locking mechanism definitions */
#define SERVO_PIN 6
#define SERVO_LOCK_POS 20
#define SERVO_UNLOCK_POS 90
Servo lockServo;
/* Display */
LiquidCrystal_I2C lcd(0x27, 16, 2); // Initialize LCD with I2C address 0x27, 16 columns, and 2 rows
/* Keypad setup */
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
byte rowPins[KEYPAD_ROWS] = {5, 4, 3, 2};
byte colPins[KEYPAD_COLS] = {A3, A2, A1, A0};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
/* SafeState stores the secret code in EEPROM */
class SafeState {
String secretCode = "1234"; // Default secret code
public:
bool locked() {
// Simulating lock state
return true;
}
void lock() {
// Simulate locking action
}
void unlock() {
// Simulate unlocking action
}
bool unlock(String code) {
return code == secretCode;
}
void setCode(String newCode) {
secretCode = newCode;
}
bool hasCode() {
return secretCode.length() > 0;
}
bool setNewCode() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter new code:");
String newCode = secretCode();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Confirm new code:");
String confirmCode = secretCode();
if (newCode.equals(confirmCode)) {
setCode(newCode);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Code changed");
delay(1000);
return true;
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Code mismatch");
lcd.setCursor(0, 1);
lcd.print("Try again");
delay(2000);
return false;
}
}
};
SafeState safeState;
void lock() {
lockServo.write(SERVO_LOCK_POS);
safeState.lock();
}
void unlock() {
lockServo.write(SERVO_UNLOCK_POS);
}
void showStartupMessage() {
lcd.setCursor(4, 0);
lcd.print("Welcome!");
delay(1000);
lcd.setCursor(0, 1);
String message = "ArduinoSafe v1.0";
for (byte i = 0; i < message.length(); i++) {
lcd.print(message[i]);
delay(100);
}
delay(500);
}
String inputSecretCode() {
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;
}
void showWaitScreen(int delayMillis) {
lcd.setCursor(2, 1);
lcd.print("[..........]");
lcd.setCursor(3, 1);
for (byte i = 0; i < 10; i++) {
delay(delayMillis);
lcd.print("=");
}
}
bool setNewCode() {
return safeState.setNewCode();
}
void showUnlockMessage() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(0); // Replace with your unlocked icon if you have one
lcd.setCursor(4, 0);
lcd.print("Unlocked!");
lcd.setCursor(15, 0);
lcd.write(0); // Replace with your unlocked icon if you have one
delay(1000);
}
void safeUnlockedLogic() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(0); // Replace with your unlocked icon if you have one
lcd.setCursor(2, 0);
lcd.print(" # to lock");
lcd.setCursor(15, 0);
lcd.write(0); // Replace with your unlocked icon if you have one
bool newCodeNeeded = true;
if (safeState.hasCode()) {
lcd.setCursor(0, 1);
lcd.print(" * = new code");
newCodeNeeded = false;
}
auto key = keypad.getKey();
while (key != '*' && key != '#') {
key = keypad.getKey();
}
bool readyToLock = true;
if (key == '*' || newCodeNeeded) {
readyToLock = setNewCode();
}
if (readyToLock) {
lcd.clear();
lcd.setCursor(5, 0);
lcd.write(0); // Replace with your unlocked icon if you have one
lcd.print(" ");
lcd.write(0); // Replace with your arrow icon if you have one
lcd.print(" ");
lcd.write(0); // Replace with your locked icon if you have one
safeState.lock();
lock();
showWaitScreen(100);
}
}
void safeLockedLogic() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(0); // Replace with your locked icon if you have one
lcd.print(" Safe Locked! ");
lcd.write(0); // Replace with your locked icon if you have one
String userCode = inputSecretCode();
bool unlockedSuccessfully = safeState.unlock(userCode);
showWaitScreen(200);
if (unlockedSuccessfully) {
showUnlockMessage();
unlock();
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Access Denied!");
showWaitScreen(1000);
}
}
void setup() {
lcd.begin(16, 2);
lockServo.attach(SERVO_PIN);
/* Make sure the physical lock is synced with the EEPROM state */
Serial.begin(115200);
if (safeState.locked()) {
lock();
} else {
unlock();
}
showStartupMessage();
}
void loop() {
if (safeState.locked()) {
safeLockedLogic();
} else {
safeUnlockedLogic();
}
}