Saturday, November 16, 2013

HC-SR04: ultrasonic sensor for Arduino

This week I will present one of the main ingredients of robotic constructions: ultrasonic sensors.

The physics

The sensor is based on a simple principle, sound echo phenomenon. A membrane emits an ultrasonic sound and a second membrane will catch the echo signal reflected by the obstacle.

The formula is therefore

D = VT/2

D = distance of the obstacle
V = sound speed
T  = measured time for trigger signal to perform the round trip

The division by 2 is due to the fact that the measured time is for the total signal trip (round trip).

Remark that the speed of sound in the air varies according to temperature as follows:

V = 331,4 + 0,62 t
where t is the temperature measured in °C and the speed is measured in meters/seconds. In our experiments we assume that temperature is 20°C and therefore sound speed is approx. 340 m/s.

In our calculations time will be measure in microseconds (us) and we want to output distance in centimeters. Therefore the previous formula turns into

D = 0.017 * T


The sound is a longitudinal wave (i.e. it progress along a horizontal line). Therefore when the obstacle is not perfectly in front of the module, sounds are deflected and echo signal may not reach back the sensor or reach it very attenuated and hence not being detected (see figure below).

When the obstacle is at an angle more than 30° w.r.t. trigger signal propagation direction, the sensor give erratic results.

Caveat 2 

Remark that also the material with which the obstacle is made has to be taken into account. Indeed, some materials tend to absorb the trigger signal and bounce back false results to the echo sensor.

The module

This is a standard low cost ultrasonic sensor. It is essentially made of two identical microphones. One is used as an emitter and the other as a receiver. On board there is also minimal electronics for signal generation. Here are the main features:

Power supply: +5 DC
Quiescent current: <2mA
Working current: 15mA
Effectual angle: <15°
Distance range: 2cm - 400cm
Resolution: 0.3cm
Measuring angle: 30°
Trigger input pulse width: 10us
Ultrasonic frequency: 40kHz
Dimensions: 45mm x 20mm x 15mm

Remark that the distance range given is theoretical. Indeed, in my experiments, distances greater than 3000cm give erratic results.

The question

      Q: How big should be the obstacle to be able the "see" it? (and not see one which is 

      A: According to the data sheet minimal obstacle should have a surface of 0.5 m^2

The module has four pins. The meaning is the following:

Vcc   = +5V DC
Trig    = trigger signal (input)
Echo  = echo signal (output)
Gnd   = 0V DC

The trigger signal
The module accepts a TTL signal on the trigger pin, it outputs the echo signal on the echo pin. The length of the output signal is proportional to the distance of the obstacle.

The module issues the trigger signal when the trigger pin goes HIGH for a period of at least 10 microseconds. Then, a burst of 8 signals of 10microseconds length each is issued at 40kHz.

The test circuit
Here is the basic connection of the HC-SR04 module with the Arduino Uno (R3). Nothing to add.
The test program
Before going into the program we should mention that the measurement routines are used a lot in a robot for example, therefore should be fast and carefully use memory. Hence let us dimension the minimal data structure that we need.

For the variable which contains the value of the round trip time (in microseconds) we just need an uint16. Indeed, we have to take the max distance (4 meters) and use the previous formula:

8 = 340 * T * 10^6

which gives T < 25000. It is also convenient to represent D using "thousands" of centimeters
instead of centimeters, so that we can make only integer computations. Using the initial formula again we obtain D < 500000. Therefore, uint32 will do.

   HC-SR04 : test program for ultrasonic module

   Author: Enrico Formenti
   Permissions: MIT licence

const uint8_t trigPin = 4;
const uint8_t echoPin = 2;
void setup() {
  // initialize serial communication:
void loop()
  uint32_t duration; // duration of the round trip
  uint32_t cm;        // distance of the obstacle
  // The sensor is triggered by a HIGH pulse of 10 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(trigPin, OUTPUT);
  digitalWrite(trigPin, LOW);

  // Start trigger signal

  digitalWrite(trigPin, HIGH);
  digitalWrite(trigPin, LOW);
  // Read the signal from the sensor: a HIGH pulse whose
  // duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.

  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
  // convert the time into a distance
  cm = (uint32_t)((duration<<4)+duration)/1000.0; // cm = 17 * duration/1000
  Serial.print(" centimeters");

What's next?
Our experiments could be extended in several directions. First of all, more accurate measures. It is clear that our sensor has some inaccuracy. Therefore it is a good idea to make several successive measurements and then take some kind of statistics over them. Clearly, to be useful such kind of extension should make a good compromise between speed and accuracy.
   Second, it is clear that using only one sensor does not help much to figure out the obstacle geometry. Therefore one can add a second (and a third or more if you want) sensor with different angle and extract more geometry informations from two measurements. A third improvement might try to mount the sensor on a servo and make the servo rotate while make measurements, collecting in this way several measures with different angles which will help to reconstruct the surrounding neighborhood. This last improvement clearly supersedes the second one.


1 comment :

  1. Good information on the ultrasonic sensor. It would help people who are using the ultrasonic sensor. Thanks for sharing this with us!