Tag Archives: Ultrasound

Lesson: Creating a Proximity Detector with an Arduino and an Ultrasonic Distance Sensor

By Robert Walsh

Engage

Most cars today have numerous sensors that help drivers detect obstacles that are nearby but potentially out of sight1. Often, they emit a series of audible tones that increase in pitch, frequency, or both as the car gets closer to the obstacle. In this lesson, we will create a similar system that uses light emitting diodes (LEDs) to indicate how far away an object is from a sensor. To complete the activity, you will need:

  • An Arduino Mega 2560 (other models will also work, but the pin numbers will be different)
  • One green, one yellow, and one red LED
  • Three 330 Ohm resistors
  • One HC-SR04 ultrasonic distance sensor
  • A breadboard
  • Several male-to-male jumper wires
  • Several male-to-female jumper wires (optional)
  • A computer and USB cable to program the Arduino

Note: All of the components needed for this lesson (except the computer) are available in the ELEGOO Mega 2560 Starter Kit available from Amazon.

Explore

Connecting the HC-SR04 Ultrasonic Distance Sensor

We are going to start by creating a simple circuit that incorporates just the HC-SR04, then we will add the LEDs in a second step. The HC-SR04 is very easy to control; it needs just four connections to the Arduino. Here is the wiring diagram:

Wiring diagram for the HC-SR04 ultrasonic distance sensor

We first need to connect the common power rail on the breadboard to a 5V pin on the Arduino. We also need to connect the common ground rail to a GND (ground) pin. The HC-SR04 has just four pins. VCC connects to common power, and GND connects to common ground. The trigger (TRIG) pin connects to output pin on the Arduino (I used pin 7), and the echo pin connects to an input pin.

Instead of inserting the HC-SR04 directly into the breadboard, it could be connected to the breadboard using male-to-female jumper wires. Then, by holding the sensor with its edges between thumb and forefinger, it can be more easily moved around. This would be a better configuration if moving the sensor is easier than moving the obstacles.

Here is the Arduino sketch for this circuit:

const int TRIGGER_PIN = 7;
const int ECHO_PIN = 6;

const float SPEED_OF_SOUND_IN_METERS_PER_SECOND = 340.0; /* define speed of sound as a float to avoid truncation with integer math */
const long ONE_MILLION_MICROSECONDS_PER_SECOND = 1000000;
const int ONE_HUNDRED_CM_PER_METER = 100;

void setup() {
  pinMode(TRIGGER_PIN, OUTPUT); /* set the trigger pin as an output pin */
  pinMode(ECHO_PIN, INPUT); /* set the echo pin as an input pin */

  Serial.begin(9600);
}

void loop() {
  /* Ensure the trigger pin is LOW */
  digitalWrite(TRIGGER_PIN, LOW);
  delayMicroseconds(2);

  /* Set the trigger pin HIGH for 10 microseconds */
  digitalWrite(TRIGGER_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER_PIN, LOW);

  /* Measure the time it takes (in microseconds) for the echo pin to go HIGH */
  float duration = pulseIn(ECHO_PIN, HIGH);
  
  /* Convert the time to distance in meters based on the speed of sound */
  float distanceInMeters = duration * (SPEED_OF_SOUND_IN_METERS_PER_SECOND / ONE_MILLION_MICROSECONDS_PER_SECOND) / 2

  /* Convert meters to centimeters */
  float distanceInCentimeters = distanceInMeters * ONE_HUNDRED_CM_PER_METER;

  /* Print the distance to the serial console */
  Serial.print("Distance: ");
  Serial.print(distanceInCentimeters);
  Serial.println(" cm");  
}

When the trigger pin on the HC-SR04 is set high for 10 microseconds (ten millionths of a second), it sends out a series of sound waves at a frequency that is higher than humans can hear. This range is referred to as ultrasonic. The HC-SR04 also starts listening on for the sound waves to bounce back. When they are detected, the HC-SR04 sets the echo pin high. Since sound travels at a constant speed, by measuring the time it takes for the echo pin to go high, we can calculate the distance to whatever obstacle caused the sound to change direction. We have to divide the distance in half since the time measured was for the sound pulses to travel from the sensor to the obstacle and back.

When the sketch is compiled and uploaded to the Arduino, it should begin printing distance readings to the serial monitor window in the Arduino IDE. (If the serial monitor window is not open, use Serial Monitor from the Tools menu to open it.). Moving an obstacle close to the sensor should decrease the distance readings, and moving the obstacle away from the sensor should increase them. The maximum range is around 4 meters (about 13 feet), and the minimum range is 2 cm2.

Adding the LEDs

When driving, it would be inconvenient, distracting, and potentially dangerous to have to constantly read the distance from some kind of a text-based display. It would be better to have some kind of visual or auditory warning that could signal the driver and indicate the threat level. We are going to add LEDs to our circuit. Based on the distance to the obstacle, we will adjust the color and brightness of the LEDs. Here is the wiring diagram for the completed circuit:

Wiring diagram for the HC-SR04 ultrasonic distance sensor and the three LEDs

The cathode (negative leg) of each of the three LEDs is connected to ground, and the anode (positive leg) of each connects to a 330 Ohm resistor which is then connected to an output pin on the Arduino (I used pin 4 for red, pin 3 for yellow, and pin 2 for green). The pins for the LEDs must support pulse width modulation (PWM) since we will be using analogWrite to vary the brightness. When the obstacle gets within 30 cm (about 1 foot) of the sensor, the green LED will light up. As it gets closer, the brightness of the green LED will increase. At 20 cm, the yellow LED will light up and get brighter until the obstacle gets to 10 cm when the red LED will light up. Here is the Arduino sketch:

const int TRIGGER_PIN = 7;
const int ECHO_PIN = 6;

const int RED_LED = 4;
const int YELLOW_LED = 3;
const int GREEN_LED = 2;

const int OFF = 0;
const int DIM = 256 / 4;
const int HALF = 256 / 2;
const int FULL = 255;

const float SPEED_OF_SOUND_IN_METERS_PER_SECOND = 340.0; /* define speed of sound as a float to avoid truncation with integer math */
const long ONE_MILLION_MICROSECONDS_PER_SECOND = 1000000;
const int ONE_HUNDRED_CM_PER_METER = 100;

void setup() {
  pinMode(TRIGGER_PIN, OUTPUT); /* set the trigger pin as an output pin */
  pinMode(ECHO_PIN, INPUT); /* set the echo pin as an input pin */

  pinMode(RED_LED, OUTPUT); /* set the pin for the red led as an output pin */
  pinMode(YELLOW_LED, OUTPUT); /* set the pin for the yellow led as an output pin */
  pinMode(GREEN_LED, OUTPUT); /* set the pin for the green led as an output pin */

  digitalWrite(RED_LED, OFF); /* ensure the red led is off */
  digitalWrite(YELLOW_LED, OFF); /* ensure the yellow led is off */
  digitalWrite(GREEN_LED, OFF); /* ensure the green led is off */
  
  Serial.begin(9600);
}

int determineLedState(float distance, int distanceThreshold)
{
  /* Determine whether (and how bright) an LED should be lit based on distance */

  /* Assume the LED should be off */
  int state = OFF;

  /* If the distance is less than the thresholod, set the state to DIM (ex., < 30 for green) */
  if (distance <= distanceThreshold)
  {
    state = DIM;
  }

  /* If the distance is between the threshold and three less than the threshold, set the state to HALF (ex., < 27 for green) */
  if (distance <= (distanceThreshold - 3))
  {
    state = HALF;
  }

  /* If the distance is between the threshold and three less than the threshold, set the state to FULL (ex., < 24 for green) */
  if (distance <= (distanceThreshold - 6))
  {
    state = FULL;
  }
  
  return state;
}

void setLeds(float distance)
{
  /* Gets and sets the state for each LED based on distance */

  /* Determine what state each LED should have */
  int greenLedState = determineLedState(distance, 30);
  int yellowLedState = determineLedState(distance, 20);
  int redLedState = determineLedState(distance, 10);

  /* Write the states to the LEDs */
  analogWrite(GREEN_LED, greenLedState);
  analogWrite(YELLOW_LED, yellowLedState);
  analogWrite(RED_LED, redLedState);    
}

void loop() {
  /* Ensure the trigger pin is LOW */
  digitalWrite(TRIGGER_PIN, LOW);
  delayMicroseconds(2);

  /* Set the trigger pin HIGH for 10 microseconds */
  digitalWrite(TRIGGER_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER_PIN, LOW);

  /* Measure the time it takes (in microseconds) for the echo pin to go HIGH */
  float duration = pulseIn(ECHO_PIN, HIGH);
  
  /* Convert the time to distance in meters based on the speed of sound */
  float distanceInMeters = duration * (SPEED_OF_SOUND_IN_METERS_PER_SECOND / ONE_MILLION_MICROSECONDS_PER_SECOND) / 2

  /* Convert meters to centimeters */
  float distanceInCentimeters = distanceInMeters * ONE_HUNDRED_CM_PER_METER;

  /* Set the states for the LEDs based on the distance */
  setLeds(distanceInCentimeters);

  /* Print the distance to the serial console */
  Serial.print("Distance: ");
  Serial.print(distanceInCentimeters);
  Serial.println(" cm");  
}

We added two functions to do the work of determining which LEDs should be lit and how bright each should be. Most of this is done in determineLedState. This function takes two parameters, the distance and the threshold at which the LED should be lit. For example, we want the green LED to light up when the object is 30 cm or less from the sensor. The function first assumes the LED will be off. However, if the distance to the obstacle is less than or equal to the threshold, the LED should be lit, and we need to determine how brightly. Again, using green as the example, the LED should be dim (1/4 brightness) if the object is less than 30 but more than 27 cm from the sensor; it should be lit to half its maximum brightness if the object is less than 27 and more than 24 cm; and it should be fully bright is the object is closer than 25 cm (<= 24). For the other LEDs, we simply use different threshold values. This logic means that the green LED will be fully bright anytime the yellow or red LED is also lit.

Compile and upload the sketch, then experiment by moving objects towards and away from the sensor (or moving the sensor towards or away from objects). As the object gets within 30 cm, the LEDs should come on, and they should get brighter as the object gets closer. Feel free to adjust the threshold distances and modifiers to make the LEDs more responsive for your environment.

Explain

Using reflected sound to detect obstacles is called echolocation3. Several animal species, including bats and dolphins, use echolocation to move safely and hunt effectively. The same principle is used in radar (an acronym that stands for radio detection and ranging)4 and sonar (sound navigation and ranging)5.

Modern cars include various kinds sensors, including ultrasonic sensors, that are capable of measuring the distance to nearby obstacles1. Combining these sensors with sounds, lights, and cameras allows the car to notify the driver when it is in danger of striking an obstacle. Other features like cruise control, self-parking, and even driverless cars use data from the sensors to make decisions about whether to slow down, stop, or turn. The HC-SR04 ultrasonic distance sensor is a common component of robot car kits that enables the robot to detect objects in its environment and to navigate around them.

Extend

Our code assumes that the speed of sound is a constant 340 meters per second. More accurately, though, the speed of sound varies with the air temperature6. Our distance sensor could be made more accurate if we incorporated a second sensor to measure the air temperature and to then calculate the speed of sound accordingly. Additionally, we could add multiple LEDs in each color and have the number that are lit help to indicate the distance to the detected object.

While colored lights at varying brightnesses make be appropriate warning indicators for some environments, using sounds might be better in others. Cars often use tones that vary in pitch and frequency based on the distance to the obstacle. For example, a high pitch sound that repeats at a fast rate indicates that we are very close to the object, while a slower, lower sound tells us we are farther away. A piezo buzzer7 could be incorporated into the circuit to generate tones based on the distance to the detected object. A camera, too, could be incorporated; however, this might be easier using a Raspberry Pi than an Arduino.

Evaluate

What we learned in this lesson:

  • How to use the HC-SR04 ultrasonic distance sensor to measure the distance to an object
  • How to calculate distance using the time required for a sound wave to reflect off an object and travel back to its source
  • How to use pulse width modulation to vary the brightness of an LED

How did you do with this lesson?

  • What parts were easy and what parts were confusing?
  • Were any parts a review of things you already knew?
  • What would you like to know more about?

References

1Stevenson, J. (2016, May 4). What are car proximity sensors and how do they work? Here360. https://360.here.com/2016/05/04/what-are-car-proximity-sensors-and-how-do-they-work/

2Elec Freaks. (n.d.). Ultrasonic ranging module HC-SR04 [Datasheet]. https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf

3Price, J. (n.d.). What is echolocation and which animals use it? Discover Wildlife. https://www.discoverwildlife.com/animal-facts/mammals/what-is-echolocation/

4Rouse, M. (n.d.). Radar (radio detection and ranging). Tech Target. https://searchmobilecomputing.techtarget.com/definition/radar

5National Oceanic and Atmospheric Administration. (n.d.). What is sonar? https://oceanservice.noaa.gov/facts/sonar.html

6NDT Resource Center. (n.d.). Temperature and the speed of sound. https://www.nde-ed.org/EducationResources/HighSchool/Sound/tempandspeed.htm

7Adafruit. (2020, August 5). Overview: Using piezo buzzers with CircuitPython and Arduino. https://learn.adafruit.com/using-piezo-buzzers-with-circuitpython-arduino