← All projects
Sensors Beginner

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.

Difficulty
Beginner
Time
30 min
Category
Sensors
Updated

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

  1. The ESP32 puts a 10 µs pulse on TRIG.
  2. The module sends 8 cycles of ultrasound and raises ECHO HIGH.
  3. When the echo returns, ECHO drops LOW.
  4. 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.