In this tutorial, we’ll build a ESP32 Parking System using three IR sensors. The system will monitor three parking slots and display their status (free or occupied) on a web page. You’ll learn how to set up an ESP32 web server, read sensor data, and update the webpage dynamically.
What You’ll Need
Hardware:
- ESP32 Development Board (e.g., ESP32 DevKit).
- 3 IR Sensors (for detecting vehicles in parking slots).
- Breadboard and Jumper Wires.
Software:
- Arduino IDE (with ESP32 board package installed).
- ESPAsyncWebServer Library (for handling the web server).
- AsyncTCP Library (for handling ESPAsyncWebServer requests)
How It Works
- Each parking slot has an IR sensor that detects whether a vehicle is present.
- The ESP32 reads the sensor data and updates the web page in real time.
- The web page displays the status of each slot (e.g., “Slot 1: Free” or “Slot 2: Occupied”).
Wiring Diagram

IR Sensors:
- Connect the VCC pin of each IR sensor to the VIN pin on the ESP32.
- Connect the GND pin of each IR sensor to the GND pin on the ESP32.
- Connect the OUT pin of each IR sensor to GPIO pins on the ESP32:
- Slot 1: GPIO 14
- Slot 2: GPIO 12
- Slot 3: GPIO 13
Code: ESP32 Parking System
Below is the complete code for the project. It uses the ESPAsyncWebServer
library to create a web server and update the parking slot status dynamically.
Installing the Required Libraries
You’ll need these libraries:
Install them via Arduino Library Manager or download manually from GitHub.
- Go to Sketch > Include Library > Manage Libraries in the Arduino IDE.
- Search for ESPAsyncWebServer and install it.

- Search for AsyncTCP and install it.

uploading the code
//---- ESP32 Parking System by ArduinoYard ----\\
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
// Replace with your network credentials
const char* ssid = "YourSSID";
const char* password = "YourPassword";
// GPIO pins for IR sensors
#define SLOT_1_SENSOR 14
#define SLOT_2_SENSOR 12
#define SLOT_3_SENSOR 13
// Create a web server object on port 80
AsyncWebServer server(80);
// HTML webpage with inline CSS styling for icons and layout
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ESP32 Parking System</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
margin-top: 50px;
}
.slot {
font-size: 24px;
margin: 20px;
padding: 10px;
border: 2px solid #000;
display: inline-block;
width: 150px;
}
.free { background-color: #90EE90; }
.occupied { background-color: #FF6347; }
</style>
</head>
<body>
<h1>ESP32 Parking System</h1>
<div id="slots">
<div class="slot" id="slot1">Slot 1: Loading...</div>
<div class="slot" id="slot2">Slot 2: Loading...</div>
<div class="slot" id="slot3">Slot 3: Loading...</div>
</div>
<script>
function updateSlots() {
fetch("/status")
.then(response => response.json())
.then(data => {
document.getElementById("slot1").innerText = "Slot 1: " + (data.slot1 ? "Occupied" : "Free");
document.getElementById("slot1").className = "slot " + (data.slot1 ? "occupied" : "free");
document.getElementById("slot2").innerText = "Slot 2: " + (data.slot2 ? "Occupied" : "Free");
document.getElementById("slot2").className = "slot " + (data.slot2 ? "occupied" : "free");
document.getElementById("slot3").innerText = "Slot 3: " + (data.slot3 ? "Occupied" : "Free");
document.getElementById("slot3").className = "slot " + (data.slot3 ? "occupied" : "free");
});
}
setInterval(updateSlots, 1000); // Update every second
</script>
</body>
</html>
)rawliteral";
void setup() {
Serial.begin(9600);
// Initialize IR sensor pins as inputs
pinMode(SLOT_1_SENSOR, INPUT);
pinMode(SLOT_2_SENSOR, INPUT);
pinMode(SLOT_3_SENSOR, INPUT);
// Connect to Wi-Fi
Serial.println("Connecting to Wi-Fi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWi-Fi connected!");
Serial.println("IP Address: ");
Serial.println(WiFi.localIP());
// Define the root URL handler
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
request->send(200, "text/html", index_html);
});
// Define the status API
server.on("/status", HTTP_GET, [](AsyncWebServerRequest* request) {
String json = "{";
json += "\"slot1\":" + String(digitalRead(SLOT_1_SENSOR)) + ",";
json += "\"slot2\":" + String(digitalRead(SLOT_2_SENSOR)) + ",";
json += "\"slot3\":" + String(digitalRead(SLOT_3_SENSOR));
json += "}";
request->send(200, "application/json", json);
});
// Start the server
server.begin();
Serial.println("Web server started.");
}
void loop() {
// Nothing to do here; the server handles everything asynchronously
}
How the Code Works
- HTML Page:
- The webpage displays three parking slots and updates their status dynamically using JavaScript.
- The
fetch()
function calls the/status
API every second to get the latest sensor data.
- Web Server:
- The ESP32 hosts a web server that serves the HTML page and provides a
/status
API to fetch sensor data in JSON format.
- The ESP32 hosts a web server that serves the HTML page and provides a
- IR Sensors:
- The ESP32 reads the sensor data and updates the JSON response accordingly.
Testing the System
- Upload the code to your ESP32.
- Open the Serial Monitor to check the ESP32’s IP address.

- Open a web browser and enter the ESP32’s IP address.

- Place objects in front of the IR sensors and observe the web page updating in real time.
Video Demonstration
CUSTOMIZING THE PROJECT
The ESP32 parking system project we’ve built is a great starting point for many other IoT applications. By customizing the HTML and ESP32 code, you can adapt this project for a wide range of use cases. Below are some ideas and tips for customization.
1. Add More Parking Slots
If you need to monitor more than three parking slots, you can easily expand the system:
- Hardware: Add more IR sensors and connect them to available GPIO pins on the ESP32.
- Code: Update the HTML and ESP32 code to include additional slots. For example:
- Add more sensor pins in the
#define
section. - Update the
/status
API to include the new sensors. - Modify the HTML to display the new slots.
- Add more sensor pins in the
2. Add Visual and Audio Alerts
Enhance the system by adding visual (LEDs) or audio (buzzer) alerts when a slot is occupied or freed:
- Hardware: Connect LEDs or a buzzer to GPIO pins.
- Code: Add logic to turn on/off the LEDs or buzzer based on sensor data. For example:
if (digitalRead(SLOT_1_SENSOR)
{
digitalWrite(LED_PIN, HIGH); // Turn on LED
}
else
{
digitalWrite(LED_PIN, LOW); // Turn off LED
}
3. Integrate with a Database
Store parking slot data in a database for long-term monitoring and analysis:
- Use Case: Track parking usage over time or generate reports.
- Implementation:
- Use a cloud platform like Firebase, AWS, or Google Sheets.
- Send sensor data to the database using HTTP POST requests.
- Example: Use Firebase Realtime Database to store slot status and timestamps.
4. Send Notifications
Send real-time notifications when a slot is occupied or freed:
- Use Case: Alert parking attendants or users via email, SMS, or push notifications.
- Implementation:
- Use services like Twilio (for SMS), IFTTT (for email), or Pushbullet (for push notifications).
- Add logic to send notifications when the sensor state changes.
5. Create a Mobile-Friendly Dashboard
Make the web page responsive and mobile-friendly for better user experience:
- Customization:
- Use CSS frameworks like Bootstrap to create a responsive layout.
- Add buttons or sliders to control devices (e.g., turn on/off lights or gates).
- Example:
<button onclick="controlDevice(1)">Open Gate</button> <script> function controlDevice(deviceId) { fetch("/control?device=" + deviceId) .then(response => response.text()) .then(data => console.log(data)); } </script>
6. Add User Authentication
Secure the web page with user authentication to restrict access:
- Use Case: Allow only authorized users to view or control the system.
- Implementation:
- Use basic HTTP authentication or integrate with OAuth services.
- Example:
server.on("/admin", HTTP_GET, [](AsyncWebServerRequest* request) { if (!request->authenticate("admin", "password")) { return request->requestAuthentication(); } request->send(200, "text/html", "Welcome, Admin!"); });
7. Integrate with Other Sensors
Expand the system by integrating other sensors for additional functionality:
- Examples:
- Ultrasonic Sensors: Measure the distance of parked vehicles.
- Temperature Sensors: Monitor environmental conditions in the parking area.
- Light Sensors: Automatically turn on lights when it gets dark.
8. Control Devices Remotely
Add functionality to control devices (e.g., gates, lights) from the web page:
- Use Case: Allow users to open/close gates or turn on/off lights remotely.
- Implementation:
- Add buttons or sliders to the HTML page.
- Use the ESP32 to control relays or actuators connected to the devices.
9. Add a History Log
Display a history of parking slot status changes on the web page:
- Use Case: Track when slots were occupied or freed.
- Implementation:
- Store timestamps and status changes in an array or external storage.
- Display the history in a table or list on the web page.
10. Deploy to the Cloud
Host the web page on a cloud server for remote access:
- Use Case: Access the parking system from anywhere in the world.
- Implementation:
- Use platforms like Heroku, AWS, or Google Cloud to host the HTML page.
- Use the ESP32 to send data to the cloud server via APIs.
Example: Customizing for a Smart Home System
You can adapt this ESP32 Parking System code for a Smart Home System:
- Replace IR sensors with motion sensors or door/window sensors.
- Update the HTML to display room occupancy or door/window status.
- Add controls for lights, fans, or appliances.
Conclusion
The ESP32 Parking System project is highly customizable and can serve as a base for many other IoT applications. Whether you’re building a smart home, industrial monitoring system, or environmental sensor network, the principles remain the same. Experiment with the code, add new features, and create something unique!
Thank You!!!
In case you missed:
ESP32 Webserver Alarm System: Building An Alarm System Using A Webpage – ArduinoYard