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-SR501 PIR with Wemos D1 mini — interrupt-driven motion

Wire an HC-SR501 PIR sensor to a Wemos D1 mini on D5, catch motion with an IRAM_ATTR interrupt and light the built-in LED — plus the Wi-Fi false-trigger fix.

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

Community draft — report a mistake

A PIR sensor and a D1 mini make a motion-triggered light, an intrusion alert or a room-occupancy logger. Power the HC-SR501 from the 5V pin, connect OUT to D5, and the ESP8266 can react the instant someone walks in.

The sketch uses an interrupt, which brings out two ESP8266 rules: the handler must be in IRAM, and D0 can’t do interrupts at all. It also covers the most common D1 mini PIR complaint — false triggers caused by the board’s own Wi-Fi.

Wiring

Wemos D1 miniOnly the pins used are shown · 3.3 V logicHC-SR501 PIR motion sensorD5GND5VVCCOUTGND
Every connection
Wemos D1 miniHC-SR501 PIR motion sensorWireNotes
5VVCCredThe HC-SR501 wants 4.5 V or more; the 5V pin gives USB 5 V.
D5OUTyellowOUT is a 3.3 V signal, safe on the ESP8266.
GNDGNDblack

4.5–20 V (5 V typical) part, 3.3 V board. Power it from 5 V (VIN/5V pin). Its output is a 3.3 V logic signal, so it connects directly to ESP32, Pico and Uno GPIOs.

Board quirks

  • Interrupt handlers on the ESP8266 must be marked IRAM_ATTR. Without it the board crashes (or refuses to attach the interrupt) the moment motion is seen.
  • D0 (GPIO16) has no interrupt on the ESP8266, which is why the PIR goes on D5. D1–D8 all support attachInterrupt.
  • The HC-SR501 is known to false-trigger when an ESP8266 transmits close by — its amplifier picks up the 2.4 GHz bursts. Keep the PIR at least 10–15 cm from the D1 mini’s antenna end, or put it on a short cable.
  • After power-up the sensor needs about a minute to settle; expect a few motion events in that time. The on-board time and sensitivity pots set how long OUT stays high and how far it sees.
  • The built-in LED is on D4 and lights when the pin is LOW, so the sketch writes LOW for “motion”.

Code

pir-d1mini.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// HC-SR501 PIR motion sensor on a Wemos D1 mini (ESP8266), read with an interrupt.
// VCC → 5V, OUT → D5 (GPIO14), GND → GND. The built-in LED (D4) lights while motion is seen.
const uint8_t PIR_PIN = D5;          // GPIO14 - D0 can't do interrupts on the ESP8266
const uint8_t LED_PIN = LED_BUILTIN; // D4 / GPIO2, lit when LOW

volatile bool changed = false;

// Interrupt handlers must live in IRAM on the ESP8266, or the board crashes when one fires.
void IRAM_ATTR onPirChange() {
  changed = true;
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  pinMode(PIR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);  // LED off
  attachInterrupt(digitalPinToInterrupt(PIR_PIN), onPirChange, CHANGE);
  Serial.println("PIR on D5 - give it about 60 s to settle after power-up");
}

void loop() {
  if (changed) {
    changed = false;
    bool motion = digitalRead(PIR_PIN);
    digitalWrite(LED_PIN, motion ? LOW : HIGH);
    Serial.printf("[%lus] %s\n", millis() / 1000, motion ? "Motion detected" : "Motion ended");
  }
}

Expected serial output

Serial Monitor · 115200Output
PIR on D5 - give it about 60 s to settle after power-up
[64s] Motion detected
[69s] Motion ended
[112s] Motion detected

Common errors

Board reboots when motion is detected

The interrupt handler isn’t in IRAM. Add IRAM_ATTR before the function. Full fix.

Motion every few seconds with nobody there

Wi-Fi interference or the settle time. Move the PIR away from the antenna and wait a minute after power-up; turn the sensitivity pot down.

OUT stays high for ages

The time-delay pot is turned up (up to several minutes), or the jumper is on repeat-trigger (H). Turn the pot anticlockwise.

↑↓ to move · Enter to open