Arduino & Microcontrollers, Blog

The Complete Guide to Using Ultrasonic Sensor with Arduino

Complete Guide to Using Ultrasonic Sensor with Arduino

An ultrasonic sensor is a powerful device that uses sound waves to detect objects and measure distances, much like bats and dolphins navigate their environments. When paired with an Arduino, these affordable sensors open up endless possibilities for creating smart projects that can detect movement, measure distances, and interact with the physical world.

In this tutorial, I will explain everything you need to know about integrating ultrasonic sensors with Arduino boards to create intelligent and responsive projects. I have crafted this tutorial to help hobbyists, students, and professional makers master ultrasonic sensing technology.

What You’ll Learn

  • How ultrasonic sensors work
  • Connecting an HC-SR04 ultrasonic sensor to Arduino
  • Programming your Arduino to read and interpret sensor data
  • Practical project examples
  • Troubleshooting common issues
  • Advanced techniques and optimizations

Understanding Ultrasonic Sensors

You may be wondering about how the ultrasonic sensor works. Well, ultrasonic sensors operate on a fundamental principle of sound wave propagation. They emit high-frequency sound waves, typically above 20 kHz, which is beyond human hearing, and then listen for the echo that returns after these waves reflect off a surface or object. The process consists of two key phases: signal transmission and echo reception.

Signal Transmission

Ultrasonic sensor sending high frequency signal
Ultrasonic sensor transmitting a high frequency signal

In the image above, you can see that the sensor generates an ultrasonic pulse (an invisible high-frequency signal). This pulse propagates through the air in a straight line until it encounters an obstacle. The emitted waves travel at a constant speed, roughly equal to the speed of sound in air (approximately 343 meters per second at room temperature).

Echo Reception

Ultrasonic sensor receiving a high frequency signal
Ultrasonic sensor receiving a high frequency signal

Once the sound wave strikes an object, it reflects and travels back to the sensor, as illustrated in the image above. The sensor’s receiver detects this returning signal and records the time delay between transmission and reception.

Distance Calculation

The distance between the sensor and the object is determined using the following formula:

The division by two accounts for the round-trip travel of the sound wave outward to the object and back to the sensor.

The most commonly used ultrasonic sensor with Arduino is the HC-SR04, which is known for its affordability, reliability, and ease of use. It has four pins:

  1. VCC – Power supply (5V)
  2. Trig – Trigger input to send ultrasonic pulses
  3. Echo – Receives the reflected (returning ) signal
  4. GND – Ground connection

Key Specifications of the HC-SR04

  • Working Voltage: 5V DC
  • Working Current: 15mA
  • Working Frequency: 40kHz
  • Measuring Range: 2cm to 400cm
  • Measuring Angle: 15 degrees
  • Resolution: Up to 3mm

Ultarsonic & Arduino Hardware Setup

Components Needed

Connection Diagram

Connecting the HC-SR04 to your Arduino is straightforward as illustrated in the diagram below:

HC-SR04 Ultrasonic and Arduino Uno Connection
HC-SR04 Ultrasonic and Arduino Uno Connection
  1. Connect VCC on the sensor to 5V on the Arduino
  2. Connect GND on the sensor to GND on the Arduino
  3. Connect Trig on the sensor to a digital pin (Here, I used pin 9)
  4. Connect Echo on the sensor to another digital pin (Here, I used pin 10)

Programming the Arduino

Basic Distance Measurement Code

// Define pins
const int trigPin = 9;
const int echoPin = 10;

// Define variables
long duration;
int distance;

void setup() {
  // Initialize Serial communication
  Serial.begin(9600);
  
  // Set pin modes
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  // Clear the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  
  // Set the trigPin HIGH for 10 microseconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Read the echoPin, calculate distance
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
  
  // Display the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");
  
  delay(500); // Wait before next measurement
}

Understanding the Code

The code follows these steps:

  1. Setup: Configure the trigger pin as output and the echo pin as input
  2. Trigger the sensor: Send a 10-microsecond pulse to the trigger pin
  3. Measure echo time: Use pulseIn() to measure how long it takes for the echo to return
  4. Calculate distance: Convert the time to distance using the speed of sound
  5. Display results: Show the distance in the Serial Monitor

The Math Behind Distance Calculation

The formula distance = duration * 0.034 / 2 is based on:

  • Sound travels at approximately 343 meters/second (or 0.034 cm/microsecond) in air at room temperature
  • We divide by 2 because the sound wave travels to the object and back

Practical Projects

1. Simple Distance Alarm

Create a system that triggers an alarm when an object comes within a certain distance:

const int trigPin = 9;
const int echoPin = 10;
const int buzzerPin = 7;
const int thresholdDistance = 20; // in centimeters

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  long duration;
  int distance;
  
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2;
  
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");
  
  if (distance < thresholdDistance) {
    digitalWrite(buzzerPin, HIGH);
  } else {
    digitalWrite(buzzerPin, LOW);
  }
  
  delay(300);
}

2. Parking Assistant

Help guide a car into a garage by using LEDs to indicate distance:

const int trigPin = 9;
const int echoPin = 10;
const int greenLED = 7;
const int yellowLED = 6;
const int redLED = 5;

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(redLED, OUTPUT);
}

void loop() {
  long duration;
  int distance;
  
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2;
  
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");
  
  // Turn all LEDs off
  digitalWrite(greenLED, LOW);
  digitalWrite(yellowLED, LOW);
  digitalWrite(redLED, LOW);
  
  // Turn on appropriate LED based on distance
  if (distance > 100) {
    digitalWrite(greenLED, HIGH); // Far away
  } else if (distance > 50) {
    digitalWrite(yellowLED, HIGH); // Getting closer
  } else {
    digitalWrite(redLED, HIGH); // Very close - stop!
  }
  
  delay(300);
}

3. Water Level Monitor

const int trigPin = 9;
const int echoPin = 10;
const int containerHeight = 30; // Height of your container in cm

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  long duration;
  int distance;
  int waterLevel;
  int percentFull;
  
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2;
  
  // Calculate water level (assuming sensor is mounted above container)
  waterLevel = containerHeight - distance;
  if (waterLevel < 0) waterLevel = 0; // Handle out-of-range readings
  
  // Calculate percentage full
  percentFull = (waterLevel * 100) / containerHeight;
  
  Serial.print("Water level: ");
  Serial.print(waterLevel);
  Serial.print(" cm (");
  Serial.print(percentFull);
  Serial.println("%)");
  
  delay(1000);
}

Troubleshooting Common Issues

Inaccurate Readings

If you’re getting inconsistent or inaccurate readings:

  1. Environmental factors: Temperature affects the speed of sound. For precise measurements, you can add temperature compensation:
// With a temperature sensor (e.g., TMP36)
float temperatureC = (analogRead(A0) * 5.0 / 1024.0 - 0.5) * 100;
float speedOfSound = 331.3 + (0.606 * temperatureC); // in m/s
distance = duration * speedOfSound / 20000; // in cm

  1. Surface properties: Soft, irregular, or angled surfaces might not reflect sound waves effectively.
  2. Interference: Multiple ultrasonic sensors can interfere with each other. Ensure they’re separated or trigger them sequentially.

No Readings or Out-of-Range Values

  1. Check wiring: Ensure all connections are secure.
  2. Power supply: Confirm the sensor is receiving adequate 5V power.
  3. Distance limits: Remember the HC-SR04 has a range of 2cm to 400cm.

Noisy Signal

  1. Add filtering: Implement a simple moving average to smooth readings:
const int numReadings = 10;
int readings[numReadings];
int readIndex = 0;
int total = 0;
int average = 0;

void setup() {
  // Initialize all readings to 0
  for (int i = 0; i < numReadings; i++) {
    readings[i] = 0;
  }
}

void loop() {
  // Get distance measurement as before
  
  // Subtract the last reading
  total = total - readings[readIndex];
  // Add the new reading
  readings[readIndex] = distance;
  total = total + readings[readIndex];
  // Advance to the next position in the array
  readIndex = (readIndex + 1) % numReadings;
  
  // Calculate the average
  average = total / numReadings;
  
  Serial.print("Smoothed distance: ");
  Serial.print(average);
  Serial.println(" cm");
}

Advanced Techniques

Using Multiple Sensors

For projects requiring broader coverage or object tracking, you can use multiple ultrasonic sensors:

Connecting multiple HC-SR04 Ultrasonic and Arduino Uno
Multiple HC-SR04 Ultrasonic and Arduino Uno Connection

Core for Multiple Ultrasonic Sensors with Arduino

const int trigPins[] = {9, 7, 5};
const int echoPins[] = {10, 8, 6};
const int numSensors = 3;

void setup() {
  Serial.begin(9600);
  for (int i = 0; i < numSensors; i++) {
    pinMode(trigPins[i], OUTPUT);
    pinMode(echoPins[i], INPUT);
  }
}

void loop() {
  for (int i = 0; i < numSensors; i++) {
    int distance = measureDistance(trigPins[i], echoPins[i]);
    
    Serial.print("Sensor ");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(distance);
    Serial.println(" cm");
  }
  Serial.println();
  delay(500);
}

int measureDistance(int trigPin, int echoPin) {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  long duration = pulseIn(echoPin, HIGH);
  return duration * 0.034 / 2;
}

Non-Blocking Measurements

For more responsive projects, use non-blocking techniques:

unsigned long previousMillis = 0;
const long interval = 100; // Measurement interval in milliseconds
int distance = 0;

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  
  // Other code can run here without being delayed
  
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    
    // Measure distance
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    
    long duration = pulseIn(echoPin, HIGH);
    distance = duration * 0.034 / 2;
    
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.println(" cm");
  }
  
  // More code can run here
}

Integrating with Other Sensors and Outputs

With an LCD Display

#include <LiquidCrystal.h>

// Initialize the LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  lcd.begin(16, 2); // Set up the LCD's number of columns and rows
  lcd.print("Distance Sensor");
}

void loop() {
  // Measure distance as before
  
  // Display on LCD
  lcd.setCursor(0, 1);
  lcd.print("Distance: ");
  lcd.print(distance);
  lcd.print(" cm   ");
  
  delay(300);
}

Ultrasonic Sensor with a Servo Motor for Object Tracking

An ultrasonic sensor paired with a servo motor can be used for object tracking by continuously scanning an area and detecting obstacles. The servo motor adjusts its angle based on the object’s detected position, enabling real-time tracking. This setup is commonly used in robotics, security systems, and automation projects. Check the connection diagram and sample code below:

Ultrasonic Sensor with a Servo Motor for Object Tracking

Code for Ultrasonic Sensor with a Servo Motor

#include <Servo.h>

Servo myServo;
const int servoPin = 11;

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
  myServo.attach(servoPin);
  myServo.write(90); // Start at middle position
}

void loop() {
  // Measure distance as before
  
  // Map distance to servo angle (closer objects = higher angle)
  int angle = map(distance, 5, 100, 180, 0);
  angle = constrain(angle, 0, 180);
  
  myServo.write(angle);
  
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.print(" cm, Angle: ");
  Serial.println(angle);
  
  delay(100);
}

Conclusion

Ultrasonic sensors are versatile components that can enhance your Arduino projects with distance-sensing capabilities. From simple distance measurement to complex object detection systems, these sensors offer a cost-effective way to interact with the physical world.

By understanding how ultrasonic sensors work and mastering the techniques covered in this guide, you can create more interactive and responsive Arduino projects. Whether you’re building a robot, a security system, or an automated home solution, ultrasonic sensors provide the “eyes” your projects need to perceive the environment.

Additional Resources

Remember that practice is key to mastering any technology. Start with simple projects and gradually work your way up to more complex implementations. If you need a specific circuit diagram for any of the sample projects discussed above, please mention it in the comments, and I’ll be happy to help!

Happy tinkering!

author-avatar

About Boateng Oduro

I am a passionate innovator, educator, and tech enthusiast dedicated to transforming electronics, robotics, STEM education and technological advancement in Ghana. With a strong background in Electrical and Electronics Engineering, I hold a Higher National Diploma (HND), a BSc in Electrical and Electronics Technology Education, and currently pursuing Master of Technology in Electrical and Electronics Engineering. My expertise spans STEM education, robotics, IoT, embedded systems, and automation.

Leave a Reply

Your email address will not be published. Required fields are marked *