Search Microcontrollers

Thursday, May 22, 2014

Arduino Robot - Ultrasound Sensor

Ultrasound sensors are one of the first things you want to implement in a robotic rover.
They are quite cheap, easy to use and can provide a lot of fun as they can sense obstacles in front of the robot.

You are probably familiar with Sonars (SOund Navigation And Ranging) as they are equipped on ships to sense objects below the water surface.
The principle is quite easy : an ultrasonic wave is generated by an emitter, it travels through a medium (water in the case of sonars, air in our case), eventually bounces against an obstacle and is reflected back where a receiver detects it.

Sound is quite fast, but way slower than light and slow enough to allow us to measure the time it takes to travel to the obstacle and back.
As we know the speed of sound in air (about 340 m/s, can vary a bit depending on temperature, air pressure etc) and a microcontroller is fast enough to measure the time between the emission of the sound and the detection of its reflected wave, we can measure the distance with acceptable accuracy.

The equation we use is s = v x t where s is the distance we are trying to calculate, v is the speed of sound (340 m/s) and t is the time we measure with the microcontroller.

One of the most commonly used sensors is the HC-SR04 which has an incredibly easy to use interface.
It is a 5V device (perfect for Arduino) that uses a trigger pin to fire out an ultrasonic pulse and sends back the echo on an echo pin.

In fact the sensor makes it a bit easier for us to calculate the time since the echo pin goes high once the sound is emitted (which happens roughly 0.5ms after we activate the trigger) and back low once the reflected wave is detected.

In the picture you can see I hooked the sensor to an Arduino Uno, and my oscilloscope to the trigger (channel one, red) and echo (channel 2, yellow) signals.
The target was placed at about 12 cm from the sensor, so the sound must travel about 24 cm (it goes to the target and is reflected back, so it travels the distance twice).

Using the cursors on my scope, I checked the time the echo pin was high and found it was 0.742 ms (sorry, was unable to focus better on the screen).

Using the formula we have 2 * s = 340 * (0.742/1000)  => s =  170 * (0.000742) = 0.126 m = 12.6 cm which is reasonably accurate (I calculated 12 cm from the edge of the emitter, but I guess the sound is emitted a bit back of that).

Arduino has a nice function to detect the duration of a pulse (so you don' t need to actively poll the pin, it does it for you), it is called pulseIn() and returns the duration of the pulse in microseconds.

Let's see the test sketch.

#define triggerPin 8
#define echoPin 9

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

float distance() // distance in mm
  long pulse = 0;
  digitalWrite(triggerPin, LOW);  
// force a low/high transition 
  digitalWrite(triggerPin, HIGH);
  digitalWrite(triggerPin, LOW);
  pulse = pulseIn(echoPin, HIGH);
  return pulse * 0.17; 

void loop() {
  Serial.println(" mm");

From where the 0.17 constant is coming?

The pulse is measured in microseconds, but the speed of sound is measured in meters per seconds (340) => we need to divide by 1.000.0000.
However we want to measure in millimeters, not meters, so we need to multiply by 1.000.
We also know we have to divide by two since the sound travels the distance twice (to the obstacle and back).

340 / 1000000 * 1000 /2 = 0.17

With this simple formula we can easily calculate the distance of obstacles in front of our robot.

Each sensor, according to the datasheet, covers a 15 degree angle and for our rover we will probably want to detect obstacles on a 90 degree angle on the front side.
Probably we will achieve this with 3 sensors, one of which (the center one) will also be mounted on a stepping motor to allow the rover to scan the area around.
In normal operation the center sensor will be still and facing forward, the other two sensors will face 45 degrees (or maybe 30 which should be more than enough to avoid interference) on the left and right.
It is in theory possible that small obstacles can land between two sensors, but as the rovers moves towards them, it is unlikely they will never be detected.
We then might start the scanning upon detection of a near obstacle, to assess in detail the scene in front.

To ensure there will be no interference between the center sensor and the two side ones, we will activate them separately, plus the Arduino is not capable of measuring multiple pulses at the same time anyways.

The Idea of having a moving sensor is to allow scanning of the area to " map"  the space in front of the robot.
Obviously we will need to mount this scanning sensor a bit higher than the others, else it might be in the shadow of the other sensors.
A possible solution would be to mount the two side sensors BELOW the chassis and the scanning one on top.

As you can see in the picture, the sensor and the stepping motor would fit below the chassis without reducing the clearance since they do not pass the level of the wheel motor.

Some versions of the rover have two layer in the chassis, not the one I bought, but if needed I might add another layer protecting the circuitry mounted in the bottom part.

No comments: