The HC-SR501 is the undisputed workhorse of hobbyist motion detection, but its quirks—like a mandatory 60-second initialization lock and extreme susceptibility to WiFi RF noise—routinely trip up builders. Unlike simple digital switches, this module relies on the BISS0001 analog processing IC to translate microvolt pyroelectric spikes into clean logic signals. This guide provides the exact electrical specifications, hardware timing math, and ESP32 integration steps required to extract reliable occupancy data without battling false triggers.
The Pyroelectric Sensing Principle
The core of the HC-SR501 is a dual-element pyroelectric infrared (PIR) sensor, typically a D203B or D203S variant, which generates a surface electrical charge when exposed to fluctuating levels of infrared radiation. Because the two sensing elements are wired in opposition, uniform ambient thermal changes (like a room slowly warming in the afternoon sun) cancel each other out. However, a localized moving heat source (like a human walking across the detection zone) hits one element before the other, creating a differential voltage spike in the microvolt range.
This raw signal is far too weak for a microcontroller to read directly. The white plastic dome capping the sensor is a multi-faceted Fresnel lens that focuses infrared energy from a wide 120-degree cone onto the tiny sensor elements, effectively amplifying the signal while defining distinct detection zones. The onboard BISS0001 IC then amplifies this microvolt spike, applies bandpass filtering to reject high-frequency electrical noise and low-frequency thermal drift, and compares it against an internal threshold to output a clean digital logic signal.
HC-SR501 Pinout and Electrical Specifications
Before wiring this to an ESP32 or Arduino, you must understand the module's voltage tolerances. The HC-SR501 features an onboard 3.3V LDO voltage regulator (usually a 7133 or similar) that powers the BISS0001 IC. Because of this, the OUT pin will typically max out at ~3.3V HIGH even if you supply 5V to the VCC pin, making it natively safe for 3.3V ESP32 GPIO pins without a logic level shifter.
| Parameter | Min | Typical | Max | Unit |
|---|---|---|---|---|
| Operating Voltage (VCC) | 4.5 | 5.0 | 20.0 | VDC |
| Quiescent Current | - | 50 | 65 | µA |
| Output Logic High (OUT) | 3.0 | 3.3 | 3.5 | V |
| Output Logic Low (OUT) | 0 | 0 | 0.1 | V |
| Delay Time Range | 0.3 | - | 200+ | sec |
| Blocking Time | - | 2.5 | - | sec |
| Detection Angle | - | 120 | - | deg |
| Module Pin | Label | Function | ESP32 Connection |
|---|---|---|---|
| 1 (Left) | GND | Ground Reference | GND |
| 2 (Middle) | OUT | Digital Signal Output | GPIO 4 (or any input pin) |
| 3 (Right) | VCC | Power Supply | VIN / 5V (Do not use 3V3) |
digitalRead() or configure a digital interrupt.
Output Signal Logic, Timing Math, and Calibration
The output of the HC-SR501 is a simple digital logic level: HIGH (approx 3.3V) when motion is detected, and LOW (0V) when the area is clear. There is no analog scaling, PWM, or I2C data payload. However, translating this raw digital state into a physical unit (occupancy duration in seconds) requires understanding both the hardware timing math and the microcontroller polling math.
Hardware Timing Math (The BISS0001 RC Network)
The physical delay time—how long the OUT pin stays HIGH after motion ceases—is governed by an external RC (Resistor-Capacitor) network connected to the BISS0001 IC. The yellow potentiometer on the module adjusts the resistance ($R_{pot}$). According to the Adafruit PIR Sensor Guide and the BISS0001 datasheet, the output delay time ($T_d$) is calculated as:
T_d ≈ 2.5 × R_pot × C_delay
On standard HC-SR501 modules, the timing capacitor ($C_{delay}$) is typically a 104 ceramic cap (0.1 µF). If you turn the delay potentiometer to its maximum resistance (approx. 2.2 MΩ), the theoretical delay is 2.5 × 2,200,000 × 0.0000001 = 0.55 seconds. Wait, that's too low. In reality, the module uses a secondary timing multiplier pin on the BISS0001, scaling this base formula up by a factor of roughly 100 to 400 depending on the specific board revision, yielding the practical 0.3s to 200s range. To calibrate for a specific physical unit (e.g., a 10-second delay), set the potentiometer to its minimum (fully counter-clockwise), test with a stopwatch, and incrementally adjust clockwise.
Microcontroller Math: Raw Reading to Physical Occupancy
To convert the raw digital pulse width into physical seconds of room occupancy, your ESP32 must measure the duration of the HIGH state. The math is straightforward:
Occupancy_Seconds = (pulse_end_millis - pulse_start_millis) / 1000.0
This calculation is critical for HVAC or lighting automation, where you need to know how long a space was occupied, not just that motion occurred.
Calibration and Initialization Constraints
The HC-SR501 requires a mandatory 30 to 60-second warm-up period upon receiving power. During this time, the BISS0001 is calibrating its internal baseline to the ambient infrared environment. If you poll the sensor during this window, it will output erratic, continuous HIGH signals. Your firmware must implement a blocking delay or a non-blocking state machine that ignores all inputs for the first 60 seconds after boot.
ESP32 Integration, Code, and Interference Mitigation
Integrating the HC-SR501 with an ESP32 introduces a specific, non-obvious hardware hurdle: Radio Frequency (RF) interference.
Common Interference Sources
- ESP32 WiFi Antenna: The 2.4 GHz RF emissions from the ESP32's PCB trace antenna can rectify inside the high-impedance pyroelectric sensor element, causing false triggers. Fix: Maintain at least 10 cm (4 inches) of physical separation between the ESP32 antenna and the PIR dome.
- Thermal Drafts: HVAC vents, space heaters, or even a pet walking under a heating register will flood the Fresnel lens with shifting IR signatures. Fix: Aim the sensor away from air returns and radiators.
- Direct Sunlight: Incandescent bulbs and direct sunlight contain massive amounts of infrared radiation that can saturate the sensor. Fix: Avoid facing the sensor toward windows or unshielded halogen lamps.
Non-Blocking ESP32 Arduino Code
Using hardware interrupts for the HC-SR501 on an ESP32 can lead to watchdog timer resets if the sensor chatters. The most robust approach is a non-blocking polling loop using millis(), as recommended in the Espressif ESP32 GPIO API Reference for handling noisy external signals.
// HC-SR501 PIR Sensor Non-Blocking Integration for ESP32
const int PIR_PIN = 4;
const unsigned long WARMUP_TIME = 60000; // 60 seconds initialization
unsigned long bootTime;
unsigned long motionStartTime = 0;
bool isOccupied = false;
bool sensorReady = false;
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
bootTime = millis();
Serial.println("HC-SR501 initializing... Do not move in front of sensor.");
}
void loop() {
// 1. Handle 60-second warm-up calibration phase
if (!sensorReady) {
if (millis() - bootTime >= WARMUP_TIME) {
sensorReady = true;
Serial.println("Sensor calibrated and ready.");
}
return; // Skip reading during warmup
}
// 2. Read raw digital state
int pirState = digitalRead(PIR_PIN);
// 3. Edge Detection and Timing Math
if (pirState == HIGH && !isOccupied) {
// Motion just started
isOccupied = true;
motionStartTime = millis();
Serial.println("[MOTION] Occupancy started.");
}
else if (pirState == LOW && isOccupied) {
// Motion just ended
isOccupied = false;
unsigned long durationMs = millis() - motionStartTime;
float occupancySeconds = durationMs / 1000.0;
Serial.print("[CLEAR] Occupancy ended. Duration: ");
Serial.print(occupancySeconds);
Serial.println(" seconds.");
}
// Add a small debounce delay to prevent CPU hogging
delay(50);
}
Look closely at the bottom left corner of the HC-SR501 PCB. There is a 3-pin header with a jumper cap.
- H (High/Retrigger): The output stays HIGH as long as motion is continuously detected. This is the default and best for room occupancy tracking.
- L (Low/Non-Retrigger): The output goes HIGH for the set delay time, then forces LOW for a 2.5-second blocking period, ignoring all motion during the block. Use this only for simple alarm triggers.
By respecting the BISS0001's initialization sequence, maintaining physical distance from the ESP32's RF antenna, and utilizing non-blocking edge detection, the HC-SR501 transitions from a frustrating, erratic component into a highly reliable occupancy sensor for your embedded projects.






