ESP32 HC-SR04 Ultrasonic Distance Sensor
The HC-SR04 ultrasonic sensor calculates distance by measuring the time it takes for the sound wave it emits to bounce off an object and return (Time of Flight). In this project, we will send a 10-microsecond pulse from the ESP32 to the sensor's TRIG pin and read the echo duration from the ECHO pin using `pulseIn()`. We will display the calculated distance in centimeters on a 16x2 I2C LCD. Since the HC-SR04 operates at 5V, a **voltage divider** is required on the ECHO pin—otherwise, the ESP32’s

Video
Circuit Diagram

Source Code
1// ─────────────────────────────────────────
2// BlueGrays · bluegrays.com
3// ESP32 HC-SR04 Ultrasonic Distance Sensor
4// ─────────────────────────────────────────
5// Triggers the HC-SR04 with a TRIG pulse, computes the distance (cm) from
6// the ECHO time and shows it on a 16x2 I2C LCD every 0.2 s. If no echo
7// comes back, the screen shows "Menzil disinda" (out of range).
8//
9// Pins:
10// GPIO 5 -> HC-SR04 TRIG
11// GPIO 18 -> HC-SR04 ECHO (via a voltage divider)
12// Divider: ECHO -> 1k -> GPIO 18 -> 2k -> GND
13// GPIO 21 -> LCD SDA, GPIO 22 -> LCD SCL
14// HC-SR04 and LCD VCC -> 5V (VIN), GND -> GND
15
16#include <Wire.h>
17#include <LiquidCrystal_I2C.h>
18
19// Pin definitions
20const int TRIG_PIN = 5;
21const int ECHO_PIN = 18; // Needs a 1k + 2k voltage divider
22
23// LCD addr 0x27 or 0x3F
24LiquidCrystal_I2C lcd(0x27, 16, 2);
25
26const float SOUND_SPEED_CM_PER_US = 0.0343f; // Speed of sound (cm/us)
27const unsigned long PULSE_TIMEOUT_US = 30000UL; // Echo timeout (~5 m)
28
29void setup() {
30 pinMode(TRIG_PIN, OUTPUT);
31 pinMode(ECHO_PIN, INPUT);
32 digitalWrite(TRIG_PIN, LOW);
33
34 // DevKit V1 default I2C pins
35 Wire.begin(21, 22);
36
37 lcd.init();
38 lcd.backlight();
39
40 // Splash screen 3 s
41 lcd.setCursor(3, 0);
42 lcd.print("BlueGrays");
43 lcd.setCursor(1, 1);
44 lcd.print("HC-SR04 v1.0");
45 delay(3000);
46
47 // Main screen
48 lcd.clear();
49 lcd.setCursor(0, 0);
50 lcd.print("Mesafe:");
51}
52
53// Reads the distance in cm, -1 on error
54float readDistanceCm() {
55 // A 10 us TRIG pulse starts a measurement
56 digitalWrite(TRIG_PIN, LOW);
57 delayMicroseconds(2);
58 digitalWrite(TRIG_PIN, HIGH);
59 delayMicroseconds(10);
60 digitalWrite(TRIG_PIN, LOW);
61
62 unsigned long duration = pulseIn(ECHO_PIN, HIGH, PULSE_TIMEOUT_US);
63 if (duration == 0) return -1.0f;
64 // Round trip, so divide by 2
65 return (duration * SOUND_SPEED_CM_PER_US) / 2.0f;
66}
67
68void loop() {
69 float distance = readDistanceCm();
70
71 // Clear bottom row
72 lcd.setCursor(0, 1);
73 lcd.print(" ");
74 lcd.setCursor(0, 1);
75
76 if (distance < 0) {
77 lcd.print("Menzil disinda");
78 } else {
79 lcd.print(distance, 1); // 1 decimal place
80 lcd.print(" cm");
81 }
82
83 delay(200);
84}
85FAQ
Why is a voltage divider installed on the ECHO line?▾
The HC-SR04 operates at 5 V and the ECHO pin outputs 5 V; the ESP32 inputs accept a maximum of 3.3 V. A voltage divider made with 1 kΩ and 2 kΩ resistors reduces the 5 V to approximately 3.3 V, thereby protecting the ESP32.
Does the TRIG pin also require a divider?▾
No. TRIG is a signal from the ESP32 to the sensor; the ESP32's 3.3 V HIGH is generally detected reliably by the HC-SR04.
Is a divider needed with the HC-SR04P?▾
Models such as the HC-SR04P and RCWL-1601 can be powered by 3.3 V; in this case, the ECHO output is also 3.3 V, and no divider is required.
How can distance measurements be made more accurate?▾
The speed of sound varies with temperature (approximately 343 m/s at 20 °C). Correcting for the speed of sound using a temperature sensor and taking the median of several measurements improves accuracy.
