#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <Encoder.h>
int btnNext = 10;
int iCount1 = 0;
int iCount2 = 0;
int iCount3 = 0;
int iCount4 = 0;
int iPin = 0;
int digitEdit = 1;
Servo servo_11;
// Rotary encoder value setup
int prevVal = 0;
int codeVal = 0;
long oldPosition = -999;
Encoder myEnc(5, 6); //data, clock
LiquidCrystal_I2C lcd_1(0x27, 16, 2);
// Define LED and Buzzer pins
const int redLED = 8;
const int greenLED = 9;
const int buzzer = 12; // Pin for Piezo Buzzer
// Distance sensor pins
const int triggerPin = 2;
const int echoPin = 3;
// Debounce variables
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 500; // Debounce delay in milliseconds
// Variable to store distance reading
int currentDistance = 0;
void setup(){
pinMode(btnNext, INPUT_PULLUP);
// Initialize LED and Buzzer pins
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(buzzer, OUTPUT);
// Set LEDs and Buzzer to off initially
digitalWrite(redLED, LOW);
digitalWrite(greenLED, LOW);
digitalWrite(buzzer, LOW);
// Initialize distance sensor pins
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
// Serial monitor setup
Serial.begin(9600);
// LCD screen setup
lcd_1.init();
lcd_1.backlight();
lcd_1.blink();
lcd_1.setCursor(1, 0);
lcd_1.print("0");
lcd_1.setCursor(3, 0);
lcd_1.print("0");
lcd_1.setCursor(5, 0);
lcd_1.print("0");
lcd_1.setCursor(7, 0);
lcd_1.print("0");
lcd_1.setCursor(1, 0);
// Servo Motor setup
servo_11.attach(11);
servo_11.write(0);
}
void loop() {
int val = encVal(); // Read value change from rotary encoder
String valChange;
// Respond to change in encoder value
if (val != prevVal) {
if (val > prevVal) {
valChange = "increase";
} else if (val < prevVal) {
valChange = "decrease";
}
Serial.println(valChange);
prevVal = val; // Reset previous value to new value
// Update counts based on selected digit
updateCounts(valChange);
// Display updated count on LCD
displayCounts();
}
// Move to next number
next();
// Check if passcode is correct and distance is valid
checkPasscode();
// Handle distance sensor reading with debounce
handleDistanceSensor();
}
// Method to update counts based on the value change
void updateCounts(const String &valChange) {
if (iPin == 0) {
if (valChange.equals("increase")) {
iCount1++;
if (iCount1 > 9) {
iCount1 = 0;
}
} else if (valChange.equals("decrease")) {
iCount1--;
if (iCount1 < 0) {
iCount1 = 9;
}
}
} else if (iPin == 1) {
if (valChange.equals("increase")) {
iCount2++;
if (iCount2 > 9) {
iCount2 = 0;
}
} else if (valChange.equals("decrease")) {
iCount2--;
if (iCount2 < 0) {
iCount2 = 9;
}
}
} else if (iPin == 2) {
if (valChange.equals("increase")) {
iCount3++;
if (iCount3 > 9) {
iCount3 = 0;
}
} else if (valChange.equals("decrease")) {
iCount3--;
if (iCount3 < 0) {
iCount3 = 9;
}
}
} else if (iPin == 3) {
if (valChange.equals("increase")) {
iCount4++;
if (iCount4 > 9) {
iCount4 = 0;
}
} else if (valChange.equals("decrease")) {
iCount4--;
if (iCount4 < 0) {
iCount4 = 9;
}
}
}
}
// Method to display counts on LCD
void displayCounts() {
lcd_1.setCursor(digitEdit, 0);
if (iPin == 0) lcd_1.print(iCount1);
else if (iPin == 1) lcd_1.print(iCount2);
else if (iPin == 2) lcd_1.print(iCount3);
else if (iPin == 3) lcd_1.print(iCount4);
lcd_1.setCursor(digitEdit, 0);
Serial.println(iCount1);
}
// Method to check if passcode is correct and distance is valid
void checkPasscode() {
if (iCount1 == 1 && iCount2 == 2 && iCount3 == 3 && iCount4 == 4) {
if (currentDistance <= 20) { // Check if distance is 20 cm or less
servo_11.write(90);
digitalWrite(greenLED, HIGH); // Turn on green LED
digitalWrite(redLED, LOW); // Ensure red LED is off
buzzerTone(1000, 500); // Turn on buzzer with tone
delay(1000); // Keep buzzer on for a second
int iInput = digitalRead(btnNext);
while (iInput == 1) {
iInput = digitalRead(btnNext);
}
delay(100);
Reset();
Serial.println(iPin);
} else {
// If distance is not valid, do not open the lock
digitalWrite(greenLED, LOW); // Ensure green LED is off
digitalWrite(redLED, HIGH); // Turn on red LED
digitalWrite(buzzer, LOW); // Ensure buzzer is off
}
} else {
// If passcode is incorrect, do not open the lock
digitalWrite(greenLED, LOW); // Ensure green LED is off
digitalWrite(redLED, HIGH); // Turn on red LED
digitalWrite(buzzer, LOW); // Ensure buzzer is off
}
}
// Method to handle distance sensor reading with debounce
void handleDistanceSensor() {
unsigned long currentTime = millis();
if (currentTime - lastDebounceTime >= debounceDelay) {
lastDebounceTime = currentTime;
// Trigger the sensor
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
// Read the echo
long duration = pulseIn(echoPin, HIGH);
currentDistance = duration * 0.0344 / 2; // Convert to centimetres
if (currentDistance > 0 && currentDistance <= 100) {
Serial.print("Distance: ");
Serial.print(currentDistance);
Serial.println(" cm");
} else {
Serial.println("Out of range");
}
}
}
// Method to reset all the code back to its original value
void Reset() {
servo_11.write(0);
iCount1 = 0;
iCount2 = 0;
iCount3 = 0;
iCount4 = 0;
iPin = 0;
digitEdit = 1;
lcd_1.setCursor(1, 0);
lcd_1.print(iCount1);
lcd_1.setCursor(3,0);
lcd_1.print(iCount2);
lcd_1.setCursor(5,0);
lcd_1.print(iCount3);
lcd_1.setCursor(7,0);
lcd_1.print(iCount4);
lcd_1.setCursor(1, 0);
lcd_1.setCursor(1, 0);
delay(100);
}
// Method used when the push button that is inbuilt into the rotary encoder
// is pressed causing it to switch to the next digit of the password
void next() {
int iNext = digitalRead(btnNext);
// When clicking the inbuilt push button within the rotary encoder it
// increases the value of iPin, switching to the next digit of the password
if (iNext == 0) {
iPin++;
if (iPin > 3) {
iPin = 0;
}
if (iPin == 0) {
digitEdit = 1;
} else if (iPin == 1) {
digitEdit = 3;
} else if (iPin == 2) {
digitEdit = 5;
} else if (iPin == 3) {
digitEdit = 7;
}
lcd_1.setCursor(digitEdit, 0);
Serial.print(iPin);
delay(300);
}
}
// Method to read value change from rotary encoder
int encVal() {
long newPosition = myEnc.read();
int val = prevVal;
if (newPosition != oldPosition) {
oldPosition = newPosition;
val = newPosition / 4;
}
return val;
}
// Method to generate a tone for the buzzer
void buzzerTone(int frequency, int duration) {
tone(buzzer, frequency, duration);
}