Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

HC-SR04 with Raspberry Pi Pico W — safe 5 V wiring and MicroPython code

Measure distance with an HC-SR04 on a Pico W: 5 V from VBUS, a 1 kΩ / 2 kΩ divider on Echo into GP15, and time_pulse_us in MicroPython.

MicroPythonVerified — micropython (mpy-cross v1.29.0), 3 Nov 2026Compile-only

Community draft — report a mistake

The HC-SR04 is a 5 V part, and the Pico W is strictly 3.3 V — so this guide powers the sensor from VBUS and brings the Echo pulse down with a 1 kΩ / 2 kΩ divider before it reaches GP15.

MicroPython needs no library here: time_pulse_us() times the echo in microseconds, and the script prints the median of five pings in centimetres.

Wiring

Raspberry Pi Pico WOnly the pins used are shown · 3.3 V logicHC-SR04 ultrasonic sensor1k│2kGNDGP14GP15VBUSVCCTrigEchoGND
Also needed: 1 kΩ resistor, 2 kΩ resistor (or two 1 kΩ in series).
Every connection
Raspberry Pi Pico WHC-SR04 ultrasonic sensorWireNotes
VBUSVCCredVBUS (pin 40) is USB 5 V — the classic HC-SR04 does not work on 3.3 V.
GP14TrigpurpleGP14 is physical pin 19. A 3.3 V pulse is enough to trigger.
GP15EchogreenVia 1 kΩ / 2 kΩ divider — Echo is 5 V. 1 kΩ from Echo to GP15, 2 kΩ from GP15 to GND → about 3.3 V. GP15 is physical pin 20.
GNDGNDblack

5 V (HC-SR04P / RCWL-1601: 3–5.5 V) part, 3.3 V board. The classic HC-SR04 needs 5 V and its ECHO pin outputs 5 V. On a 3.3 V board (ESP32, Pico) send ECHO through a 1 kΩ / 2 kΩ divider. A 3.3 V trigger signal is enough for TRIG.

Board quirks

  • Never wire Echo straight to the Pico W: no RP2040 pin is 5 V tolerant, and a 5 V pulse slowly damages the input.
  • VBUS only carries 5 V while the Pico runs from USB. On a battery into VSYS, use the 3.3 V HC-SR04P (or RCWL-1601) on 3V3 and drop the divider.
  • machine.time_pulse_us() returns −2 if the echo never started and −1 if it lasted past the timeout; the code treats both as “out of range”.
  • The median of five pings rejects the odd wild reading from a soft or angled surface.

Code

main.pyMicroPython
# HC-SR04 ultrasonic distance on a Raspberry Pi Pico W (MicroPython, no library).
# Wiring: VCC -> VBUS (pin 40, USB 5 V), GND -> GND, Trig -> GP14 (pin 19),
# Echo -> 1 kOhm -> GP15 (pin 20), and 2 kOhm from GP15 to GND. Echo is a 5 V pulse; the Pico
# is not 5 V tolerant, so the divider is not optional.
from machine import Pin, time_pulse_us
import time

trig = Pin(14, Pin.OUT, value=0)
echo = Pin(15, Pin.IN)


def distance_cm():
    trig.value(1)
    time.sleep_us(10)
    trig.value(0)
    t = time_pulse_us(echo, 1, 30000)  # 30 ms timeout = about 5 m
    if t < 0:
        return None  # -2: echo never started, -1: echo too long
    return t * 0.0343 / 2  # speed of sound ~343 m/s at 20-25 C, there and back


def median_cm(n=5):
    vals = []
    for _ in range(n):
        d = distance_cm()
        if d is not None:
            vals.append(d)
        time.sleep_ms(60)  # let the last echo die out
    if not vals:
        return None
    vals.sort()
    return vals[len(vals) // 2]


print("HC-SR04: Trig GP14, Echo GP15 (through divider)")
while True:
    d = median_cm()
    if d is None:
        print("Out of range (no echo)")
    else:
        print("Distance: {:.1f} cm".format(d))
    time.sleep_ms(200)

Expected serial output

REPL / Thonny shellOutput
HC-SR04: Trig GP14, Echo GP15 (through divider)
Distance: 42.7 cm
Distance: 42.5 cm
Out of range (no echo)
Distance: 118.3 cm

Common errors

Always "Out of range (no echo)"

VCC is on 3V3 instead of VBUS, Trig/Echo are swapped, or the divider is reversed (1 kΩ belongs next to the sensor, 2 kΩ to GND).

Works on USB, not on battery

VBUS is dead without USB. Use a 3.3 V-capable HC-SR04P on 3V3, or give the sensor its own 5 V with a shared GND.

Readings jump around

Soft or angled targets scatter the ping. Aim at something flat and hard; the median filter handles the rest.

↑↓ to move · Enter to open