Distance sensing with Raspberry Pi and an HC-SR04 sensor
I randomly selected this HC-SR04 distance sensor from a “45 in 1 sensor set” I bought, with the idea to try out the GPIO pins available on the Raspberry Pi. After some tinkering, I got a rudimentary setup and some sensor readouts.
Bill of Materials
- HC-SR04 sensor
- Resistors: $1.5k\Omega$, $2.2k\Omega$
- Raspberry Pi
- Breadboard
- jumper cables
HC-SR04, a Distance sensor
The HC-SR04 is an ultrasonic distance sensor, it uses sound waves to measure distance. I would be happy to reference to a datasheet, but to my surprise, it was a hard time finding one. Information seems really scattered all over the internet. As much information as possible will be consolidated on this page so you have it all in one place. And, if you think something might be incomplete or incorrect, don’t hesitate to put your questions or remarks in the comments section below! All used references will be added to the references section below.
The figure below shows the front side of the sensor.

On the left lower-side of the board, we notice a “T” and the right lower-side, we notice an “R”. By deduction, these should stand for Transmitter and Receiver respectively. The transmitter will send the sound pulse and the receiver side will capture it after it has bounced off the surface to which the distance is measured.
4 pins can be seen, Vcc, Trig, Echo and Gnd.
The image below shows the back side of the HC-SR04.

The voltage of Vcc depends on whether you are using an older or newer sensor. The older version seems to be requiring a $5V$ power supply, whereas the newer component could be run with a $3.3V$ power supply. You can find the differentiation of the older vs the newer component in the image below. It took me an AliExpress site [1] to discover this.
| Older component (5V) | Newer component (3.3V - 5V) |
|---|---|
![]() | ![]() |
The Trig and Echo pin are both related to the functionality of the echolocation. According to [2], the module can be triggered to the Trig pin to emit a sonar wave consisting of a series of 8 pulses at 40kHz. When an object is in front of the transmitter, the wave will reflect and arrive at the receiver, which will in turn trigger the Echo pin.
Connecting the HC-SR04 to the Raspberry Pi
We ultimately need to connect the 4 pins of this sensor to the Raspberry Pi. I like to start out by referencing [3] which gives a clear view of the 40-pin GPIO header that is installed on the Raspberry Pi board. I like starting out by connecting the $Gnd$ and $V_{cc}$ pins. The $Gnd$ pin will be connected to pin 6 and since the Vcc is required to be connected to $5V$, I’ll be connecting this one to pin 2. In [2] they mention how the $V_{cc}$ pin should be brought up after the $Gnd$ pin is connected. I’m not quite sure if this is a typical behavior when starting up the raspberry Pi. However, if you are still on a breadboard, you could manually enforce this behavior by disconnecting and reconnecting the $V_{cc}$ pin to ascertain this.
The Trig pin of the sensor is connected to some available GPIO pin, like GPIO17, available on pin 11. We notice how Raspberry Pi GPIO pins can only be set to high ($3.3V$) or low ($0V$) [3]. Since [4] indicates the trigger input signal should be a TTL pulse, every voltage above $2V$ could be considered as high.
The Echo pin is also connected to an available GPIO pin, here GPIO27, or pin 13 on the header was chosen for this connection. However the connection happens indirectly in this case! The Echo pin is an output pin, and, whenever this pin is driven high, it will be pulled up to the voltage of its Vcc pin. So in this case it will be pulled up to $5V$ and you must not connect this to a Raspberry Pi GPIO pin, which is only able to handle a maximum of $3.3V$. A voltage divider (using resistors R1 and R2) is used to keep the voltage in the safe zone.
The final schematics can be seen in the image below.

Using the formula for the voltage divider, we get: $V_{R2} = \frac{R2}{R1+R2}V_{Echo}$. An $R1 = 1.5k\Omega$ and an $R2 = 2.2k\Omega$, results in $V_{R2} \approx 0.595V_{Echo}$, so when $V_{Echo} = 5V$, we will have a maximum of $V_{R2} \approx 2.97V$. A voltage well below the maximum of $3.3V$ and high enough to be seen as a logical 1 by the GPIO pin.
Raspberry Pi Code
Now that we have our hardware all set up, we can start to write the necessary code to interface the distance sensor. Python and the RPi.GPIO module [5] were used as an easy way into getting some initial results from this sensor. The code can be seen hereafter:
Python
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
pin_trig = 11
pin_echo = 13
time_sleep_next_measurement = 60E-3
def trigger_pin_trig():
#Set the trig pin high for 10us
GPIO.output(pin_trig, GPIO.LOW)
time.sleep(5E-6)
GPIO.output(pin_trig, GPIO.HIGH)
time.sleep(10E-6)
GPIO.output(pin_trig, GPIO.LOW)
def read_echo_duration():
start = GPIO.wait_for_edge(pin_echo, GPIO.RISING, timeout=1000)
if start is None:
print("Timeout occurred")
return None
t0=time.time()
end = GPIO.wait_for_edge(pin_echo, GPIO.FALLING, timeout=1000)
if end is None:
print("Timeout occurred")
return None
t1=time.time()
return t1-t0
def calculate_distance_cm(elapsed_time):
return (elapsed_time*343/2)*100
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin_trig, GPIO.OUT, initial=GPIO.LOW) #Trig initially low
GPIO.setup(pin_echo, GPIO.IN) #Echo
time.sleep(1)
try:
while True:
#Allow some time between measurements
time.sleep(time_sleep_next_measurement)
trigger_pin_trig()
echo_duration = read_echo_duration()
if echo_duration is None:
continue
print("cm: ", calculate_distance_cm(echo_duration))
except KeyboardInterrupt:
print("\nMeasurement stopped")
finally:
print("Program ending...")
print("Cleaning up GPIO...")
GPIO.cleanup()
print("Cleaned up GPIO")
print("Program ended")
Code discussion
What we have here is an endless while-loop that is continuously printing the measured distance by the sensor. In order to start a measurement, we need to trigger the Trig pin using a pulse for 10us. The sensor will then send 8 sonic pulses which it uses to detect if they get reflected back. As soon as the reflection is detected, the sensor will pull the Echo pin high for a duration proportional to the time it took for the detection of the reflected pulses.

The calculate_distance_cm() function then calculates the distance in centimeters. Knowing that the speed of sound is 343 $m/s$ and the elapsed_time is in seconds, the distance is simply how long the sound pulse traveled back and forth between transmission and reception. Since the time in flight of the sonic pulses is back and forth, you still need the division by 2. The multiplication by 100 is then simply to convert the meters in centimeters.
The practical measurement range for the HC-SR04 is about 2 cm to 400 cm. Distances below 2 cm fall within the sensor’s “blind zone” due to transducer ringing, and readings above 4 m often become unreliable as the reflected signal weakens.
Sensor calibration
It could be useful to think about calibrating the sensor, but that might be a subject for another post. Also, the speed of sound is a function of temperature and humidity. The 343 $m/s$ might therefore need to be compensated as well.
Also, this sensor might be sensitive to background 40kHz noise. Therefore, if using multiple of these sensors, it might be best to trigger them sequentially.
Noteworthy
I encountered a comment from a reader that mentioned that the sensor can be used for measuring the liquid level in a container. Nevertheless, when the container was sealed off, with the sensor inside, condensation could form on the reader, affecting accurate readouts. I did not experiment with this, but, if you would like to use it this way, it might be worth considering. Please note that there are some other, condensation and splash water proof distance sensors like the JSN-SR04T
Useful references
- [1]: Ali Express product page comparing 5V and 3.3V versions of HC-SR04 Shows the difference between 5V and the 3.3V-5V version.
- [2]: Shop page with HC-SR04 specs and behavior
- [3]: Raspberry Pi GPIO pinout documentation
- [4]: What looks to me like an unofficial datasheet
- [5]: RPI.GPIO - a package that provides a Python module to control the GPIO on a Rapsberry Pi


