//Import libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Servo.h>
#include <Keypad.h>
// LCD setup
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Servo setup
Servo lockerServo;
const int servoPin = 13;
// PIR sensor setup
const int pirSensorPin = 34;
// LED setup
const int redLedPin = 12;
const int greenLedPin = 25;
// Keypad setup
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {19, 18, 5, 4}; //Row #1,2,3,4
byte colPins[COLS] = {15, 14, 27, 26}; //Col #1,2,3,4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Locker state
bool isLockerOccupied = false;
const char* correctPin = "1234"; // Change to desired PIN
char enteredPin[5] = {0};
unsigned long lastMotionTime = 0;
const unsigned long motionTimeout = 5000; // 5 seconds to assume parcel placed
void setup() {
// Initialize components
Serial.begin(115200);
lcd.init();
lcd.backlight();
lockerServo.attach(servoPin);
pinMode(pirSensorPin, INPUT);
pinMode(redLedPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
// Lock the servo initially
lockerServo.write(0); // Locked position
updateStatus();
//lcd init
lcd.print("Init lcd");
}
void loop() {
// Check PIR sensor
int pirState = digitalRead(pirSensorPin);
if (pirState == HIGH) {
lastMotionTime = millis(); // Record motion time
if (!isLockerOccupied) {
isLockerOccupied = true; // Assume parcel placed
updateStatus();
}
} else if (isLockerOccupied && (millis() - lastMotionTime > motionTimeout)) {
isLockerOccupied = false; // Assume parcel removed after timeout
updateStatus();
}
// Handle keypad input using '#' to submit PIN
char key = keypad.getKey();
if (key) {
static int pinIndex = 0;
if (key == '#') {
enteredPin[pinIndex] = '\0';
if (strcmp(enteredPin, correctPin) == 0) {
Serial.println("Open locker");
unlockLocker();
} else {
lcd.clear();
lcd.print("Wrong PIN!");
Serial.println("Wrong PIN!");
delay(2000);
}
pinIndex = 0;
memset(enteredPin, 0, sizeof(enteredPin));
} else if (pinIndex < 4) {
enteredPin[pinIndex++] = key;
lcd.clear();
lcd.print("Enter PIN: ");
for (int i = 0; i < pinIndex; i++) lcd.print("*");
}
}
}
void updateStatus() {
digitalWrite(redLedPin, isLockerOccupied ? HIGH : LOW);
digitalWrite(greenLedPin, isLockerOccupied ? LOW : HIGH);
lcd.clear();
lcd.print(isLockerOccupied ? "Locker: Occupied" : "Locker: Empty");
Serial.println(isLockerOccupied ? "Locker: Occupied" : "Locker: Empty");
}
void unlockLocker() {
lcd.clear();
lcd.print("Unlocking...");
lockerServo.write(90); // Unlocked position
delay(5000); // Keep unlocked for 5 seconds
lockerServo.write(0); // Lock again
lcd.clear();
lcd.print("Locked");
}