Ultrasonic Parking Indicator
Build a tabletop distance indicator: the onboard LED blinks faster as a target approaches, while invalid echoes are reported separately.

Steps
Choose a tabletop target
Use a UNO, an HC-SR04, its matching USB cable and jumper wires. A flat cardboard sheet is easier to detect than a thin wire or angled fabric. This is a desk experiment illustrating distance thresholds, not a vehicle parking aid or collision protection system.
Connect the sensor
With power removed, connect HC-SR04 VCC to UNO 5V, GND to GND, TRIG to D9 and ECHO to D10. Read the labels on your module instead of copying a pin order from a photograph. This direct ECHO connection is for the 5V UNO; a 3.3V ESP32 needs suitable level reduction.
Upload the indicator sketch
Select UNO and upload the supplied code. Open Serial Monitor at 115200 baud. The trigger is a 10 microsecond pulse; readings are spaced by at least 100 ms. pulseIn has a 25,000 microsecond timeout so missing echoes do not leave the sketch waiting for the default long timeout.
Try the distance zones
Move the target slowly between 10 and 80 cm from the sensor face. Below 15 cm, the LED changes state every 100 ms. From 15 to below 40 cm it changes every 500 ms. At 40 cm or more it is off. These are adjustable teaching thresholds, not a calibrated stopping distance.
Test a missing echo
Point the sensor away from a useful target or disconnect ECHO only after removing power. A zero-duration echo or a reading outside this demo's 2–200 cm range is marked invalid. The LED is off during invalid readings, so an unlit LED alone must never be interpreted as a clear path. Check the Serial message.
Improve stability thoughtfully
Compare the reading with a ruler at several positions. Surface angle and temperature influence results. Next, try a median of recent valid readings and separate enter/leave thresholds, as explained in the filtering guide. Keep a freshness timeout: old values must not survive indefinitely after valid echoes stop.
Code
#include <Arduino.h>
const uint8_t TRIG = 9, ECHO = 10;
uint32_t measuredAt = 0, blinkAt = 0;
float distanceCm = -1;
bool ledOn = false;
void setup() {
Serial.begin(115200);
pinMode(TRIG, OUTPUT); pinMode(ECHO, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(TRIG, LOW); digitalWrite(LED_BUILTIN, LOW);
}
void loop() {
uint32_t now = millis();
if (uint32_t(now - measuredAt) >= 100UL) {
measuredAt = now;
digitalWrite(TRIG, LOW); delayMicroseconds(2);
digitalWrite(TRIG, HIGH); delayMicroseconds(10); digitalWrite(TRIG, LOW);
unsigned long duration = pulseIn(ECHO, HIGH, 25000UL);
float candidate = duration * 0.0343f / 2.0f;
distanceCm = (duration > 0 && candidate >= 2.0f && candidate <= 200.0f) ? candidate : -1;
if (distanceCm < 0) Serial.println("No valid reading - check sensor and target.");
else { Serial.print("Distance cm: "); Serial.println(distanceCm, 1); }
now = millis();
}
if (distanceCm < 0 || distanceCm >= 40.0f) {
ledOn = false; digitalWrite(LED_BUILTIN, LOW); blinkAt = now; return;
}
uint32_t interval = distanceCm < 15.0f ? 100UL : 500UL;
if (uint32_t(now - blinkAt) >= interval) {
blinkAt = now; ledOn = !ledOn; digitalWrite(LED_BUILTIN, ledOn ? HIGH : LOW);
}
}
