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 Wemos D1 mini — 5 V sensor, safe 3.3 V echo

Wire an HC-SR04 to a Wemos D1 mini: VCC on the 5V pin, Trig on D5 and Echo on D6 through a 1 kΩ / 2 kΩ divider, with median-filtered distance code.

Arduino C++Verified — core esp8266 3.1.2, 3 Nov 2026Compile-only

Community draft — report a mistake

The HC-SR04 is a 5 V part on a 3.3 V board, and the D1 mini makes the power side easy: its 5V pin gives the sensor USB 5 V directly. The only extra parts are two resistors that bring the 5 V Echo pulse down to a level the ESP8266 can take.

Trig goes on D5 and Echo on D6, keeping the I2C pins free for a display shield and well clear of the boot pins. The sketch takes five pings and prints the median, which is what you want for a water tank or parking sensor.

Wiring

Wemos D1 miniOnly the pins used are shown · 3.3 V logicHC-SR04 ultrasonic sensor1k│2kD5D6GND5VVCCTrigEchoGND
Also needed: 1 kΩ resistor, 2 kΩ resistor (or two 1 kΩ in series).
Every connection
Wemos D1 miniHC-SR04 ultrasonic sensorWireNotes
5VVCCredThe classic HC-SR04 needs 5 V. The 5V pin carries USB 5 V.
D5TrigpurpleA 3.3 V trigger pulse is enough.
D6EchogreenVia 1 kΩ / 2 kΩ divider — Echo is a 5 V pulse: 1 kΩ from Echo to D6, 2 kΩ from D6 to GND → about 3.3 V.
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

  • The ESP8266’s pins are rated for 3.6 V. Echo from a 5 V HC-SR04 must go through the divider; “it worked without one” only means it hasn’t failed yet.
  • D5 and D6 are used here so D1/D2 stay free for an I2C display shield, and D3/D4/D8 (boot pins) stay untouched.
  • The 5V pin is only 5 V while the board runs from USB or a 5 V supply. On a single Li-ion cell it is 3.0–4.2 V and the classic HC-SR04 gets unreliable — use the HC-SR04P / RCWL-1601, which runs from 3V3 and needs no divider.
  • pulseIn() busy-waits, so it has a 25 ms timeout here. A pulseIn with no timeout and no echo would hold the CPU for a full second, long enough to upset Wi-Fi once you add it.
  • The median of five pings throws out the stray long echo that a single reading lets through — useful for tank levels where the walls bounce sound around.

Code

hc-sr04-d1mini.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// HC-SR04 on a Wemos D1 mini (ESP8266).
// VCC → 5V, Trig → D5 (GPIO14), Echo → D6 (GPIO12) through a 1 kΩ / 2 kΩ divider, GND → GND.
// Prints the median of 5 pings, which throws away the odd bad echo.
const uint8_t TRIG_PIN = D5;
const uint8_t ECHO_PIN = D6;
const unsigned long TIMEOUT_US = 25000;  // about 4 m there and back; pulseIn() returns 0 after this

float pingCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  unsigned long us = pulseIn(ECHO_PIN, HIGH, TIMEOUT_US);
  return us ? us * 0.0343f / 2.0f : -1.0f;
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  Serial.println("HC-SR04: Trig D5, Echo D6 (through the divider)");
}

void loop() {
  float r[5];
  for (int i = 0; i < 5; i++) {
    r[i] = pingCm();
    delay(60);  // lets the last echo die out, and lets the ESP8266's system tasks run
  }
  for (int i = 1; i < 5; i++) {  // insertion sort, then take the middle value
    for (int j = i; j > 0 && r[j] < r[j - 1]; j--) {
      float t = r[j];
      r[j] = r[j - 1];
      r[j - 1] = t;
    }
  }
  if (r[2] < 0) Serial.println("Out of range (no echo)");
  else Serial.printf("Distance: %.1f cm\n", r[2]);
  delay(500);
}

Expected serial output

Serial Monitor · 115200Output
HC-SR04: Trig D5, Echo D6 (through the divider)
Distance: 42.7 cm
Distance: 42.6 cm
Out of range (no echo)
Distance: 118.3 cm

Common errors

Always “Out of range” or 0

VCC on 3V3 instead of 5V, or the divider is the wrong way round (1 kΩ on the sensor side, 2 kΩ to GND). Full fix.

Readings jump around

Soft or angled targets absorb the ping. Aim at something flat and hard; in a tank, mount the sensor square to the water surface.

↑↓ to move · Enter to open