TheSolderBenchnotes from my electronics bench

Log #40 · Sep 27, 2026

Build an Arduino Parking Sensor

A garage parking assistant with an HC-SR04 sensor, a buzzer that beeps faster as you get closer and LEDs that go from green to red.

Projects · 3 min read · Beginner

Cars with parking sensors beep slowly when an obstacle is far away and faster as you get closer, until the tone becomes continuous. This project recreates that with an ultrasonic sensor, a buzzer and three LEDs. Mounted on a garage wall, it tells you exactly when to stop. It is also a good exercise in turning a measurement into smooth, responsive feedback without blocking the program.

Parts list

Part Quantity Notes
Arduino Uno or Nano 1
HC-SR04 ultrasonic sensor 1 See the HC-SR04 guide
Active or passive buzzer 1
Green, yellow and red LEDs 1 each
220 Ω resistors 3 For the LEDs
Breadboard, wires
5 V USB power adapter 1 For permanent installation

How it behaves

Distance LEDs Sound
More than 100 cm Green Silent
100 to 50 cm Yellow Slow beeps, faster as you approach
50 to 20 cm Red Fast beeps
Under 20 cm Red flashing Continuous tone: stop
Parking sensor zones: green beyond 100 centimeters, yellow from 100 to 50, red from 50 to 20, and stop under 20, with beep intervals getting shorter
The closer the car, the shorter the gap between beeps.

Wiring

Part Arduino pin
HC-SR04 VCC / GND 5 V / GND
HC-SR04 TRIG / ECHO 9 / 10
Green LED + 220 Ω 4
Yellow LED + 220 Ω 5
Red LED + 220 Ω 6
Buzzer + 8 (− to GND)

The code

The key idea is to map distance to the interval between beeps, and to time the beeps with millis() so the sensor keeps measuring continuously. The millis() guide explains the pattern.

const int TRIG = 9, ECHO = 10;
const int GREEN = 4, YELLOW = 5, RED = 6, BUZZ = 8;

unsigned long lastPing = 0, lastBeep = 0;
float distance = 400;
bool beepOn = false;

float readCm() {
  digitalWrite(TRIG, LOW);  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  unsigned long us = pulseIn(ECHO, HIGH, 30000);
  return us == 0 ? 400 : us / 58.0;
}

void lights(bool g, bool y, bool r) {
  digitalWrite(GREEN, g); digitalWrite(YELLOW, y); digitalWrite(RED, r);
}

void setup() {
  pinMode(TRIG, OUTPUT); pinMode(ECHO, INPUT);
  pinMode(GREEN, OUTPUT); pinMode(YELLOW, OUTPUT); pinMode(RED, OUTPUT);
  pinMode(BUZZ, OUTPUT);
}

void loop() {
  unsigned long now = millis();

  if (now - lastPing >= 60) {                  // measure ~16 times per second
    lastPing = now;
    float d = readCm();
    distance = distance * 0.6 + d * 0.4;       // smooth out jumps
  }

  if (distance > 100) {                        // far: all quiet
    lights(1, 0, 0);
    noTone(BUZZ);
    return;
  }

  if (distance < 20) {                         // stop!
    bool flash = (now / 150) % 2;
    lights(0, 0, flash);
    tone(BUZZ, 2000);
    return;
  }

  lights(0, distance >= 50, distance < 50);

  // 100 cm -> 600 ms between beeps, 20 cm -> 80 ms
  unsigned long interval = map((long)distance, 20, 100, 80, 600);
  if (now - lastBeep >= (beepOn ? 60 : interval)) {
    lastBeep = now;
    beepOn = !beepOn;
    if (beepOn) tone(BUZZ, 2000); else noTone(BUZZ);
  }
}

How the beeping works

Each beep lasts 60 ms; the silent gap between beeps is the mapped interval. At 100 cm the gap is 600 ms, and at 20 cm it is only 80 ms, so the beeps speed up smoothly as the car approaches. The simple smoothing line blends each new reading with the previous value, which stops the beep rate from stuttering when a reading jumps.

If you use an active buzzer, which beeps by itself with power, replace tone(BUZZ, 2000) with digitalWrite(BUZZ, HIGH) and noTone(BUZZ) with digitalWrite(BUZZ, LOW).

Why the readings are smoothed

The HC-SR04 occasionally returns a wrong value, for example when the sound bounces off an angled part of the car. Without smoothing, one bad reading would make the beeping suddenly jump faster or slower, which is distracting while you are driving. The line distance = distance * 0.6 + d * 0.4 is an exponential filter: each new reading only moves the result 40% of the way toward the new value. A single spike barely changes it, while a real, steady approach still comes through within a few tenths of a second. Raise the 0.4 for a faster response, or lower it for a steadier one.

Testing on the bench

  1. Upload the sketch and move your hand slowly toward the sensor. The LEDs should change at 100, 50 and 20 cm.
  2. If readings are erratic, check the sensor is not pointing at the edge of the table; see the tips in the HC-SR04 guide.
  3. If nothing lights at all, check the LED orientation and the breadboard rows, as explained in breadboard basics.

Installing it in a garage

  • Mount the sensor at bumper height, pointing straight at where the car's front will be. Ultrasound reflects well from a flat bumper or number plate.
  • Adjust the "stop" distance to your garage: park where you want the car, read the distance with the Serial Monitor and use that value instead of 20.
  • Put the electronics in a small box and power it from a USB adapter.
  • Place the LEDs where the driver can see them, for example on a strip of wire at eye level.

Ideas to extend it

  • Add a PIR sensor from the motion sensor guide so the system only wakes up when someone is in the garage.
  • Show the distance in centimeters on an OLED display.
  • Turn off the buzzer automatically after the car has been stopped for 10 seconds, so it does not beep all night.

— TheSolderBench · found a mistake? tell me

More pages from this notebook

Build an Obstacle-Avoiding Robot

A complete build with parts list, wiring table and full Arduino code for a two-wheel robot that scans with an ultrasonic sensor and steers around obstacles.

→ misses chair legs, raise STOP_CM

Automatic Plant Watering System

Build a soil-moisture-controlled watering system with a capacitive sensor, a relay or MOSFET, a small pump and Arduino code with safety limits.

→ limit waterings per day!

Digital Thermometer with an OLED Display

Build a waterproof digital thermometer with a DS18B20 probe and a 0.96 inch SSD1306 OLED, showing live temperature plus the minimum and maximum.

→ blank screen? try address 0x3D

Build a Reaction-Time Game

A two-button Arduino game that waits a random time, lights an LED and measures who reacts first in milliseconds, with anti-cheat and a buzzer.

→ use millis(), and catch early presses