The HC-SR04 is the standard 5V Arduino ultrasonic sensor for indoor distance measurement up to 400cm, while the JSN-SR04T is the waterproof alternative for outdoor or wet environments. Both operate on the same principle: the microcontroller sends a 10µs HIGH pulse to the Trigger pin, the module emits an eight-cycle 40kHz ultrasonic burst, and the Echo pin goes HIGH until the sound wave bounces back. You measure the Echo pulse width to calculate distance. If you are reading this because your sensor is stuck outputting 0 cm or throwing compilation errors, the fix is usually a logic-level mismatch or a blind-zone obstruction. Below is the exact hardware spec, wiring procedure, and fail-safe code to get your build running.
HC-SR04 vs JSN-SR04T vs RCWL-1601: Choosing the Right Module
Before you wire anything, you need to match the sensor to your environment. The classic HC-SR04 is cheap but fragile; the JSN-SR04T survives rain but has a massive blind zone; the RCWL-1601 solves the 3.3V logic problem that plagues ESP32 and Raspberry Pi Pico builders. Here is how they stack up on the bench.
| Feature | HC-SR04 (Standard) | JSN-SR04T (Waterproof) | RCWL-1601 (3.3V Compatible) |
|---|---|---|---|
| Operating Voltage | 5V DC (Strict) | 5V DC | 3.3V to 5V DC |
| Measuring Range | 2 cm – 400 cm | 20 cm – 450 cm | 2 cm – 450 cm |
| Blind Zone | < 2 cm | < 20 cm (due to cable ringing) | < 2 cm |
| Beam Angle | ~15° (Narrow cone) | ~30° (Wide cone) | ~15° (Narrow cone) |
| Logic Level | 5V TTL (Needs divider for 3.3V) | 5V TTL | 3.3V / 5V Tolerant |
| Typical Price (2026) | $1.50 – $2.00 | $4.50 – $6.00 | $2.00 – $3.00 |
Bench Note: If you are using an ESP32 or ESP8266, do not feed the HC-SR04 Echo pin directly into a 3.3V GPIO. The 5V return pulse will fry the input over time. Use the RCWL-1601 instead, or build a voltage divider (e.g., 10kΩ and 20kΩ) on the Echo line.
Hardware Spec Sheet and Pin Mapping
The code and wiring below specifically target the Arduino Uno R4 Minima and the classic Arduino Uno R3. Both boards operate at 5V logic, meaning you can wire the HC-SR04 directly without level shifters. The Uno R4's ARM Cortex-M4 processor handles the microsecond timing of the pulseIn() function with far less jitter than the older AVR ATmega328P, but the physical wiring remains identical.
Module Specifications
| Parameter | Value | Notes |
|---|---|---|
| Acoustic Frequency | 40 kHz | Inaudible to humans; highly directional. |
| Trigger Pulse | 10 µs TTL HIGH | Must be exact; shorter pulses won't fire the burst. |
| Quiescent Current | 2 mA | Idle state before trigger. |
| Active Current | 15 mA – 20 mA | Spikes during the 40kHz acoustic burst. |
| Resolution | ~3 mm (0.3 cm) | Limited by the speed of sound and MCU timer granularity. |
Pin Mapping (Arduino Uno R3 / R4 Minima)
| HC-SR04 Pin | Arduino Pin | Wire Color (Standard) | Function |
|---|---|---|---|
| VCC | 5V | Red | Power supply (Do not use 3.3V out) |
| TRIG | D9 | Yellow | Receives 10µs start pulse from MCU |
| ECHO | D10 | Blue | Outputs HIGH pulse proportional to distance |
| GND | GND | Black | Common ground reference |
Step-by-Step Wiring and Fail-Safe NewPing Code
Do not use the default Arduino pulseIn() function for ultrasonic sensors. It blocks the main loop while waiting for the echo, which can stall your entire project for up to 30 milliseconds if the sound wave scatters and never returns. Instead, we use the NewPing library by Tim Eckel, which handles timer interrupts and non-blocking pings.
Wiring Steps
- Power Down: Disconnect the USB cable from your Arduino Uno before wiring.
- Mount the Sensor: Insert the HC-SR04 into a breadboard. Ensure the silver mesh transducers are facing forward, unobstructed by the breadboard's plastic lip.
- Connect Power: Run a jumper from the Arduino 5V pin to the HC-SR04 VCC. Connect Arduino GND to HC-SR04 GND. Warning: Reversing VCC and GND on cheap HC-SR04 clones will instantly destroy the onboard MAX232 inverter chip.
- Connect Signal: Wire HC-SR04 TRIG to Arduino Digital Pin 9. Wire HC-SR04 ECHO to Arduino Digital Pin 10.
- Verify: Double-check that the Echo pin is on D10 and Trigger is on D9 before applying power.
Compilable Code with Error Handling
Install the NewPing library via the Arduino IDE Library Manager (Sketch > Include Library > Manage Libraries > search "NewPing"). This code targets the Arduino Uno R3/R4 and includes median filtering to discard acoustic echoes and false zero-reads.
#include <NewPing.h>
// --- PIN DEFINITIONS ---
#define TRIGGER_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 400 // Maximum distance we want to ping (in cm)
#define PING_INTERVAL 35 // Milliseconds between sensor pings (min 29ms)
#define ITERATIONS 5 // Number of pings for median filtering
// Initialize NewPing object
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
unsigned long lastPingTime = 0;
void setup() {
Serial.begin(115200);
// Wait for serial port to connect (useful for Leonardo/Micro, harmless on Uno)
while (!Serial && millis() < 3000);
Serial.println("HC-SR04 Ultrasonic Sensor Initialized.");
}
void loop() {
// Non-blocking delay to respect the 35ms ping interval
if (millis() - lastPingTime >= PING_INTERVAL) {
lastPingTime = millis();
// Get median distance in cm. ping_median() handles the iterations.
unsigned int uS = sonar.ping_median(ITERATIONS);
// Convert microseconds to centimeters
float distance_cm = sonar.convert_cm(uS);
// Error Handling: NewPing returns 0 if no echo is received within MAX_DISTANCE
if (distance_cm == 0) {
Serial.println("Error: Out of range or acoustic scatter (0 cm).");
} else if (distance_cm < 2.0) {
Serial.println("Warning: Inside sensor blind zone (< 2 cm).");
} else {
Serial.print("Distance: ");
Serial.print(distance_cm, 1);
Serial.println(" cm");
}
}
// You can run other non-blocking code here
}
Debugging: Fixing '0 cm' Reads and Compilation Errors
Ultrasonic sensors are notorious for failing silently or throwing cryptic errors when moved from a breadboard prototype to a soldered perfboard. If your build fails, here are the first three things to check:
- Power Starvation (Brownout): The HC-SR04 draws up to 20mA during the acoustic burst. If you are powering the Arduino via a weak USB hub and sharing the 5V rail with a servo or OLED display, the voltage will dip below 4.5V, causing the sensor's internal oscillator to fail. Measure the VCC pin with a multimeter during a ping.
- Trigger and Echo Swapped: The silkscreen on cheap clones is sometimes printed backward. If you get constant 0 cm reads, physically swap the yellow and blue wires on D9 and D10.
- Blind Zone Obstruction: The HC-SR04 cannot see anything closer than 2 cm. If your sensor is mounted flush inside a 3D-printed enclosure and the housing lip is 1 cm away from the transducers, the sound will reflect off the housing immediately, confusing the timing logic.
Common Error Strings and Ranked Causes
Error 1: 'NewPing' does not name a type
This is a compilation error. It means the IDE cannot find the library.
- Cause A: You downloaded the ZIP from the internet but didn't extract it into the
Documents/Arduino/librariesfolder. Fix: Use the IDE Library Manager to install it cleanly. - Cause B: You named your sketch file
NewPing.ino. The IDE gets confused when the sketch name matches the library name. Rename your sketch file.
Error 2: Runtime output is constantly Distance: 0 cm
The sensor is firing, but the Echo pin never goes HIGH, or it goes HIGH for 0 microseconds.
- Cause A: 5V Logic Mismatch. If you accidentally wired VCC to the 3.3V pin on the Arduino, the module lacks the voltage to drive the 40kHz transducers.
- Cause B: Acoustic Scatter. The sound wave is hitting a soft, angled, or sound-absorbing surface (like a curtain or foam) and never bouncing back to the receiver.
- Cause C: Dead Module. The MAX232 voltage inverter chip on the HC-SR04 is fried. Swap in a known-good module to verify.
Extending and Simplifying the Build
Once you have stable distance readings, you will likely need to adapt the sensor for real-world physics or simplify the hardware for production.
How to Extend: Temperature Compensation
The speed of sound in air is not a constant 343 m/s; it changes with temperature. According to acoustic physics calculators, the speed of sound increases by roughly 0.6 m/s for every 1°C rise in temperature. If your Arduino project operates in an unheated garage (5°C) versus a warm living room (25°C), your distance calculations will drift by over 3%.
To fix this, add a DS18B20 waterproof temperature sensor to your build. Read the ambient temperature in Celsius, calculate the current speed of sound (v = 331.4 + (0.6 * tempC)), and manually calculate the distance using distance = (uS / 2) * (v / 10000) instead of relying on NewPing's hardcoded convert_cm() function.
How to Simplify: 3-Pin Mode and Sensor Swaps
If you are short on GPIO pins, the NewPing library supports a 3-pin mode. By connecting the Trigger and Echo pins together through a 2.2kΩ resistor, you can control the HC-SR04 using a single Arduino pin. Note that the JSN-SR04T waterproof version is actually available in a native 3-pin hardware variant (VCC, GND, SIG), which eliminates the need for the resistor entirely.
However, if you find that ultrasonic sensors are fundamentally failing your use case—perhaps because you need to measure through a narrow tube, or you need millimeter precision—simplify your life by abandoning acoustics altogether. Swap the HC-SR04 for a VL53L1X Time-of-Flight (ToF) laser sensor. It uses I2C (only 2 GPIO pins), ignores temperature changes, and provides millimeter accuracy up to 4 meters, completely eliminating the acoustic scatter and blind-zone headaches inherent to ultrasonic modules.
For further reading on Arduino timing and interrupt handling, refer to the official Arduino documentation. Always verify your specific module's datasheet, as clone manufacturers frequently swap internal components without updating the silkscreen.






