Build a real car-park proximity system using an HC-SR04 ultrasonic sensor, LED bar graph, and variable-speed buzzer — simulated entirely in Wokwi.
What You'll Build
A smart distance detection system that mimics the reverse parking sensor found in modern cars — complete with visual and audio alerts.
Ultrasonic Sensing
Use the HC-SR04 to measure distances by timing sound echoes.
LED Bar Graph
5 LEDs light up progressively as an object gets closer.
Variable Buzzer
Beep rate increases from slow → rapid as distance shrinks.
LCD Status
Live distance readout and zone status on a 16×2 display.
Non-Blocking Code
Master millis()-based timing — essential for real robotics.
Real-World IoT
Direct application to cars, robotics, smart garages, and more.
How Ultrasonic Sensing Works
The HC-SR04 uses sound waves — the same principle as bat echolocation — to measure distance. Here's the physics:
Speed of sound ≈ 0.034 cm/µs at room temperature
dist = duration × 0.034 / 2Why divide by 2?
The sound wave travels to the object AND back — so the measured time covers double the actual distance. Dividing by 2 gives us the one-way distance to the obstacle.
Components Used
All available as virtual parts in Wokwi — no shopping cart needed.
Wiring the Circuit
Open Wokwi and Create a New Project
Go to wokwi.com → click New Project → select Arduino UNO. Or open the pre-built simulation directly using the button above.
Quick Setup: Paste the diagram.json
The fastest way to get started — paste the complete circuit JSON into Wokwi:
- Click the diagram.json tab in the Wokwi editor
- Select all (Ctrl+A) and delete existing content
- Paste the full JSON below
- Press Ctrl+S — your circuit appears instantly!
{
"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:VCC", "uno:5V", "red", ["v0"] ],
[ "lcd:GND", "uno:GND.1", "black", ["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": {}
}
Ultrasonic Sensor (HC-SR04) Wiring
| HC-SR04 Pin | Arduino Pin | Wire Color |
|---|---|---|
| VCC | 5V | Red |
| TRIG | Pin 7 | Violet |
| ECHO | Pin 6 | Blue |
| GND | GND | Black |
LED Bar Graph Wiring
Each LED connects through a 220Ω resistor. The cathode (−, short leg) goes to GND.
| LED Color | Arduino Pin | Resistor |
|---|---|---|
| Green | Pin 8 | 220Ω |
| Light Green | Pin 9 | 220Ω |
| Yellow | Pin 10 | 220Ω |
| Orange | Pin 11 | 220Ω |
| Red | Pin 12 | 220Ω |
Buzzer & LCD Wiring
| Component | Pin | Arduino |
|---|---|---|
| Buzzer | + (positive) | Pin 13 |
| Buzzer | − (negative) | GND |
| LCD | VCC | 5V |
| LCD | GND | GND |
| LCD | SDA | A4 |
| LCD | SCL | A5 |
Arduino Code — Explained
Paste the full code into the sketch.ino tab in Wokwi. Let's understand each section:
① Setup — Initialising Everything
Runs once at power-on. Sets pin modes, initialises LCD, shows a welcome screen, and runs a boot test on the LEDs.
// Library for the I²C LCD display #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}; const int NUM_LEDS = 5; // Distance thresholds in centimetres const int SAFE_DISTANCE = 100; // >100cm → all clear const int WARNING_DISTANCE = 50; // 50–100cm → approaching const int DANGER_DISTANCE = 20; // 20–50cm → caution const int CRITICAL_DISTANCE = 10; // <10cm → critical! LiquidCrystal_I2C lcd(0x27, 16, 2); // I²C address, 16 cols, 2 rows void setup() { pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT); for (int i = 0; i < NUM_LEDS; i++) { pinMode(LED_PINS[i], OUTPUT); digitalWrite(LED_PINS[i], LOW); } pinMode(BUZZER_PIN, OUTPUT); lcd.init(); lcd.backlight(); displayWelcome(); // Show splash + boot LED test delay(2000); lcd.clear(); }
② Measuring Distance with pulseIn()
float measureDistance() { // Step 1: Clear TRIG, wait 2µs digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2); // Step 2: Send a 10µs HIGH pulse → triggers sonic burst digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); // Step 3: Measure how long ECHO stays HIGH (max 30ms timeout) long duration = pulseIn(ECHO_PIN, HIGH, 30000); // Step 4: Convert microseconds → centimetres // Speed of sound = 0.034 cm/µs, divide by 2 for one-way float dist = duration * 0.034 / 2; if (dist == 0 || dist > 200) return 200; // Out of range return dist; }
③ The Main Loop — Non-Blocking Architecture
Using millis() means the sensor reads every 100ms AND the buzzer beeps independently — nothing blocks anything else.
void loop() { unsigned long currentTime = millis(); // ── Measure sensor every 100ms ────────────────────── if (currentTime - previousMeasureTime >= 100) { previousMeasureTime = currentTime; distance = measureDistance(); updateLEDs(distance); // Update bar graph updateLCD(distance); // Refresh display buzzerInterval = calculateBuzzerInterval(distance); } // ── Buzzer beeping — completely independent ────────── if (distance < SAFE_DISTANCE) { if (currentTime - previousBuzzerTime >= buzzerInterval) { previousBuzzerTime = currentTime; if (!buzzerState) { tone(BUZZER_PIN, 2000, 50); // 2 kHz beep, 50ms buzzerState = true; } else { noTone(BUZZER_PIN); buzzerState = false; } } } else { noTone(BUZZER_PIN); // Silence when clear buzzerState = false; } }
④ Add Libraries in Wokwi
Create a libraries.txt file in your Wokwi project with:
LiquidCrystal I2C
Distance Zones & Behaviour
The system uses threshold-based logic — just like a real parking sensor computer. Each zone triggers a different combination of outputs.
Buzzer Timing Visualised
Testing in Wokwi
Upload Code and Start
With your circuit set up and code in sketch.ino, click the green ▶ Play button. You'll see the LCD show "PARKING AID / SIMULATOR" for 2 seconds, followed by a quick LED flash test.
Adjust the HC-SR04 Distance Slider
Click on the ultrasonic sensor in the simulation — a slider appears! Try dragging it to different values:
- Set to 150 cm → All clear, no LEDs, silent
- Set to 70 cm → 1 LED on, slow beep
- Set to 35 cm → 3 LEDs, medium beep
- Set to 15 cm → 4 LEDs, fast beep
- Set to 5 cm → All LEDs blinking, rapid alarm!
Use the Serial Monitor for Debugging
Click the Serial Monitor tab at the bottom of Wokwi. You'll see live output like:
Distance: 45.3 cm | LEDs: 3 | Beep Interval: 500 ms Distance: 22.1 cm | LEDs: 3 | Beep Interval: 500 ms Distance: 8.6 cm | LEDs: 5 | Beep Interval: 100 ms
Observe the STOP! Blinking Behaviour
At distances below 10 cm, the code uses millis() % 200 to make all 5 LEDs blink on and off every 100ms, and the LCD "STOP!" text alternates with blank space. This is a great example of time-based state switching without any delay().
Quick Quiz
Test your understanding before submitting your project.

Comments
Post a Comment