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 sensor with Seeed XIAO ESP32C3

Detect motion with an HC-SR501 PIR on a Seeed XIAO ESP32C3: 5V from USB, 3.3 V output straight to D2, read with an interrupt.

Arduino C++Verified — core esp32 3.3.12, 3 Nov 2026Compile-only

Community draft — report a mistake

An HC-SR501 detects people by their body heat — for a stair light, a door alert or waking a display. With the XIAO ESP32C3, power it from 5V and connect OUT to D2.

The sketch reports motion start and end through an interrupt, so the loop stays free for other work such as sending an alert over Wi-Fi.

Wiring

XIAO ESP32C3Only the pins used are shown · 3.3 V logicHC-SR501 PIR motion sensorD25VGNDVCCOUTGND
Every connection
XIAO ESP32C3HC-SR501 PIR motion sensorWireNotes
5VVCCredNeeds 4.5 V or more; the module regulates down to 3.3 V itself.
D2OUTyellow3.3 V signal — direct connection is safe.
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

  • The HC-SR501 wants 4.5 V or more on VCC, so it uses the XIAO’s 5V pin — which is only live on USB power. On a LiPo, use a 3.3 V PIR such as the AM312 on 3V3 instead.
  • Its OUT pin is driven from the module’s own 3.3 V regulator, so D2 sees 3.3 V at most.
  • The sketch uses an interrupt on D2. digitalPinToInterrupt(D2) works with the XIAO’s D-names.

Code

pir-xiaoc3.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// HC-SR501 PIR motion sensor on a Seeed XIAO ESP32C3.
// VCC → 5V (USB power), GND → GND, OUT → D2 (GPIO4). OUT is a 3.3 V signal.
volatile bool changed = false;

void IRAM_ATTR onPir() { changed = true; }

void setup() {
  Serial.begin(115200);
  delay(1500);
  pinMode(D2, INPUT);
  attachInterrupt(digitalPinToInterrupt(D2), onPir, CHANGE);
  Serial.println("PIR on D2 - warming up for about 60 s");
}

void loop() {
  if (changed) {
    changed = false;
    bool motion = digitalRead(D2) == HIGH;
    Serial.printf("[%lu s] %s\n", millis() / 1000, motion ? "Motion detected" : "Motion ended");
  }
  delay(10);
}

Expected serial output

Serial Monitor · 115200Output
PIR on D2 - warming up for about 60 s
[71 s] Motion detected
[76 s] Motion ended

Common errors

Constant triggers in the first minute

Warm-up. Ignore the first 60 s.

False triggers near the XIAO

Wi-Fi bursts from the antenna. Keep the PIR at least 10 cm from the antenna.

↑↓ to move · Enter to open