To connect an HC-SR501 PIR motion sensor to an Arduino Uno R3, wire the module's VCC to the Arduino's 5V pin, GND to GND, and the OUT pin to Digital Pin 2. The HC-SR501 outputs a 3.3V HIGH signal when it detects infrared movement, which the Arduino reads via digitalRead(). This direct answer applies to the standard 3-pin HC-SR501 module and any 5V-tolerant AVR or ARM-based Arduino board.

Project Difficulty: Beginner (2/5)
Estimated Time: 20 minutes for wiring, 30 minutes for calibration and tuning
Target Board Variant: Arduino Uno R3, Uno R4 Minima, or Arduino Nano (ATmega328P)

Hardware Requirements and Pin Mapping

The HC-SR501 is built around the BISS0001 PIR controller IC, which amplifies the microvolt-level signals from the pyroelectric sensor and filters out ambient thermal noise. When sourcing parts, avoid the smaller, dome-less SR602 modules if you need the adjustable delay and sensitivity pots found on the full-sized HC-SR501.

Bill of Materials (BOM)
Component Exact Variant / Model Approx. Price (2026)
Microcontroller Arduino Uno R3 (or genuine R4 Minima) $25.00 - $28.00
Motion Sensor HC-SR501 PIR Module (with Fresnel lens) $2.50 - $4.00
Wiring 22 AWG solid core or standard male-to-male jumpers $3.00
Optional Resistor 10kΩ pull-down (for floating pin mitigation) $0.10
Pin Mapping Table
HC-SR501 Pin Arduino Uno R3 Pin Function
VCC (Left) 5V Power input (Requires 4.5V to 20V DC)
OUT (Middle) Digital Pin 2 Signal output (HIGH = 3.3V on motion)
GND (Right) GND Common ground reference

Step-by-Step Wiring Procedure

  1. De-energize the circuit: Disconnect the USB cable and any external power supplies from the Arduino Uno before making connections to prevent accidental short circuits on the 5V rail.
  2. Identify the HC-SR501 pins: Hold the module with the Fresnel lens facing away from you and the three pins pointing down. From left to right, the pins are VCC, OUT, and GND. (Verify this against the silkscreen on the PCB, as some cloned batches reverse the order).
  3. Connect Power: Route a red jumper from the Arduino's 5V pin to the left VCC pin on the sensor. Route a black jumper from the Arduino's GND to the right GND pin on the sensor.
  4. Connect the Signal Line: Connect a yellow or green jumper from the middle OUT pin on the sensor to Digital Pin 2 (D2) on the Arduino.
  5. Install the pull-down resistor (Optional but recommended): If your environment is electrically noisy, insert a 10kΩ resistor between the OUT pin and GND. This prevents the Arduino input from floating if the sensor's internal BISS0001 output stage enters a high-impedance state during its 30-second boot calibration.
  6. Verify connections: Tug gently on the jumper wires to ensure solid friction fit in the female headers before applying power.

Complete Arduino Motion Sensor Code

The following C++ code targets the Arduino Uno R3 (and is fully compatible with the R4 Minima and Nano). It uses state-change detection rather than continuous polling prints, which prevents flooding the serial buffer and crashing the IDE's serial monitor—a common failure mode in beginner motion sensor projects.

// Target Board: Arduino Uno R3 / R4 Minima / Nano
// Library Dependencies: None (Core Arduino API)

#define PIR_PIN 2      // HC-SR501 OUT pin connected to D2
#define LED_PIN 13     // Onboard LED for visual confirmation
#define BAUD_RATE 9600 // Standard serial communication rate

// State variables for edge detection
int pirState = LOW;    // Assumes sensor starts in LOW state
int currentVal = 0;    // Stores the current digitalRead value

void setup() {
  pinMode(PIR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  
  Serial.begin(BAUD_RATE);
  Serial.println("Initializing HC-SR501...");
  
  // The BISS0001 chip requires 30-60 seconds to calibrate its baseline
  // thermal environment upon first receiving power.
  Serial.println("Calibrating sensor (wait 30 seconds)...");
  delay(30000); 
  
  Serial.println("Calibration complete. System armed.");
}

void loop() {
  currentVal = digitalRead(PIR_PIN);
  
  // Error handling: Check for floating pin anomalies (rapid toggling)
  // If the pin reads HIGH, confirm it with a microsecond delay to debounce
  if (currentVal == HIGH) {
    delayMicroseconds(50);
    currentVal = digitalRead(PIR_PIN);
  }

  if (currentVal == HIGH) {
    digitalWrite(LED_PIN, HIGH);
    
    // Only print on the rising edge (state change from LOW to HIGH)
    if (pirState == LOW) {
      Serial.println("Motion detected!");
      pirState = HIGH;
    }
  } else {
    digitalWrite(LED_PIN, LOW);
    
    // Only print on the falling edge (state change from HIGH to LOW)
    if (pirState == HIGH) {
      Serial.println("Motion ended.");
      pirState = LOW;
    }
  }
  
  // Small delay to prevent CPU hogging and reduce EMI noise
  delay(50); 
}

Debugging: First Three Checks and Common Errors

When your motion sensor Arduino project fails to trigger, or triggers endlessly, do not rewrite the code immediately. Hardware and configuration faults account for 95% of HC-SR501 issues. Run through these first three physical checks:

  1. Check the Power Rail Voltage: The HC-SR501 requires a minimum of 4.5V to operate its internal voltage regulator reliably. If you are powering the Arduino via a low-quality USB hub, the 5V rail might sag to 4.2V under load. This brownout causes the BISS0001 chip to reset continuously, resulting in erratic OUT pin behavior. Measure the VCC pin with a multimeter; it must read ≥ 4.7V.
  2. Verify the Jumper Cap Position: The module has a 3-pin header for a jumper cap near the potentiometers. If the cap bridges the bottom two pins, it is in Single Trigger mode (outputs HIGH, then LOW, ignoring continuous motion). If it bridges the top two pins, it is in Repeatable Trigger mode (stays HIGH as long as motion persists). For most Arduino logic, Repeatable Trigger is required.
  3. Adjust the Potentiometers: The two orange trim pots control Time Delay (left) and Sensitivity (right). If the Time Delay pot is turned fully counter-clockwise, the output pulse is only ~300ms—often too short for the Arduino loop() to catch if other delays exist in your code. Turn the Time Delay pot clockwise to increase the pulse up to ~200 seconds.

Exact Error Strings and Ranked Causes

Compilation Error: error: 'pirPin' was not declared in this scope
Ranked Causes: (1) You copied the loop() logic but forgot the #define PIR_PIN 2 at the top of the sketch. (2) You placed executable code outside of the setup() or loop() functions. (3) Case-sensitivity mismatch (e.g., defining PIR_PIN but calling pirPin).
Runtime Crash (ESP8266/ESP32 Porting): ISR not in IRAM!
Ranked Causes: If you port this exact logic to an ESP32 and use hardware interrupts (attachInterrupt) instead of polling, the ESP32 will throw a fatal exception if the Interrupt Service Routine (ISR) function is not stored in fast RAM. Fix: Add the IRAM_ATTR attribute before your ISR function declaration, or revert to the digitalRead() polling method shown in the code above. For more on ESP32 memory constraints, refer to the Espressif ESP-IDF documentation.

Extending and Simplifying the Build

To Simplify: If you are building a standalone security light and do not need serial logging, strip out all Serial.begin() and Serial.println() commands. Connect the HC-SR501 OUT pin directly to the gate of a logic-level N-channel MOSFET (like an IRLZ44N) to drive a 12V LED strip without an Arduino in the loop at all. The HC-SR501's 3.3V output is sufficient to trigger many logic-level gates directly.

To Extend: Add an LDR (Light Dependent Resistor) voltage divider to Analog Pin A0. Before checking the PIR state in the loop(), read the LDR value. If the ambient light level is above a defined threshold (e.g., analogRead(LDR_PIN) > 700), bypass the motion logic and keep the lights off. This prevents your motion-activated night light from turning on during the day. See the Arduino analogRead() reference for ADC scaling details.

Frequently Asked Questions

Why is my HC-SR501 motion sensor Arduino project triggering randomly?

Random 'ghost' triggers are almost always caused by thermal or electrical interference. The pyroelectric sensor detects rapid changes in infrared radiation. If the sensor is facing a heat source (HVAC vent, incandescent bulb, or direct sunlight moving through a window), it will false-trigger. Electrically, long jumper wires acting as antennas can induce 60Hz/50Hz mains hum into the high-impedance OUT line. Keep wires under 12 inches, or use a shielded cable with the shield tied to GND at the Arduino end only.

Can I power the HC-SR501 motion sensor with 3.3V from an Arduino Pro Mini?

No, not directly. The HC-SR501 module features an onboard 7133 voltage regulator that drops the input voltage down to 3.3V for the BISS0001 IC. The regulator requires a minimum dropout voltage, meaning the input (VCC) must be at least 4.5V. If you feed it 3.3V, the sensor will not power up. To use it with a 3.3V microcontroller, power the sensor's VCC from a separate 5V source, but ensure the microcontroller's GPIO pin is 5V-tolerant, or use a logic level shifter on the OUT line.

What is the difference between single and repeatable trigger modes on the HC-SR501?

In Single Trigger mode (jumper on bottom pins), the OUT pin goes HIGH when motion is detected, stays HIGH for the duration set by the time-delay potentiometer, and then goes LOW. It will ignore all motion during the cooldown period and the delay period. In Repeatable Trigger mode (jumper on top pins), the OUT pin goes HIGH on motion and stays HIGH as long as motion is continuously detected, resetting the timer with every new movement. Repeatable mode is generally preferred for Arduino projects controlling lights or alarms, as it prevents the system from turning off while a person is still standing in the room.