In this tutorial, you will learn how the HC-SR501 PIR motion sensor works and how you can use it with Arduino. You can find Passive Infrared (PIR) sensors all around you, they are not only used for security purposes, but also in most automatically-activated lighting systems.
In this article, I have included a wiring diagram and example codes so you can start experimenting with your sensor. After each example, I break down and explain how the code works, so you should have no problems modifying it to suit your needs.
First I will show you how you can use the HC-SR501 as a standalone unit. Next, we will connect it to an Arduino UNO and I will show you how to use it as a simple alarm system.
This tutorial focuses on the HC-SR501 sensor, but you can also use the provided code for similar sensors like the HC-SR505 or AM312. The main difference is that these cheaper sensors have a smaller detection range and don’t have a potentiometer to adjust the sensitivity and time delay.
Supplies
Hardware components
HC-SR501 PIR motion sensor | × 1 | Amazon | |
Arduino Uno Rev3 | × 1 | Amazon | |
Breadboard | × 1 | Amazon | |
Jumper wires | × 10 | Amazon | |
Resistor assortment | × 1 | Amazon | |
LEDs | × 1 | Amazon | |
Passive buzzer | × 1 | Amazon | |
USB cable type A/B | × 1 | Amazon |
Software
Makerguides.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to products on Amazon.com. As an Amazon Associate we earn from qualifying purchases.
How does a PIR Motion Sensor work?
PIR motion sensors consist of two main parts: a pyroelectric sensing element and a fresnel lens. The pyroelectric sensing element can detect infrared radiation. All objects with a temperature above absolute zero (0 Kelvin / -273.15 °C) emit heat energy in the form of infrared radiation, including human bodies.
A pyroelectric sensor has two rectangular slots in it made of a material that allows the infrared radiation to pass. Behind these, there are two separate infrared sensor electrodes, one responsible for producing a positive output and the other a negative output. The reason for that is that we are looking for a change in IR levels and not ambient IR levels. The two electrodes are wired up so that they cancel each other out. If one half sees more or less IR radiation than the other, the output will swing high or low.
The on-board signal processing IC processes this signal and turns the output pin of the sensor HIGH or LOW accordingly.
The white dome in front of the sensing element is a fresnel lens. This lens focuses the infrared radiation onto the sensor.
HC-SR501 PIR Motion Sensor
The HC-SR501 PIR motion sensor is built around the BISS0001 Micro Power PIR Motion Detector IC. This IC is specifically developed to process the signal from PIR motion sensors.
If you remove the fresnel lens, you will see the RE200B pyroelectric sensing element. On the PCB you can also find a built-in voltage regulator. This means you can power the board with a large DC voltage range, typically 5 V is used.
The specifications of the HC-SR501 are given in the table below, note that there might be small differences between manufacturers.
HC-SR501 Specifications
Operating voltage | 4.5 – 20 V |
Quiescent current | 50 μA |
Level output | HIGH 3.3 V / LOW 0 V |
Trigger | L single trigger / H repeating trigger |
Delay time | 3 – 300 s |
Blocking time | 2.5 s (default) |
Trigger | L single trigger / H repeating trigger |
Measuring range | 3 – 7 m maximum |
2 mm | |
Measuring angle | < 110° cone angle |
PCB dimensions | 32.5 x 24 mm |
Mounting holes | 2 mm, 28.5 mm spacing |
Fresnel lens dimensions | 15 mm x 23 mm diameter |
Operating temperature | -15 – 70 °C |
Cost | Check price |
For more information, you can check out the datasheets below:
Adjusting the HC-SR501
On the back of the board you will find two potentiometers and a jumper, which you can use to adjust several parameters:
Sensitivity (range) adjustment
The HC-SR501 has a maximum sensing distance (detection range) of 7 meters. You can adjust the sensing distance by rotating the sensitivity potentiometer CW or CCW (see picture above). Rotating the potentiometer clockwise increases the sensing distance to a maximum of 7 meters. Rotating it counterclockwise decreases the sensing distance to a minimum of 3 meters.
Time-delay adjustment (Tx)
This potentiometer can be used to adjust the time that the output stays HIGH for after motion is detected. At a minimum, the delay is 3 seconds and at a maximum, it is 300 seconds or 5 minutes. Turn the potentiometer clockwise to increase the delay and counterclockwise to decrease the delay.
Trigger selection jumper
The (yellow) jumper can be used to select one of the two trigger modes. It can be set to either L (single trigger) or H (repeating trigger):
- Single trigger – The output will turn HIGH as soon as motion is detected. It will stay HIGH for the time set by the potentiometer. Any movement during this period is not processed and does not restart the timer.
- Repeating trigger – Every time motion is detected, the delay timer is restarted.
The difference between the single and repeating trigger mode is shown in the figure below.
Adding a thermistor and/or LDR to the HC-SR501
As can be seen in the image below, the HC-SR501 has solder pads for two additional components. These pads are typically labeled ‘RL’ and ‘RT’.
- RL – Here you can add a light dependent resistor (LDR) or photoresistor which has a low resistance under strong ambient light. This causes the detector to be operational only when the detection area is sufficiently dark.
- RT – This pad is meant for a thermistor. Adding this makes the sensitivity of the sensor less dependent on the ambient temperature
Unfortunately, no additional information is provided in the datasheets, so I am not entirely sure about what component values you should use.
Using the HC-SR501 PIR motion sensor as a standalone unit
For most applications, you can just use the HC-SR501 as a standalone unit. You can use the output signal to trigger things like relays and LEDs.
The wiring is very simple as can be seen in the picture below. Simply connect VCC and GND to a battery and a red LED between the output pin and ground. The output voltage is 3.3 V, so I added a 68 Ω current limiting resistor in series with the LED.
Note that after powering up the sensor, you need to wait 30 – 60 seconds for the sensor to initialize. During this period, the LED might blink a couple of times. After waiting for a minute, you can wave your hand in front of the sensor and you should be able to see the LED light up.
With this setup, it is easy to test the functionality of the sensor. This is also a good moment to play around with the sensitivity and time-delay settings, as well as the two different trigger modes.
Wiring – Connecting HC-SR501 PIR motion sensor to Arduino UNO
By connecting the motion sensor to a microcontroller like the Arduino UNO, you can use it to control all kinds of things: LEDs, relays, motors, buzzers etc.
In the wiring diagram below, you can see how to hook it up to the Arduino. You can read the sensor with one of the general-purpose input/output (GPIO) pins of the Arduino. In this example, I connected it to digital pin 2. The VCC and GND pins are connected to 5 V and GND respectively.
The connections are also given in the table below:
HC-SR501 PIR Motion Sensor Connections
HC-SR501 PIR Motion Sensor | Arduino |
---|---|
VCC | 5 V |
OUT | Pin 2 |
GND | GND |
Once you have wired up the sensor, the next step is to upload some example code.
HC-SR501 PIR motion sensor with Arduino UNO example code
With the following example code, you can read out the sensor and control the on-board LED of the Arduino (connected to pin 13). This code can also be used to control simple relays to turn a bigger light on or off.
You can upload the example code with the Arduino IDE.
For this code to work properly, it is best to set the trigger mode jumper to ‘H’ (repeat trigger mode). Also adjust the time-delay potentiometer to the lowest value. Turn it counterclockwise as far as it will go.
The code will read the state of the sensor (HIGH or LOW) and turn on or off the on-board LED accordingly. It will also print a message to the Serial Monitor, which you can access under Tools or type (Ctrl+Shift+M).
/* Example code for HC-SR501 PIR motion sensor with Arduino. More info: www.www.makerguides.com */ // Define connection pins: #define pirPin 2 #define ledPin 13 // Create variables: int val = 0; bool motionState = false; // We start with no motion detected. void setup() { // Configure the pins as input or output: pinMode(ledPin, OUTPUT); pinMode(pirPin, INPUT); // Begin serial communication at a baud rate of 9600: Serial.begin(9600); } void loop() { // Read out the pirPin and store as val: val = digitalRead(pirPin); // If motion is detected (pirPin = HIGH), do the following: if (val == HIGH) { digitalWrite(ledPin, HIGH); // Turn on the on-board LED. // Change the motion state to true (motion detected): if (motionState == false) { Serial.println("Motion detected!"); motionState = true; } } // If no motion is detected (pirPin = LOW), do the following: else { digitalWrite(ledPin, LOW); // Turn off the on-board LED. // Change the motion state to false (no motion): if (motionState == true) { Serial.println("Motion ended!"); motionState = false; } } }
You should see the following output in the serial monitor:
Code explanation:
The code is quite simple and you don’t need any Arduino libraries to use this sensor.
The sketch starts with defining the PIR sensor pin and LED pin. I connected them to Arduino pin 2 and 13 (on-board LED).
The statement #define
is used to give a name to a constant value. The compiler will replace any references to this constant with the defined value when the program is compiled. So everywhere you mention pirPin
, the compiler will replace it with the value 2 when the program is compiled.
I also created two variables, val
and motionState
, which are an integer and boolean (true/false) respectively. The variable val
is used to store the output of the PIR sensor (HIGH or LOW) and motionState
will turn to true while motion is detected and to false when there is no motion.
// Define connection pins: #define pirPin 2 #define ledPin 13 // Create variables: int val = 0; bool motionState = false; // We start with no motion detected.
In the setup()
, we set the pins as input or output with the function pinMode(pin,mode)
. The pirPin is an input and the ledPin is an output. We also begin serial communication at a baud rate of 9600. Make sure that the Serial Monitor is also set to 9600.
void setup() { // Configure the pins as input or output: pinMode(ledPin, OUTPUT); pinMode(pirPin, INPUT); // Begin serial communication at a baud rate of 9600: Serial.begin(9600); }
In the loop()
, I first read out the sensor with the function digitalRead(pin)
. This function returns HIGH or LOW.
// Read out the pirPin and store as val: val = digitalRead(pirPin);
When the sensor output/val is HIGH, I turn the LED on with the function digitalWrite(pin,value)
.
// If motion is detected (pirPin = HIGH), do the following: if (val == HIGH) { digitalWrite(ledPin, HIGH); // Turn on the on-board LED. // Change the motion state to true (motion detected): if (motionState == false) { Serial.println("Motion detected!"); motionState = true; } }
Next, the motionState is changed to true and the message ‘Motion detected!’ is printed to the Serial Monitor. Note that I first check the current motionState, this makes sure that the message is only printed once per motion event.
If there is no longer motion in front of the sensor, val
will change to LOW and the LED is turned off and the message ‘Motion ended!’ is printed to the serial monitor.
Create an alarm system with PIR motion sensor and buzzer
With some simple changes, you can create an alarm system with the HC-SR501 and a piezoelectric buzzer. I connected the buzzer with a 100 Ω resistor between digital pin 5 and GND. You can probably use the buzzer without a resistor (this makes it louder), but it will not sound as nice.
The code below is mostly the same as the previous example. I only added a function to create the beeping alarm sound. You can change the pitch of the buzzer by changing the input parameter of the alarm(duration,frequency)
function.
/* Example code to create an alarm system with HC-SR501 PIR motion sensor, buzzer and Arduino. More info: www.www.makerguides.com */ // Define connection pins: #define buzzerPin 5 #define pirPin 2 #define ledPin 13 // Create variables: int val = 0; bool motionState = false; // We start with no motion detected. void setup() { // Configure the pins as input or output: pinMode(buzzerPin, OUTPUT); pinMode(ledPin, OUTPUT); pinMode(pirPin, INPUT); // Begin serial communication at a baud rate of 9600: Serial.begin(9600); } void loop() { // Read out the pirPin and store as val: val = digitalRead(pirPin); // If motion is detected (pirPin = HIGH), do the following: if (val == HIGH) { digitalWrite(ledPin, HIGH); // Turn on the on-board LED. alarm(500, 1000); // Call the alarm(duration, frequency) function. delay(150); // Change the motion state to true (motion detected): if (motionState == false) { Serial.println("Motion detected!"); motionState = true; } } // If no motion is detected (pirPin = LOW), do the following: else { digitalWrite(ledPin, LOW); // Turn off the on-board LED. noTone(buzzerPin); // Make sure no tone is played when no motion is detected. delay(150); // Change the motion state to false (no motion): if (motionState == true) { Serial.println("Motion ended!"); motionState = false; } } } // Function to create a tone with parameters duration and frequency: void alarm(long duration, int freq) { tone(buzzerPin, freq); delay(duration); noTone(buzzerPin); }
Things to consider when designing a PIR sensor system
Just like other PIR sensors, the HC-SR501 needs some time to initialize and adjust to the infrared levels in the room. This takes approximately 1 minute when it is first powered up. Try to eliminate any motion in front of the sensor during this period.
Wind and a light source close to the sensor can cause interference, so try to adjust your setup to avoid this. Also, note that you must mount the sensor horizontally since most motion will happen in the horizontal plane (e.g. walking).
Besides the delay-time (Tx), the sensor also has a ‘blocking-time’ (Ti). By default, the blocking time is 2.5 seconds and it is not very easy to change (see BISS0001 datasheet). Each time the output goes from HIGH to LOW, the blocking period start. During this time period, the sensor will not detect any motion.
When designing a system based on the HC-SR501, you will need to take these delay periods into account.
Conclusion
In this article, I have shown you how the HC-SR501 PIR motion sensor works and how you can use it with Arduino. I hope you found it useful and informative. If you did, please share it with a friend who also likes electronics and making things!
I would love to know what projects you plan on building (or have already built) with this sensor. If you have any questions, suggestions, or if you think that things are missing in this tutorial, please leave a comment down below.
Note that comments are held for moderation to prevent spam.
Benne is professional Systems Engineer with a deep expertise in Arduino and a passion for DIY projects.
Roy
Sunday 2nd of June 2024
Great article, thanks. I am using the hc-sr501 in stand alone mode and I would like to utilise the RL feature with an LDR. I want to switch the circuit off during the day but I have no experience of LDR’s can someone suggest a specific device?
Stefan Maetschke
Sunday 2nd of June 2024
Hi, You will need one of these: https://amzn.to/3wQ0QsP Which one depends at what level of light the PIR sensor should switch off. The set has LDRs with different base resistances and you will have to try out which works best for your use case.
J van Wezel
Thursday 28th of March 2024
Hello Benne, I connected a HC501 sensor to a HW307 relay. Immediatly both te leds (red and green) go on and the relay doesn't react on the sensor (stays High). I try this connection without using arduino. Can you help me to solve this "mistery"?
Johan van Wezel
Monday 1st of April 2024
@Stefan Maetschke, Thx for your quick response. But I still have the same problem. I made some pictures that might help you. But I don’t know how to send them to you.
Stefan Maetschke
Thursday 28th of March 2024
Hi, the HC-SR501 sensor can take up to one minute to initialize and the output might be high during that time. Then there is an adjustable delay of up to 5mins (depending on the setting of that little poti on the sensor). (https://www.mpja.com/download/31227sc.pdf) So, worst case your relay may stay on for 6 minutes before the sensor/circuit starts to react to motion and if there is any motion detected during that time frame the sensor stays high as well.
Reduce the time delay as much as possible (turn poti left) and it should react nicely. I recreated the circuit and with a short time delay it reacts within less on 1 sec.
Hope this helps ; )
hogo
Wednesday 18th of May 2022
hello every body when I use PIR SR501 with a peizo buzzer, when buzzer sound, the PIR sensor activated falsely. I use a buzzer like below. https://assoc-redirect.amazon.com/g/r/https://www.amazon.com/Xnrtop-Continuous-Decibel-Buzzer-Speaker/dp/B07VCK2FTK/ref=sr_1_11?keywords=piezoelectric+buzzer&linkCode=ll2&linkId=6096839e36d5708a1bd01b38ae7968eb&qid=1652877367&sr=8-11 anyone has recommend?
NEIL IVES
Sunday 21st of March 2021
To avoid cold surprises, I'm planning a system to shut the hot water taps in the house when someone is in the shower. This IR detector will be mounted so it detects a person standing under the shower head at the end of the bath. The output will trigger CMOS switches to close water valves in the house. I need sensitivity to be adjustable so a person taking a bath does not trigger the circuit. I also want the valves to stay closed for a while in the case of the showeree standing still long enough for the circuit release; the delay adjuster will be important.
Ron K
Saturday 23rd of January 2021
To me, the data sheet doesn't provide critical information. Does the minimum range change with the maximum range? I did find it on another site. No. The minimum remains a constant zero. Full CW, the range of sensing distance increases, and the maximum sensing distance range is about 0-7 meters.
Full CCW, the range of sensing distance is reduced, and the minimum sensing distance range is about 0-3 meters.