Ultrasonic Sensor (HC-SR04)

Details

HC-SR04 Ultrasonic Distance Sensor — Trigger/Echo, 5 V

Summary

The HC-SR04 Ultrasonic Sensor measures distance by emitting a 40 kHz pulse and timing the echo return. It provides separate TRIG and ECHO pins and works best from ~2 cm to ~400 cm.

Note: The module is a 5 V device. When using 3.3 V MCUs (e.g., Raspberry Pi, ESP32), add a voltage divider or level shifter on ECHO.

Pins & Wiring
  • VCC: 5 V
  • GND: Ground
  • TRIG: Input — 10 µs HIGH to start a burst
  • ECHO: Output — HIGH for echo time (µs)

Tip: Keep sensors away from soft/angled surfaces and from each other to avoid cross-talk.

Wiring Diagram

Basic hookup to a microcontroller or Raspberry Pi (with divider on ECHO for 3.3 V logic).

HC-SR04 wiring: VCC 5V, GND, TRIG to MCU pin, ECHO to MCU pin (use divider on 3.3 V)
Arduino Code

Direct Timing (no library)

// HC-SR04 — direct timing
const int TRIG=9, ECHO=8;
void setup(){
  Serial.begin(115200);
  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
}
long readUS(){
  digitalWrite(TRIG, LOW); delayMicroseconds(3);
  digitalWrite(TRIG, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  return pulseIn(ECHO, HIGH, 30000UL); // timeout 30 ms (~5 m)
}
void loop(){
  long us = readUS();
  if(us==0){ Serial.println("No echo"); }
  else{
    float cm = us / 58.0;      // cm ≈ us/58
    float inches = us / 148.0; // in ≈ us/148
    Serial.print(cm,1); Serial.println(" cm");
  }
  delay(200);
}

Median Filter (smoother readings)

// Take N samples and return median (reduces outliers)
const int N=7;
long samples[N];
long medianUS(){
  for(int i=0;i<N;i++){
    samples[i]=pulseIn(8, HIGH, 30000UL); // after a trigger as above
  }
  // simple insertion sort
  for(int i=1;i<N;i++){ long k=samples[i]; int j=i-1; while(j>=0 && samples[j]>k){ samples[j+1]=samples[j]; j--; } samples[j+1]=k; }
  return samples[N/2];
}

Tip: For multiple sensors, trigger them sequentially with a small delay to avoid cross-interference.

Raspberry Pi

Use a voltage divider on ECHO (e.g., 1 kΩ : 2 kΩ) to bring 5 V down to 3.3 V.

RPi.GPIO: Measure Distance

# sudo apt install python3-rpi.gpio
import time, RPi.GPIO as GPIO
TRIG, ECHO = 23, 24   # BCM pins
GPIO.setmode(GPIO.BCM)
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)

def ping_us():
    GPIO.output(TRIG, False); time.sleep(0.000003)
    GPIO.output(TRIG, True);  time.sleep(0.000010)
    GPIO.output(TRIG, False)
    t0 = time.time()
    while GPIO.input(ECHO)==0:
        if time.time()-t0>0.03: return 0
    start = time.time()
    while GPIO.input(ECHO)==1:
        if time.time()-start>0.03: return 0
    end = time.time()
    return (end-start)*1e6

try:
    while True:
        us = ping_us()
        if us==0: print("No echo")
        else: print(f"{us/58.0:.1f} cm")
        time.sleep(0.2)
finally:
    GPIO.cleanup()

pigpio (more precise timing)

# sudo apt install pigpio python3-pigpio
# sudo systemctl start pigpiod
import time, pigpio
TRIG, ECHO = 23, 24
pi = pigpio.pi()
pi.set_mode(TRIG, pigpio.OUTPUT)
pi.set_mode(ECHO, pigpio.INPUT)

def ping_us():
    pi.gpio_trigger(TRIG, 10, 1)  # 10 µs HIGH
    t0 = time.time()
    while pi.read(ECHO)==0:
        if time.time()-t0>0.03: return 0
    start = time.time()
    while pi.read(ECHO)==1:
        if time.time()-start>0.03: return 0
    end = time.time()
    return (end-start)*1e6

try:
    while True:
        us = ping_us()
        print("No echo" if us==0 else f"{us/58.0:.1f} cm")
        time.sleep(0.2)
finally:
    pi.stop()
ESP Coding

ESP32/ESP8266 (Arduino core): TRIG can be 3.3 V. ECHO outputs 5 V — use a divider (e.g., 1 kΩ to GND, 2 kΩ to ECHO) or a logic shifter before connecting to the ESP pin.

ESP32: Read Distance

#include <Arduino.h>
const int TRIG=5, ECHO=18;  // ECHO must be level-shifted to 3.3V

long pingUS(){
  digitalWrite(TRIG, LOW); delayMicroseconds(3);
  digitalWrite(TRIG, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  return pulseIn(ECHO, HIGH, 30000UL); // ~5 m timeout
}
void setup(){
  Serial.begin(115200);
  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
}
void loop(){
  long us = pingUS();
  if(us==0) Serial.println("No echo");
  else      Serial.printf("%.1f cm\n", us/58.0);
  delay(200);
}

ESP8266: Read Distance

#include <Arduino.h>
const int TRIG=D5, ECHO=D6; // Level-shift ECHO to 3.3V

long pingUS(){
  digitalWrite(TRIG, LOW); delayMicroseconds(3);
  digitalWrite(TRIG, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  return pulseIn(ECHO, HIGH, 30000UL);
}
void setup(){
  Serial.begin(115200);
  pinMode(TRIG, OUTPUT); pinMode(ECHO, INPUT);
}
void loop(){
  long us = pingUS();
  Serial.println(us ? String(us/58.0,1) + " cm" : "No echo");
  delay(200);
}

ESP-IDF: Use gpio + rmt (receive) or a high-resolution timer to timestamp edges on ECHO; trigger using a 10 µs pulse on TRIG.

Drivers

The HC-SR04 itself needs no drivers. If you use a USB-serial adapter for logging/control, you may need:

Resources
Specifications
Model HC-SR04 Ultrasonic Sensor
Operating Voltage 5 V
Current ~15 mA (typ.)
Frequency 40 kHz
Range ~2 cm to ~400 cm (best ~3–300 cm)
Resolution ~3 mm (ideal conditions)
FOV ~15° cone (approx.)
Interface TRIG (input), ECHO (output, 5 V TTL)
Dimensions ~45 × 20 × 15 mm

Note: Environmental factors (temperature, airflow, surface angle/material) affect readings.

FAQ
“No echo” / zero readings
Check wiring and 5 V supply, ensure the target is within range and not angled. Avoid soft/absorbent materials.
Unstable values
Take multiple samples and median/average; isolate vibrations; power from a stable 5 V; avoid cross-talk between sensors.
Using with Raspberry Pi 3.3 V GPIO
Keep TRIG as 3.3 V-tolerant input to the sensor (OK), but level-shift ECHO down to 3.3 V using a divider or logic shifter.
Safety & Compliance

Important Notice For educational, prototype, experimental, laboratory and R&D use only. (non-RoHS)

WEEE

Not subject to WEEE marking; obligations apply to final equipment.

Manufacturer

Little Muffins Things Limited
166 River Heights, 90 High Street
London E15 2GQ
littlemuffinsthings.com

EU Responsible Person

eucomply OU
Parnu mnt. 139b–141
13117 Tallinn, Estonia
hello@eucompliancepartner.com