This guide covers setup, wiring, and use of the HC-SR04 Ultrasonic Distance Measuring Sensor Module — one of the most popular and affordable distance sensors for Arduino, ESP32, and Raspberry Pi projects. It uses ultrasonic sound waves (sonar) to measure the distance to an object with up to 3mm accuracy at ranges from 2cm to 400cm (1 inch to 13 feet).
Whether you're building a parking sensor, a robot that avoids obstacles, a liquid level monitor, or a contactless ruler, this guide will walk you through everything — from basic wiring to advanced techniques like temperature-compensated measurements and using the NewPing library.
💡 How Ultrasonic Distance Measurement Works
The HC-SR04 works exactly like sonar on a submarine or the echolocation used by bats — it sends out a burst of sound and listens for the echo.
The Process (Step by Step)
- Your microcontroller sends a trigger pulse: You send a 10-microsecond HIGH pulse to the sensor's Trigger pin.
- The sensor emits ultrasonic sound: The transmitter (the "T" cylinder) sends out a burst of 8 ultrasonic pulses at 40 KHz — far above human hearing range.
- Sound travels to the object and bounces back: The ultrasonic pulses hit the nearest object and reflect back toward the sensor.
- The sensor detects the echo: The receiver (the "R" cylinder) picks up the reflected sound waves.
- The sensor outputs a timed pulse: The Echo pin goes HIGH for a duration equal to the time it took for the sound to travel to the object and back.
- Your code calculates the distance: Since the speed of sound is known (~343 m/s at 20°C), you can calculate the distance from the echo time.
The Distance Formula
The Echo pin's HIGH duration represents the round-trip time (to the object and back), so you divide by 2 to get the one-way distance:
Distance (cm) = Echo Time (µs) × 0.0343 / 2
Distance (cm) = Echo Time (µs) / 58.2
Distance (inches) = Echo Time (µs) / 148
Where does 0.0343 come from? The speed of sound at 20°C is approximately 343 meters per second, which equals 0.0343 cm per microsecond.

HC-SR04 Pulse Diagram
What It Can and Can't Detect
- ✅ Works well with: Hard, flat surfaces — walls, floors, furniture, metal, plastic, wood, glass, water surfaces.
- ✅ Works regardless of: Color, lighting conditions, transparency. Unlike optical sensors, ultrasonic sensors work in complete darkness and aren't fooled by black or transparent objects.
- ⚠️ Reduced accuracy with: Soft, sound-absorbing materials — fabric, foam, fur, thick carpet. These absorb the ultrasonic pulses instead of reflecting them.
- ⚠️ Reduced accuracy with: Very small objects, thin wires, or objects at steep angles (the sound bounces away instead of back).
- ❌ Cannot detect: Objects closer than 2cm (minimum range) or farther than 400cm (maximum range).
- ❌ Cannot detect: Objects outside the ~15° detection cone.
⭐ Features
- Non-contact distance measurement: Measures distance without touching the object — 2cm to 400cm (1" to 13 ft).
- High accuracy: Up to 3mm resolution.
- Narrow detection cone: ~15° beam angle — focused enough to avoid false readings from nearby objects, wide enough for practical use.
- Works in any lighting: Ultrasonic — not affected by sunlight, darkness, or object color/transparency.
- Simple interface: Just 4 pins — VCC, Trig, Echo, GND. No I2C, SPI, or libraries required (though libraries are available).
- Low power: Less than 2mA quiescent current, ~15mA during measurement.
- Fast measurement cycle: Can take approximately 20 measurements per second.
- Compact: 45mm × 20mm × 15mm — the two ultrasonic transducers give it a distinctive "eyes" appearance.
📋 Specifications
| Parameter | Value |
|---|---|
| Operating Voltage | 5V DC |
| Operating Current | ~15mA (during measurement) |
| Quiescent Current | <2mA |
| Ultrasonic Frequency | 40 KHz |
| Measuring Range | 2cm – 400cm (1" – 13 ft) |
| Accuracy | Up to 3mm |
| Measuring Angle | ~15° cone |
| Trigger Input | 10µs TTL pulse |
| Echo Output | TTL pulse (duration = round-trip time) |
| Output Voltage | 5V (HIGH) / 0V (LOW) |
| Measurement Cycle | ~50ms minimum (20 Hz max rate) |
| Dimensions | 45mm × 20mm × 15mm (1.77" × 0.79" × 0.59") |
| Weight | ~11g |
📌 Pinout
The HC-SR04 has 4 pins, clearly labeled on the PCB. Looking at the module from the front (transducers facing you), the pins from left to right are:
| Pin | Label | Connect To | Function |
|---|---|---|---|
| 1 | VCC | Arduino 5V | Power supply — must be 5V DC. |
| 2 | Trig | Digital pin (e.g., D9) | Trigger input — send a 10µs HIGH pulse to start a measurement. |
| 3 | Echo | Digital pin (e.g., D10) | Echo output — goes HIGH for a duration proportional to the measured distance. |
| 4 | GND | Arduino GND | Ground — must share common ground with your microcontroller. |
Note: The Echo pin outputs a 5V signal. This is safe for Arduino (5V logic) but requires a voltage divider for 3.3V microcontrollers like ESP32, ESP8266, and Raspberry Pi. See the Compatibility section below.
🔌 Wiring
What You'll Need
- Arduino Uno, Mega, Nano, or compatible board
- 4 × jumper wires (male-to-female or male-to-male with breadboard)
- USB cable for Arduino programming
- (Optional) Breadboard for prototyping
Arduino Wiring
| HC-SR04 Pin | Arduino Pin |
|---|---|
| VCC | 5V |
| Trig | D9 |
| Echo | D10 |
| GND | GND |
That's it — four wires. No pull-up resistors, no capacitors, no additional components needed for basic Arduino use.
ESP32 Wiring (with Voltage Divider)
The HC-SR04's Echo pin outputs 5V, but ESP32 GPIO pins are 3.3V tolerant only. You need a simple voltage divider on the Echo line:
- Connect VCC to the ESP32's VIN or an external 5V supply (not 3.3V — the sensor needs 5V to operate).
- Connect Trig directly to any ESP32 GPIO pin (e.g., GPIO 5). The ESP32's 3.3V HIGH output is sufficient to trigger the sensor.
- For Echo, create a voltage divider:
- Connect a 1KΩ resistor from the Echo pin to the ESP32 GPIO pin (e.g., GPIO 18).
- Connect a 2KΩ resistor (or two 1KΩ in series) from the ESP32 GPIO pin to GND.
- This divides the 5V Echo signal down to ~3.3V, safe for the ESP32.
- Connect GND to ESP32 GND (common ground).
Raspberry Pi Wiring (with Voltage Divider)
Same voltage divider approach as ESP32 — the Pi's GPIO is 3.3V only:
| HC-SR04 Pin | Raspberry Pi Pin | Notes |
|---|---|---|
| VCC | 5V (Pin 2 or 4) | Must be 5V |
| Trig | Any GPIO (e.g., GPIO 23 / Pin 16) | Direct connection — 3.3V is enough to trigger |
| Echo | Any GPIO via voltage divider (e.g., GPIO 24 / Pin 18) | Use 1KΩ + 2KΩ voltage divider |
| GND | GND (Pin 6 or any GND) | Common ground |
🏗️ Voltage Divider Schematic for 3.3V Systems
If you're using an ESP32, ESP8266, Raspberry Pi, or any 3.3V microcontroller, you need this simple voltage divider on the Echo pin:
HC-SR04 Echo Pin ──── [1KΩ Resistor] ──┬── ESP32/Pi GPIO Pin
│
[2KΩ Resistor]
│
GND
This divides the 5V Echo signal: 5V × (2KΩ / (1KΩ + 2KΩ)) = 3.33V — safe for 3.3V GPIO.
Alternative: If you don't have a 2KΩ resistor, use two 1KΩ resistors in series (1KΩ + 1KΩ = 2KΩ). Or use a 1KΩ + 2.2KΩ combination — the exact ratio isn't critical as long as the output stays below 3.3V.
💻 Arduino Example Code
Example 1: Basic Distance Measurement (No Library)
This example uses only built-in Arduino functions — no external libraries needed:
const int trigPin = 9;
const int echoPin = 10;
long duration;
float distanceCm;
float distanceInch;
void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.println("HC-SR04 Distance Sensor Ready");
}
void loop() {
// Clear the trigger pin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Send a 10-microsecond trigger pulse
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read the echo pulse duration (in microseconds)
duration = pulseIn(echoPin, HIGH);
// Calculate distance
distanceCm = duration / 58.2;
distanceInch = duration / 148.0;
// Print results
Serial.print("Distance: ");
Serial.print(distanceCm, 1);
Serial.print(" cm | ");
Serial.print(distanceInch, 1);
Serial.println(" inches");
delay(100); // Wait before next measurement
}
Example 2: Using the NewPing Library (Recommended)
The NewPing library by Tim Eckel simplifies HC-SR04 code, adds built-in timeout handling, supports median filtering, and works with multiple sensors. Install it from the Arduino Library Manager (Sketch → Include Library → Manage Libraries → search "NewPing").
#include <NewPing.h>
#define TRIGGER_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 400 // Maximum distance in cm
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
void setup() {
Serial.begin(9600);
Serial.println("HC-SR04 with NewPing Library Ready");
}
void loop() {
delay(50); // Wait between pings (min 29ms recommended)
unsigned int distance = sonar.ping_cm();
if (distance == 0) {
Serial.println("Out of range or no echo");
} else {
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
}
}
Example 3: Median Filtering for Stable Readings
Single readings can be noisy. The NewPing library includes a built-in median filter that takes multiple readings and returns the middle value — much more stable:
#include <NewPing.h>
#define TRIGGER_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 400
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
void setup() {
Serial.begin(9600);
Serial.println("HC-SR04 Median Filter Ready");
}
void loop() {
delay(50);
// Take 5 readings and return the median
unsigned int distance = sonar.ping_median(5);
distance = sonar.convert_cm(distance);
if (distance == 0) {
Serial.println("Out of range");
} else {
Serial.print("Distance (median of 5): ");
Serial.print(distance);
Serial.println(" cm");
}
}
Example 4: Proximity Alert with LED and Buzzer
const int trigPin = 9;
const int echoPin = 10;
const int ledPin = 13;
const int buzzerPin = 8;
const int alertDistance = 30; // Alert when object is within 30cm
void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
}
void loop() {
// Trigger measurement
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
float distance = duration / 58.2;
Serial.print("Distance: ");
Serial.print(distance, 1);
Serial.println(" cm");
if (distance > 0 && distance < alertDistance) {
// Object is close — activate alert
digitalWrite(ledPin, HIGH);
tone(buzzerPin, 1000, 100); // 1KHz beep for 100ms
} else {
digitalWrite(ledPin, LOW);
noTone(buzzerPin);
}
delay(100);
}
Example 5: Temperature-Compensated Distance
The speed of sound changes with temperature. At 20°C it's ~343 m/s, but at 0°C it's ~331 m/s and at 40°C it's ~355 m/s. For maximum accuracy, you can compensate using a temperature sensor (like a DHT11 or DS18B20):
const int trigPin = 9;
const int echoPin = 10;
// If you have a temperature sensor, read the actual temperature.
// Otherwise, set this to your approximate ambient temperature.
float temperatureC = 20.0; // Default: 20°C
void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
// Calculate speed of sound based on temperature
// Formula: speed (m/s) = 331.3 + (0.606 × temperature in °C)
float speedOfSound = 331.3 + (0.606 * temperatureC); // m/s
float speedCmPerUs = speedOfSound / 10000.0; // cm/µs
// Trigger measurement
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
// Calculate distance with temperature compensation
float distance = (duration * speedCmPerUs) / 2.0;
Serial.print("Temp: ");
Serial.print(temperatureC, 1);
Serial.print("°C | Distance: ");
Serial.print(distance, 1);
Serial.println(" cm");
delay(200);
}
🔧 Tips for Accurate Measurements
- Wait between measurements: Allow at least 50ms (ideally 60ms) between measurements. Faster polling can cause the previous echo to interfere with the next reading.
-
Use median filtering: Take 3–5 readings and use the median value. This eliminates occasional outlier readings caused by stray echoes or noise. The NewPing library makes this easy with
ping_median(). - Mount the sensor properly: The two transducers should face the target squarely. Angling the sensor more than ~15° from perpendicular to the target surface will reduce or eliminate the echo.
- Avoid narrow tubes or corners: Sound can bounce multiple times in enclosed spaces, creating false readings.
- Account for temperature: If you need high accuracy across a wide temperature range, use the temperature-compensated formula. At room temperature (20°C), the standard formula is accurate enough for most projects.
- Minimum range is 2cm: Objects closer than 2cm will return 0 or erratic readings. This is a hardware limitation.
- Maximum practical range: While the spec says 400cm, reliable readings typically max out at 200–300cm depending on the target size and surface. Large, flat, hard surfaces reflect best at long range.
- Avoid cross-talk with multiple sensors: If using multiple HC-SR04 modules, trigger them sequentially (not simultaneously) to prevent one sensor from picking up another's echo. Wait for each measurement to complete before triggering the next.
🔌 Compatibility
| Platform | VCC | Trig | Echo | Notes |
|---|---|---|---|---|
| Arduino (5V) | 5V | Direct | Direct | No additional components needed. Simplest setup. |
| ESP32 | VIN / ext. 5V | Direct (3.3V OK) | Voltage divider required | 1KΩ + 2KΩ divider on Echo. See schematic above. |
| ESP8266 | VIN / ext. 5V | Direct (3.3V OK) | Voltage divider required | Same divider as ESP32. Only one analog pin available. |
| Raspberry Pi | 5V (Pin 2/4) | Direct (3.3V OK) | Voltage divider required | 1KΩ + 2KΩ divider on Echo. Use GPIO library for timing. |
| STM32 (3.3V) | External 5V | Direct (3.3V OK) | Voltage divider required | Same divider approach as ESP32. |
Key point: The HC-SR04 requires 5V power to operate. The Trig pin will accept a 3.3V input signal, but the Echo pin outputs 5V. For any 3.3V microcontroller, you must use a voltage divider (or a level shifter) on the Echo pin to avoid damaging your board.
🎯 Project Ideas & Applications
- Obstacle-avoiding robot: Mount the sensor on the front of a robot. When an obstacle is detected within a set distance, the robot turns or stops. Add a servo to sweep the sensor for wider coverage.
- Parking sensor / backup alert: Mount in a garage to show how close a car is to the wall. Use LEDs or a buzzer that beeps faster as the car gets closer.
- Liquid level monitor: Mount the sensor above a tank or container, pointing down at the liquid surface. Calculate the liquid level from the distance to the surface. Works well with water, oil, and other liquids.
- Contactless ruler / tape measure: Point at a wall and read the distance on an LCD or OLED display. Add a button to freeze the reading.
- People counter: Mount in a doorway to detect people passing through. Count transitions from "no object" to "object detected."
- Automatic hand sanitizer / soap dispenser: Detect when a hand is placed under the dispenser (within 5–10cm) and trigger a pump.
- Smart trash can: Detect when a hand approaches the lid and open it automatically with a servo.
- Musical instrument (theremin-style): Map the distance reading to a tone frequency — move your hand closer or farther to change the pitch.
- Security / intrusion detection: Monitor a fixed distance (e.g., a doorway or window). Alert when the distance changes (something entered the beam).
- Height measurement station: Mount the sensor on a ceiling or overhead bar, pointing down. Calculate height as (sensor height − measured distance).
🛠️ Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| Always reads 0 cm | No echo received, wiring error, or object out of range | Check all 4 wires. Verify VCC is 5V (not 3.3V). Ensure an object is within 2–400cm range and within the 15° cone. Try a large, flat, hard surface like a wall. |
| Reads a fixed value that doesn't change | Trig and Echo pins swapped | Verify Trig is connected to your defined trigger pin and Echo to your defined echo pin. They are commonly swapped by accident. |
| Erratic or jumping readings | Electrical noise, too-fast polling, or soft target surface | Add a 50–60ms delay between measurements. Use median filtering (3–5 samples). Add a 0.1µF capacitor across VCC and GND at the sensor. Avoid fabric, foam, or fur targets. |
| Maximum range is much less than 400cm | Small target, soft surface, or angled surface | 400cm is achievable only with large, flat, hard surfaces perpendicular to the sensor. Practical range for small objects is 100–200cm. This is normal. |
| Readings are inaccurate by several cm | Temperature not accounted for, or sensor not perpendicular to target | Use the temperature-compensated formula if accuracy is critical. Ensure the sensor faces the target squarely. Verify with a tape measure and calibrate if needed. |
| Sensor doesn't work with ESP32 / Raspberry Pi | Echo pin is 5V, damaging the 3.3V GPIO | You MUST use a voltage divider on the Echo pin for 3.3V systems. See the Wiring and Schematic sections above. |
| pulseIn() times out (returns 0) | No echo received within the timeout period | Default pulseIn() timeout is 1 second. If measuring long distances, this is fine. If the sensor is pointed at open air (no object), it will return 0 — this is expected behavior. Use NewPing library for better timeout handling. |
| Multiple sensors interfere with each other | Cross-talk — one sensor picks up another's echo | Trigger sensors sequentially, not simultaneously. Wait for each measurement to complete (60ms) before triggering the next sensor. |
| Readings are unstable near minimum range (2cm) | Below minimum detection distance | The HC-SR04 cannot reliably measure distances below 2cm. This is a hardware limitation. Move the object further away. |
| Sensor works but readings drift over time | Temperature changes affecting speed of sound | Use temperature-compensated distance calculation. A 10°C temperature change causes approximately 1.7% distance error. |
⚠️ Important Notes & Safety
- Requires 5V power. The HC-SR04 will not operate reliably at 3.3V. Always power from a 5V source.
- Echo pin outputs 5V. For 3.3V microcontrollers (ESP32, ESP8266, Raspberry Pi, STM32), you must use a voltage divider or level shifter on the Echo pin. Connecting 5V directly to a 3.3V GPIO pin can damage your board.
- Minimum measurement distance is 2cm. Objects closer than 2cm will return 0 or unreliable readings.
- Allow 50–60ms between measurements. Faster polling can cause echo interference and erratic readings.
- The 40 KHz ultrasonic frequency is inaudible to humans but may be audible to dogs, cats, and other animals. If you notice pets reacting to the sensor, consider reducing the measurement frequency.
- Not waterproof. The standard HC-SR04 is not sealed. For liquid level measurement, mount the sensor above the liquid, not submerged. For waterproof applications, consider the JSN-SR04T waterproof ultrasonic sensor instead.
- Avoid using near other ultrasonic sources. Other HC-SR04 sensors, ultrasonic cleaners, or ultrasonic pest repellers operating near 40 KHz can interfere with readings.
- The sensor has a ~15° cone. Objects outside this cone will not be detected. Be aware of the beam width when mounting — the cone expands with distance.
📊 HC-SR04 vs. Other Distance Sensors
| Feature | HC-SR04 (Ultrasonic) | IR Distance (Sharp GP2Y0A21) | VL53L0X (Laser ToF) |
|---|---|---|---|
| Technology | Ultrasonic (40 KHz sound) | Infrared light | Laser time-of-flight |
| Range | 2cm – 400cm | 10cm – 80cm | 3cm – 200cm |
| Accuracy | ~3mm | ~10mm | ~3mm |
| Affected by light? | No | Yes (sunlight interferes) | Slightly |
| Affected by color? | No | Yes (dark surfaces) | Slightly |
| Affected by sound? | Yes (other ultrasonics) | No | No |
| Soft surfaces? | Poor (absorbs sound) | Good | Good |
| Interface | Trig/Echo (digital) | Analog voltage | I2C |
| Voltage | 5V only | 5V | 3.3V or 5V |
| Price | Low ($) | Medium ($$) | Medium ($$) |
| Best for | General distance, robots, parking | Short-range proximity | Precision, small objects |
📋 Quick Reference Card
| Parameter | Value |
|---|---|
| Supply Voltage | 5V DC (required) |
| Pins | VCC, Trig, Echo, GND |
| Range | 2cm – 400cm |
| Accuracy | ~3mm |
| Beam Angle | ~15° cone |
| Trigger | 10µs HIGH pulse on Trig pin |
| Distance (cm) | = pulseIn(echoPin, HIGH) / 58.2 |
| Distance (inches) | = pulseIn(echoPin, HIGH) / 148 |
| Min delay between readings | 50–60ms |
| 3.3V systems | Voltage divider required on Echo pin |
| Best library | NewPing (Arduino Library Manager) |
💡 Quick Formula: Distance (cm) = pulseIn(echoPin, HIGH) / 58.2 | Distance (inches) = pulseIn(echoPin, HIGH) / 148
🛒 Where to Buy the HC-SR04
HC-SR04 Ultrasonic Distance Measuring Sensor Module at Envistia Mall →
📚 Additional Resources
- HC-SR04 Complete Guide — How To Mechatronics
- HC-SR04 Complete Guide — Random Nerd Tutorials
- NewPing Library Documentation
- Sensor, Detector & Input Modules at Envistia Mall
- All Sensor, Detector & Input Module Guides
-
Ultrasonic rangefinder module test & interface with microcontroller from JohnAudioTech (YouTube Video)
This guide is provided by Envistia Mall for educational and technical reference purposes. The manufacturer and Envistia LLC (dba Envistia Mall) are not responsible for any damages or losses resulting from the use of this product. Always follow proper electrical safety practices when working with electronic components. Specifications are based on manufacturer data and may vary between production batches.