Sonar Sensor (Ultrasonic Distance Detector)

Sonar Sensor Basics

Sonar sensors are complex devices that return the distance between the front of the sensor and a remote object.

Find your sensor in your kit.

I call these sonar sensors — you will also see them referred to as ultrasonic distance sensors, ultrasonic distance detectors and sometimes just distance sensors.

There are many flavours of this sensor on the market. The ones in our kit are SRF05’s. You will also find tutorials for SRF04’s – which are basically the same. there is even an Sf03 (BTW, the numbers indicate count of pins on the sensor).

How do they work?

Sonar distance sensors work on the same principle as bat sonar. The two silver cylinders on the front of the sensor are a transmitter and receiver. They work in concert with one another to detect distance. First the transmitter sends out a rapid burst of ultrasonic (high frequency) sound. The receiver ‘listens’ for the echo or return of the sounds that bounce off objects. A timer inside the sensor measures the amount of time it takes for the burst to end and the echo to return. Physics tell us that speed, time and distance are all related. So, that time lag can be easily converted to a distance.

Sonar Representations

I am not aware of a specific standardized sonar symbol. If you find one, let me know. I will use a symbol similar to the one below in schematics.

Let’s explore.

Parts required

  • Arduino
  • sonar sensor
  • M to F dupont wires

Build the Circuit

The sensor comes with male header pins which can be put into a bread board OR mounted to directly with pin-to-socket dupont wires. Direct connections are fine if you are only using sonar — but if you need any other circuits, then using a breadboard to carry power is a must.

direct connection

breadboard connection


You will need Pin (P-S) dupont wires or custom wires for this setup. Connect power to the rails of the breadboard, then rails to Arduino. This allows for other circuits to be built.

Connection Pattern

There are four connections to make. Sensor Vcc gets connected to Arduino 5V, sensor GND to Arduino ground, sensor trigger to pin 12 and sensor echo to pin 13. The pin connections are modifiable in code. The pins on the sensors are silk screen labelled. Some sensors have 5 pins — some only have 4 — if you don’t have an out pin, ignore it.

Add Library

The easiest way to use this sensor is to take advantage of one of the many libraries available for sonar and Arduino.

I like this one— you may find your own favourite.

To install the library go to the developer page and download the most recent version (at time of writing: v03.0.0).

It will download as a .zip — leave it compressed.

Open Arduino –> Sketch –> Include Library –> Add .zip library

Navigate to the downloaded .zip and select it.

You should be good to go.

Check your install by looking for the Ultrasonic examples in Arduino. Navigate to Arduino -> File -> Examples -> Ultrasonic … 3 examples.

Installed libraries are in the last section of the examples drop down. Depending on how many libraries you have installed, you may need to scroll way down.

Add code

The following code is a basic example to get readings from a sonar sensor. You can upload this code and open the serial plotter to view how the sensor performs.

// File :: 1-sonarTest

//https://www.arduinolibraries.info/libraries/ultrasonic

/*
 * print each single sonar reading as it comes in.
 *
 */

#include <Ultrasonic.h>

//Ultra sonic sensor pin definitions
int trigpin = 12;//appoint trigger pin
int echopin = 13;//appoint echo pin

Ultrasonic ultrasonic(trigpin,echopin); // create object

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {

    int distanceReading = ultrasonic.read(); // default single reading

    Serial.println( distanceReading );  
    delay(10);
}

Because we are using a library, there are a few lines of code worth mentioning.

First we need to tell the Arduino compiler to include the code in the Ultrasonic library.

#include <Ultrasonic.h>

Then we must create an Ultrasonic object. This line needs us to tell the system where it will find the trigger and echo pins of the sensor. The object type is Ultrasonic (capital U).
The object name is ultrasonic (small u).

Ultrasonic ultrasonic(trigpin,echopin); // create object

When we want to read the sonar value we call ultrasonic.read(). This follow a standard Object.function() notation pattern.

int distanceReading = ultrasonic.read();

The sensor is read once every time loop executes.

The new reading is then printed out to serial plotter or monitor — depending on which you open.

What to expect

With the plotter open, try moving your hand toward and away from the sensor. You should see the trace drop when you get close and go back up when you pull your hand away. You have to be careful to go straight towards and away from the sensor.

In the trace above two things are going on. First there are some big spikes. They happen for me when I move quickly towards the sensor. Under those spikes is a wave that undulates with my hand moving towards and away from the sensor.

You may want to try moving a book instead of your hand. Try moving the sensor towards a wall or the floor rather than just using small objects — you will get cleaner traces.

There will be a lot of noise (spikes) — just part of the sensors — we will look at a simple way to deal with noise below. I will have to create a more advanced filtering post.

In the monitor you will see a rapidly changing column of numbers. The plotter is your friend here.

Averaging Readings

One quick and dirty way to deal with noise in ANY sensor is to take several measurements very rapidly and average them. Then work with the average rather than raw readings.

This is a bit crude but its easy to do — so we may as well do it.

We can add a function call and the corresponding function that will average the number of readings we ask for:

Function call:

int distanceReading = averageUltraSonic(5);

This line replaces the sensor read() line in the example above.

The number inside the brackets is the number of readings you want to average.

The function to add

int averageUltraSonic( int howMany ){
  int dist = 0;
  for (int i = 0; i < howMany; i++){
      dist += ultrasonic.read();
  }
  return dist = (int) dist / howMany;
}

This function will loop howMany times.

Each time through the loop a sonar reading is taken. The new reading is added to a running total (sum) of all readings.

At the end, the average of the readings is sent back to the line that called the function and stored in the variable distanceReading.

Note/Aside the label howMany is called a function parameter. The actual number placed inside that label (in this case 5) is a function argument.

Here is the new code:

// File :: 2-sonarAverage


#include <Ultrasonic.h>

//Ultra sonic sensor pin definitions
int trigpin = 12;//appoint trigger pin
int echopin = 13;//appoint echo pin

Ultrasonic ultrasonic(trigpin,echopin); // create object

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {

    int distanceReading = averageUltraSonic(5);   // average (X) readings
    Serial.println( distanceReading );  
    delay(10);
}


// this function reads the distance 'howMany' times
// it then returns the average of those readings

int averageUltraSonic( int howMany ){
  long dist = 0;
  for (int i = 0; i < howMany; i++){
      dist += ultrasonic.read();
  }
  return dist = (int) dist / howMany;
}
What to Expect

With the averaging code (above) you should see that many spikes are removed (trace below). Without the spikes the autoscaling of the plotter calms down and you see the motion of my hand much more clearly. Filtering can be pushed much further than this simple example.

Sensor Timeout

You may notice the code gets slower when the sensor doesn’t see anything, or sees only really far things.

This sensor is relying on the time until an echo returns to determine distance. It therefore waits for a long time when distances get large.

Advanced users can minimize this delay using the sensor timeout in setup().

  ultrasonic.setTimeout(30000UL);

The unit in the time out is microseconds (that is 1/1000 of a millisecond!). The variable type is unsigned long (UL).

There is also a way to set this in the constructor. Check the example files that came with the library for details.

Going further

Original ultrasonic tutorial for this library

Thresholding an analog sensor reading — the principles apply to sonar as well as photocells.

I find this a really unstable way to use these sensors. But if you want to take readings without the library try this tutorial.