The Verdict: Which Ultrasonic Sensor Should You Actually Buy?
Before wiring anything, confirm you have the right module for your environment. The market is flooded with clones, and picking the wrong variant is the number one cause of project failure. Use this decision matrix to select your part:| Sensor Model | Logic Level | Range & Blind Spot | Environment | When to Choose (Decision Path) |
|---|---|---|---|---|
| HC-SR04 (Classic) | 5V Only | 2cm - 400cm (2cm blind) | Indoor, Dry | Choose if using a 5V Arduino Uno/Mega and budget is strictly under $2. |
| HC-SR04+ | 3.3V to 5V | 2cm - 450cm (2cm blind) | Indoor, Dry | Default Pick: Choose for ESP32, Pi Pico, or any 3.3V logic board. Prevents GPIO damage. |
| JSN-SR04T | 5V | 20cm - 600cm (20cm blind) | Outdoor, Wet, Dusty | Choose for water tank level monitoring or outdoor robotics (IP67 sealed transducer). |
| A02YYUW (UART) | 3.3V to 5V | 3cm - 450cm (No blind spot) | Indoor/Outdoor | Choose if you need millimeter precision, no acoustic crosstalk, and have a spare UART port. |
HC-SR04 Spec Sheet and Pin Mapping
The HC-SR04 works by sending a 40kHz ultrasonic burst and measuring the time it takes for the echo to return. Sound travels at roughly 343 meters per second in air at 20°C. The module calculates distance using the formula:Distance = (Time × Speed of Sound) / 2.
Parts List (Exact Variants)
- Microcontroller: Arduino Uno R3 (ATmega328P, 5V logic) or Arduino Uno R4 Minima.
- Sensor: HC-SR04 (5V) or HC-SR04+ (3.3V/5V compatible).
- Resistors: 1x 10kΩ and 1x 20kΩ (Only required if using a classic 5V HC-SR04 with a 3.3V ESP32/Pico to divide the Echo pin voltage).
- Wiring: 4x male-to-female or male-to-male Dupont jumper wires.
Pin Mapping Table
| HC-SR04 Pin | Arduino Uno R3 Pin | Function & Electrical Notes |
|---|---|---|
| VCC | 5V | Requires 5V. Running the classic HC-SR04 on 3.3V will cause intermittent trigger failures. |
| TRIG | Digital Pin 9 | Input. Requires a 10µs HIGH pulse to initiate the ultrasonic burst. |
| ECHO | Digital Pin 10 | Output. Goes HIGH for the duration of the sound travel time. Warning: Outputs 5V on the classic model. |
| GND | GND | Common ground. Must share ground with the microcontroller. |
Wiring and Compilable Code (Arduino Uno R3 Target)
Difficulty Rating: Beginner (15 minutes)
Target Board: Arduino Uno R3 / Nano (ATmega328P, 5V AVR)
Step-by-Step Wiring
- Connect the HC-SR04 VCC pin to the Arduino 5V pin.
- Connect the HC-SR04 GND pin to the Arduino GND pin.
- Connect the TRIG pin to Arduino Digital Pin 9.
- Connect the ECHO pin to Arduino Digital Pin 10.
- Double-check that no bare wire strands are bridging the VCC and TRIG pins on the sensor header; this is a common cause of dead-on-arrival sensors.
Hang-Proof Code Implementation
The standard pulseIn() function will hang your Arduino indefinitely if the HC-SR04 fails to pull the Echo pin low (a known hardware bug when the sensor receives no echo). We use the NewPing library, which utilizes hardware timer interrupts to enforce a strict timeout, preventing the sketch from freezing.
Prerequisite: Install the "NewPing" library via the Arduino IDE Library Manager (Tools > Manage Libraries).
#include <NewPing.h>
// --- PIN DEFINITIONS ---
#define TRIGGER_PIN 9 // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN 10 // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 400 // Maximum distance we want to ping (in cm). 400cm is the sensor max.
// Initialize the NewPing object
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
// Variables for error handling and smoothing
unsigned int lastValidDistance = 0;
unsigned int errorCount = 0;
void setup() {
Serial.begin(115200);
Serial.println("HC-SR04 Ultrasonic Sensor Initialized.");
Serial.println("Target Board: Arduino Uno R3 (5V Logic)");
}
void loop() {
// ping_cm() returns 0 if out of range or if no echo is received within MAX_DISTANCE
unsigned int distance = sonar.ping_cm();
// --- ERROR HANDLING & STATE MACHINE ---
if (distance == 0) {
errorCount++;
Serial.print("Error: Out of range or no echo (0 cm). Consecutive failures: ");
Serial.println(errorCount);
// Trigger a hardware reset or safe state if sensor is completely unresponsive
if (errorCount >= 10) {
Serial.println("CRITICAL: Sensor unresponsive. Check 5V supply and wiring.");
// In a real robot, you would trigger a motor stop or watchdog reset here.
}
} else {
errorCount = 0; // Reset error counter on successful read
lastValidDistance = distance;
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
}
// The HC-SR04 requires a brief recovery time between pings to avoid acoustic crosstalk
delay(35);
}
Debugging: Why Your HC-SR04 Reads "0 cm" or Hangs
When the serial monitor outputsError: Out of range or no echo (0 cm) continuously, or if your board completely freezes (if you ignored the NewPing warning and used raw pulseIn), follow this diagnostic path.
The First Three Things to Check
- VCC Voltage Drop: The HC-SR04 is highly sensitive to undervoltage. If you are powering it from the Arduino's 3.3V pin (which you shouldn't on the classic model), or if your USB cable has high resistance causing the 5V rail to sag to 4.2V under load, the internal oscillator will fail to generate the 40kHz burst. Fix: Measure VCC at the sensor header with a multimeter. It must be >4.8V.
- Logic Level Mismatch (The Echo Pin Fry): If you are using an ESP32 or Raspberry Pi Pico, the classic HC-SR04 outputs a 5V HIGH signal on the Echo pin. Feeding 5V into a 3.3V GPIO will permanently damage the microcontroller's pin, causing it to read floating or dead. Fix: Use the HC-SR04+ variant, or build a voltage divider (10kΩ to GND, 20kΩ in series with Echo) to drop 5V to ~3.3V.
- Acoustic Absorption and Blind Spots: The HC-SR04 has a hard physical blind spot of 2cm. Furthermore, 40kHz ultrasound is easily absorbed by soft materials (foam, heavy curtains, clothing) and reflected poorly by angled surfaces. Fix: Test the sensor against a flat, hard surface (like a wooden board or textbook) at a distance of 10cm to 50cm to verify baseline functionality.
Ranked Causes for Intermittent "0 cm" Errors
| Rank | Symptom | Root Cause | Solution |
|---|---|---|---|
| 1 | Reads 0cm randomly, then recovers | Acoustic crosstalk from a nearby sensor or bouncing off angled walls. | Increase delay() between pings to 50ms. Add physical acoustic baffles around the transducers. |
| 2 | Reads 0cm when object is < 2cm away | Hardware blind spot. The echo returns before the transmitter stops ringing. | Physically move the sensor back, or switch to a Time-of-Flight laser sensor (VL53L0X). |
| 3 | Reads 0cm, sensor gets hot | Short circuit between VCC and TRIG, or reversed VCC/GND. | Discard the sensor. The internal MAX232 equivalent IC is burned out. |
Extending and Simplifying the Build
How to Extend the Build
- Add a Median Filter: Ultrasonic sensors are noisy. Instead of taking a single
ping_cm()reading, usesonar.ping_median(iterations)to fire 5 to 9 pings and return the mathematical median. This eliminates acoustic outliers caused by stray reflections. - Temperature Compensation: Wire a DS18B20 or BME280 sensor. Read the ambient temperature in Celsius, calculate the exact speed of sound using
v = 331.4 + (0.606 * temp), and manually calculate the distance usingsonar.ping()(which returns raw microseconds) instead ofping_cm(). - I2C OLED Display: Add an SSD1306 128x64 OLED display via I2C (SDA to A4, SCL to A5 on the Uno R3) using the
Adafruit_SSD1306library to create a standalone digital tape measure.
How to Simplify (or When to Abandon the HC-SR04)
If your application requires measuring distances under 2cm, detecting transparent objects (like glass), or operating in high-noise environments, the HC-SR04 is the wrong tool. Simplify your hardware stack and eliminate the acoustic debugging headaches by switching to a VL53L0X Time-of-Flight (ToF) Laser Sensor. It uses I2C, has a 30mm to 2000mm range, ignores acoustic crosstalk, and costs roughly $4.00. For liquid level sensing in tanks, abandon the HC-SR04 entirely and use the waterproof JSN-SR04T or a non-contact radar level transmitter.






