Robot Maker Toolkit › Projects › Parking sensor

Arduino parking sensor

The classic first "real" build: a car-style distance sensor. Green means clear, yellow means you're getting close (with the beep speeding up as you do), red plus a continuous tone means stop. One sensor, three LEDs, a buzzer, and no libraries.

Beginner · ~30 min Arduino UNO No libraries
✔ Wiring datasheet-verified ✔ Matches the app, pin for pin ◻ Simulation re-run pending ◻ Bench-tested — be the first, get credited

Verification: the wiring below is the app's audited table, and the sketch's pins are checked against it automatically. The four zones are green >100 cm · yellow 100–40 cm · red 40–20 cm · continuous tone <20 cm. It has not yet been run on physical hardware — build it, tell us it works via support@infinitxlabs.com, and we'll credit you here.

Parts

Wiring

FromTo (UNO)Notes
HC-SR04 VCC5V5 V sensor — happy on the UNO
HC-SR04 GNDGND
HC-SR04 TRIGD9
HC-SR04 ECHOD10Direct is fine on a 5 V board. On 3.3 V boards (ESP32/Pico) use a voltage divider.
Green LED (+)D2via 220 Ω, cathode to GND. 150–470 Ω all work.
Yellow LED (+)D3via 220 Ω, cathode to GND
Red LED (+)D4via 220 Ω, cathode to GND
Buzzer (+)D5active or passive — the sketch uses tone(), so either works
Buzzer (−)GND

Every pin on this page is the same one the Robot Maker Toolkit app shows for this project — not by hand, but because the app's build script refuses to publish unless the sketch.ino and diagram.json served here are byte-for-byte the app's own (build_projects.py --site). The HC-SR04 pins (TRIG→D9, ECHO→D10) come from the app's audited module table.

▶ Run it in your browser first

Try the whole build before you buy a single part — no login, nothing to install:

  1. Open wokwi.com/projects/new/arduino-uno
  2. Paste in sketch.ino and diagram.json from this page
  3. Press the green ▶ play button, click the HC-SR04 and drag its distance slider
  4. Watch the LEDs switch zones and hear the beep speed up as you "reverse"

Those two files are the ones the Robot Maker Toolkit app ships for this project, byte for byte — what you simulate is what the app tells you to wire.

How it works

The sketch

sketch.ino (copy everything)
/*
  Parking sensor — Robot Maker Toolkit
  Arduino UNO + HC-SR04 + 3 LEDs + buzzer

  Distance drives a traffic light and a beep that speeds up as you close in,
  exactly like a car's reversing sensor.

  Pins follow the HC-SR04 page in the app (TRIG D9, ECHO D10).

  Zones:
    > 100 cm      green,  silent
    40 - 100 cm   yellow, slow beep
    20 - 40 cm    red,    fast beep
    < 20 cm       red,    solid tone  (STOP)
*/

const int TRIG_PIN   = 9;
const int ECHO_PIN   = 10;
const int LED_GREEN  = 2;
const int LED_YELLOW = 3;
const int LED_RED    = 4;
const int BUZZER_PIN = 5;

// 25 ms ~= 4.3 m. Caps how long pulseIn() can stall the loop when nothing
// is in front of the sensor; without a timeout it blocks for a full second.
const unsigned long ECHO_TIMEOUT_US = 25000UL;

const float ZONE_STOP_CM = 20.0;
const float ZONE_CLOSE_CM = 40.0;
const float ZONE_NEAR_CM = 100.0;

unsigned long lastBeepToggle = 0;
bool beepOn = false;

void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_YELLOW, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  Serial.begin(9600);
}

// One reading, in cm. Returns -1 when nothing echoes back in time.
float readDistanceCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  unsigned long us = pulseIn(ECHO_PIN, HIGH, ECHO_TIMEOUT_US);
  if (us == 0) return -1.0;

  // 343 m/s = 0.0343 cm/us, halved because the pulse travels there and back.
  return (us * 0.0343) / 2.0;
}

// Median of three. A single HC-SR04 reading occasionally returns a wild
// value off a soft or angled surface; the median throws those away without
// the lag that averaging adds.
float readDistanceStable() {
  float a = readDistanceCm();
  delay(15);
  float b = readDistanceCm();
  delay(15);
  float c = readDistanceCm();

  if (a < 0 || b < 0 || c < 0) return -1.0;
  float hi = max(a, max(b, c));
  float lo = min(a, min(b, c));
  return a + b + c - hi - lo;
}

void showZone(int green, int yellow, int red) {
  digitalWrite(LED_GREEN, green);
  digitalWrite(LED_YELLOW, yellow);
  digitalWrite(LED_RED, red);
}

// Non-blocking beep: toggles on its own schedule so distance keeps updating.
// interval 0 = silent, -1 = solid tone.
void updateBuzzer(long interval) {
  if (interval == 0) {
    noTone(BUZZER_PIN);
    beepOn = false;
    return;
  }
  if (interval < 0) {
    tone(BUZZER_PIN, 2000);
    beepOn = true;
    return;
  }
  if (millis() - lastBeepToggle >= (unsigned long)interval) {
    lastBeepToggle = millis();
    beepOn = !beepOn;
    if (beepOn) tone(BUZZER_PIN, 2000); else noTone(BUZZER_PIN);
  }
}

void loop() {
  float cm = readDistanceStable();

  if (cm < 0) {
    // Out of range or no echo — treat as clear.
    showZone(HIGH, LOW, LOW);
    updateBuzzer(0);
    Serial.println("no echo");
  } else if (cm > ZONE_NEAR_CM) {
    showZone(HIGH, LOW, LOW);
    updateBuzzer(0);
  } else if (cm > ZONE_CLOSE_CM) {
    showZone(LOW, HIGH, LOW);
    updateBuzzer(400);
  } else if (cm > ZONE_STOP_CM) {
    showZone(LOW, LOW, HIGH);
    updateBuzzer(120);
  } else {
    showZone(LOW, LOW, HIGH);
    updateBuzzer(-1);
  }

  if (cm >= 0) {
    Serial.print(cm, 1);
    Serial.println(" cm");
  }
  delay(50);
}
diagram.json (for the Wokwi simulation)
{
  "version": 1,
  "author": "Infinitx Labs",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 130, "left": 0, "attrs": {} },
    { "type": "wokwi-hc-sr04", "id": "dist", "top": -60, "left": 100, "attrs": { "distance": "80" } },
    { "type": "wokwi-led", "id": "ledGreen", "top": 20, "left": 320, "attrs": { "color": "green" } },
    { "type": "wokwi-led", "id": "ledYellow", "top": 20, "left": 370, "attrs": { "color": "yellow" } },
    { "type": "wokwi-led", "id": "ledRed", "top": 20, "left": 420, "attrs": { "color": "red" } },
    { "type": "wokwi-resistor", "id": "rGreen", "top": 120, "left": 320, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "rYellow", "top": 160, "left": 370, "attrs": { "value": "220" } },
    { "type": "wokwi-resistor", "id": "rRed", "top": 200, "left": 420, "attrs": { "value": "220" } },
    { "type": "wokwi-buzzer", "id": "buzzer", "top": 20, "left": 200, "attrs": { "volume": "0.1" } }
  ],
  "connections": [
    [ "dist:VCC", "uno:5V", "red", [] ],
    [ "dist:GND", "uno:GND.1", "black", [] ],
    [ "dist:TRIG", "uno:9", "blue", [] ],
    [ "dist:ECHO", "uno:10", "purple", [] ],

    [ "uno:2", "rGreen:1", "green", [] ],
    [ "rGreen:2", "ledGreen:A", "green", [] ],
    [ "ledGreen:C", "uno:GND.2", "black", [] ],

    [ "uno:3", "rYellow:1", "gold", [] ],
    [ "rYellow:2", "ledYellow:A", "gold", [] ],
    [ "ledYellow:C", "uno:GND.2", "black", [] ],

    [ "uno:4", "rRed:1", "red", [] ],
    [ "rRed:2", "ledRed:A", "red", [] ],
    [ "ledRed:C", "uno:GND.2", "black", [] ],

    [ "uno:5", "buzzer:1", "orange", [] ],
    [ "buzzer:2", "uno:GND.3", "black", [] ]
  ]
}

Going further

Want the full reference on your bench? 55+ sensor wiring diagrams, 9 board pinouts, shield maps and maker calculators — all offline.

Get it onGoogle Play
Board pinout library →