To code an ultrasonic sensor with an Arduino Uno R3, wire the HC-SR04 Trig pin to D9 and Echo pin to D10, power it with 5V, and use the NewPing library to handle timing interrupts and prevent the microcontroller from blocking. This guide provides the exact pinout, compilable code, and bench-tested debugging steps for when your serial monitor spits out 0 cm or erratic data.
NewPing library rather than the native pulseIn() function, as it prevents the CPU from hanging during timeout events and natively handles out-of-range errors.
Project Overview & Difficulty Rating
| Parameter | Value | Notes |
|---|---|---|
| Operating Voltage | 5V DC | Do not power directly from 3.3V pins |
| Operating Current | 15 mA (active) | Quiescent current is < 2 mA |
| Measuring Range | 2 cm to 400 cm | Blind zone is 0-2 cm |
| Trigger Pulse | 10 µs TTL | Minimum HIGH time required |
| Echo Signal | 5V TTL Pulse | Width proportional to distance |
Parts List
- Microcontroller: Arduino Uno R3 (ATmega328P) or Arduino Nano v3 (ATmega328P)
- Sensor: HC-SR04 4-pin Ultrasonic Module (5V logic variant)
- Wiring: 4x Male-to-Male or Male-to-Female jumper wires (22 AWG)
- Breadboard: Standard 830-point solderless breadboard
- Library:
NewPing(Install via Arduino Library Manager)
HC-SR04 Pin Mapping & Wiring Steps
The HC-SR04 uses two digital pins for communication: one to send the ultrasonic burst (Trigger) and one to listen for the return echo (Echo). Because the Echo pin outputs a 5V HIGH signal, it is strictly compatible with 5V-tolerant microcontrollers like the Arduino Uno.
| HC-SR04 Pin | Arduino Uno R3 Pin | Wire Color (Standard) |
|---|---|---|
| VCC | 5V | Red |
| Trig | Digital 9 (D9) | Yellow |
| Echo | Digital 10 (D10) | Green |
| GND | GND | Black |
Wiring Procedure
- De-energize the board: Disconnect the Arduino from USB or external power before wiring.
- Connect Power: Route the red jumper from the Arduino
5Vpin to the HC-SR04VCCpin. Route the black jumper fromGNDtoGND. - Connect Trigger: Connect the yellow jumper from Arduino
D9to the sensorTrigpin. - Connect Echo: Connect the green jumper from Arduino
D10to the sensorEchopin. - Verify: Double-check that VCC and GND are not swapped. Reversing polarity on the HC-SR04 will instantly destroy the onboard MAX232 equivalent driver chip.
Complete Arduino Code for Ultrasonic Sensor
This code targets the Arduino Uno R3 and Nano v3 (AVR architecture). It uses the NewPing library, which is vastly superior to the native Arduino pulseIn() function because it uses timer interrupts and doesn't freeze your sketch if the echo never returns.
#include <NewPing.h>
// Pin Definitions - Change these if your wiring differs
#define TRIGGER_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in cm)
// Initialize NewPing object
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
void setup() {
// Start serial communication at 9600 baud
Serial.begin(9600);
Serial.println("HC-SR04 Ultrasonic Sensor Initialized.");
}
void loop() {
// ping_cm() returns the distance in centimeters, or 0 if out of range
unsigned int distance = sonar.ping_cm();
// Error handling for out-of-range or timeout
if (distance == 0) {
Serial.println("Error: Out of range, object too close (<2cm), or no echo received.");
} else {
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
}
// Wait 50ms between pings (29ms is the minimum recommended delay)
delay(50);
}
Advanced: Temperature Compensation
The speed of sound changes with air temperature. The NewPing library assumes 20°C (343 m/s). If your project operates in extreme environments, use sonar.ping_median(5) to get the raw microsecond time, then apply the formula: distance_cm = (ping_time / 2) * (331.3 + 0.606 * temp_C) / 10000.
Debugging: Fixing '0 cm' and Erratic Readings
When your serial monitor outputs Error: Out of range... or constantly prints 0 cm, do not immediately assume the sensor is dead. Follow these first three diagnostic steps to isolate the fault.
The First 3 Things to Check When It Fails
- Measure VCC at the Sensor Pins: Use a digital multimeter (DMM) to probe the
VCCandGNDpins directly on the HC-SR04 header. You must read between 4.8V and 5.2V. If you read 3.3V or 0V, your breadboard power rail is broken or you are plugged into the wrong Arduino pin. - Verify the Trigger Pulse Width: The HC-SR04 requires a minimum 10 µs HIGH pulse on the Trigger pin. If your code uses a custom digitalWrite sequence without
delayMicroseconds(10), the sensor will never fire.NewPinghandles this automatically, but custom code often misses it. - Check for Acoustic Blind Spots: The HC-SR04 has a physical blind zone of 2 cm. If an object is pressed directly against the metal mesh of the transducers, the echo returns before the receiver circuit finishes its initialization, resulting in a
0 cmreading.
Ranked Causes for Exact Error Strings
| Serial Monitor Output | Most Likely Cause | Fix |
|---|---|---|
0 cm continuously | Power rail disconnected or Trig pin wired to wrong D-pin. | Verify DMM reads 5V at sensor. Check #define TRIGGER_PIN matches physical wire. |
200 cm (or MAX_DISTANCE) when object is close | Echo pin wire disconnected or broken internally. | Swap the Echo jumper wire. Measure Echo pin with DMM; it should pulse 5V when triggered. |
| Erratic jumping (e.g., 14cm, 85cm, 15cm) | Sound reflecting off soft/angled surfaces, or 5V ripple on power line. | Aim at a flat, hard surface. Add a 100µF decoupling capacitor across VCC and GND on the breadboard. |
Extending and Simplifying the Build
How to Simplify the Build (Zero Dependencies)
If you cannot use external libraries or are coding on a constrained platform without the Arduino Library Manager, you can simplify the build by using the native pulseIn() function. However, be aware that pulseIn() is a blocking function. If the sensor is pointed at an open window and no echo returns, the Arduino will freeze for up to 1 second (the default timeout) before moving to the next line of code. For simple LED-proximity alarms, this is acceptable; for motor control or multi-sensor arrays, it will cause system jitter.
How to Extend the Build
- Multi-Sensor Arrays: The
NewPinglibrary supports up to 15 sensors. You can trigger them sequentially using theping_timer()method, which uses hardware timers to ping sensors in the background without blocking the mainloop(). - Add an I2C OLED Display: Wire an SSD1306 128x64 OLED display to the A4 (SDA) and A5 (SCL) pins. Use the
Adafruit_SSD1306library to render the distance visually, turning the project into a standalone digital tape measure. - Implement a Moving Average Filter: Ultrasonic sensors suffer from acoustic jitter. Store the last 5 readings in an array, sort them, and return the median value to eliminate outlier spikes caused by stray acoustic reflections.
Frequently Asked Questions
Can I code an ultrasonic sensor with Arduino without the NewPing library?
Yes. You can write raw C++ using digitalWrite() to pulse the Trigger pin HIGH for 10 microseconds, then use pulseIn(ECHO_PIN, HIGH) to measure the return time. Divide the resulting microseconds by 58 to get centimeters. While this requires no external libraries, it blocks the CPU during the measurement and lacks built-in timeout handling, making it unsuitable for real-time robotics applications. For a detailed breakdown of the native timing, refer to the SparkFun HC-SR04 Hookup Guide.
Why does my HC-SR04 code ultrasonic sensor Arduino project read 0 cm constantly?
A constant 0 cm reading usually indicates a hardware fault, not a code error. The most common culprits are: (1) The 5V power rail on your breadboard is split and not jumpered, leaving the sensor unpowered. (2) The Trigger and Echo pins are swapped in your physical wiring but not in your code. (3) The object is inside the 2 cm acoustic blind zone. Always verify power with a multimeter before rewriting your code.
How do I wire an HC-SR04 to a 3.3V ESP32 instead of a 5V Arduino?
The HC-SR04 requires 5V to operate reliably, so you must power its VCC pin from the ESP32's VIN or 5V pin (if available via USB). However, the Echo pin outputs a 5V HIGH signal, which will fry the ESP32's 3.3V GPIO. You must build a voltage divider on the Echo line: connect a 1kΩ resistor between the Echo pin and the ESP32 GPIO, and a 2kΩ resistor between that same GPIO and GND. This drops the 5V pulse down to a safe ~3.3V.
What is the maximum reliable range when coding an ultrasonic sensor?
While the HC-SR04 datasheet claims a 400 cm (4 meter) maximum range, real-world bench testing shows reliable accuracy drops off significantly past 250 cm. At distances beyond 3 meters, the 40 kHz acoustic wave attenuates in the air, and the return echo is often too weak for the onboard comparator to trigger cleanly. For reliable industrial or robotic applications, cap your MAX_DISTANCE variable at 200 cm to prevent false timeouts.






