Project Difficulty: Beginner | Estimated Time: 20 Minutes
Target Board Variant: Arduino Uno R3 (ATmega328P, 5V Logic)
Core Components: HC-SR04 (Standard) or JSN-SR04T (Waterproof)

The Direct Answer: Wiring a Sonar Distance Sensor to Arduino

To wire a standard HC-SR04 sonar distance sensor to an Arduino Uno R3, connect the sensor's VCC pin to the Arduino's 5V pin, GND to GND, Trig to digital pin 9, and Echo to digital pin 10. The sensor operates by emitting a 40kHz ultrasonic burst when the Trig pin is held HIGH for 10 microseconds, then measuring the time it takes for the echo to return on the Echo pin. Because the speed of sound in air at 20°C is approximately 343 meters per second, you can calculate the distance by dividing the echo pulse duration by 58.2 (which accounts for the round-trip travel time in centimeters).

If you are using a 3.3V microcontroller like an ESP32 or Raspberry Pi Pico, you must use a voltage divider on the Echo pin to step the 5V return signal down to 3.3V, or you will permanently damage the GPIO pin. For the 5V Arduino Uno R3, direct wiring is safe.

Parts List & Specifications

Choosing the right module depends on your environment. The standard HC-SR04 is perfect for indoor robotics, while the JSN-SR04T is required for outdoor or high-humidity applications due to its sealed transducer.

Specification HC-SR04 (Standard) JSN-SR04T (Waterproof)
Operating Voltage 5V DC 3.3V - 5V DC
Measuring Range 2 cm to 400 cm 20 cm to 600 cm
Blind Zone (Minimum Distance) ~2 cm ~20 cm (Transducer ringing)
Beam Angle ~15 degrees ~10 degrees (More directional)
Working Current ~15 mA ~30 mA
Typical Price (2026) $1.50 - $2.50 $4.50 - $7.00

Step-by-Step Wiring & Pin Mapping

Follow these steps to ensure a solid physical connection. Loose Dupont wires are the number one cause of intermittent sensor failures on the bench.

  1. Power the Breadboard: Run a jumper from the Arduino Uno 5V pin to the red (+) rail, and from GND to the blue (-) rail.
  2. Seat the Sensor: If using the HC-SR04, straddle the 4-pin header across the breadboard center trench. If using the JSN-SR04T, plug its 3-pin or 4-pin connector into the board (note: some JSN variants combine Trig and Echo onto a single pin; check your specific silkscreen).
  3. Connect Power: Wire the sensor VCC to the red rail and GND to the blue rail.
  4. Wire the Signal Pins: Connect Trig to D9 and Echo to D10 using solid-core 22 AWG jumper wires for better contact than stranded Dupont cables.

Pin Mapping Table

Sensor Pin Arduino Uno R3 Pin Wire Color (Standard)
VCC5VRed
TrigDigital 9Yellow
EchoDigital 10Blue
GNDGNDBlack
Callout Tip: The 3.3V Logic Trap
The HC-SR04 Echo pin outputs a 5V HIGH signal when measuring. If you are adapting this exact wiring to an ESP32 or RP2040, you must build a voltage divider. Connect a 1kΩ resistor between the Echo pin and the microcontroller GPIO, and a 2kΩ resistor between that same GPIO and GND. This drops the 5V signal to a safe 3.33V.

Complete Arduino C++ Code with Error Handling

Raw pulseIn() readings are notoriously noisy due to acoustic multipath (sound bouncing off adjacent objects before returning). The code below targets the Arduino Uno R3 and implements a 5-sample median filter to reject outlier spikes, alongside strict timeout handling to prevent the microcontroller from hanging if the echo never returns.

// Target Board: Arduino Uno R3 (ATmega328P)
// Sonar Distance Sensor Arduino Implementation with Median Filter

#define TRIG_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 400 // Maximum distance in cm
#define TIMEOUT_US 25000 // 25ms timeout (covers >4 meters safely)
#define SAMPLE_SIZE 5

void setup() {
  Serial.begin(115200);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  
  // Ensure Trig starts LOW to prevent false triggers on boot
  digitalWrite(TRIG_PIN, LOW);
  delay(50);
  Serial.println("Sonar Sensor Initialized.");
}

void loop() {
  float distance = getMedianDistance();
  
  // Error Handling: Check for timeout or out-of-bounds
  if (distance < 0) {
    Serial.println("Error: pulseIn timeout. Check wiring or blind zone.");
  } else if (distance > MAX_DISTANCE) {
    Serial.println("Error: Out of range. Object beyond 400cm.");
  } else {
    Serial.print("Distance: ");
    Serial.print(distance, 1);
    Serial.println(" cm");
  }
  
  delay(100); // 10Hz polling rate (prevents echo overlap)
}

// Function to trigger sensor and read raw pulse
float readRawDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10); // Datasheet requires >= 10us pulse
  digitalWrite(TRIG_PIN, LOW);
  
  // Read the echo pulse with a timeout to prevent blocking
  unsigned long duration = pulseIn(ECHO_PIN, HIGH, TIMEOUT_US);
  
  if (duration == 0) {
    return -1.0; // Timeout occurred
  }
  
  // Calculate distance: duration (us) / 29.1 (us/cm) / 2 (round trip)
  // Simplified: duration / 58.2
  return duration / 58.2;
}

// Median filter to eliminate acoustic multipath spikes
float getMedianDistance() {
  float samples[SAMPLE_SIZE];
  int validSamples = 0;
  
  for (int i = 0; i < SAMPLE_SIZE; i++) {
    float raw = readRawDistance();
    if (raw > 0 && raw <= MAX_DISTANCE) {
      samples[validSamples] = raw;
      validSamples++;
    }
    delay(10); // Short delay between pings to let transducer settle
  }
  
  if (validSamples == 0) return -1.0; // All samples failed
  
  // Simple bubble sort for small array to find median
  for (int i = 0; i < validSamples - 1; i++) {
    for (int j = 0; j < validSamples - i - 1; j++) {
      if (samples[j] > samples[j+1]) {
        float temp = samples[j];
        samples[j] = samples[j+1];
        samples[j+1] = temp;
      }
    }
  }
  
  return samples[validSamples / 2];
}

Debugging: First Three Things to Check When It Fails

When your serial monitor outputs garbage or the sensor fails to trigger, follow this ranked decision path. These are the most common failure modes encountered on the workbench.

1. Symptom: Serial Monitor prints "Error: pulseIn timeout" or "Distance: 0 cm"

The Cause: The Arduino sent the 10µs trigger pulse, but the Echo pin never went HIGH. This means the sensor isn't firing, or the return signal isn't reaching the microcontroller.
The Fix: First, verify the common ground. If the sensor GND and Arduino GND are not tied together, the logic levels are floating. Second, swap the jumper wire on the Echo pin; internal breadboard breaks are common. Finally, if using a JSN-SR04T, some batches have a hardware quirk requiring a 10kΩ pull-up resistor between the Echo pin and 5V to stabilize the logic threshold.

2. Symptom: Erratic jumping values (e.g., 14cm → 85cm → 12cm)

The Cause: Acoustic multipath interference or 5V USB power ripple. Ultrasonic waves bounce off table legs, walls, and your hands, returning late and confusing the pulseIn() timer.
The Fix: Ensure the median filter code provided above is uploaded. Physically, mount the sensor on a non-resonant material (like foam tape) rather than hard-screwing it to a metal chassis, which causes the chassis itself to vibrate and create false echoes. For power ripple, solder a 100µF electrolytic capacitor across the sensor's VCC and GND pins.

3. Symptom: Reading is stuck at exactly "2.0 cm" or "20.0 cm"

The Cause: The object is inside the sensor's blind zone. The HC-SR04 cannot distinguish an echo that arrives while the transducer is still physically vibrating from the initial 40kHz burst (transducer ringing).
The Fix: Move the object further away. If your application requires measuring distances under 2cm, an ultrasonic sensor is the wrong tool; switch to an infrared Time-of-Flight sensor like the VL53L0X.

Extending and Simplifying the Build

Once you have the raw physics working, you can optimize your firmware or add hardware to improve accuracy.

How to Simplify: If you don't want to manage your own median filters and timeouts, use the community-standard NewPing Library. It handles the timer interrupts natively, freeing your Arduino Uno to run other tasks without blocking on pulseIn().

How to Extend (Temperature Compensation): The speed of sound is not a constant; it changes with ambient temperature. At 0°C, sound travels at 331 m/s, but at 30°C, it travels at 349 m/s. If your Arduino project operates in an unheated garage or outdoors, your distance calculations will drift by up to 5%. To fix this, wire a DS18B20 digital temperature sensor to your Arduino. Read the Celsius temperature, apply the formula speed_of_sound = 331.3 + (0.606 * temp_C), and dynamically update your divisor in the code. For a deeper look at the physics, refer to the Engineering ToolBox's speed of sound data.

Frequently Asked Questions

Can I use a sonar distance sensor Arduino setup with an ESP32?

Yes, but you cannot wire it directly. The ESP32 operates on 3.3V logic, and its GPIO pins are not 5V tolerant. The HC-SR04 outputs a 5V HIGH signal on the Echo pin. You must use a voltage divider (1kΩ and 2kΩ resistors) on the Echo line to step the voltage down to ~3.3V. Alternatively, purchase the HC-SR04P variant, which is specifically designed with a 3.3V logic output.

Why is my HC-SR04 sonar sensor reading stuck at 0?

A persistent 0 reading usually indicates a pulseIn timeout where the function gives up before the echo returns. Check that your Trig pin is actually outputting a 5V pulse using a multimeter. Also, ensure your USB power supply can deliver at least 500mA; the sensor draws a spike of current when firing the transducer, which can cause a brownout on cheap USB cables, resetting the sensor mid-ping.

What is the maximum accurate range for an Arduino sonar distance sensor?

While the HC-SR04 datasheet claims a 400cm (4 meter) range, practical bench testing shows reliable accuracy drops off significantly past 250cm. Beyond 2.5 meters, the 40kHz acoustic wave attenuates in the air, and the returning echo is too weak to reliably cross the sensor's internal comparator threshold. For distances beyond 3 meters, consider a LiDAR module like the TF-Luna.

How do I waterproof my sonar distance sensor for outdoor Arduino projects?

Do not attempt to coat a standard HC-SR04 in conformal coating or epoxy; this dampens the transducer's vibration and kills the acoustic output. Instead, use the JSN-SR04T module. It features a sealed, waterproof aluminum transducer head connected via a shielded cable. Note that the JSN-SR04T has a larger blind zone (20cm minimum) and a narrower beam angle, so plan your physical mounting accordingly.