This project is a Smart Door Access Control and People Counting System designed using the ESP32 microcontroller. It allows users to unlock a door via a web interface after entering a password. Once the correct password is provided, the door opens for a limited time (10 seconds), then automatically closes. Meanwhile, the system uses two infrared (IR) sensors to detect the direction of movement—identifying whether a person is entering or exiting—and updates a real-time counter displayed on a web interface along with a live graph.
The aim is to provide a low-cost, responsive, and real-time system suitable for securing rooms, monitoring occupancy, and enhancing access control in small-scale environments such as labs, classrooms, or offices.
In today's world, real-time monitoring and automation are becoming essential in both residential and commercial environments. Manual tracking of occupancy or relying solely on physical access cards or keys has limitations in terms of scalability, logging, and remote monitoring.
This project addresses several modern needs:
By combining IoT (Internet of Things) principles with basic access control and data visualization, this system serves as a foundation for smarter building management solutions.
Technologies Used
#include <WiFi.h> #include <WebServer.h> #define BUZZER_PIN 4 #define IR_SENSOR_A 25 #define IR_SENSOR_B 26 const char* ssid = ""; const char* wifiPassword = ""; const char* correctPassword = ""; WebServer server(80); int peopleCount = 0; unsigned long doorOpenTime = 0; const unsigned long doorOpenDuration = 10000; bool doorOpen = false; enum IRState { IDLE, ENTER_STAGE_1, EXIT_STAGE_1 }; IRState state = IDLE; unsigned long lastTriggerTime = 0; void buzzerSuccess() { for (int i = 0; i < 3; i++) { tone(BUZZER_PIN, 1000); delay(150); noTone(BUZZER_PIN); delay(150); } } void buzzerError() { tone(BUZZER_PIN, 500); delay(1000); noTone(BUZZER_PIN); } void handleSubmit() { if (!server.hasArg("pass")) { server.send(400, "text/plain", "Bad Request"); return; } String enteredPass = server.arg("pass"); if (enteredPass == correctPassword) { doorOpen = true; doorOpenTime = millis(); buzzerSuccess(); Serial.println("Door opened for 10 seconds."); server.send(200, "text/plain", "Access Granted: door open"); } else { buzzerError(); server.send(200, "text/plain", "Access Denied"); } } void handleCount() { String json = "{\"count\": " + String(peopleCount) + "}"; server.send(200, "application/json", json); } void handleDoorStatus() { if (doorOpen) { server.send(200, "text/plain", "opened"); } else { server.send(200, "text/plain", "closed"); } } void setup() { Serial.begin(115200); pinMode(BUZZER_PIN, OUTPUT); pinMode(IR_SENSOR_A, INPUT_PULLUP); pinMode(IR_SENSOR_B, INPUT_PULLUP); WiFi.begin(ssid, wifiPassword); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nConnected to WiFi"); Serial.println(WiFi.localIP()); server.on("/", handleRoot); server.on("/submit", HTTP_POST, handleSubmit); server.on("/count", handleCount); server.on("/doorstatus", handleDoorStatus); server.begin(); } void loop() { server.handleClient(); unsigned long now = millis(); int sensorA = digitalRead(IR_SENSOR_A); int sensorB = digitalRead(IR_SENSOR_B); if (doorOpen && now - doorOpenTime >= doorOpenDuration) { doorOpen = false; Serial.println("Door closed"); state = IDLE; return; } if (!doorOpen) { state = IDLE; return; } switch (state) { case IDLE: if (sensorA == LOW && sensorB == HIGH) { state = ENTER_STAGE_1; lastTriggerTime = now; } else if (sensorB == LOW && sensorA == HIGH) { state = EXIT_STAGE_1; lastTriggerTime = now; } break; case ENTER_STAGE_1: if (sensorB == LOW && now - lastTriggerTime < 2000) { peopleCount++; Serial.print("Entered → Total: "); Serial.println(peopleCount); state = IDLE; delay(500); } else if (now - lastTriggerTime >= 2000) { state = IDLE; } break; case EXIT_STAGE_1: if (sensorA == LOW && now - lastTriggerTime < 2000) { peopleCount = max(0, peopleCount - 1); Serial.print("Exited → Total: "); Serial.println(peopleCount); state = IDLE; delay(500); } else if (now - lastTriggerTime >= 2000) { state = IDLE; } break; } }
WEB
Sensor Accuracy and Timing
Resource Limitations on ESP32
Security Considerations