The HC-SR04 is the workhorse of hobbyist distance measurement. It fires a 40kHz ultrasonic burst and listens for the echo, calculating distance based on the speed of sound. To get reliable readings on an Arduino Uno R3, you must wire it to the 5V rail, use a dedicated ground, and implement strict timeout handling in your code to prevent the microcontroller from hanging.

This guide provides the exact pinout, a production-ready code block with error handling, and a diagnostic matrix for the most common failure modes—specifically the dreaded "0 cm" and timeout errors.

HC-SR04 Specification & Parts List

Before wiring, verify your components. The HC-SR04 is strictly a 5V device; feeding it 3.3V will result in erratic triggers, while reversing the power pins will instantly destroy the onboard ASIC because it lacks reverse-polarity protection.

Project Difficulty: Beginner | Time Required: 15 minutes | Target Board: Arduino Uno R3 (Rev3, ATmega328P)

Required Parts

  • Microcontroller: Arduino Uno R3 (Official part A000066 or high-quality clone with ATmega16U2 USB chip) — ~$25.00
  • Sensor: HC-SR04 Ultrasonic Module (Generic or Elecrow variant) — ~$2.50
  • Wiring: 4x Male-to-Male jumper wires (22 AWG solid core) and a standard 830-point solderless breadboard.
  • Power: High-quality USB-A to USB-B cable (poor cables cause voltage sag that starves the sensor's 5V rail).

Sensor Spec Sheet

ParameterValueNotes
Operating Voltage5V DCDo not use the Uno's 3.3V pin.
Operating Current15 mA (typical)Spikes to ~20mA during burst transmission.
Frequency40 kHzInaudible to humans; interferes with other 40kHz sensors.
Measuring Range2 cm to 400 cmBlind zone exists below 2 cm.
Beam Angle~15 degreesSoft, angled surfaces will scatter the wave, returning no echo.
Resolution0.3 cmLimited by the speed of sound and timer resolution.

Pin Mapping & Wiring Steps

The HC-SR04 uses a simple 4-pin interface. The Trigger pin accepts a 10-microsecond HIGH pulse to initiate measurement, and the Echo pin outputs a HIGH pulse whose duration equals the time-of-flight of the sound wave.

Pin Mapping Table

HC-SR04 PinArduino Uno R3 PinWire Color (Suggested)
VCC5VRed
TrigDigital Pin 9Yellow
EchoDigital Pin 10Green
GNDGNDBlack

Wiring Procedure

  1. De-energize the board: Unplug the Arduino USB cable before making connections.
  2. Connect Power: Insert the HC-SR04 into the breadboard. Run the Red jumper from the sensor's VCC to the Arduino's 5V pin. Run the Black jumper from GND to the Arduino's GND.
  3. Connect Logic: Run the Yellow jumper from Trig to Digital Pin 9.
  4. Connect Echo: Run the Green jumper from Echo to Digital Pin 10.
  5. Verify: Double-check that VCC and GND are not swapped. Reversing these will permanently short the sensor's internal oscillator.

Compilable Arduino Code with Error Handling

The standard Arduino pulseIn() function is blocking. If the sensor fails to return an echo (e.g., the sound wave scatters off a soft surface), pulseIn() will halt the entire sketch until the timeout expires. The code below implements a strict 30,000-microsecond timeout and explicit error handling to catch dead sensors and out-of-bounds readings.

/*
 * HC-SR04 Ultrasonic Sensor with Error Handling
 * Target Board: Arduino Uno R3 (Rev3, ATmega328P)
 * Author: ElectricalFlux
 */

#define TRIG_PIN 9
#define ECHO_PIN 10
#define TIMEOUT_US 30000 // 30ms covers max 400cm range + margin
#define SPEED_OF_SOUND_CM_US 0.0343 // Speed of sound at 20C in cm/us

void setup() {
  Serial.begin(115200);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  
  // Ensure Trigger pin is low on startup
  digitalWrite(TRIG_PIN, LOW);
  Serial.println("HC-SR04 Initialized. Waiting for readings...");
}

void loop() {
  // 1. Send 10us HIGH pulse to Trigger
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // 2. Read Echo pulse duration with timeout
  unsigned long duration = pulseIn(ECHO_PIN, HIGH, TIMEOUT_US);

  // 3. Error Handling & Calculation
  if (duration == 0) {
    Serial.println("ERROR: Echo timeout (0us) - Check wiring or sensor obstruction.");
  } else {
    // Calculate distance: (time * speed) / 2 (round trip)
    float distance_cm = (duration * SPEED_OF_SOUND_CM_US) / 2.0;

    if (distance_cm < 2.0) {
      Serial.println("ERROR: Distance out of bounds (<2cm) - Object in blind zone.");
    } else if (distance_cm > 400.0) {
      Serial.println("ERROR: Distance out of bounds (>400cm) - Acoustic cross-talk.");
    } else {
      Serial.print("Distance: ");
      Serial.print(distance_cm, 1);
      Serial.println(" cm");
    }
  }

  // Wait 60ms between readings to prevent acoustic interference (echo overlap)
  delay(60);
}
Bench Tip: The speed of sound changes with temperature (roughly 0.6 m/s per °C). For high-precision indoor applications, read the room temperature via a DHT22 or BME280 sensor and dynamically adjust the SPEED_OF_SOUND_CM_US constant in your code.

Debugging: Exact Errors and Ranked Causes

When the HC-SR04 fails, it usually fails in one of two ways. Here is the diagnostic decision path based on the exact serial output.

Symptom 1: "ERROR: Echo timeout (0us)"

This means the Arduino sent the trigger pulse, but the Echo pin never went HIGH within the 30ms window. The pulseIn() function timed out and returned 0.

The First Three Things to Check:

  1. Trig and Echo Swapped (90% of cases): Verify your physical wiring against the pin mapping table. If Pin 9 is wired to Echo and Pin 10 to Trig, the Arduino is listening to the output pin and triggering the input pin.
  2. VCC Sag or Floating Ground: Measure the voltage between the sensor's VCC and GND pins with a multimeter while the circuit is live. If it reads below 4.8V, your USB cable or power supply is sagging under load. If it reads 0V, your breadboard ground rail is disconnected.
  3. Sensor ASIC Failure: If wiring and power are confirmed, the sensor is likely dead. The HC-SR04 has no reverse-polarity protection; a momentary VCC/GND swap will fry the internal EM4205 or equivalent ASIC instantly.

Symptom 2: Jittery Readings or "ERROR: Distance out of bounds"

The sensor is returning data, but the numbers are jumping wildly (e.g., 15cm, 142cm, 16cm) or throwing out-of-bounds errors.

  1. Acoustic Cross-Talk: If you have multiple HC-SR04 sensors in the same room, their 40kHz waves will bounce off walls and trigger each other. Fix: Increase the delay() at the end of the loop to 100ms, or fire them sequentially rather than simultaneously.
  2. Soft or Angled Targets: Ultrasonic waves reflect poorly off fabric, foam, or surfaces angled greater than 15 degrees away from the sensor's centerline. The wave scatters, returning a weak or delayed echo. Fix: Attach a small piece of rigid, flat plastic to your target object.
  3. Electrical Noise on Echo Pin: Long jumper wires (over 20cm) act as antennas, picking up EMI from motors or servos. Fix: Keep wires short, or add a 10kΩ pull-down resistor between the Echo pin and GND to stabilize the logic LOW state.

Extending and Simplifying the Build

How to Simplify: The NewPing Library

If you are managing multiple sensors or need non-blocking code (so your Arduino can run motors while waiting for an echo), abandon raw pulseIn() and use the NewPing library. NewPing handles the 10µs trigger timing, timeout management, and median filtering (averaging 5 pings to eliminate jitter) natively via hardware timers.

How to Extend: 3.3V Logic Level Shifting

The HC-SR04 outputs a 5V HIGH signal on the Echo pin. If you migrate this exact circuit to an ESP32 or Raspberry Pi Pico, that 5V signal will feed directly into a 3.3V GPIO pin, eventually degrading or destroying the microcontroller's silicon.

To extend this build to 3.3V boards, you must step down the Echo voltage. The cheapest method is a resistor voltage divider (e.g., a 1kΩ resistor in series with the Echo pin, and a 2kΩ resistor to GND). For professional reliability, use a bidirectional logic level shifter (like the BSS138 MOSFET-based modules from Adafruit or SparkFun) to safely translate the 5V echo to 3.3V.

Frequently Asked Questions

Can I connect the HC-SR04 directly to an ESP32 or Raspberry Pi?

No, not safely. The HC-SR04 requires 5V to operate reliably and outputs a 5V logic HIGH on the Echo pin. ESP32 and Raspberry Pi GPIO pins are strictly 3.3V tolerant. While the ESP32 has some 5V-tolerant pins in specific deep-sleep states, standard operation requires a voltage divider or a dedicated logic level shifter on the Echo pin to prevent long-term hardware damage.

Why is my HC-SR04 reading jumping or jittering by 1-2 cm?

A 1-2 cm jitter is physically normal for the HC-SR04. The speed of sound is roughly 343 meters per second, meaning sound travels about 0.034 cm per microsecond. A timing variance of just 30 microseconds in the microcontroller's interrupt handling or the sensor's internal comparator will result in a 1 cm physical discrepancy. To smooth this out, take 5 rapid readings, discard the highest and lowest values, and average the remaining three (a technique known as median filtering).

What is the minimum delay between HC-SR04 sensor readings?

You must wait at least 50 to 60 milliseconds between consecutive trigger pulses. The HC-SR04's acoustic cone is roughly 15 degrees. If you trigger a second ping before the first ping's sound wave has completely dissipated or bounced back from distant objects (up to 400cm away, which takes ~23ms round-trip), the sensor will detect the tail-end of the previous echo and calculate a falsely short distance. A 60ms delay ensures the acoustic environment is quiet before the next measurement.