This shows you the differences between two versions of the page.
|
iothings:proiecte:2025sric:esp32-smart-access-monitor [2025/05/29 16:59] robert_george.pancu [Context] |
iothings:proiecte:2025sric:esp32-smart-access-monitor [2025/05/29 17:48] (current) robert_george.pancu [Challenges] |
||
|---|---|---|---|
| Line 24: | Line 24: | ||
| 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. | 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. | ||
| ====== Hardware ====== | ====== Hardware ====== | ||
| + | Components: | ||
| + | * ESP32 | ||
| + | * 2 x IR sensor | ||
| + | * Buzzer | ||
| + | * wires | ||
| + | * breadboard | ||
| + | |||
| + | {{iothings:proiecte:2025sric:poza_esp.jpg?400 | ESP32 Setup}} | ||
| ====== Software ====== | ====== Software ====== | ||
| + | |||
| + | Technologies Used | ||
| + | |||
| + | * Arduino Framework (ESP32 Core): Used to program the microcontroller. | ||
| + | |||
| + | * HTML/CSS/JavaScript: Used for building a responsive web interface. | ||
| + | |||
| + | * Chart.js: JavaScript library used for rendering the real-time people count chart. | ||
| + | |||
| + | * Embedded Web Server (ESP32): Hosts the HTML page and handles HTTP requests. | ||
| + | |||
| === Code Snippets === | === Code Snippets === | ||
| + | |||
| + | <code cpp> | ||
| + | #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; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </code> | ||
| + | |||
| + | WEB | ||
| + | |||
| + | {{iothings:proiecte:2025sric:dashboard.png?600 | Web Dashboard}} | ||
| + | |||
| ====== Challenges ====== | ====== Challenges ====== | ||
| + | Sensor Accuracy and Timing | ||
| + | |||
| + | * Differentiating between entry and exit requires precise detection and timing. | ||
| + | * Simultaneous movement or people hesitating at the doorway can cause incorrect counts. | ||
| + | * Solution: Implemented a state machine with timeouts to improve reliability. | ||
| + | |||
| + | Resource Limitations on ESP32 | ||
| + | |||
| + | * Hosting a full HTML page, JavaScript logic, and handling concurrent client requests pushed the memory limits. | ||
| + | * Optimized the web page content and avoided large libraries to keep the firmware lean. | ||
| + | |||
| + | Security Considerations | ||
| + | * Password is sent in plain text and checked locally, making it vulnerable in open networks. | ||
| + | * Future improvements could include HTTPS support or token-based authentication. | ||
| ====== References ====== | ====== References ====== | ||
| + | * https://ocw.cs.pub.ro/courses/iothings/laboratoare/2022/lab3 | ||
| + | * https://randomnerdtutorials.com/esp32-web-server-arduino-ide/ | ||
| + | * https://www.w3schools.com/ | ||