HC-SR04: Difference between revisions
updated the pin assignment image |
|||
Line 31: | Line 31: | ||
* ''Vcc'' for the 5 V supply voltage. | * ''Vcc'' for the 5 V supply voltage. | ||
[[File:sensor_HC-SR04_pin_assignment.png | 120px]] | |||
<p style="text-align:justify; margin-top:1em"> | <p style="text-align:justify; margin-top:1em"> | ||
The sensor circuit is designed for TTL-level signals (0 V for LOW and 5 V for HIGH) while the GPIO pins of most microcontrollers and single-board-computers (SBC) are designed for 3.3 V. We definitely need to drop the signal coming from the ''Echo'' pin to 3.3 V, otherwise we risk damaging the connected GPIO input. One would assume that we also need to transform the 3.3 V trigger signal from the GPIO to 5 V before feeding it to the ''Trig'' pin. Such a circuit is depicted below, where a simple voltage divider is used on ''Echo'' and a BJT transistor is used to step up the voltage for ''Trig''. | The sensor circuit is designed for TTL-level signals (0 V for LOW and 5 V for HIGH) while the GPIO pins of most microcontrollers and single-board-computers (SBC) are designed for 3.3 V. We definitely need to drop the signal coming from the ''Echo'' pin to 3.3 V, otherwise we risk damaging the connected GPIO input. One would assume that we also need to transform the 3.3 V trigger signal from the GPIO to 5 V before feeding it to the ''Trig'' pin. Such a circuit is depicted below, where a simple voltage divider is used on ''Echo'' and a BJT transistor is used to step up the voltage for ''Trig''. |
Revision as of 2025-05-02T18:13:25
The information here about the HC-SR04 ultrasonic distance sensor is based on vendor datasheets and various online sources, including a ModMyPi article for Raspberry Pi and the Elecfreaks user guide for integration into Arduino.
Sensor Properties
Operating Voltage | 5 V DC |
Operating Current | 15 mA |
Operating Frequency | 40 kHz |
Nearest Range | 3 cm |
Farthest Range | 4 m |
Beam Angle | 15 degrees |
Input Trigger Signal | 10 μs TTL pulse (low: 0-0.8 V, high: 2 V to VCC, where VCC = 5 V ±10%) |
Output Echo Signal | Output TTL level signal, proportional to range |
Wiring and Voltage Levels
The sensor module has four pins:
- Gnd for Ground,
- Echo for the ultrasonic echo output signal,
- Trig for the ultrasonic burst trigger signal input, and
- Vcc for the 5 V supply voltage.
The sensor circuit is designed for TTL-level signals (0 V for LOW and 5 V for HIGH) while the GPIO pins of most microcontrollers and single-board-computers (SBC) are designed for 3.3 V. We definitely need to drop the signal coming from the Echo pin to 3.3 V, otherwise we risk damaging the connected GPIO input. One would assume that we also need to transform the 3.3 V trigger signal from the GPIO to 5 V before feeding it to the Trig pin. Such a circuit is depicted below, where a simple voltage divider is used on Echo and a BJT transistor is used to step up the voltage for Trig.
It turns out that we don't need to shift the 3.3 V trigger GPIO output to 5 V. The Trig input of the HC-SR04 can be connected directly to the GPIO pin of the microcontroller or SBC because the HIGH voltage of the trigger pulse just needs to be higher than 2 V. The simplified circuit below, with just the voltage divider is our preferred solution then.
Operation
The controller starts the range measurement by raising pin Trig to 5 V for at least 10 μs and thereby triggering eight 40 kHz ultrasonic pulses (beyond the 20 kHz high frequency limit of human hearing). The pulse waves bounce off any nearby objects and some are reflected back to the sensor. The sensor detects these reflected waves and raises the Echo pin to 5 V for a duration proportional to the distance of the objects that the waves are reflected from.
A single range measurement is therefore performed like this:
- Initialize by setting the Trig and Echo pins to LOW.
- Raise the Trig pin to HIGH for at least 10 μs.
- Wait for a rising edge on the Echo pin, start a timer when detected.
- Wait for the falling edge on the Echo pin, stop the timer when detected.
- Calculate the distance from the time that the ultrasonic waves spent travelling in air (distance = time * velocity / 2, where the velocity of ultrasonic waves in air is 340 m/s).
This capture from an oscilloscope shows the short trigger pulse (blue), and the following long echo pulse (green) for an object placed approximately 12 cm in front of the sensor.
Limitations
The ultrasonic sensor is not able to measure distances to objects with highly diffuse surfaces or surfaces that are angled so that most incoming waves are reflected away from the sensor.
Programming Examples
For Raspberry Pi, using Python
Before trying out the code example below, make sure that Raspberry Pi GPIO support for the Python programming environment is installed via
sudo apt install python-rpi.gpio
The code below assumes that the output to the sensor's Trig pin is connected to GPIO pin #23 and the input from the sensor's Echo pin is connected to GPIO pin #24.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
TRIG = 23
ECHO = 24
print "Distance Measurement In Progress"
GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)
GPIO.output(TRIG, False)
print "Waiting For Sensor To Settle"
time.sleep(0.25)
GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)
while GPIO.input(ECHO)==0:
pulse_start = time.time()
while GPIO.input(ECHO)==1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
distance = pulse_duration * 17150
distance = round(distance, 2)
print "Distance:",distance,"cm"
GPIO.cleanup()
For Raspberry Pi Pico, using the C SDK
#include <hardware/gpio.h>
#include <pico/stdlib.h>
#include <pico/types.h>
#include <pico/time.h>
// GPIO pins
const uint TRIG = 6;
const uint ECHO = 9;
const uint64_t SpeedOfSound = 34300; // centimeters per second
/// @return distance in centimeters, or -1 if there was an error
int measure()
{
// configuring GPIO pins
gpio_init(TRIG);
gpio_set_dir(TRIG, GPIO_OUT);
gpio_put(TRIG, false);
gpio_init(ECHO);
gpio_set_dir(ECHO, GPIO_IN);
gpio_set_input_enabled(ECHO, true);
absolute_time_t echoRiseTime = nil_time;
absolute_time_t echoFallTime = nil_time;
absolute_time_t echoTimeoutTime = nil_time;
// sending the trigger pulse
gpio_put(TRIG, true);
sleep_us(20); // must be at least 10 microseconds
gpio_put(TRIG, false);
echoTimeoutTime = make_timeout_time_ms(500); // 0.5 second
// waiting for the echo signal
while (echoFallTime == nil_time) {
sleep_us(3);
auto now = get_absolute_time();
if (now > echoTimeoutTime) {
return -1;
}
bool const echoIsHigh = gpio_get(ECHO);
if (echoRiseTime == nil_time) {
if (echoIsHigh) {
echoRiseTime = now;
}
} else if (echoIsHigh == false) {
echoFallTime = now;
}
}
if (echoRiseTime == nil_time || echoFallTime == nil_time || (echoRiseTime >= echoFallTime)) {
return -1;
}
// calculating the distance
auto duration = echoFallTime - echoRiseTime;
auto distance = (int)(duration * SpeedOfSound / 2 / 1000000);
return distance;
}