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 ESP32C3 | HC-SR501 PIR motion sensor | Wire | Notes |
|---|---|---|---|
| 5V | VCC | red | Needs 4.5 V or more; the module regulates down to 3.3 V itself. |
| D2 | OUT | yellow | 3.3 V signal — direct connection is safe. |
| GND | GND | black |
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
// 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);
}// 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
PIR on D2 - warming up for about 60 s
[71 s] Motion detected
[76 s] Motion endedPIR 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.