Ultrasonic echolocation is common practice in many areas including nature itself. We all know how bats or dolphins navigate – they emit ultrasonic waves and depending on the time delay of reflected echoes, they can determine the distance from obstacles or catch. From an engineering perspective it is relatively easy to measure distances with ultrasound – all you need to know is sound speed in the air and time delay between sent and received pulses.
L is the measured distance; CAIR – ultrasound speed; t – the time between transmitted and received pulses.
The accuracy of measured distance mainly depends on air temperature. The following formula can calculate sound speed in the air approximately :
For instance, at 25ºC the speed of sound in dry air CAIR = 346.13 m/s. If you want greater accuracy, you should also measure temperature to adjust sound speed.
There are several cheap ultrasonic echolocation modules available, but probably most known and used is HC-SR04. You can find lots of projects built around them including distance meters, robots, radars, thickness, and security barrier, parking, and liquid level. These modules have pretty good characteristics that make them so popular:
|Working Voltage||DC 5V|
|Working Frequency||40 kHz|
|Measuring Angle||15 degree|
|Trigger Input Signal||10µS TTL pulse|
|Dimension||45 x 20 x 15mm|
Interfacing module is straight forward – it comes with only four pins. Two of them are power (VCC and GND), one pin is Trigger pin and one Echo pin. The hard work of transmitting and receiving signals is done by the module itself. To perform basic measurement send at least 10us pulse to Trigger pin and wait for rising edge signal on Echo pin. Once raising edge is detected start microcontroller counter and wait for a falling edge on Echo pin. Pulse on the Echo is the time between transmit and receive signals. Having time delay you can calculate the distance from the obstacle by the formula above.
Running HC-SR04 with Arduino and LCD keypad shield
Let’s build a prototype using Arduino, LCD keypad shield and HC-SR04. The distance will be displayed on LCD. We will use a button to implement couple of different functionalities. Also, it will be interesting to see how accurate the measured distance is comparing with tape meter. LCD keypad shield is connected to Arduino as reviewed previously here. So it occupies pins 8, 9, 4, 5, 6, 7, 10 (backlight) and analog 0 for buttons. So we are left with 1 to 5 analog pins and 0, 1, 2, 3, 11, 12, 13 digital. We will leave 0 and 1 digital pins for serial output and use digital pin 2 for HC-SR04 trigger and digital 3 for Echo. Also, we need to connect VCC and GND.
Additionally we want to monitor environment temperature to calculate sound speed in order to achieve better accuracy. So for this we are going to use DS18D20 where sense pin is connected to A1 pin of Arduino pulled up to VCC with 4.7k resistor.
Programming Arduino is relatively easy, especially when special libraries are used. First of all, let us deal with temperature measurement. To read temperature value, we need two libraries: OneWire and DallasTemperature. Using them life becomes much more comfortable as you only need to initialize temperature sensor, assign pin and read its value.
The same situation is with LCD keypad. The LCD is controlled with standard Arduino library, and no additional libraries are required. If you need to work with buttons that are read with a single analog pin, then you should get LCDKeypad.zip library which makes key reading more robust. We are not going to analyze them more deeply, and the working is evident in the source code.
We have used temperature to calculate sound speed in the air. A simple empirical formula is used to get speed values in cm/us:
sound_speed = 20.0457*sqrt(273.15+temp1)/10000.0; //cm/us
Let’s pay a bit attention on how we can read distance out of HC-SR04 sensor. We have assigned Arduino pin 2 for Trigger and pin 3 for Echo signals. So, first of all, we need to get pulse time information which indicates the duration of ultrasonic pulse flight and return. There is a simple routine to trigger sensor and get time value in microseconds:
digitalWrite(Trigger, LOW); delayMicroseconds(5); digitalWrite(Trigger, HIGH); delayMicroseconds(10); digitalWrite(Trigger, LOW);
First of all, we give short 5us LOW pulse before sending a clean high pulse. High trigger pulse needs to be at least 10us. When trigger pulse drops LOW, the sensor sends eight 40kHz square pulses. At same time Echo pin becomes HIGH until bounced back signals are received. Arduino needs to capture the duration of the HIGH state of Echo pin. Luckily Arduino comes with the handy function
pulselength = pulseIn(Echo, HIGH); //microseconds
Which returns time duration in microseconds of pin state high.
Once we have time pulse duration and sound speed we can calculate the distance using simple formula:
//centimeters distancecm = sound_speed * (pulselength/2); //inches distancein = distancecm * 0.39370;
With keypad buttons UP and DOWN we can change centimeters units to inches. With LEFT and RIGHT buttons we can switch secondary screen where pulse time and sound speed values are visible.
And with SELECT button we can call REL function which allows measuring relative distances from position where button was pressed.
To evaluate measuring accuracy, I have constructed simple rig with measuring tape.
I didn’t do any statistical analysis, just a simple comparison of two values. As you can see with tape meter, I get 39.7cm while with SR04 sensor 38.9. The difference is 0.8cm.
Practically we cannot expect greater accuracy without additional measures. We have calculated sound speed by taking the only temperature into account. But other factors also influence sound speed – air density which in it hand depends on altitude. Also, there is an influence of sensor position, measured surface properties, and temperature measurement accuracy. In my opinion, 0.3cm accuracy can only be reached in a controlled environment where sound of speed is known for real or is directly measured.
Download source code (echolocator.zip) to give it a try.