← Back to insights
ESP8266ESP32IoTBlynkSensorsRemote MonitoringIntermediate

Ultrasonic Smart Parking Assistant Using ESP8266/ESP32 and Blynk

Build a two-slot smart parking assistant using ESP8266 or ESP32, two ultrasonic sensors, an I2C LCD, and Blynk to show distance, parking status, and Safe/Warning/Stop zones.

  • ESP8266
  • ESP32
  • Ultrasonic Sensor
  • HC-SR04
  • Smart Parking
  • Parking Assistant
  • I2C LCD
  • Blynk
  • IOT
  • Distance Measurement
Published
Updated
Reading time
3 min read
Author
Saroj Chaudhary
Role
IoT & Embedded Systems Engineer

This project creates a two-slot smart parking assistant using two ultrasonic sensors.

Each sensor measures the distance between a vehicle and the end of a parking slot. The ESP8266 or ESP32 classifies the distance into Safe, Warning, and Stop zones, shows the slot condition on a 16x2 I2C LCD, and sends the same information to Blynk.

The same project works with both ESP8266 and ESP32. The required library and GPIO differences are explained below.

Components Required

Component Quantity
ESP8266 NodeMCU or ESP32 Dev Board 1
HC-SR04 Ultrasonic Sensor 2
16x2 I2C LCD 1
Breadboard 1
Jumper Wires As required
Resistors for Echo voltage divider 4
USB / Suitable Power Supply 1

Important: The HC-SR04 Echo pin can output around 5V. ESP8266 and ESP32 GPIO are 3.3V devices, so use a voltage divider on each Echo pin.

A simple divider can be:

HC-SR04 Echo
     |
    1kΩ
     |
     +-----> ESP GPIO
     |
    2kΩ
     |
    GND

How the Parking System Works

Two ultrasonic sensors monitor two separate parking slots.

Sensor 1 -> Slot 1
              \
               ESP8266 / ESP32
              /
Sensor 2 -> Slot 2
               |
          +----+----+
          |         |
         LCD      Blynk

The controller checks the distance and decides whether each slot is:

EMPTY
PARKED - SAFE
PARKED - WARNING
PARKED - STOP

Parking Distance Zones

The example uses:

Distance > 100 cm  -> EMPTY
26-100 cm          -> PARKED / SAFE
11-25 cm           -> PARKED / WARNING
0-10 cm            -> PARKED / STOP

These values can be changed according to the dimensions of your parking model.

LCD Display

The LCD displays both slot conditions at the same time.

Example:

S1 42cm SAFE
S2 EMPTY

Another condition:

S1 08cm STOP
S2 18cm WARN

ESP8266 and ESP32 Connections

ESP8266 NodeMCU

Device ESP8266 Pin
LCD SDA D2 / GPIO4
LCD SCL D1 / GPIO5
Slot 1 Trig D5 / GPIO14
Slot 1 Echo D6 / GPIO12
Slot 2 Trig D7 / GPIO13
Slot 2 Echo D0 / GPIO16

ESP32

Device ESP32 Pin
LCD SDA GPIO21
LCD SCL GPIO22
Slot 1 Trig GPIO18
Slot 1 Echo GPIO19
Slot 2 Trig GPIO25
Slot 2 Echo GPIO26

Both ultrasonic sensors may share the same supply and ground, but each sensor must use its own Trig and Echo pins.

Required Libraries

Install these libraries from Arduino IDE Library Manager:

Blynk
LiquidCrystal_I2C

For ESP8266, the code uses:

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

For ESP32, the code uses:

#include <WiFi.h>
#include <BlynkSimpleEsp32.h>

The code below selects the correct libraries automatically.

Blynk Setup

Create these datastreams:

Datastream Virtual Pin Type
Slot 1 Distance V0 Integer
Slot 1 Status V1 String
Slot 2 Distance V2 Integer
Slot 2 Status V3 String

Example values:

Slot 1 Distance: 42 cm
Slot 1 Status: PARKED-SAFE

Slot 2 Distance: 150 cm
Slot 2 Status: EMPTY

Complete ESP8266/ESP32 Code

#define BLYNK_PRINT Serial

#define BLYNK_TEMPLATE_ID "YOUR_TEMPLATE_ID"
#define BLYNK_TEMPLATE_NAME "Smart Parking Assistant"
#define BLYNK_AUTH_TOKEN "YOUR_AUTH_TOKEN"

#if defined(ESP8266)

  #include <ESP8266WiFi.h>
  #include <BlynkSimpleEsp8266.h>

  const int TRIG1 = D5;
  const int ECHO1 = D6;

  const int TRIG2 = D7;
  const int ECHO2 = D0;

#elif defined(ESP32)

  #include <WiFi.h>
  #include <BlynkSimpleEsp32.h>

  const int TRIG1 = 18;
  const int ECHO1 = 19;

  const int TRIG2 = 25;
  const int ECHO2 = 26;

#else
  #error "Select an ESP8266 or ESP32 board in Arduino IDE."
#endif

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

char ssid[] = "YOUR_WIFI_NAME";
char pass[] = "YOUR_WIFI_PASSWORD";

LiquidCrystal_I2C lcd(0x27, 16, 2);

BlynkTimer timer;

const int STOP_DISTANCE = 10;
const int WARNING_DISTANCE = 25;
const int OCCUPIED_DISTANCE = 100;

long readDistanceCM(int trigPin, int echoPin)
{
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);

  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH, 30000);

  if (duration == 0)
    return 999;

  return duration * 0.0343 / 2;
}

String getParkingStatus(long distance)
{
  if (distance > OCCUPIED_DISTANCE)
    return "EMPTY";

  if (distance <= STOP_DISTANCE)
    return "PARKED-STOP";

  if (distance <= WARNING_DISTANCE)
    return "PARKED-WARN";

  return "PARKED-SAFE";
}

String getLCDStatus(long distance)
{
  if (distance > OCCUPIED_DISTANCE)
    return "EMPTY";

  if (distance <= STOP_DISTANCE)
    return "STOP";

  if (distance <= WARNING_DISTANCE)
    return "WARN";

  return "SAFE";
}

void printSlotToLCD(int row, int slotNumber, long distance, String status)
{
  lcd.setCursor(0, row);
  lcd.print("                ");

  lcd.setCursor(0, row);
  lcd.print("S");
  lcd.print(slotNumber);
  lcd.print(" ");

  if (status == "EMPTY")
  {
    lcd.print("EMPTY");
  }
  else
  {
    if (distance < 10)
      lcd.print("0");

    lcd.print(distance);
    lcd.print("cm ");
    lcd.print(status);
  }
}

void updateParking()
{
  long distance1 = readDistanceCM(TRIG1, ECHO1);

  // Small delay reduces interference between the two ultrasonic sensors.
  delay(60);

  long distance2 = readDistanceCM(TRIG2, ECHO2);

  String slot1Status = getParkingStatus(distance1);
  String slot2Status = getParkingStatus(distance2);

  String slot1LCD = getLCDStatus(distance1);
  String slot2LCD = getLCDStatus(distance2);

  printSlotToLCD(0, 1, distance1, slot1LCD);
  printSlotToLCD(1, 2, distance2, slot2LCD);

  Serial.print("Slot 1: ");
  Serial.print(distance1);
  Serial.print(" cm | ");
  Serial.println(slot1Status);

  Serial.print("Slot 2: ");
  Serial.print(distance2);
  Serial.print(" cm | ");
  Serial.println(slot2Status);

  if (Blynk.connected())
  {
    Blynk.virtualWrite(V0, distance1);
    Blynk.virtualWrite(V1, slot1Status);

    Blynk.virtualWrite(V2, distance2);
    Blynk.virtualWrite(V3, slot2Status);
  }
}

void setup()
{
  Serial.begin(115200);

  pinMode(TRIG1, OUTPUT);
  pinMode(ECHO1, INPUT);

  pinMode(TRIG2, OUTPUT);
  pinMode(ECHO2, INPUT);

#if defined(ESP8266)
  Wire.begin(D2, D1);
#elif defined(ESP32)
  Wire.begin(21, 22);
#endif

  lcd.init();
  lcd.backlight();

  lcd.setCursor(0, 0);
  lcd.print("Smart Parking");

  lcd.setCursor(0, 1);
  lcd.print("Starting...");

  Blynk.begin(
    BLYNK_AUTH_TOKEN,
    ssid,
    pass
  );

  timer.setInterval(1000L, updateParking);

  delay(1000);
  lcd.clear();
}

void loop()
{
  Blynk.run();
  timer.run();
}

Arduino IDE Board Selection

ESP8266

Select:

Tools
-> Board
-> ESP8266 Boards
-> NodeMCU 1.0 (ESP-12E Module)

The ESP8266 build automatically uses:

ESP8266WiFi.h
BlynkSimpleEsp8266.h
D5, D6, D7 and D0

ESP32

Select:

Tools
-> Board
-> ESP32 Arduino
-> ESP32 Dev Module

The ESP32 build automatically uses:

WiFi.h
BlynkSimpleEsp32.h
GPIO18, GPIO19, GPIO25 and GPIO26

Testing the Parking System

Empty Slot

If no vehicle is within 100 cm:

LCD:
S1 EMPTY

Blynk:
Slot 1 Status = EMPTY

Safe Zone

Distance = 55 cm

LCD:
S1 55cm SAFE

Blynk:
PARKED-SAFE

Warning Zone

Distance = 20 cm

LCD:
S1 20cm WARN

Blynk:
PARKED-WARN

Stop Zone

Distance = 8 cm

LCD:
S1 08cm STOP

Blynk:
PARKED-STOP

Test both Slot 1 and Slot 2 independently.

Adjusting the Parking Zones

Change:

const int STOP_DISTANCE = 10;
const int WARNING_DISTANCE = 25;
const int OCCUPIED_DISTANCE = 100;

according to your parking model.

Common Problems

Distance Shows 999

Check:

  • Trig connection
  • Echo connection
  • sensor power
  • common ground
  • Echo voltage divider

Unstable Readings

Two ultrasonic sensors can interfere with each other if triggered at the same time.

This example reads them one after another with a short delay to reduce interference.

LCD Shows Nothing

Check:

  • SDA and SCL wiring
  • LCD power
  • I2C address

Common LCD addresses include:

0x27
0x3F

Blynk Does Not Update

Check:

  • Wi-Fi credentials
  • Blynk Template ID
  • Auth Token
  • V0 to V3 datastream configuration

Final Result

The completed system monitors two parking slots.

Each slot shows:

Distance
PARKED or EMPTY
SAFE / WARNING / STOP

The same information is available locally on the LCD and remotely through Blynk.

For a real outdoor parking system, use weather-resistant sensors and a suitable enclosure instead of relying on an exposed HC-SR04 module.

Related Articles

ESP8266Beginner

IoT Home Intruder Detection System Using ESP8266/ESP32 and Blynk

Build an IoT home intruder detection system using ESP8266 or ESP32, PIR and IR sensors, and Blynk for movement detection, entry monitoring, security status, and remote intrusion alerts.

  • ESP8266
  • ESP32
  • Nodemcu
4 min readESP32
Read article
ESP8266Beginner

Motion Activated Smart Room Light Using ESP8266/ESP32 and Blynk

Build a motion-activated smart room light using ESP8266 or ESP32, a PIR sensor, relay, bulb, and Blynk with automatic timeout control and remote monitoring.

  • ESP8266
  • ESP32
  • PIR Sensor
2 min readESP32
Read article
ESP8266Beginner

Automatic Night Light with IoT Monitoring Using ESP8266 and Blynk

Build an automatic night light using ESP8266, an LDR sensor, relay, bulb, and Blynk for light-level monitoring and manual override control.

  • ESP8266
  • Nodemcu
  • LDR
2 min readIoT
Read article

Author

Saroj Chaudhary

IoT & Embedded Systems Engineer

Founder-led engineering notes from IoTSolutions, focused on practical device, firmware, and telemetry decisions.

Apply the idea

Need help turning this article into a working prototype plan?

If you are working through device architecture, connectivity, firmware structure, or dashboard scope, IoTSolutions can help turn the question into a cleaner build path.