Raspberry Pi Pico · HC-SR04

Raspberry Pi Pico HC-SR04 Simulator: Wiring, Code and a Live Circuit

This is an HC-SR04 ultrasonic distance sensor wired to a Raspberry Pi Pico, measuring live: the board pings ten times a second and prints the distance in centimeters. In the editor, drag the sensor’s distance slider and the reading follows.

The module runs from VBUS (5 V from USB), TRIG is on GP15 (physical pin 20) and ECHO on GP14 (physical pin 19). Because the Raspberry Pi Pico is a 3.3 V board, the wiring notes show the two resistors a real ECHO line needs.

  • 3.3 V logic
  • No library: pulseIn()
  • TRIG 15, ECHO 14
  • Range 2 to 400 cm
Raspberry Pi Pico · HC-SR04live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running on the simulator with the sketch below. Press what can be pressed; click anything else to open it in the editor.

Wiring the HC-SR04 to the Raspberry Pi Pico

Every connection in the circuit above, with the board’s own pin names.

HC-SR04 pinRaspberry Pi Pico pinWhy
VCCVBUS (5 V from USB)The HC-SR04 is a 5 V module; below about 4.5 V many units stop answering.
TRIGGP15 (physical pin 20)Output from the board: a 10 microsecond pulse starts a ping.
ECHOGP14 (physical pin 19)Input to the board. It swings to 5 V, so on a real board put a divider here (see below).
GNDGNDCommon ground.

The HC-SR04 needs 5 V, so VCC goes to VBUS (5 V from USB), and its ECHO output is then a 5 V signal. The RP2040’s pins are not 5 V tolerant, so on the bench put a divider on ECHO: 1 k from ECHO to GP14 (physical pin 19), and 2 k from GP14 (physical pin 19) to GND, which brings 5 V down to 3.3 V. TRIG needs nothing; 3.3 V is enough to trigger it. The simulator draws the direct wire so the circuit stays readable, and does not model the damage.

Pins to leave alone on the Raspberry Pi Pico

The numbers in the code are GP numbers, not the physical pin numbers printed beside the header: GP15 is pin 20. GP23 to GP25 are used on the board itself, and GP25 is the LED.

On a real bench

Solder headers on the Pico and press it into the breadboard across the center channel; the HC-SR04 goes in beside it. GND pins sit every fifth pin down both sides (pins 3, 8, 13, 18 and so on), so there is always one close. The first upload needs BOOTSEL held while plugging in.

The code

The sketch the circuit above runs. Open it in the editor, change a line and press Run: it compiles in your browser.

HC-SR04 on Raspberry Pi Pico
const int TRIG_PIN = 15;   // GP15 (physical pin 20)
const int ECHO_PIN = 14;   // GP14 (physical pin 19)

void setup() {
  Serial.begin(115200);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}

void loop() {
  // A pulse of at least 10 us on TRIG starts one measurement.
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // ECHO stays high for the sound's round trip; 38 ms means nothing in range.
  unsigned long us = pulseIn(ECHO_PIN, HIGH, 38000UL);
  if (us == 0) {
    Serial.println("Out of range");
  } else {
    Serial.print("Distance: ");
    Serial.print(us / 58);
    Serial.println(" cm");
  }
  delay(100);
}

Holding TRIG high for 10 microseconds (the module needs at least 10) makes it send eight 40 kHz pulses. It then raises ECHO and lowers it again when the echo returns, so the width of the ECHO pulse is the round trip time of the sound.

pulseIn(ECHO_PIN, HIGH, 38000UL) measures that width in microseconds. Sound covers a centimeter and back in about 58 microseconds, so dividing by 58 gives centimeters. The 38 ms timeout is what the module does with nothing in range; without a timeout pulseIn() waits a full second.

The 100 ms delay keeps one ping’s echo from being heard by the next. Serial.begin(115200) opens the serial monitor. Serial is the USB port at 115200 baud in this sketch; on a real Pico it appears once the board has enumerated.

Common mistakes with the HC-SR04 on the Raspberry Pi Pico

ECHO straight into a 3.3 V pin

It reads correctly, so it looks fine. But ECHO swings to 5 V and the RP2040 is rated to 3.6 V, so the pin is overstressed on every ping. Add the 1 k and 2 k divider, or use an HC-SR04P, the 3.3 V version.

pulseIn() without a timeout

With nothing in front of the sensor, pulseIn() with no third argument waits a whole second for a pulse that never comes, and the sketch looks frozen. Pass a timeout of about 38000 microseconds.

Pinging too fast

Fire the next ping before the last echo has died away and the module hears its own previous ping, so short random distances appear. Leave at least 60 ms between measurements.

Questions and answers

Can I simulate an HC-SR04 with a Raspberry Pi Pico?

Yes. The circuit at the top of this page is a Raspberry Pi Pico with a HC-SR04, running in your browser on a simulated RP2040. The sensor’s slider sets the distance to the object, from nothing in range up to 4 meters, and the ECHO pulse is as wide as a real one would be. Press Run it in the editor to change the wiring or the code; it is free and needs no account.

Does the HC-SR04 work with the Raspberry Pi Pico?

Yes, powered from VBUS (5 V from USB). TRIG works from a 3.3 V pin; ECHO needs a voltage divider down to 3.3 V on real hardware, or use the 3.3 V HC-SR04P.

Why do I get 0 or "Out of range"?

pulseIn() timed out. Either nothing is within 4 meters, TRIG and ECHO are swapped, or the module has no power. A soft or angled surface can also scatter the sound so no echo returns.

Should I use the NewPing library?

You can; NewPing.h compiles here too. This page uses pulseIn() because it shows what the module actually does, and it needs no library at all.

Build your own HC-SR04 project

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