arduino-sensor-aparcamiento-hcsr04

How to Build a Parking Sensor with Arduino and HC-SR04

  • 8 min

A parking sensor is a system that measures the distance to an obstacle and warns of its proximity using light or acoustic signals.

If in the traffic light project we learned to control timing, here we will learn to measure the physical world. We will not simply turn on a light; our Arduino will have to send a signal, wait for it to bounce back, and based on the time it took, calculate the distance to an obstacle with precision.

This project is the perfect introduction to wave physics and the use of Time of Flight sensors, principles used from submarines (sonar) to the most advanced LiDAR sensors.

How We Measure Distance with Sound

For this project we will use the ubiquitous HC-SR04 sensor. This component is, in essence, a small electronic bat.

Its operation is based on echolocation. The sensor has two “eyes” (which are actually transducers):

  1. Transmitter (Trig): Emits a burst of ultrasound at 40 kHz (inaudible to humans).
  2. Receiver (Echo): Listens and waits to receive the bounce of that wave.

The physical principle is basic kinematics. We know that speed equals distance divided by time (v = d / t). Since we know the speed of sound in air and can measure time, we solve for distance.

Why do we divide by 2? Crucial! The sound has to go to the obstacle and return to the sensor. The time we measure is for the round trip. If we didn’t divide by 2, we would be calculating double the actual distance.

The speed of sound is approximately 343 m/s (at 20°C). To make calculations easier for the microcontroller (which works in microseconds, ), we convert that speed: . Therefore, the formula we will use in the code will be:

Components

We are going to build a complete system: measurement (sensor) and warning (buzzer + LEDs).

  • [1x|blue] Arduino Uno | The brain of the project
  • [1x|orange] Ultrasonic Sensor HC-SR04 | Measures distances with ultrasound
  • [1x|purple] Active Buzzer | Acoustic warning
  • [1x|green] Green LED | Safe zone
  • [1x|yellow] Yellow LED | Caution
  • [1x|red] Red LED | Imminent danger
  • [3x|gray] 220Ω Resistor | Limits LED current
  • [Several|gray] Breadboard and wires | Connections

Connection Diagram

The HC-SR04 has 4 pins: VCC, Trig, Echo, and GND.

HC-SR04 Sensor

The sensor needs 5V power and two signals: Trig to send the pulse, and Echo to measure how long it takes to return.

[ { “from”: “HC-SR04 VCC”, “to”: “Arduino 5V”, “color”: “red” }, { “from”: “HC-SR04 GND”, “to”: “Arduino GND”, “color”: “black” }, { “from”: “HC-SR04 Trig”, “to”: “Pin 9”, “color”: “orange”, “note”: “Arduino Output” }, { “from”: “HC-SR04 Echo”, “to”: “Pin 10”, “color”: “yellow”, “note”: “Arduino Input” } ]

Warning Buzzer

The buzzer activates with proximity beeps.

[ { “from”: “Buzzer (+)”, “to”: “Pin 6”, “color”: “purple” }, { “from”: “Buzzer (-)”, “to”: “Arduino GND”, “color”: “black” } ]

Indicator LEDs

The LEDs act as a visual traffic light for safe distance, caution, and danger.

[ { “from”: “Red LED + 220Ω”, “to”: “Pin 3”, “color”: “red” }, { “from”: “Yellow LED + 220Ω”, “to”: “Pin 4”, “color”: “yellow” }, { “from”: “Green LED + 220Ω”, “to”: “Pin 5”, “color”: “green” }, { “from”: “LED Cathodes”, “to”: “Arduino GND”, “color”: “black” } ]

The Code

Let’s divide the code into two logical parts: the function that measures and the logic that warns.

To measure the pulse, we will use the native pulseIn() function, which waits for a pin to change state and counts how much time has passed in microseconds.

// --- Hardware Configuration ---
const int pinTrig = 9;
const int pinEcho = 10;
const int pinBuzzer = 6;

// Pins for the LEDs (optional, but recommended)
const int pinGreenLed = 5;
const int pinYellowLed = 4;
const int pinRedLed = 3;

// Physical constants
// Speed of sound / 2 = 0.0343 / 2 = 0.01715
const float SPEED_OF_SOUND = 0.01715; 

void setup() {
  Serial.begin(9600); // For screen debugging

  // Pin configuration
  pinMode(pinTrig, OUTPUT);
  pinMode(pinEcho, INPUT);
  pinMode(pinBuzzer, OUTPUT);
  
  pinMode(pinGreenLed, OUTPUT);
  pinMode(pinYellowLed, OUTPUT);
  pinMode(pinRedLed, OUTPUT);
  
  // Start with Trigger off
  digitalWrite(pinTrig, LOW);
}
Copied!

The Main Loop and Warning Logic

In the loop, we take the measurement. Depending on the distance, we make the buzzer sound at different rates (like in a real car: closer = faster beeps).

void loop() {
  // 1. GET DISTANCE
  long distance = measureDistance();
  
  // Print for debugging
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");

  // 2. WARNING LOGIC (The "Beep Beep")
  // Define distance thresholds
  if (distance < 10) {
    // IMMINENT DANGER (< 10cm)
    // Continuous beep and red light
    digitalWrite(pinBuzzer, HIGH); // Continuous sound
    turnOnTrafficLight(true, false, false); // Red only
  } 
  else if (distance < 30) {
    // CAUTION (< 30cm)
    // Fast beeps and yellow light
    intermittentAlert(100); // Fast beep
    turnOnTrafficLight(false, true, false); // Yellow only
  } 
  else if (distance < 60) {
    // ATTENTION (< 60cm)
    // Slow beeps and green light
    intermittentAlert(300); // Slow beep
    turnOnTrafficLight(false, false, true); // Green only
  } 
  else {
    // SAFE ZONE (> 60cm)
    digitalWrite(pinBuzzer, LOW); // Silence
    turnOffAll();
  }
  
  delay(50); // Small pause for stability
}
Copied!

Helper Functions

Here is where we encapsulate the complexity. The measureDistance function performs the strict sequence required by the HC-SR04 sensor to work.

  1. Send a 10 microsecond pulse on the Trig pin.
  2. Listen on the Echo pin.
  3. Apply the formula.
long measureDistance() {
  // 1. Generate trigger pulse
  digitalWrite(pinTrig, LOW);
  delayMicroseconds(2);
  digitalWrite(pinTrig, HIGH);
  delayMicroseconds(10); // The pulse must last at least 10us
  digitalWrite(pinTrig, LOW);
  
  // 2. Measure the echo time
  // pulseIn waits for the pin to go HIGH and counts until it goes LOW
  unsigned long duration = pulseIn(pinEcho, HIGH, 30000UL);
  
  // 3. Convert to distance
  // If duration is 0, it means no echo was received (out of range)
  if (duration == 0) return 999; 
  
  return duration * SPEED_OF_SOUND;
}

// Function to make the "Beep-Beep"
void intermittentAlert(int speed) {
  digitalWrite(pinBuzzer, HIGH);
  delay(speed);
  digitalWrite(pinBuzzer, LOW);
  delay(speed);
}

// Helper to manage the LEDs cleanly
void turnOnTrafficLight(bool r, bool y, bool g) {
    digitalWrite(pinRedLed, r ? HIGH : LOW);
    digitalWrite(pinYellowLed, y ? HIGH : LOW);
    digitalWrite(pinGreenLed, g ? HIGH : LOW);
}

void turnOffAll() {
    digitalWrite(pinRedLed, LOW);
    digitalWrite(pinYellowLed, LOW);
    digitalWrite(pinGreenLed, LOW);
}
Copied!

Analysis of Common Problems

You will likely encounter strange readings when you set this up. This is normal; we are working with sound in the real world.

  • False echoes: If the sensor points at a soft surface (like cloth or a sponge), the sound doesn’t bounce back well and the sensor “sees” nothing.
  • Angles: If the surface is very slanted relative to the sensor, the sound bounces elsewhere and never returns to the receiver (like a billiard ball hitting a rail).
  • Code blocking: The intermittentAlert function uses delay. This means that while it is beeping, it does not measure. In a more reactive setup we would use millis() to beep and measure without blocking the processor.
  • Echo timeout: The third parameter of pulseIn() limits the wait to 30 ms. Without this limit, a measurement without an echo could block the program for a much longer time.

Next Steps

This project is the foundation of mobile robotics. A robot that doesn’t bump into things is basically this code on wheels.

Do you dare improve it?

  1. Replace the LEDs with an LCD Screen that shows the exact distance in centimeters.
  2. Use the tone() function on the buzzer so that the sound becomes higher-pitched the closer the object is, instead of just changing the beep speed.
  3. Try implementing the NewPing library, which greatly optimizes reading and prevents blocking if the sensor doesn’t receive a response.