Built-in project · Raspberry Pi Pico W

Pico W reversing aid: HC-SR04 and a beeper

MicroPython on a Pico W: an HC-SR04 on GP17 and GP16 measures the gap, and an active buzzer and an LED beep faster as an obstacle gets closer. The whole build, a Raspberry Pi Pico W and 8 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 30 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $9.80. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • Measuring distance with an ultrasonic sensor
  • Dividing a 5 V signal down for a 3.3 V pin
  • Turning a distance into beep timing
  • Switching a buzzer with a transistor
  • Difficulty: Intermediate
  • Time: About 30 minutes
  • Board: Raspberry Pi Pico W
  • Parts: 11

How it works

An HC-SR04 ultrasonic ranger measures the gap behind a car. The Pico W sends a short pulse on TRIG (GP17) and times how long ECHO (GP16) stays high. The echo goes through a resistor divider, 1k and 2k, so the 5 V signal is safe for the 3.3 V pin.

The closer the obstacle, the faster the beeps. Beyond 50 cm it beeps every 2000 ms. Between 20 and 50 cm it is 1000 ms, between 10 and 20 cm it is 500 ms, and under 10 cm it is 300 ms.

Each beep lasts 100 ms. The buzzer on GP15 and the LED on GP14 switch on together.

Kits that can build it

These 2 starter kits have every part in the circuit. Each kit's page lists what else it can build.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Resistor, 220 Ω pin 2Raspberry Pi Pico W pin GP14
Resistor, 1k Ω (2) pin 1Raspberry Pi Pico W pin GP15
Ultrasonic ranger pin TRIGRaspberry Pi Pico W pin GP17
Resistor, 1k Ω (1) pin 2Raspberry Pi Pico W pin GP16
Resistor, 2k Ω pin 1Raspberry Pi Pico W pin GP16
Ultrasonic ranger pin VCC5 V
Resistor, 1k Ω (1) pin 1Ultrasonic ranger pin ECHO
Ultrasonic ranger pin GNDGround
Resistor, 2k Ω pin 2Ground
Buzzer pin 13.3 V
Transistor (NPN or PNP) pin CBuzzer pin 2
Resistor, 1k Ω (2) pin 2Transistor (NPN or PNP) pin B
Transistor (NPN or PNP) pin EGround
LED, red pin AResistor, 220 Ω pin 1
LED, red pin CGround

The code

The MicroPython code exactly as the editor opens it. Change a line there and press Run: the board runs it on the official MicroPython firmware, with nothing to compile.

main.py · Raspberry Pi Pico W
# Reversing aid: the HC-SR04 (TRIG GP17, ECHO GP16) measures the gap
# behind the car. The closer the obstacle, the faster the buzzer (GP15)
# beeps and the LED (GP14) blinks.
from machine import Pin
import time

trig = Pin(17, Pin.OUT)
echo = Pin(16, Pin.IN)
buzzer = Pin(15, Pin.OUT)
led = Pin(14, Pin.OUT)

def distance_cm():
    trig.value(1)
    time.sleep_us(20)
    trig.value(0)
    while echo.value() == 0:
        pass
    began = time.ticks_us()
    while echo.value() == 1:
        pass
    return time.ticks_diff(time.ticks_us(), began) * 0.0340 / 2

def interval(cm):
    if cm > 50:
        return 2000
    if cm > 20:
        return 1000
    if cm > 10:
        return 500
    return 300

while True:
    cm = distance_cm()
    wait = interval(cm)
    print("%.0f cm, beep every %d ms" % (cm, wait))
    buzzer.value(1)
    led.value(1)
    time.sleep_ms(100)
    buzzer.value(0)
    led.value(0)
    time.sleep_ms(wait - 100)

Code walkthrough

The key functions of the sketch, and what each one does.

distance_cm main.py

It sends a 20 microsecond pulse on TRIG. Then it waits for ECHO to go high and times how long it stays high. That time, multiplied by 0.0340 and halved because the sound goes out and back, gives the distance in centimeters.

def distance_cm():
    trig.value(1)
    time.sleep_us(20)
    trig.value(0)
    while echo.value() == 0:
        pass
    began = time.ticks_us()
    while echo.value() == 1:
        pass
    return time.ticks_diff(time.ticks_us(), began) * 0.0340 / 2

interval main.py

It turns a distance in centimeters into a wait time in milliseconds. Over 50 cm gives 2000, over 20 gives 1000, over 10 gives 500, and anything closer gives 300. The main loop uses it to space the beeps.

def interval(cm):
    if cm > 50:
        return 2000
    if cm > 20:
        return 1000
    if cm > 10:
        return 500
    return 300

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The distance never updates or the program hangs. This project
    The code waits for ECHO forever. Check TRIG is on GP17 and ECHO reaches GP16 through the divider.
  • The buzzer stays silent. This project
    Check the transistor: collector to the buzzer, emitter to ground, base to GP15 through the 1k resistor.
  • Distance reads zero, or never changes. Ultrasonic ranger
    Power it from 5 V and share ground. Send a 10 microsecond HIGH pulse on TRIG, then time ECHO with pulseIn. Check TRIG and ECHO are not swapped.
  • Readings jump around or are wrong on a 3.3 V board. Ultrasonic ranger
    ECHO outputs 5 V, so divide it down for 3.3 V boards. Aim at flat, hard surfaces. The range is about 2 cm to 4 m, and soft or angled targets bounce the sound away.
  • The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
    Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure.
  • A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
    Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground.
  • The buzzer makes a constant tone, or you cannot change its pitch. Buzzer
    An active buzzer has its own oscillator, so it only beeps on and off. A passive buzzer needs tone() to set pitch. Check which type you have.
  • The buzzer is silent or very quiet. Buzzer
    Check polarity: the plus mark goes to the pin or supply. For loud buzzers, drive them through a transistor instead of straight from a pin.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.