/*
Voltaat learn (http://learn.voltaat.com)
Link for full tutorial:
LiquidCrystal I2C Library:
Wire Library:
Keypad Library:
Servo Library:
Tutorial: Build a Secure Safe with Password Protection
Connections from the keypad to Arduino:
• Keypad pin 1 → Arduino pin 2
• Keypad pin 2 → Arduino pin 3
• Keypad pin 3 → Arduino pin 4
• Keypad pin 4 → Arduino pin 5
• Keypad pin 5 → Arduino pin 6
• Keypad pin 6 → Arduino pin 7
• Keypad pin 7 → Arduino pin 8
• Keypad pin 8 → Arduino pin 9
Connections from the servo motor:
• Servo GND pin→ breadboard GND line
• Servo 5V pin→ breadboard 5V line
• Servo signal pin → Arduino pin 10
Connections from the LCD:
• I2C module GND pin → Breadboard GND line
• I2C module 5V pin → breadboard GND line
• I2C module SDA pin → Arduino pin A4
• I2C module SCL pin → Arduino pin A5
*/
// Define libraries
#include "Keypad.h"
#include "Wire.h"
#include "LiquidCrystal_I2C.h"
#include "Servo.h"
// Define the 4x4 keypad pins
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
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}; // Connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; // Connect to the column pinouts of the keypad
// Initialize the keypad, LCD, and servo
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD I2C address and dimensions
Servo myServo; // Create a Servo object
// Set password and other variables
String password = "1234B"; // Set the password to open the safe
const int MAX_PASSWORD_LENGTH = 4; // maximum password length, change accordingly
String enteredPassword = ""; // Store the entered password
bool safeOpen = false; // Store the state of the safe (open or closed)
// Commands inside void setup run once
void setup() {
Serial.begin(9600); // Initialize serial communication
lcd.init(); // Initialize the LCD
lcd.backlight(); // Turn on the LCD backlight
myServo.attach(10); // Attach the servo to pin 10
myServo.write(0); // Initialize the servo to closed position
lcd.setCursor(1, 0);
lcd.print("Voltaat Learn"); // Display "Security Safe" on the first line
lcd.setCursor(1, 1);
lcd.print("Security Safe"); // Clear the second line
}
// Commands inside void loop run forever
void loop() {
static bool showEnterPassword = false;
static unsigned long prevMillis = 0;
const unsigned long delayTime = 5000; // 5 seconds
static bool showSafeClosed = false;
static unsigned long safeClosedMillis = 0;
const unsigned long safeClosedDelayTime = 2000; // 2 seconds
// Show "Enter Password" message after 5 seconds
if (!showEnterPassword && millis() - prevMillis >= delayTime) {
showEnterPassword = true;
prevMillis = millis();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Password:");
}
// Read keypad input and handle password entry
char key = keypad.getKey();
if (showEnterPassword && key != NO_KEY) {
if (key == '#') { // Check if enter key is pressed
if (enteredPassword == password) { // Compare entered password with the correct password
if (safeOpen) { // If safe is already open, close it and ask to enter password again
safeOpen = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Press C to close");
enteredPassword = ""; // Clear entered password
} else { // If safe is closed, open it and ask to close it
safeOpen = true;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Safe is open");
lcd.setCursor(0, 1);
lcd.print("Press C to close");
myServo.write(90); // Open the safe by turning the servo to 90 degrees
enteredPassword = ""; // Clear entered password
}
} else { // Incorrect password entered
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Wrong Password!");
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Password:");
enteredPassword = ""; // Clear entered password
}
} else if (key == '*') { // Check if clear key is pressed
enteredPassword = ""; // Clear entered password
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Password:");
} else if (key == 'C' || key == 'c') { // Check if C key is pressed
if (safeOpen) { // If safe is open, close it
safeOpen = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Safe is closed");
myServo.write(0); // Close the safe by turning the servo to 0 degrees
showSafeClosed = true;
safeClosedMillis = millis();
enteredPassword = ""; // Clear entered password
}
} else if (key == 'D' || key == 'd') { // Check if D key is pressed
if (enteredPassword.length() > 0) { // If password is not empty, delete last character
enteredPassword = enteredPassword.substring(0, enteredPassword.length() - 1);
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the password field on the LCD screen
lcd.setCursor(0, 1);
// Print asterisks instead of the actual password characters
for (int i = 0; i < enteredPassword.length(); i++) {
lcd.print("*");
}
}
} else { // Append entered key to the entered password
if (enteredPassword.length() < 5 && !safeOpen) { // Limit password to 5 characters
enteredPassword += key;
lcd.setCursor(0, 1);
// Print asterisks instead of the actual password characters
for (int i = 0; i < enteredPassword.length(); i++) {
lcd.print("*");
}
}
}
}
// show "Safe Closed" message for 2 seconds after the safe is closed
if (showSafeClosed && millis() - safeClosedMillis >= safeClosedDelayTime) {
showSafeClosed = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Password:");
}
}