The HC-SR04 Sensing Principle
The HC-SR04 measures distance using the piezoelectric effect. When the microcontroller pulls the Trigger pin high for at least 10 microseconds, the sensor's internal oscillator drives the transmitter transducer with an 8-cycle burst at 40 kHz. This ultrasonic pulse travels through the air, strikes a physical object, and bounces back as an echo. The receiver transducer detects this returning acoustic wave and converts it back into a tiny electrical signal, which the onboard comparator amplifies into a clean digital logic pulse.
Timing is the entire mechanism here. The moment the 8-cycle burst finishes transmitting, the sensor pulls its Echo pin HIGH. This pin stays HIGH until the returning acoustic echo is detected (or until it times out). By measuring the exact duration the Echo pin remains HIGH, your microcontroller calculates the total round-trip flight time of the sound wave. Because the speed of sound in air is relatively constant at a given temperature, this time-domain measurement translates directly into a physical distance.
Datasheet Specs vs. Bench Reality
Before wiring this sensor, we need to clarify a common misconception found in beginner forums: the HC-SR04 output is strictly a digital 5V TTL timing pulse. It does not output an analog voltage proportional to distance, nor does it use a 4-20mA current loop. You must read it using a digital input pin configured to measure pulse width, not an ADC (Analog-to-Digital Converter) pin.
While the generic datasheet lists the operating voltage as 5V DC and the quiescent current at 2mA, bench measurements tell a slightly different story. During the 40 kHz transmit burst, current spikes to roughly 15mA–20mA. If you are powering multiple HC-SR04 sensors (which cost about $1.50 each in single quantities) from an Arduino Uno's onboard 5V regulator, keep the total sensor count under four to avoid brownout resets. Furthermore, the Echo pin outputs a full 5V logic HIGH. If you are interfacing with a 3.3V microcontroller like the ESP32-WROOM-32 or Raspberry Pi Pico, feeding 5V directly into a 3.3V GPIO will eventually degrade or destroy the silicon.
| Pin | Function | Supply / Logic Range | Microcontroller Connection |
|---|---|---|---|
| VCC | Power Supply | 4.5V to 5.5V DC | 5V pin on Arduino / 5V pin on ESP32 (VIN) |
| Trig | Trigger Input | Accepts 3.3V or 5V | Any Digital Output GPIO |
| Echo | Echo Output | Outputs 5V TTL | Digital Input GPIO (Use divider for 3.3V boards) |
| GND | Ground | 0V Reference | Common Ground (GND) |
Output Signal Math: Raw Pulse to Centimeters
Once your microcontroller captures the pulse width in microseconds (µs), you need to convert that raw time value into a physical unit. The fundamental physics equation is Distance = (Time × Velocity) / 2. We divide by 2 because the sound wave travels to the target and back (round-trip).
At a standard room temperature of 20°C (68°F), the speed of sound in dry air is approximately 343 meters per second. Converted to centimeters per microsecond, this is 0.0343 cm/µs. Therefore, the raw-to-unit math looks like this:
distance_cm = (pulse_duration_us × 0.0343) / 2
For faster integer math on 8-bit microcontrollers like the ATmega328P (Arduino Uno), makers often simplify the divisor. Multiplying 2 by the reciprocal of 0.0343 gives roughly 58.3. Thus, dividing the raw microsecond reading by 58 yields the distance in centimeters. For inches, divide by 148. You can read the exact pulse timing using the Arduino pulseIn() function.
// Pin definitions
const int trigPin = 9;
const int echoPin = 10;
void setup() {
Serial.begin(115200);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
// 1. Clear the trigger pin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// 2. Send 10us HIGH pulse to trigger
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// 3. Read the echo pin (returns time in microseconds)
long duration = pulseIn(echoPin, HIGH, 38000); // 38ms timeout prevents infinite hang
// 4. Raw-to-unit math
float distance_cm = (duration * 0.0343) / 2.0;
if (duration == 0) {
Serial.println("Timeout: Out of range or disconnected.");
} else {
Serial.print("Distance: ");
Serial.print(distance_cm);
Serial.println(" cm");
}
delay(60); // Min 60ms cycle time per datasheet
}
Common Interference Sources and Calibration
The HC-SR04 is notoriously susceptible to environmental interference, which is rarely detailed in the basic distributor datasheets. The most common issue is acoustic crosstalk. If you mount two HC-SR04 sensors facing the same direction and fire them simultaneously, Sensor A's receiver will pick up Sensor B's echo, resulting in wildly inaccurate phantom readings. The fix is sequential polling: fire Sensor A, wait for its echo or timeout, then fire Sensor B.
Another major interference source is target material and geometry. Ultrasonic waves reflect poorly off soft, sound-absorbing materials (like clothing or foam) and scatter away from angled surfaces. If the target is angled more than 15 degrees relative to the sensor face, the echo may bounce away entirely, causing a timeout (reading 0). Furthermore, the sensor has a physical blind spot; the datasheet specifies a minimum range of 2 cm. In reality, due to the transducer's mechanical ringing decay, reliable readings usually don't start until 4 cm to 5 cm.
Finally, temperature scaling is required for high-precision applications. The speed of sound changes by roughly 0.6 m/s for every 1°C change in temperature. If your project operates in an unheated garage at 5°C versus a living room at 25°C, your distance calculations will drift by over 3%. For strict calibration, wire a DS18B20 digital temperature sensor alongside the HC-SR04 and dynamically calculate the speed of sound using the Engineering ToolBox acoustic formulas before applying the distance math.
HC-SR04 Datasheet FAQ
Can I run the HC-SR04 directly on a 3.3V ESP32 GPIO pin?
You can power the VCC pin from a 5V source and connect the Trigger pin directly to a 3.3V ESP32 GPIO (the HC-SR04's internal logic chip recognizes 3.3V as a valid HIGH). However, you cannot connect the Echo pin directly to the ESP32. The Echo pin outputs a 5V pulse when triggered, which exceeds the ESP32's 3.3V absolute maximum rating. You must use a resistor voltage divider (e.g., 1kΩ and 2kΩ) on the Echo line to step the 5V signal down to a safe 3.3V logic level.
Why does my HC-SR04 read 0 or timeout randomly?
A reading of 0 usually means the pulseIn() function timed out before the Echo pin went HIGH and back LOW. This happens for three reasons: 1) The target is beyond the sensor's maximum range (roughly 400 cm), 2) The target is heavily angled or made of sound-absorbing material, causing the echo to scatter, or 3) You are experiencing power supply brownouts. If your 5V rail sags below 4.5V during the 20mA transmit burst, the internal comparator resets, and the Echo pulse is never generated. Add a 100µF decoupling capacitor across the VCC and GND pins on the sensor to stabilize the local power delivery.
What is the actual blind spot distance listed in the HC-SR04 datasheet?
The official generic datasheets list the measuring angle as 15 degrees and the effective range as 2 cm to 400 cm. However, the 2 cm minimum is a theoretical limit. Because the transmitter and receiver transducers are physically separated by about 1.5 cm on the PCB, and because the receiver circuit is temporarily deafened (blanked) while the transmitter is actively ringing, the practical blind spot is closer to 4 cm or 5 cm. If you need to measure distances under 4 cm, you should switch to an infrared Time-of-Flight (ToF) sensor like the VL53L0X.
How do I filter out HC-SR04 ultrasonic sensor noise in code?
Ultrasonic sensors occasionally return 'spikes'—readings that jump wildly due to acoustic multipath reflections (sound bouncing off a wall, then the floor, then the target). A simple moving average filter will lag and smear these spikes. Instead, implement a median filter. Take 5 rapid sequential readings, sort them in an array from lowest to highest, and discard the highest and lowest values. Return the middle (3rd) value. This completely eliminates outlier spikes without introducing the phase lag associated with standard averaging.






