Dual-Sensor People Counter: ESP32 & Firebase Web Interface

by Orange Digital Center in Circuits > Arduino

12 Views, 0 Favorites, 0 Comments

Dual-Sensor People Counter: ESP32 & Firebase Web Interface

INSTRUCTABLES.PNG

This project was developed within the Orange Digital Center Morocco , a space dedicated to fostering innovation, creativity, and rapid prototyping. At the FabLab, individuals and teams have access to state-of-the-art tools, including 3D printers, laser cutters, and a variety of electronic and mechanical resources. The center provides a collaborative environment where innovators, entrepreneurs, and students can transform their ideas into tangible products. By focusing on sustainable and impactful solutions .

Imagine a system that counts the number of people in a room in real time and displays the data on a website via Firebase. More than just a sensor, it's a connected solution for efficient space management—whether for security, energy optimization, or occupancy analytics. With an intuitive web interface, you can monitor room occupancy remotely, from anywhere. Whether you're a professional looking to optimize workspace usage, an event organizer tracking attendance, or simply a tech enthusiast, this project opens the door to smart, automated management. Because every presence counts, and every data point makes a difference!

Supplies

SUPP2.PNG
SUPP1.PNG

--> ESP32 WROOM

Acts as the central controller of the project. It continuously reads distance data from the two ultrasonic sensors, determines the direction of movement (entry or exit) based on the triggering

sequence, and updates the internal people count. It can also be programmed to send the data to a server or display it on a screen.

--> 2x HC-SR04 Ultrasonic Sensors

Mounted side by side at the entrance.

1. Sensor A is placed first in the path, followed closely by Sensor B.

2. When someone walks in, Sensor A triggers before Sensor B → entry detected.

3. When someone walks out, Sensor B triggers before Sensor A → exit detected.

4. Their job is to detect the direction of movement and trigger the counting logic in the ESP32.

--> KCD1-101 Toggle Switch

Connected between the power source and the ESP32 circuit. It allows you to manually turn the system ON or OFF, useful for saving battery or resetting the system when needed.

--> Jumper Wires

Used to connect the sensors, ESP32, switch, and power module together. These ensure proper communication between components and power distribution in the circuit.

--> 2x 3.7V 2600mAh Lithium Batteries

Serve as the main power supply for the project. They provide enough voltage and current to run the ESP32 and the sensors for extended periods, making the system portable and wireless.

--> LM2596 DC-DC Buck Converter

Takes the ~7.4V from the two lithium batteries and steps it down to 5V, which is safe and stable for powering the ESP32 and sensors. The digital display helps you adjust and monitor the output voltage easily to avoid damaging components;

Building the Circuit Hardware

CIRCUIT.PNG

Hardware Assembly Instructions:

Let's start by assembling our hardware components! We'll connect two HC-SR04 ultrasonic

sensors to our ESP32:

1. Sensor 1:

2. TRIG → GPIO 04

3. ECHO → GPIO 02

4. Sensor 2:

5. TRIG → GPIO 05

6. ECHO → GPIO 34

The LM2596 buck converter will regulate power from our 3.7V lithium battery to a stable 5V/3.3V

for the ESP32.

Pro Tip:

1. Use a breadboard for prototyping before making permanent connections.

Setting Up Firebase

FIREBASE2.PNG
FIREBASE1.PNG

Firebase will be our cloud database. We need to:

1. Create a new project in Firebase Console

2. Set up Realtime Database with a simple structure{"NbrPersonne": 0}

3. Configure security rules to allow read/write access (temporarily for testing, then secure it

later)

4. Enable Firebase anonymous auth to obtain a temporary API key.

5. Note down your Firebase credentials (API key, project ID) for the ESP32 code

Programming the ESP32

Now for the brains of our project! We'll program the ESP32 in Arduino IDE to:

1. Measure distances with the ultrasonic sensor

2. Implement people counting logic (detecting entry/exit when distance changes)

3. Connect to WiFi and push data to Firebase

4. Don't forget to install the Firebase ESP Client library! The code will run a continuous loop,

updating counts every second.

Creating the Web Interface

KK2.PNG
KK1.PNG

Let's build a simple but effective web dashboard:

1. Basic HTML/CSS page with a large counter display

2. JavaScript to listen for Firebase database changes

3. Visual indicators when counts increase/decrease

4. The page will automatically update whenever someone enters/leaves the room - no refresh needed!

5.Replace these values with your actual Firebase project details

apiKey: "your API",

databaseURL: "your database URL",

projectId: "your Project ID"

<!DOCTYPE html>

<html lang="fr">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Compteur de Personnes - Synchro Firebase</title>

<style>

body {

font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

display: flex;

justify-content: center;

align-items: center;

height: 100vh;

margin: 0;

background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);

transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55);

}.counter-container {

text-align: center;

padding: 40px;

border-radius: 15px;

background: rgba(255, 255, 255, 0.9);

box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);

}

.counter {

font-size: 5rem;

font-weight: bold;

margin: 20px 0;

color: #2c3e50;

}

.status {

font-size: 1.2rem;

margin-top: 15px;

font-weight: 600;

}

</style>

</head>

<body>

<div class="counter-container">

<h1>Compteur de Personnes</h1>

<div class="counter" id="counter">0</div>

<div class="status" id="status">Connexion en cours...</div>

</div>

<!-- Chargement conditionnel de Firebase -->

<script>

// Détection Electron

const isElectron = window && window.process && window.process.type;

// Configuration Firebase

const firebaseConfig = {

apiKey: "your API",

databaseURL: "your database URL",

projectId: "your Project ID"

};

// Initialisation

function initFirebase() {

const app = firebase.initializeApp(firebaseConfig);

const database = firebase.database();

const counterElement = document.getElementById('counter');

const statusElement = document.getElementById('status');

let previousCount = 0;

// Écoute des changements en temps réel

database.ref('NbrPersonne').on('value', (snapshot) => {

const currentCount = snapshot.val() || 0;

counterElement.textContent = currentCount;

// Logique de notification

if (currentCount > previousCount) {

showNotification('Entrée détectée', `Total: ${currentCount}`);

statusElement.textContent = 'Entrée enregistrée';

statusElement.style.color = '#2ecc71';

} else if (currentCount < previousCount) {

showNotification('Sortie détectée', `Total: ${currentCount}`);

statusElement.textContent = 'Sortie enregistrée';

statusElement.style.color = '#e74c3c';

}

previousCount = currentCount;

}, (error) => {

statusElement.textContent = 'Erreur de connexion';

statusElement.style.color = '#e74c3c';

console.error("Firebase error:", error);

});

}

// Gestion des notifications

function showNotification(title, body) {

if (isElectron) {

const { ipcRenderer } = require('electron');

ipcRenderer.send('show-notification', { title, body });

} else if ('Notification' in window && Notification.permission === 'granted') {

new Notification(title, { body });

}

}

// Chargement dynamique de Firebase en mode navigateur

if (!isElectron) {

const firebaseScript = document.createElement('script');

firebaseScript.src = "https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js";

firebaseScript.onload = () => {

const databaseScript = document.createElement('script');

databaseScript.src = "https://www.gstatic.com/firebasejs/8.10.0/firebase-database.js";

databaseScript.onload = initFirebase;

document.head.appendChild(databaseScript);

};

document.head.appendChild(firebaseScript);

} else {

// En Electron, require est disponible

const { initializeApp } = require('firebase/app');

const { getDatabase, ref, onValue } = require('firebase/database');

initFirebase();

}

</script>

</body>

</html>

3D Design

MOD1.PNG

1. Main Box

2. Holds ESP32 and sensors

3. Has special holes for the pivot stick

4. Designed for easy wire management

5. Cover Plate

6. Simple flat piece

7. Has matching holes for the pivot stick

8. Clicks or screws in place

9. Pivot Stick (Long Rod)

10. Long rod shape (like a chopstick)

11. Fits through holes in both other pieces

12. Lets the main box rotate while cover stays fixed

</body>

</html>

- Instructables https://www.instructables.com/preview/EEZ195HMB3O6AUA/