Parking Sensor Simulator using Arduino Uno and HC-SR04 Ultrasonic Sensor

 

 Parking Sensor Simulator using Arduino & Ultrasonic Sensor

The Parking Sensor Simulator is a smart distance detection system built using the Arduino Uno and the HC-SR04.

It mimics real car reverse parking sensors by:

  • Measuring distance using ultrasonic waves

  • Displaying distance on a 16×2 I2C LCD

  • Lighting LEDs as a proximity bar graph

  • Increasing buzzer beep speed as the object gets closer

This project can be built physically or simulated in the Wokwi.


 How It Works

 Ultrasonic Distance Measurement

The HC-SR04 works by:

1️⃣ Sending a 40kHz ultrasonic pulse
2️⃣ The sound wave hits an obstacle
3️⃣ The echo returns to the sensor
4️⃣ Arduino measures the time taken

 Distance Formula

Distance=Time×Speed of Sound2Distance = \frac{Time × Speed\ of\ Sound}{2}

In code:

float dist = duration * 0.034 / 2;

Where:

  • Speed of sound ≈ 0.034 cm/µs

  • Division by 2 accounts for forward & return travel


 Hardware Connections

Ultrasonic Sensor

HC-SR04 PinArduino Pin
VCC5V
GNDGND
TRIG7
ECHO6

LEDs (Distance Indicator Bar)

LED ColorArduino Pin
Green8
Light Green9
Yellow10
Orange11
Red12

Each LED uses a 220Ω resistor.


Buzzer

BuzzerArduino Pin
+13
GND

LCD Display (I2C)

LCD PinArduino Pin
VCC5V
GNDGND
SDAA4
SCLA5

The display uses:

LiquidCrystal_I2C lcd(0x27, 16, 2);

System Logic

Distance Zones

DistanceStatusLEDsBuzzer
>100 cmAll ClearOFFOFF
50–100 cmApproaching1 LEDSlow beep
20–50 cmCaution2–3 LEDsMedium beep
10–20 cmDanger4 LEDsFast beep
<10 cmSTOP!All LEDs blinkingVery fast beep

 Buzzer Control Logic

The beep interval changes dynamically:

unsigned long calculateBuzzerInterval(float dist)

Closer distance → Smaller interval → Faster beeping

This perfectly simulates real car parking sensors.


 LED Bar Graph Logic

int calculateActiveLEDs(float dist)
  • LEDs turn on progressively

  • In critical distance → LEDs blink

  • Gives a clear visual warning


LCD Display Features

Line 1:

Displays exact distance:

Dist: 45.3 cm

Line 2:

Displays status:

  • ALL CLEAR

  • APPROACHING

  • CAUTION

  • DANGER

  • STOP! (blinking)

Also includes a mini bar indicator.


Smart Programming Techniques Used

✔ Non-blocking timing using millis()
✔ Sensor reading every 100ms
✔ Dynamic tone generation
✔ Threshold-based logic
✔ LCD custom characters
✔ Multi-output synchronization

This makes it an advanced beginner to intermediate-level project.


 Learning Outcomes

Students learn:

  • Ultrasonic distance measurement

  • Speed of sound calculation

  • Real-time object detection

  • I2C LCD interfacing

  • Multi-LED control

  • Non-blocking programming

  • Embedded system design principles


Applications

  •  Car reverse parking assistance system

  •  Robotics obstacle detection

  •  Smart garage automation

  •  IoT-based parking monitoring

  •  STEM robotics education projects


 How It Works

Diagram.json:
{
  "version": 1,
  "author": "Claude",
  "editor": "wokwi",
  "parts": [
    {
      "type": "wokwi-arduino-uno",
      "id": "uno",
      "top": 0,
      "left": 0,
      "attrs": {}
    },
    {
      "type": "wokwi-hc-sr04",
      "id": "ultrasonic",
      "top": -182.7,
      "left": -39.5,
      "attrs": { "distance": "50" }
    },
    {
      "type": "wokwi-lcd1602",
      "id": "lcd",
      "top": -192,
      "left": 204.8,
      "attrs": { "pins": "i2c" }
    },
    {
      "type": "wokwi-led",
      "id": "led1",
      "top": 172.8,
      "left": -182.6,
      "attrs": { "color": "green" }
    },
    {
      "type": "wokwi-led",
      "id": "led2",
      "top": 172.8,
      "left": -124.2,
      "attrs": { "color": "limegreen" }
    },
    {
      "type": "wokwi-led",
      "id": "led3",
      "top": 172.8,
      "left": -65.8,
      "attrs": { "color": "yellow" }
    },
    {
      "type": "wokwi-led",
      "id": "led4",
      "top": 172.8,
      "left": -7.4,
      "attrs": { "color": "orange" }
    },
    {
      "type": "wokwi-led",
      "id": "led5",
      "top": 172.8,
      "left": 51,
      "attrs": { "color": "red" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": 230.4,
      "left": -172.8,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r2",
      "top": 230.4,
      "left": -114.4,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r3",
      "top": 230.4,
      "left": -56,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r4",
      "top": 230.4,
      "left": 2.4,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r5",
      "top": 230.4,
      "left": 60.8,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-buzzer",
      "id": "buzzer",
      "top": 249.6,
      "left": 268.2,
      "attrs": {}
    }
  ],
  "connections": [
    [ "ultrasonic:VCC", "uno:5V", "red", [ "v0" ] ],
    [ "ultrasonic:TRIG", "uno:7", "violet", [ "v0" ] ],
    [ "ultrasonic:ECHO", "uno:6", "blue", [ "v0" ] ],
    [ "ultrasonic:GND", "uno:GND.1", "black", [ "v0" ] ],
   
    [ "lcd:GND", "uno:GND.1", "black", [ "v0" ] ],
    [ "lcd:VCC", "uno:5V", "red", [ "v0" ] ],
    [ "lcd:SDA", "uno:A4", "green", [ "v0" ] ],
    [ "lcd:SCL", "uno:A5", "yellow", [ "v0" ] ],
   
    [ "led1:A", "r1:1", "green", [ "v0" ] ],
    [ "r1:2", "uno:8", "green", [ "v0" ] ],
    [ "led1:C", "uno:GND.2", "black", [ "v0" ] ],
   
    [ "led2:A", "r2:1", "green", [ "v0" ] ],
    [ "r2:2", "uno:9", "green", [ "v0" ] ],
    [ "led2:C", "uno:GND.2", "black", [ "v0" ] ],
   
    [ "led3:A", "r3:1", "green", [ "v0" ] ],
    [ "r3:2", "uno:10", "green", [ "v0" ] ],
    [ "led3:C", "uno:GND.2", "black", [ "v0" ] ],
   
    [ "led4:A", "r4:1", "green", [ "v0" ] ],
    [ "r4:2", "uno:11", "green", [ "v0" ] ],
    [ "led4:C", "uno:GND.2", "black", [ "v0" ] ],
   
    [ "led5:A", "r5:1", "green", [ "v0" ] ],
    [ "r5:2", "uno:12", "green", [ "v0" ] ],
    [ "led5:C", "uno:GND.2", "black", [ "v0" ] ],
   
    [ "buzzer:1", "uno:13", "green", [ "v0" ] ],
    [ "buzzer:2", "uno:GND.3", "black", [ "v0" ] ]
  ],
  "dependencies": {}
}

The HC-SR04 ultrasonic sensor works by:

  1. Sending an ultrasonic sound wave (40kHz frequency).

  2. The wave reflects back after hitting an obstacle.

  3. Arduino calculates the time taken for the echo to return.

  4. Distance is calculated using the speed of sound formula:

Distance=(Time×SpeedofSound)/2Distance = (Time × Speed of Sound) / 2

As the object gets closer:

  • 🔴 Buzzer beeps faster

  • 🟢 LEDs change from green → yellow → red


 Components Required

  • Arduino Uno

  • HC-SR04 Ultrasonic Sensor

  • Piezo Buzzer

  • 3 LEDs (Green, Yellow, Red)

  • 220Ω Resistors

  • Breadboard & Jumper Wires

Code:
/*
 * Parking Sensor Simulator
 * - HC-SR04 Ultrasonic Sensor for distance measurement
 * - 5 LED bar graph (distance indicator)
 * - Buzzer with variable beep rate (faster when closer)
 * - 16x2 LCD display showing exact distance
 *
 * Hardware connections:
 * - Ultrasonic Sensor: Trig=7, Echo=6
 * - LEDs (Bar Graph): Pins 8, 9, 10, 11, 12 (Green to Red)
 * - Buzzer: Pin 13
 * - LCD: I2C (SDA=A4, SCL=A5)
 */

#include <LiquidCrystal_I2C.h>

// Pin definitions
const int TRIG_PIN = 7;
const int ECHO_PIN = 6;
const int BUZZER_PIN = 13;
const int LED_PINS[] = {8, 9, 10, 11, 12}; // Green -> Yellow -> Orange -> Red -> Red
const int NUM_LEDS = 5;

// LCD initialization (I2C address 0x27, 16 columns, 2 rows)
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Distance thresholds (in cm)
const int SAFE_DISTANCE = 100;      // > 100cm: All clear
const int WARNING_DISTANCE = 50;    // 50-100cm: Getting close
const int DANGER_DISTANCE = 20;     // 20-50cm: Danger zone
const int CRITICAL_DISTANCE = 10;   // < 10cm: Critical!

// Buzzer timing variables
unsigned long previousBuzzerTime = 0;
unsigned long buzzerInterval = 1000;
bool buzzerState = false;

// Distance measurement variables
float distance = 0;
unsigned long previousMeasureTime = 0;
const unsigned long measureInterval = 100; // Measure every 100ms

// Custom LCD characters for bar graph
byte fullBlock[8] = {
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

byte emptyBlock[8] = {
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};

void setup() {
  Serial.begin(9600);
 
  // Initialize ultrasonic sensor pins
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
 
  // Initialize LED pins
  for (int i = 0; i < NUM_LEDS; i++) {
    pinMode(LED_PINS[i], OUTPUT);
    digitalWrite(LED_PINS[i], LOW);
  }
 
  // Initialize buzzer
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);
 
  // Initialize LCD
  lcd.init();
  lcd.backlight();
 
  // Create custom characters
  lcd.createChar(0, fullBlock);
  lcd.createChar(1, emptyBlock);
 
  // Welcome message
  displayWelcome();
  delay(2000);
  lcd.clear();
 
  Serial.println("Parking Sensor Simulator");
  Serial.println("=========================");
}

void loop() {
  unsigned long currentTime = millis();
 
  // Measure distance periodically
  if (currentTime - previousMeasureTime >= measureInterval) {
    previousMeasureTime = currentTime;
    distance = measureDistance();
   
    // Update display and indicators
    updateLEDs(distance);
    updateLCD(distance);
   
    // Calculate buzzer interval based on distance
    buzzerInterval = calculateBuzzerInterval(distance);
   
    // Debug output
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.print(" cm | LEDs: ");
    Serial.print(calculateActiveLEDs(distance));
    Serial.print(" | Beep Interval: ");
    Serial.print(buzzerInterval);
    Serial.println(" ms");
  }
 
  // Handle buzzer beeping
  if (distance < SAFE_DISTANCE) {
    if (currentTime - previousBuzzerTime >= buzzerInterval) {
      previousBuzzerTime = currentTime;
     
      if (!buzzerState) {
        // Turn on buzzer
        tone(BUZZER_PIN, 2000, 50); // 2kHz tone for 50ms
        buzzerState = true;
      } else {
        // Turn off buzzer
        noTone(BUZZER_PIN);
        buzzerState = false;
      }
    }
  } else {
    // Far away - no buzzer
    noTone(BUZZER_PIN);
    buzzerState = false;
  }
}

float measureDistance() {
  // Send ultrasonic pulse
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
 
  // Read echo pulse duration
  long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout
 
  // Calculate distance in cm (speed of sound = 343 m/s)
  float dist = duration * 0.034 / 2;
 
  // Return reasonable distance (limit to 200cm max)
  if (dist == 0 || dist > 200) {
    return 200; // Out of range
  }
  return dist;
}

void updateLEDs(float dist) {
  int activeLEDs = calculateActiveLEDs(dist);
 
  // Light up LEDs according to distance
  for (int i = 0; i < NUM_LEDS; i++) {
    if (i < activeLEDs) {
      digitalWrite(LED_PINS[i], HIGH);
    } else {
      digitalWrite(LED_PINS[i], LOW);
    }
  }
 
  // Add blinking effect for critical distance
  if (dist < CRITICAL_DISTANCE) {
    unsigned long blinkTime = millis() % 200;
    bool blinkState = blinkTime < 100;
   
    for (int i = 0; i < NUM_LEDS; i++) {
      digitalWrite(LED_PINS[i], blinkState ? HIGH : LOW);
    }
  }
}

int calculateActiveLEDs(float dist) {
  if (dist > SAFE_DISTANCE) {
    return 0; // All clear - no LEDs
  } else if (dist > WARNING_DISTANCE) {
    return 1; // 1 LED (green)
  } else if (dist > DANGER_DISTANCE) {
    return 2; // 2 LEDs
  } else if (dist > CRITICAL_DISTANCE) {
    return 3; // 3 LEDs
  } else if (dist > 5) {
    return 4; // 4 LEDs
  } else {
    return 5; // All LEDs - STOP!
  }
}

unsigned long calculateBuzzerInterval(float dist) {
  if (dist > SAFE_DISTANCE) {
    return 10000; // No beep (effectively off)
  } else if (dist > WARNING_DISTANCE) {
    return 1000; // Slow beep (1 second)
  } else if (dist > DANGER_DISTANCE) {
    return 500; // Medium beep (0.5 second)
  } else if (dist > CRITICAL_DISTANCE) {
    return 250; // Fast beep (0.25 second)
  } else {
    return 100; // Very fast beep (0.1 second) - CRITICAL!
  }
}

void updateLCD(float dist) {
  // Line 1: Distance value
  lcd.setCursor(0, 0);
  lcd.print("Dist: ");
 
  if (dist > 200) {
    lcd.print("---.--");
  } else {
    // Format distance with padding
    if (dist < 100) lcd.print(" ");
    if (dist < 10) lcd.print(" ");
    lcd.print(dist, 1);
  }
  lcd.print(" cm ");
 
  // Line 2: Status message
  lcd.setCursor(0, 1);
 
  if (dist > SAFE_DISTANCE) {
    lcd.print("  ALL CLEAR     ");
  } else if (dist > WARNING_DISTANCE) {
    lcd.print(" APPROACHING... ");
  } else if (dist > DANGER_DISTANCE) {
    lcd.print("   CAUTION!     ");
  } else if (dist > CRITICAL_DISTANCE) {
    lcd.print(">> DANGER! <<   ");
  } else {
    // Critical - blinking text
    unsigned long blinkTime = millis() % 600;
    if (blinkTime < 300) {
      lcd.print(">>> STOP! <<<   ");
    } else {
      lcd.print("                ");
    }
  }
 
  // Add visual bar on LCD (optional)
  drawBarGraph(dist);
}

void drawBarGraph(float dist) {
  // Draw a simple bar graph on the LCD (top right)
  int barLevel = map(constrain(dist, 0, 100), 0, 100, 0, 5);
 
  lcd.setCursor(14, 0);
  if (barLevel >= 1) {
    lcd.write((uint8_t)0); // Full block
  } else {
    lcd.print(" ");
  }
 
  lcd.setCursor(15, 0);
  if (barLevel >= 2) {
    lcd.write((uint8_t)0);
  } else {
    lcd.print(" ");
  }
}

void displayWelcome() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  PARKING AID  ");
  lcd.setCursor(0, 1);
  lcd.print("   SIMULATOR   ");
 
  // Flash LEDs
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < NUM_LEDS; j++) {
      digitalWrite(LED_PINS[j], HIGH);
    }
    delay(200);
    for (int j = 0; j < NUM_LEDS; j++) {
      digitalWrite(LED_PINS[j], LOW);
    }
    delay(200);
  }
 
  // Buzzer beep
  tone(BUZZER_PIN, 1000, 200);
  delay(250);
  tone(BUZZER_PIN, 1500, 200);
}

Comments