HC-SR04 Ultrasonic Range Finder and a Voltage Divider for ESP32
We measure distances up to 4 m from the echo time of an ultrasonic pulse. TRIG/ECHO and pulseIn(), the speed of sound, and above all a 1 kΩ / 2 kΩ divider, because the 5 V ECHO signal harms an ESP32 pin.
About the project
The HC-SR04 works like a bat: it sends a short burst of 40 kHz ultrasound and listens for the echo. The time between the "shout" and the echo is proportional to the distance. It covers 2–400 cm with about 3 mm resolution, and it costs next to nothing.
What you need
- ESP32 DevKit
- HC-SR04 module
- 1 kΩ and 2 kΩ (or 2.2 kΩ) resistors for the divider
Wiring
| HC-SR04 | Connection |
|---|---|
| VCC | 5V |
| TRIG | GPIO5 |
| ECHO | → 1 kΩ → GPIO18, and from GPIO18 → 2 kΩ → GND |
| GND | GND |
Why the divider is mandatory. The HC-SR04 runs from 5 V, so its ECHO output is 5 V, while the ESP32 inputs are 3.3 V parts. The excess flows through the protection diodes into the supply rail, and the pin degrades or dies. A 1 kΩ / 2 kΩ divider gives 5 × 2 / (1 + 2) ≈ 3.3 V.
The TRIG input is fine with the ESP32's 3.3 V, so it needs no divider. There is also an HC-SR04P / RCWL-1601 version that runs from 3.3 V; with it the divider is not needed.
How a measurement goes
- The ESP32 puts a 10 µs pulse on TRIG.
- The module sends 8 cycles of ultrasound and raises ECHO HIGH.
- When the echo returns, ECHO drops LOW.
pulseIn(ECHO, HIGH, 30000)measures how long it stayed HIGH, in microseconds. 30000 is the timeout (~5 m). With no echo the function returns 0.
The sound travels there and back, so:
distance (cm) = time (µs) × 0.0343 / 2, where 0.0343 cm/µs is the speed of sound at ~20 °C.
Code
// HC-SR04 range finder: TRIG on GPIO5, ECHO through a divider to GPIO18
const int TRIG = 5;
const int ECHO = 18;
void setup() {
Serial.begin(115200);
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
}
void loop() {
digitalWrite(TRIG, LOW);
delayMicroseconds(2);
digitalWrite(TRIG, HIGH); // 10 µs trigger pulse
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
unsigned long us = pulseIn(ECHO, HIGH, 30000); // 30 ms timeout ≈ 5 m
if (us == 0) Serial.println("out of range");
else Serial.printf("%.1f cm\n", us * 0.0343 / 2);
delay(300);
}
Good to know
- Temperature. The speed of sound is ≈ 331.3 + 0.606 × T m/s. Between −10 and +35 °C that is a ±4 % error; for accurate work add a temperature sensor.
- Soft and angled surfaces (fabric, a wall corner) scatter the sound, and no echo comes back.
- Several sensors side by side hear each other's echoes. Fire them in turn with a ~60 ms pause.
- Don't measure more often than every ~60 ms: a leftover echo from the previous ping gives phantom values.
What next
Above a water tank the sensor becomes a level gauge (it has its own article), and on a toy car's bumper, a parking sensor.