Raspberry Pi HC-SR04

HC-SR04 Ultrasonic Sensor


HC-SR04 Ultrasonic Sensor

The HC-SR04 ultrasonic sensor is a low cost ultrasonic ranging sensor which provides non-contact measurement functionality in a range from about 2cm to 4m.

The sensor consists of a small circuit board containing an ultrasonic transmitter, receiver and control circuitry. It also has 4 pins; 2 for the power supply (+5V and ground), 1 for the trigger signal (transmitter), and 1 for the echo (receiver) signal.

How it Works

When a trigger signal of duration greater than 10 micro-seconds is applied to the trigger input of the HC-SR04, a series of 8 pulses at a frequency of 40 kHz is transmitted by the HC-SR04 transmitter. Any obstacle in front of the sensor will reflect this signal back to the HC-SR04, where it is detected by the receiver. When the returned signal is received, the echo output of the HC-SR04 is set to a high (+5V) state for a duration equal to the time taken for the returned echo to be detected by the HC-SR04. So, the duration of the echo signal is equal to the time taken for the trigger signal to travel to the obstacle and then return to the sensor. By knowing the velocity of sound (approximately 34,300 cm/s at sea level) we can thus calculate the distance of the obstacle from the sensor as:-

total distance = 34,300 cm/s * time taken

This returns the total distance traveled by the trigger pulses, which is effectively twice the distance between the sensor and the obstacle. To get the actual distance between the sensor and the obstacle, this value will need to be divided by 2, thus:-

distance between sensor and obstacle (in cm) = 17,150 * time taken (in seconds)

In this post we’ll take a look at how this sensor can be connected to a Raspberry Pi, a BBC micro:bit, and an Arduino.

Raspberry Pi

Connecting the HC-SR04 to a Raspberry Pi is quite simple, as the Raspberry Pi has the ability to power both 3.3V devices and 5V devices; the HC-SR04 requiring a 5V power supply. The only slight complication is that the received echo signal from the sensor will be at a signal level of 5V. However, by connecting a couple of resistors into our circuit we can create a voltage divider circuit to ensure that this echo signal is converted to a level that will work with the Raspberry Pi (around 3V). The circuit diagram below shows the circuit we used to connect our HC-SR04 sensor to a Raspberry Pi 3.

Raspberry Pi HC-SR04

The resistors used in this circuit are a 470R and a 330R resistor. However, other values may be used and can be calculated using the equation:-

R2 / (R1 + R2) ≈ 3 / 5

where R2 is the resistor connected to the ground pin on the Raspberry Pi, and R1 is the resistor connected to the echo pin on the HC-SR04.

You can see from the circuit, that the HC-SR04 sensor is powered from one of the 5V power supply pins on the Raspberry Pi, and the ground pin of the HC-SR04 is connected to one of the ground pins of the Pi. The trigger pin of the HC-SR04 is connected to pin 18 of the Raspberry Pi, and the echo pin is connected indirectly to pin 24 of the Pi via the voltage divider circuit. The voltage divider circuit converts the 5V echo signal from the HC-SR04 to a signal voltage of around 3V; making it compatible with the Raspberry Pi.

The Raspberry Pi code to measure distances using the HC-SR04 is written in Python.

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO_TRIGGER = 18
GPIO_ECHO = 24

GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)

GPIO.output(GPIO_TRIGGER, False)

distance = 0

def measureDistance():
    GPIO.output(GPIO_TRIGGER, False)
    time.sleep(0.5)
    GPIO.output(GPIO_TRIGGER, True)
    time.sleep(0.00001)
    GPIO.output(GPIO_TRIGGER, False)
    start = time.time()
    while GPIO.input(GPIO_ECHO) == 0:
        start = time.time()

    while GPIO.input(GPIO_ECHO) == 1:
        stop = time.time()

    elapsed = stop - start
    distance = elapsed * 17150
    return distance

try:
    distance = measureDistance()
    while True:
        print (distance)
        time.sleep(0.1)
        distance = measureDistance()
except:
    time.sleep(1)
    GPIO.cleanup()

BBC micro:bit

Connecting the HC-SR04 sensor to a BBC micro:bit is a little more complicated, because the micro:bit is not capable of providing the 5V supply required by the sensor. However, we have found that it is possible to power the HC-SR04 using 3 x 1.5V batteries in a 4.5V battery cage. The circuit diagram below shows how to connect the HC-SR04 to the micro:bit and 4.5V battery cage using a breadboard.

microbit HC-SR04

The micro:bit itself can be powered either from a USB cable or a 3V battery cage.

The code for the micro:bit is written using PXT, since it is necessary to measure time intervals in micro-seconds. Also, PXT provides a ‘sonar’ package specifically to use with sensors such as the HC-SR04. In order to use the blocks shown in the code, you will need to add this sonar package to your PXT project.

microbit HC-SR04 PXT

Arduino Uno

Using the HC-SR04 with an Arduino is quite straightforward, since  the Arduino is capable of providing the 5V power supply required. The circuit diagram below shows how the HC-SR04 may be connected to an Arduino Uno, and uses a couple of LEDs to indicate the proximity of objects to the sensor.

 

Arduino Uno HC-SR04

In this circuit, the trigger contact is connected to pin 12 on the Arduino, and the echo contact is connected to pin 13. Pins 10 and 11 of the Arduino are used to control 2 LEDs, using 560R resistors to limit the current.

The code for this project is shown below.

#define triggerPin 12
#define echoPin 13
#define ledGreen 10
#define ledRed 11

void setup() {
    pinMode(triggerPin, OUTPUT);
    pinMode(echoPin, INPUT);
    pinMode(ledGreen, OUTPUT);
    pinMode(ledRed, OUTPUT);
}

void loop() {
    long duration, distance;
    digitalWrite(triggerPin, LOW); // Added this line
    delayMicroseconds(2); // Added this line
    digitalWrite(triggerPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(triggerPin, LOW);
    duration = pulseIn(echoPin, HIGH);
    distance = (duration / 2) / 34.3;
    if (distance < 10) {
        digitalWrite(ledRed,HIGH);
        digitalWrite(ledGreen,LOW);
    }
    else {
        digitalWrite(ledRed,LOW);
        digitalWrite(ledGreen,HIGH);
    }
    delay(500);
}