Ultrasonic Distance Measurement with Arduino
An ultrasonic sensor is a device used to measure the distance to an object or obstacle using sound waves. It operates by emitting high-frequency sound waves (ultrasound) and measuring the time it takes for the echo to return after reflecting off an object.The Arduino microcontroller sends a signal from a digital pin (usually connected to the Trig pin on the sensor) to initiate the transmission of ultrasonic waves into the environment. When these waves encounter an obstacle, they reflect back toward the sensor and are received by the Echo pin.
Distance = (Time × Speed of Sound) / 2
We divide by 2 because the measured time includes the trip to the object and the return trip (round-trip time).
Key Points:
- Trig pin: Used to trigger the ultrasonic pulse.
- Echo pin: Receives the reflected pulse.
- Typical speed of sound: ~340 m/s = 0.034 cm/µs
- Common sensor model: HC-SR04
The task
In this exercise, we will use an ultrasonic sensor (such as the HC-SR04) to measure the distance to an object. The Arduino sends a signal to the sensor to trigger the emission of ultrasonic waves. These waves travel through the air, bounce off an object, and return to the sensor. By measuring the time it takes for the echo to return, we can calculate how far the object is from the sensor.The following Arduino sketch demonstrates how to control the sensor, calculate the distance, and display the result in the Serial Monitor.
The wires diagram
We use two digital I/O pins for the ultrasonic sensor’s trigger and echo. An orange wire connects Arduino digital pin 9 to the sensor’s Trigger pin, and a yellow wire connects Arduino digital pin 10 to the sensor’s Echo pin.
Finally, tie the Arduino’s GND to the sensor’s GND pin to complete the circuit.
How an ultrasonic sensor measures distance - more details
The HC-SR04 uses ultrasound to measure the distance to an obstacle in front of it, sends out an ultrasonic signal (a high-frequency wave of about 40KHz) and waits for it to return, measuring the return time.Based on the time that has passed between sending and receiving the signal - it calculates the distance.
Step by Step: How HC-SR04 Measures Duration
1. Arduino sends the TRIGGER signal
On the trigger pin (usually pin 9), Arduino sends:
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // 10 microseconds
digitalWrite(trigPin, LOW);
This tells the sensor: "Send out an ultrasonic pulse!"
2. The sensor automatically emits 8 ultrasonic waves (at 40 kHz)
This lasts very briefly (less than 1 ms). At the same time, HC-SR04 activates the echo pin.
3. Echo pin goes HIGH
When the sensor sends the pulse, the echo pin becomes HIGH. It stays HIGH while the ultrasonic signal is traveling.
4. Sensor detects the returning wave
When the ultrasonic wave reflects from an object and returns, the echo pin goes LOW.
That means:
- Echo pin = HIGH → signal is on its way.
- Echo pin = LOW → signal returned, measurement complete.
How duration is measured
Arduino uses the pulseIn() function to measure how long the echo pin was HIGH, in microseconds (μs):
long duration = pulseIn(echoPin, HIGH);
Then the distance is calculated with:
float distance = duration * 0.034 / 2;
Why * 0.034 / 2?
Speed of sound: 340 m/s = 0.034 cm/μs.
We divide by 2 because the signal travels to the object and back.
| Time | Event |
|---|---|
| t0 | Arduino sends a 10μs signal to the TRIG pin |
| t1 | HC-SR04 sends ultrasonic wave and sets ECHO to HIGH |
| t2 | Wave is reflected and received, ECHO goes LOW |
| t2 - t1 | Duration of the pulse in microseconds (μs) |
Ultrasonic Distance Measurement with Arduino-code
// C++ code
//
inttrigerPin = 9; // Pin connected to the Trig pin of the ultrasonic sensorintechoPin = 10; // Pin connected to the Echo pin of the ultrasonic sensorlongdur; // Variable to store the duration of the pulsefloatdist; // Variable to store the calculated distancevoidsetup() {
// Set the mode of the pinspinMode(trigerPin, OUTPUT); // Trig pin as outputpinMode(echoPin, INPUT); // This should actually be INPUT to read Echo signal (see note below)Serial.begin(115200); // Start serial communication at 115200 baud
}
voidloop() {
// Send a 10-microsecond pulse to the trigger pindigitalWrite(trigerPin, LOW); // Ensure trigger pin is lowdelayMicroseconds(2); // Wait for 2 microsecondsdigitalWrite(trigerPin, HIGH); // Set trigger pin highdelayMicroseconds(10); // Keep it high for 10 microsecondsdigitalWrite(trigerPin, LOW); // Set it low again// Read the time it takes for the echo to returndur = pulseIn(echoPin, HIGH); // Measure the duration of HIGH pulse on echo pin// Calculate the distance (in cm)// Sound speed is ~0.034 cm/microsecond; divide by 2 because it goes to the object and backdist = dur * 0.034 / 2;
// Print the result to the serial monitorSerial.print("Distance: ");
Serial.print(dist, 2); // Print with 2 decimal placesSerial.println(" cm"); // Label the units correctly as centimetersdelay(500); // Optional: Add a short delay before repeating the measurement
}
How Trigger Pulse Length Affects Ultrasonic Sensor Operation
Trigger Pulse Duration Considerations
1. Pulse shorter than 10 μs
The HC-SR04 requires a trigger pulse of at least 10 microseconds to emit ultrasound. A shorter pulse (e.g. 5 μs) may not register, and no ultrasonic burst will be sent. In that case, pulseIn(echoPin, HIGH) returns 0 because the ECHO pin never goes HIGH.
2. Pulse longer than 10 μs
Many HC-SR04 modules still function if the trigger pulse lasts 20 μs or 50 μs, since the sensor reacts to the first rising edge and counts an internal 10 μs. However, this behavior is outside the official specification and may be unpredictable on some units. It is recommended to use exactly 10 μs for reliable operation.
3. Pulse longer than the echo return time (t₂ − t₁)
The trigger pulse initiates the ultrasonic burst, but the ECHO measurement is independent. Even if the trigger remains HIGH (e.g. 50 μs), the ECHO pin timing starts from the moment the sensor transmits, not when the trigger ends. Excess trigger duration is ignored internally.
⚠️ Potential Issues with Excessively Long Pulses
- Internal timing may be disrupted (sensor might send more than 8 pulses).
- Subsequent measurements could be delayed.
- Readings may become inconsistent.
For consistent results, always use the standard trigger sequence:
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
Summary Table
| Trigger Duration | Behavior |
|---|---|
| < 10 μs | No ultrasonic burst sent |
| = 10 μs | Correct operation |
| > 10 μs | May work but not recommended |
| > echo return time | No effect on ECHO timing |
Automatic ECHO Pin Behavior
The ECHO pin transitions to HIGH automatically, not by user code but by the HC-SR04 hardware itself.
How It Works
When a trigger pulse is sent to the sensor:
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
the following sequence occurs internally:
- Eight ultrasonic pulses are emitted at 40 kHz.
- The ECHO pin is immediately set to
HIGH. - The ECHO pin remains
HIGHuntil the returning echo is detected. - Upon echo detection, the ECHO pin is reset to
LOW.
The duration that ECHO stays HIGH corresponds to the round-trip travel time of the ultrasonic wave.
Measuring the Pulse
The pulseIn() function is used to measure this HIGH time in microseconds:
long duration = pulseIn(echoPin, HIGH);
This function:
- Waits for the ECHO pin to go
HIGH(start of pulse). - Measures how long the pin remains
HIGH. - Returns the duration in microseconds.
Since the sensor controls the ECHO output, the pin only needs to be declared as an input:
pinMode(echoPin, INPUT);
No digitalWrite(echoPin, …) calls are required, as the ECHO line is driven by the sensor hardware.
Enhancements Overview
To improve reliability and readability over the initial sketch:
- Corrected pin mode: Set the Echo pin to
INPUTso the Arduino can read the return pulse. - Modular code: Encapsulated trigger/echo logic in a
measureDistance()function for clarity. - Timeout handling: Added a timeout to
pulseIn()to prevent blocking if no echo is received. - Error checking: Returned
-1when no echo is detected, and reported “Out of range” instead of printing an invalid distance. - Constants: Defined the speed of sound as a named constant for easy adjustment.
// C++ code
// Ultrasonic distance measurement with HC-SR04, improved version
const inttriggerPin = 9; // Trig pin of the ultrasonic sensorconst intechoPin = 10; // Echo pin of the ultrasonic sensorconst floatSOUND_SPEED = 0.034; // Speed of sound in cm/μsvoidsetup() {
// Configure pin modespinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(115200);
}
voidloop() {
// Measure and report distancefloatdistance = measureDistance();
if (distance < 0) {
Serial.println("Out of range or no echo");
} else {
Serial.print("Distance: ");
Serial.print(distance, 2);
Serial.println(" cm");
}
delay(500);
}
/**
* Sends a 10μs TRIG pulse, waits for ECHO, and returns distance in cm.
* Returns -1 on timeout or no echo.
*/
floatmeasureDistance() {
// Trigger pulse
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
// Wait for echo with 30ms timeout
longduration = pulseIn(echoPin, HIGH, 30000UL);
if (duration <= 0) {
return-1.0;
}
// Calculate distance
return (duration * SOUND_SPEED) / 2.0;
}
Troubleshooting
No Readings
If pulseIn() returns zero, it usually means the HC-SR04 didn’t detect any echo. Common causes:
- Too close: Objects closer than
< 2 cmlie within the sensor’s blind zone and won’t reflect a usable echo. - Too far: Targets beyond
> 400 cmexceed its maximum range, so no echo is received. - Wiring issues: Loose or swapped trigger/echo pins can prevent the pulse from being sent or received.
Interference & Crosstalk
When using multiple ultrasonic sensors simultaneously, their pulses can collide, causing erroneous zero or sporadic readings:
- Sequential triggering: Fire each sensor one at a time with a small delay (e.g. 50 ms) between readings.
- Physical spacing: Mount sensors at least 10 cm apart (or angle them) to reduce overlap of ultrasonic beams.
- Shielding: Use small baffles or foam tubes around each sensor’s emitter/receiver to help confine the sound path.
| Previous |< Arduino-Measurement of the unknown resistor |
Next Introduction to Servo Motors >| |
