Ultrasonic Distance Measurement with Arduino
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
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
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
//
int trigerPin = 9; // Pin connected to the Trig pin of the ultrasonic sensor
int echoPin = 10; // Pin connected to the Echo pin of the ultrasonic sensor
long dur; // Variable to store the duration of the pulse
float dist; // Variable to store the calculated distance
void setup() {
// Set the mode of the pins
pinMode(trigerPin, OUTPUT); // Trig pin as output
pinMode(echoPin, INPUT); // This should actually be INPUT to read Echo signal (see note below)
Serial.begin(115200); // Start serial communication at 115200 baud
}
void loop() {
// Send a 10-microsecond pulse to the trigger pin
digitalWrite(trigerPin, LOW); // Ensure trigger pin is low
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(trigerPin, HIGH); // Set trigger pin high
delayMicroseconds(10); // Keep it high for 10 microseconds
digitalWrite(trigerPin, LOW); // Set it low again
// Read the time it takes for the echo to return
dur = 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 back
dist = dur * 0.034 / 2;
// Print the result to the serial monitor
Serial.print("Distance: ");
Serial.print(dist, 2); // Print with 2 decimal places
Serial.println(" cm"); // Label the units correctly as centimeters
delay(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 int triggerPin = 9; // Trig pin of the ultrasonic sensor
const int echoPin = 10; // Echo pin of the ultrasonic sensor
const float SOUND_SPEED = 0.034; // Speed of sound in cm/μs
void setup() {
// Configure pin modes
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(115200);
}
void loop() {
// Measure and report distance
float distance = 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.
*/
float measureDistance() {
// Trigger pulse
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
// Wait for echo with 30ms timeout
long duration = 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 >| |