Distance measurement with ultrasonic sensor HC-SR04 (Python)
This tutorial guides you through wiring a HC-SR04 ultrasonic sensor to a Raspberry Pi. A distance to an object can then be measured by a run-time measurement.
Before starting you should read What is a ROS Wrapper?, Write a ROS Wrapper (Python) and Package and Test Your Driver.
In this project, an ultrasonic sensor module (HC-SR04) is put into operation. The working principle of an HC-SR04 is explained. It is also described how a measurement with ultrasound works and on which essential factors it depends. For the commissioning of the sensor, we take a Raspberry Pi as an example.
What is ultrasonic?
Ultrasound is a high-pitched sound wave whose frequency exceeds the audible range of human hearing.
Humans can hear sound waves that vibrate in the range of about 20 times a second (a deep rumbling noise) to 20,000 times a second (a high-pitched whistle). However, ultrasound has a frequency of more than 20,000 Hz and is therefore inaudible to humans.
What is an ultrasonic sensor?
An ultrasonic sensor is generally a sensor that determines the distance to an object via a run-time measurement. It cannot classify which object is located at this distance. As shown in the following figure, the ultrasonic sensor emits ultrasonic waves. This is where it gets its name. At an object, these ultrasonic waves are reflected and reflected back. A membrane on the sensor receives these ultrasonic waves. Since it is known how fast the carrier medium is, a distance to the object is determined based on the time interval between sending and receiving the ultrasonic waves. We will take a closer look at what this means in concrete terms below.
The HC-SR04 sensor
An HC-SR04 ultrasonic distance sensor actually consists of two ultrasonic transducers. Ultrasonic transducers and ultrasonic sensors are devices that generate or sense ultrasound energy. They can be divided into three broad categories: transmitters, receivers and transceivers. Transmitters convert electrical signals into ultrasound, receivers convert ultrasound into electrical signals, and transceivers can both transmit and receive ultrasound.
The HC-SR04 sensor looks like this:
One acts as a transmitter that converts the electrical signal into 40 KHz ultrasonic sound pulses. The other acts as a receiver and listens for the transmitted pulses.
When the receiver receives these pulses, it produces an output pulse whose width is proportional to the distance of the object in front.
This sensor provides excellent non-contact range detection between 2 cm to 400 cm (~13 feet) with an accuracy of 3 mm.
Since it operates on 5 volts, it can be connected directly to a Raspberry Pi or any other 5V logic microcontroller.
Technical Specifications
Operating Voltage |
DC 5V |
Operating Current |
15mA |
Operating Frequency |
40KHz |
Max Range |
4m |
Min Range |
2cm |
Ranging Accuracy |
3mm |
Measuring Angle |
15 degree |
Trigger Input Signal |
10µS TTL pulse |
Dimension |
45 x 20 x 15mm |
Pinout
Let’s take a look at its pinout.
VCC supplies power to the HC-SR04 ultrasonic sensor. You can connect it to one of the 5V outputs from your Raspberry Pi.
Trig (Trigger) pin is used to trigger ultrasonic sound pulses. By setting this pin to HIGH for 10µs, the sensor initiates an ultrasonic burst.
Echo pin goes high when the ultrasonic burst is transmitted and remains high until the sensor receives an echo, after which it goes low. By measuring the time the Echo pin stays high, the distance can be calculated.
GND is the ground pin. Connect it to the ground of your Raspberry Pi.
Operating principle
It all starts when the trigger pin is set HIGH for 10µs. In response, the sensor transmits an ultrasonic burst of eight pulses at 40 kHz. This 8-pulse pattern is specially designed so that the receiver can distinguish the transmitted pulses from ambient ultrasonic noise.
These eight ultrasonic pulses travel through the air away from the transmitter. Meanwhile the echo pin goes HIGH to initiate the echo-back signal.
If those pulses are not reflected back, the echo signal times out and goes low after 38ms (38 milliseconds). Thus a pulse of 38ms indicates no obstruction within the range of the sensor.
If those pulses are reflected back, the echo pin goes low as soon as the signal is received. This generates a pulse on the echo pin whose width varies from 150 µs to 25 ms depending on the time taken to receive the signal.
Calculating the distance
The width of the received pulse is used to calculate the distance from the reflected object. This can be worked out using the simple distance-speed-time equation we learned in high school. An easy way to remember the equation is to put the letters in a triangle.
Let us take an example to make it more clear. Suppose we have an object in front of the sensor at an unknown distance and we receive a pulse of 500µs width on the echo pin. Now let’s calculate how far the object is from the sensor. For this we will use the below equation.
Distance = Speed x Time
Here we have the value of time i.e. 500 µs and we know the speed. Of course it’s the speed of sound! It is 340 m/s. To calculate the distance we need to convert the speed of sound into cm/µs. It is 0.034 cm/μs. With that information we can now calculate the distance!
Distance = 0.034 cm/µs x 500 µs
But we’re not done yet! Remember that the echo pulse indicates the time it takes for the signal to be sent and reflected back. So to get the distance, you have to divide your result by two.
Distance = (0.034 cm/µs x 500 µs) / 2 Distance = 8.5 cm
Now we know that the object is 8.5 cm away from the sensor.
Wiring it to the Raspberry Pi
For this example, I took the Raspberry Pi because it not only allows us to cleverly connect various sensors and actuators for our tutorials, but also because ROS can be installed on the Raspberry Pi. I could also connect the sensors and actuators to an Arduino, but would need accordingly a computer on which ROS is installed, which connects serially with the Arduino. The same applies to similar microcontrollers.
Please have a look on this:
There are 4 pins on the ultrasonic module which are connected to the Raspberry:
Sensor pin |
Raspberry Pi pin |
VCC |
Pin 2 (VCC) |
GND |
Pin 6 (GND) |
TRIG |
Pin 12 (GPIO18) |
ECHO |
to ECHO the 330 Ω resistor is connected. At its end a connection goes to pin 18 (GPIO24) and via the 10k Ω resistor a connection to pin6 (GND) |
We do this because the GPIO pins can only handle max. 3.3V. The connection to GND is due to this, so that a clear signal is present at GPIO24. If no pulse is sent, the connection to GND makes the signal 0, if there is a signal 1. If no connection to GND would be made, the state would be undefined (0 or 1 depending on chance), so it would not be unique.
Preparations on the Raspberry Pi
We need to make sure that we can use the GPIO pins. GPIO stands for General Purpose Input Output. A GPIO is a general purpose digital contact pin on an integrated circuit (IC) whose behavior, whether as an input or output contact, can be freely determined by logic programming. GPIO contacts are not given a purpose, so they are unassigned by default. Specifically, this means that we can use a GPIO pin either as input or as output. We can also do both alternately one after the other. This is left to our programming.
First we need to update the packages and paths.
sudo apt-get update sudo apt-get upgrade
For the library to work properly afterwards, we need python-dev.
sudo apt-get install python-dev
If we have pip installed we can install it via pip:
pip install RPi.GPIO
If pip is not installed then we load the Python GPIO library (the latest version is available here, adjust version if necessary: https://pypi.python.org/pypi/RPi.GPIO ).
sudo wget https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-0.7.1.tar.gz
Now unpack
tar zxvf RPi.GPIO-*
and change to the directory
cd RPi.GPIO-*
Now you can install the library.
sudo python setup.py install
Programming the distance measurement
We now create our Python script:
# import libraries import RPi.GPIO as GPIO import time # GPIO Modus (BOARD / BCM) GPIO.setmode(GPIO.BCM) # assign GPIO Pins GPIO_TRIGGER = 18 GPIO_ECHO = 24 # Set direction of GPIO pins (IN --> Input / OUT --> Output) GPIO.setup(GPIO_TRIGGER, GPIO.OUT) GPIO.setup(GPIO_ECHO, GPIO.IN) def distance(): # set trigger to HIGH GPIO.output(GPIO_TRIGGER, True) # set trigger after 0.01 ms to LOW time.sleep(0.00001) GPIO.output(GPIO_TRIGGER, False) startTime = time.time() arrivalTime = time.time() # store startTime while GPIO.input(GPIO_ECHO) == 0: startTime = time.time() # store arrivalTime while GPIO.input(GPIO_ECHO) == 1: arrivalTime = time.time() # Time difference between start and arrival timeElapsed = arrivalTime - startTime # multiply by the speed of sound (34300 cm/s) # and divide by 2, there and back again distance = (timeElapsed * 34300) / 2 return distance if __name__ == '__main__': try: while True: distance = distance() print ("Measured distance = %.1f cm" % distance) time.sleep(1) # When canceling with CTRL+C, resetting except KeyboardInterrupt: print("Measurement stopped by user") GPIO.cleanup()
This will now measure the distance every second until the script is aborted using CTRL+C.
We have learned how to handle the GPIO pins to send an output once and receive an input once. The output refers to the TRIG pin of the sensor. The trigger signal is an ultrasonic wave that the sensor emits. For the returned echo we use the ECHO pin of the sensor, which we connect to the Raspberry Pi via voltage divider. This GPIO pin now refers to the input. Since we know the speed of sound (carrier medium), we determine an elapsed time between the start time when we release the trigger and the arrival time when the echo comes back. This is called run-time measurement.
In the next chapter, we'll look at Speed measurement with ultrasonic sensor HC-SR04 (Python).