You are on page 1of 10

instructables

Ultrasonic Range Finder

by lingib

This instructable describes how to create a non- The accuracy is typically +/- 3mm depending on
contact range-finder using an Arduino and an HC- distance, air temperature, and humidity.
SR04 ultrasonic module to measure distances in the
range 2cm – 400cm.

Step 1: Parts List

Very few parts are required:

1 only HC-SR04 ultrasonic module or similar


1 only Arduino Uno R3
4 only Arduino male-female jumper wires

All items were obtained from https://www.aliexpress.com/

Ultrasonic Range Finder: Page 1


Step 2: Wiring Diagram

Only four wires are required to complete this project.

The wiring diagram is shown in photo1.

Step 3: Theory

The HC-SR04 ultrasonic range-finder module (photo 1) provides non-contact measurements in the range 2cm –
400cm. The accuracy is typically +/- 3mm depending on distance, air temperature, and humidity.

For greatest accuracy the target area should be at least 0.5 square meters. Best results are obtained when the
transducer is pointing directly at the target. Useable results, however, are possible within an imaginary “cone” of
+/- 15 degrees.

Interfacing the HC-SR04 to an Arduino is extremely simple as, apart from the two supply pins, only two wires,
“Trig” (trigger) and “Echo”, are required.

A 10uS (microsecond) trigger pulse must be applied to the “Trig” pin to start each measurement.

On receipt of a trigger pulse the module emits an eight cycle “burst” at a frequency of 40kHz (kilohertz) after which
the “Echo” line goes HIGH. There is a short 430uS interval between the trigger pulse and the rising edge of the
“Echo” pin during which time high energy +/-10 volt charges are built up in the transmitter circuit prior to the
ultrasonic burst.

The “Echo” pin drops LOW on receipt of an echo signal or 210mS whichever comes first.

[ Note:
If you block the ultrasonic signals (I used a rolled up sock against the transducers), you will observe a distance
reading of 3550cm which is outside the sensor range of approximately 400cm.

Beyond 400cm the distance readings will suddenly jump to 3550cm. The reason for this follows:

Ultrasonic Range Finder: Page 2


In normal operation the measure() function completes its measurement in less than 25mS (423cm) then waits a
further 25mS until the task scheduler next sets TaskFlag1 "TRUE".

Should an echo not be received, the task scheduler will continue to set TaskFlag1 "TRUE" every 50mS until the
HC-SR04 times out after 210mS and the Echo pin drops low. All 10uS start pulses generated by the measure()
function during this time are ignored by the HC-SR04.

The timeout value of 210mS corresponds to a distance of 3550cm ... hence the sudden jump in the distance
reading.

The important point is that all distance readings less than 400cm are correct. ]

Typical waveforms

Waveforms for 5cm, 10cm, 20cm, and 200cm distances are shown in photos 2,3,4, and 5.

The top trace in each photo is the “Trig” pin ... the lower trace in each photo is the “Echo” pin.

The duration of each “Echo” pulse can be calculated by multiplying the trace length by the “uS/div” value shown in
the lower-right corner of each photo.

Calculating the distance

The exact distance can be calculated from the formula:

distance (cm) = pulse-length * speed-of-sound / 2 * 100 ......................................... (1)

This assumes that the “speed-of-sound” is 340m/S, and that the echo-distance is twice the actual distance.

The distance can also be calculated using the formula:

distance (cm) = pulse-length (uS) / 59 ............................................................................. (2)

The exact distance can be obtained by adjusting the constant value of 59.

[ Note:
The value of 59 for the constant is derived as follows:

The speed of sound is approximately 340m/S which is 0.034cm/uS (centimeters/microsceond).

The reciprocal of 0.034cm/uS is 29.412uS/cm which, when multiplied by 2 to allow for the return path, equals
58.824 or 59 when rounded. ]

Example 1:

Substituting a pulse-length of 2400uS into equation (1) we get:

distance = 2400/1000000 * 340/2 * 100 = 40.8cm

Example 2:

Ultrasonic Range Finder: Page 3


Substituting a pulse-length of 2400uS into equation (2) we get:

distance = 2400/59 = 40.7cm

Ultrasonic Range Finder: Page 4


Step 4: The Code

The code comprises a “measure()” function that is called once every 50mS using the task-scheduler described in
instructable https://www.instructables.com/id/Multi-task-Your-...

The measure() function comprises the following code:

// ----- generate 10uS start pulse


digitalWrite(Trig,HIGH);
delayMicroseconds(10);
digitalWrite(Trig,LOW);

// ----- measure the distance


while (!digitalRead(Echo)); //wait for Echo pin to go high
start_time = micros();
while (digitalRead(Echo)); //wait for Echo pin to go low
finish_time = micros();
time_taken = finish_time - start_time;
Distance = ((float)time_taken)/59;

The complete code, “Ultrasonic_range_finder.ino”, is attached.

Copy the contents of this text file to an Arduino sketch, save it as "Ultrasonic_range_finder" (without the quotes),
then compile and upload it to your Arduino.

Download
https://www.instructables.com/ORIG/F2U/X2XC/JGWJACWP/F2UX2XCJGWJACWP.ino

Step 5: Measuring Distances

To view the distance readings click “Tools|Serial “59” value for “Distance” until an exact reading is
Monitor” and set the speed to 115200 bauds. displayed.

The distance readings may be calibrated by placing Click here to view my other instructables.
an object along a ruler then adjusting the constant
I add a 4x20 LCD IIC display and another distance measurement sensor which uses a known
distance to determine the speed of sound in air. I then used that value over the unknown distance
to create an auto calibration circuit.
// Using the SainSmart 20x4 LCD through the I2C interface of
// SDA and SCL found on the Arduino boards UNO and MEGA
//Reading Temperature with LM35 Sensor
//Measuring in both scales Celsius and Fahrenheit
//Arduino Thermometer Shield
//DFRobot.com
//Compatible with the Arduino IDE 1.0
//Library version:1.1
/* Ping))) Sensor

Ultrasonic Range Finder: Page 5


This sketch reads a PING))) ultrasonic rangefinder and returns the
distance to the closest object in range. To do this, it sends a pulse
to the sensor to initiate a reading, then listens for a pulse
to return. The length of the returning pulse is proportional to
the distance of the object from the sensor.
The circuit:
* +V connection of the PING))) attached to +5V
* GND connection of the PING))) attached to ground
* SIG connection of the PING))) attached to digital pin 11
http://www.arduino.cc/en/Tutorial/Ping
created 3 Nov 2008
by David A. Mellis
modified 30 Aug 2011
by Tom Igoe
modified 22 Dec 2017
by Patrick Scott
This example code is in the public domain.
*/
#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//Arduino Sample Code for SHT1x Humidity and Temperature Sensor
//www.DFRobot.com
//Version 1.0
#include <SHT1x.h>
// Specify data and clock connections and instantiate SHT1x object
#define dataPin 2
#define clockPin 3
SHT1x sht1x(dataPin, clockPin);
float temp_c;
float temp_f;
float humidity;
// this constant won't change. It's the pin number
// of the sensor's output:
// We will be using two sensors
// one to correct to unknown variables
// which include humidity, barometric pressure, and temperature
const int pingPin1 = 9, pingPin2 = 8; // Cal = 9, Dist = 8
const int AvgDSz = 8;

Ultrasonic Range Finder: Page 6


float duration1, duration2, avg1, avg2, sum1, sum2;
double cm, cal, inches, usec2cm;
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20 chars and 4 line display
//float AvgC, TotC, TC;
float tempC;
float tempF;
int //tempPin = 6, // A3 => analog pin 3
AvgTSz = 8; // number of samples for average
void setup()
{
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
SetupPing(pingPin1);
SetupPing(pingPin2);
duration1 = ReadPing(pingPin1);
sum1 = duration1 * AvgDSz;
avg1 = duration1;
delay(250);
duration2 = ReadPing(pingPin2);
sum2 = duration2 * AvgDSz;
avg2 = duration2;
delay(250);
lcd.init(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
//TC = analogRead(tempPin);
//TotC = TC * AvgTSz; // form an average
}
void loop()
{
// Read values from the sensor
temp_c = sht1x.readTemperatureC();
temp_f = sht1x.readTemperatureF();
humidity = sht1x.readHumidity();
//TC = analogRead(tempPin);
//TotC -= TotC / AvgTSz; // make a hole in average
//TotC += TC; // fill it
//TC = TotC / AvgTSz; // get new average
lcd.setCursor(10, 0);

Ultrasonic Range Finder: Page 7


lcd.print(humidity,1);
lcd.print("% ");
//lcd.print(TC,1);
//tempC = (500.0 * TC)/1024.0; // 500 10mv Steps / 1024 Steps
//tempF = ((tempC*9)/5) + 32;
lcd.setCursor(0, 0);
lcd.print(temp_c,1);
lcd.print("'C");
lcd.setCursor(0, 1);
lcd.print(temp_f,1);
lcd.print("'F");
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
// Create a calibration check for 8 inches
SetupPing(pingPin1);
duration1 = ReadPing(pingPin1);
// create new average for calibration
sum1 = sum1 - avg1;
sum1 = sum1 + duration1;
avg1 = sum1 / AvgDSz;
// now use the calibration value
SetupPing(pingPin2);
duration2 = ReadPing(pingPin2);
sum2 = sum2 - avg2;
sum2 = sum2 + duration2;
avg2 = sum2 / AvgDSz;
// convert the time into a distance
lcd.setCursor(13, 1);
lcd.print(sum2);
lcd.setCursor(13, 2);
lcd.print(avg2);
usec2cm = CentimetersToMicroseconds(avg2);
cm = microsecondsToCentimeters(avg1, usec2cm);
// Cal Reading should be 929.088 for 16 cm times 2
cal = microsecondsToCentimeters(avg2, 29.034); // check on original distance standard
inches = cm/2.54;
if(inches > 200)
{
lcd.setCursor(0, 2);

Ultrasonic Range Finder: Page 8


lcd.print("out of range");
}
else
{
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 2);
lcd.print(inches);
lcd.print(" in ");
lcd.setCursor(0, 3);
lcd.print(cm);
lcd.print(" cm ");
lcd.setCursor(13, 3);
lcd.print(cal);
}
delay(200);
}
double CentimetersToMicroseconds(long usec2)
{
// using a know fixed distance calculate the usec per cm
// using 16 cm find the usec
return usec2 / 32;
}
//double microsecondsToInches(long microseconds)
//{
// // According to Parallax's datasheet for the PING))), there are
// // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// // second). This gives the distance travelled by the ping, outbound
// // and return, so we divide by 2 to get the distance of the obstacle.
// // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
// return (microseconds / 2.0) / 73.746;
//}
double microsecondsToCentimeters(long microseconds, double usec)
{
// The speed of sound is 340 m/s or 29.034 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return (microseconds / 2.0) / usec;
}

Ultrasonic Range Finder: Page 9


void SetupPing(int iPin)
{
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(iPin, OUTPUT);
digitalWrite(iPin, LOW);
delayMicroseconds(2);
digitalWrite(iPin, HIGH);
delayMicroseconds(5);
digitalWrite(iPin, LOW);
}
long ReadPing(int iPin)
{
// The same pin is used to read the signal from the PING))): 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(iPin, INPUT);
return (pulseIn(iPin, HIGH));
}

Thank you for sharing your project :)


Your use of a second sensor for auto-calibration is clever.
Does the distance reading vary much between say day and night without the autocalibration?
I have not monitored the changes, just knew that there would be changes.

where is photo1??

Photo 1 is the first photo shown in any given step.


Click on any photo and that photo will be displayed along with arrows to the left and right. Now
click the left-hand arrow until it disappears. Photo 1 is the left-most image.
For example, in "Step 3", Photo 1 shows the HC-SR04 ultrasonic sensor module, and photos
2,3,4, and 5 show waveforms for distances of 5cm, 10cm, 20cm, and 200cm.
Restart your browser if you see no photos ...
How hard would it be to also have a display?
Sort of like the backup parking sensors with a progressive lighting of LEDs.
A possible solution is given in the above answers.

GREAT IDEA!...

Ultrasonic Range Finder: Page 10

You might also like