If you are researching how to create a motion detector with arduino, the direct answer is to pair an Arduino Uno R3 with an HC-SR501 Passive Infrared (PIR) sensor module. The HC-SR501 handles the heavy lifting of analog IR signal processing via its onboard BISS0001 chip, outputting a clean 5V digital HIGH when it detects a heat signature moving across its Fresnel lens. This guide skips the generic overviews and gives you the exact bench-tested wiring, a calibration-aware codebase, and a decision tree to debug the inevitable false triggers.
The Verdict: Which PIR Sensor and Board to Choose
Not all motion sensors are created equal. Before you order parts, run your project requirements through this decision path to ensure you are not buying the wrong silicon.
| Project Requirement | Recommended Sensor | Why? |
|---|---|---|
| Standard room security, 120-degree cone, adjustable delay | HC-SR501 | Onboard potentiometers for time/sensitivity; robust 5V logic output. |
| Needs to detect motion through thin drywall or plastic enclosures | RCWL-0516 (Microwave) | Uses Doppler radar (microwaves) instead of IR; penetrates non-metallic barriers. |
| Ultra-compact wearable or battery-powered node (<1mA sleep) | AM312 (Mini PIR) | Tiny footprint, no potentiometers, ultra-low quiescent current. |
| Outdoor, high false-trigger environment (pets, wind, sun) | Grid-EYE (IR Array) | Thermal imaging array; allows software-based pet-immunity algorithms. |
Hardware Spec Sheet & Parts List
Here is the exact bill of materials. Do not substitute the 220Ω resistor with a higher value if you are using a standard 5mm LED, or you will struggle to see the indicator light in a well-lit room.
| Component | Exact Variant / Spec | Estimated Cost |
|---|---|---|
| Microcontroller | Arduino Uno R3 (ATmega328P DIP or SMD) | $12.00 - $25.00 |
| Motion Sensor | HC-SR501 PIR Module (with BISS0001 IC) | $2.50 - $4.00 |
| Indicator LED | 5mm Diffused Red LED (20mA max) | $0.10 |
| Current Limiter | 220Ω 1/4W Carbon Film Resistor | $0.05 |
| Prototyping | 830-point Solderless Breadboard + Male-to-Male Jumpers | $8.00 |
Wiring the HC-SR501 to the Arduino Uno R3
The HC-SR501 requires a stable 5V supply. A common bench mistake is trying to power it from a 3.3V rail (like on an ESP32 or Arduino Nano 3.3V pin); this causes the BISS0001 chip to brownout and spam false triggers. Stick to the 5V pin on the Uno R3.
| HC-SR501 Pin | Arduino Uno R3 Pin | Wire Color (Standard) |
|---|---|---|
| VCC | 5V | Red |
| OUT | Digital Pin 2 (Interrupt capable) | Yellow |
| GND | GND | Black |
LED Wiring: Connect Digital Pin 13 to the anode (long leg) of the LED. Connect the cathode (short leg) to the 220Ω resistor, and the other end of the resistor to GND.
- Insert the Arduino Uno R3 and breadboard into your workspace. Ensure the Uno is unplugged from USB.
- Route the red jumper from the Uno 5V pin to the breadboard's positive power rail.
- Route the black jumper from the Uno GND pin to the breadboard's negative ground rail.
- Plug the HC-SR501 module into the breadboard. Connect VCC to the positive rail, GND to the negative rail, and OUT to Digital Pin 2.
- Insert the LED anode into Pin 13's row, and the cathode into an empty row. Bridge the resistor from the cathode row to the negative ground rail.
- Locate the two orange potentiometers on the HC-SR501. Using a small Phillips screwdriver, turn the left potentiometer (Time Delay) fully counter-clockwise (minimum delay, ~0.3s). Turn the right potentiometer (Sensitivity) to the middle position.
- Connect the Uno to your PC via USB. Proceed to code upload.
Compilable Arduino Code with Debounce & Calibration
This code targets the Arduino Uno R3 (ATmega328P). It includes a mandatory 30-second calibration phase in the setup() function. The BISS0001 chip needs this time to sample the ambient IR noise of your room; if you skip this, the sensor will false-trigger immediately upon boot. It also implements a software debounce to prevent the serial monitor from spamming multiple triggers during a single continuous movement.
// Target Board: Arduino Uno R3 (ATmega328P)
// Project: HC-SR501 Motion Detector with Calibration & Debounce
#define PIR_PIN 2
#define LED_PIN 13
#define BAUD_RATE 115200
#define CALIBRATION_TIME 30000 // 30 seconds for BISS0001 baseline
#define DEBOUNCE_DELAY 2000 // 2 seconds between valid serial prints
unsigned long lastTriggerTime = 0;
bool isCalibrated = false;
void setup() {
pinMode(PIR_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
Serial.begin(BAUD_RATE);
digitalWrite(LED_PIN, LOW);
Serial.println("SYSTEM: Booting HC-SR501...");
Serial.println("SYSTEM: Calibrating baseline IR noise. DO NOT MOVE.");
// Mandatory hardware calibration phase
for(int i = 0; i < 10; i++){
Serial.print("Calibrating... ");
Serial.print(30 - (i*3));
Serial.println("s remaining");
delay(3000);
}
isCalibrated = true;
Serial.println("SYSTEM: Calibration complete. Monitoring active.");
}
void loop() {
if(!isCalibrated) return;
int sensorState = digitalRead(PIR_PIN);
unsigned long currentTime = millis();
if(sensorState == HIGH) {
digitalWrite(LED_PIN, HIGH);
// Debounce logic to prevent serial spam during continuous motion
if(currentTime - lastTriggerTime > DEBOUNCE_DELAY) {
Serial.println("EVENT: Motion Detected");
lastTriggerTime = currentTime;
}
} else {
digitalWrite(LED_PIN, LOW);
}
// Hardware error catching: If pin is stuck high for > 10s without resetting
if(sensorState == HIGH && (currentTime - lastTriggerTime > 15000)) {
Serial.println("ERROR: PIR_PIN STUCK HIGH. Check ground or sensitivity pot.");
lastTriggerTime = currentTime; // Reset to avoid spamming the error
}
}
For more on handling hardware switch noise, refer to the official Arduino Debounce Example, which outlines why mechanical and solid-state sensors both require timing filters.
Debugging: First Three Things to Check When It Fails
PIR sensors are notoriously finicky on the bench. If your build is not working, do not rewrite the code immediately. Check these three physical failure modes first.
1. Symptom: Serial Monitor spamming "EVENT: Motion Detected" continuously
Exact Error String: EVENT: Motion Detected printing every 2 seconds without any physical movement in the room.
Ranked Causes:
- Sensitivity Potentiometer Maxed Out: The right orange pot is turned fully clockwise. It is picking up micro-fluctuations in room temperature or HVAC airflow. Fix: Turn it counter-clockwise by two full turns.
- Missing Common Ground: The GND wire from the HC-SR501 is loose, causing the OUT pin to float high. Fix: Reseat the black jumper wire on both the breadboard and the Uno.
- Fresnel Lens Removed: If you took the white plastic dome off, the raw pyroelectric sensor is exposed to omnidirectional IR noise. Fix: Snap the lens back on.
2. Symptom: Code compiles but Serial Monitor is blank
Exact Error String: Blank terminal, or baud rate mismatch garbled text like ÿÿÿÿ.
Ranked Causes:
- Baud Rate Mismatch: The Serial Monitor in the Arduino IDE is set to 9600, but the code specifies
115200. Fix: Change the IDE dropdown to 115200. - USB Cable is Power-Only: You are using a charge cable that lacks data lines. Fix: Swap to a known data-sync USB-A to USB-B cable.
3. Symptom: Upload fails entirely
Exact Error String: avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
Ranked Causes:
- Wrong COM Port: The IDE is targeting COM1 (usually a motherboard serial port) instead of the Arduino's assigned port. Fix: Go to Tools > Port and select the highest COM number (Windows) or
/dev/cu.usbmodem*(Mac). - Board Variant Mismatch: You selected 'Arduino Nano' in the IDE instead of 'Arduino Uno'. Fix: Correct the board selection in Tools > Board.
Extending or Simplifying the Build
Once you have the baseline detector working, you will likely want to adapt it for a real-world deployment. Here is how to pivot the design based on your end goal.
How to Extend: Add IoT and MQTT (The Smart Home Route)
The Arduino Uno R3 lacks native WiFi. To push motion events to Home Assistant or a custom dashboard, swap the Uno for an ESP32-DevKitC V4.
- Wiring Shift: The HC-SR501 outputs 5V logic. The ESP32 GPIO pins are strictly 3.3V tolerant. You must put a voltage divider (e.g., 1kΩ and 2kΩ resistors) between the PIR OUT pin and the ESP32 GPIO pin to prevent frying the ESP32's silicon.
- Power Shift: Power the HC-SR501 from the ESP32's
VINpin (assuming you are powering the ESP32 via USB 5V), not the3V3pin. - Software Shift: Use the
PubSubClientlibrary to publish a JSON payload{"status": "motion", "ts": 1700000000}to an MQTT broker on your local network.
How to Simplify: Ditch the Microcontroller Entirely
If you only need to turn on a 12V LED strip or a relay when someone walks by, you do not need an Arduino. You can simplify this to a pure analog circuit.
- Use a NE555 Timer IC configured in monostable mode.
- Feed the HC-SR501's OUT pin directly into the 555's Trigger pin (Pin 2).
- The 555 will output a clean, timed 12V/5V pulse to drive a MOSFET or relay coil, completely eliminating the need for code, calibration delays, or USB debugging.
By starting with the Uno R3 and HC-SR501, you establish a verified baseline of how the sensor behaves in your specific environment. Once the potentiometers are tuned and the false triggers are eliminated via software debounce, you can confidently migrate the hardware to a permanent, simplified, or networked installation.






