Hello friends, I hope you all are doing great. Today, I am going to share the new PIR Sensor Library for Proteus V4.0. The HC-SR501 is a very popular PIR motion sensor module: a green board with a white dome that switches its OUT pin HIGH when a person or an animal moves in front of it. You find it in motion-activated lights, alarms and automatic doors. With this PIR Sensor Library for Proteus, a person or a cat walks through a room on your schematic, and your Arduino reads the OUT pin exactly as it reads a real HC-SR501.
Version 4.0 is the next version of our PIR sensor library. You get two devices: HC-SR501 Simple, with a room scene on the schematic, and HC-SR501 Advance, with a pop-up window and four measured sensor test tools. The model has the time delay, the H / L jumper, the block time and the warm-up of the real module, the board is animated, and the new PIR sensor Arduino Proteus demo runs on two Arduino UNOs with a motion lamp and a warm-up guard, shown in the compact Simple interface of our TEP Serial Monitor.
NOTICE: This library is very special to our team. Our HC-SR501 model has the BISS0001's trigger logic with the time delay, jumper H and L, the block time and the warm-up with its false pulses, and a PIR that sees only a moving warm body inside its 110 degree cone and its range. It took our team a lot of hard work, many test runs and many design changes. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the PIR Sensor Library board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the PIR Sensor Library for Proteus:
What is a PIR Sensor (HC-SR501)?
PIR stands for passive infrared. Every warm body gives off infrared light (heat radiation) that our eyes cannot see. A PIR sensor sends nothing out, which is why it is called passive; it only watches this light. Inside the HC-SR501 sits a pyroelectric sensor with two elements, under a white plastic Fresnel lens: the dome. The lens splits the room into zones. When a warm body moves from one zone to the next, the two elements see a change of heat, and the sensor gives a small signal.
The module's controller chip, the BISS0001, turns that signal into a clean digital output: it switches the OUT pin HIGH for a set time. Two small pots set that time (TIME) and the range (SENS), and a jumper decides what happens when the motion goes on (H or L). Your Arduino needs one digital pin and no library.
The HC-SR501 at a Glance
| Feature | Value |
|---|---|
| Sensor | A dual-element pyroelectric sensor under a white Fresnel dome |
| Controller | BISS0001 PIR signal processor |
| Output | OUT, digital: HIGH = 3.3 V (motion was seen), LOW = 0 V |
| Supply | 4.5 to 20 V (5 V from the Arduino is fine) |
| Time delay (TIME pot) | About 3 s to 5 minutes |
| Range (SENS pot) | About 3 to 7 m |
| Field of view | A cone of about 110 degrees |
| Trigger jumper | H = repeat trigger, L = single trigger |
| Block time | About 2.5 s after OUT falls, not adjustable on the board |
| Warm-up | 30 to 60 s after power-on, with false pulses |
| Pins | VCC, OUT, GND (three pins) |
PIR Terms You Will See in This Article
| Term | Meaning |
|---|---|
| PIR | Passive infrared: the sensor only receives heat radiation |
| Fresnel lens | The white dome; it splits the view into zones |
| BISS0001 | The chip that turns the PIR signal into the OUT pulse |
| Trigger (PIR pulse) | One "I saw motion" signal from the PIR to the BISS0001 |
| Time delay | How long OUT stays HIGH after a trigger (the TIME pot) |
| Repeat trigger (H) | Every new trigger restarts the time delay |
| Single trigger (L) | OUT stays HIGH for the time delay only, then falls |
| Block time | After OUT falls, the sensor ignores motion for a short time |
| Warm-up | The settling time after power-on; OUT can give false pulses |
| Response | The time from the moment the PIR first sees the body to OUT going HIGH |
How the HC-SR501 Decides When OUT Goes HIGH
Only a Moving Warm Body Counts
A PIR sees changes of heat, not heat itself. A person who walks across the room gives trigger pulses; the same person standing still gives none. So the HC-SR501 is a motion sensor, not a presence sensor: OUT falls after the time delay even when someone is still in the room.
The Time Delay and the Jumper
On the first trigger, OUT goes HIGH for the time delay. On the real board, the TIME pot sets it from about 3 s to 5 minutes; our model starts at 5 s to keep the demo fast. The jumper decides what a new trigger does while OUT is HIGH:
- H, repeat trigger: every new trigger restarts the time delay. OUT stays HIGH while you keep moving and falls one time delay after the last trigger. Most projects use H.
- L, single trigger: OUT stays HIGH for exactly the time delay and then falls, even if you keep moving.
The Block Time and the Warm-Up
When OUT falls, the BISS0001 ignores every trigger for about 2.5 s, the block time. So with jumper L, a person who keeps walking makes pulses of exactly the time delay, with a gap of the block time between them.
After power-on, a real HC-SR501 needs 30 to 60 s to settle, and OUT may give false pulses meanwhile, which a sketch cannot tell from real motion. Our model gives two false pulses, at 20 % and 55 % of the warm-up; that is an approximation, because real modules vary. The demo skips the warm-up (WARMUP = SKIP); click REAL 60 s on the panel or run the Warm-up test to see it.
How Our Model Watches the Room
In our model, the PIR looks at the room every 100 ms while the body moves. The body counts as seen when it moves inside the 110 degree cone and within the range. The second look in a row that sees it gives the first trigger, and then one trigger comes every 0.5 s while the body stays seen. So OUT goes HIGH 0.2 s after the motion starts, which is 0.1 s after the PIR first sees the body: the response. A cat counts only up to half of the SENS range, because it is smaller and warms fewer zones.
What's New in PIR Sensor Library for Proteus V4.0
Our PIR sensor library had earlier versions, up to V3.0. Version 4.0 is the next one, and it brings:
- Two devices in
TEPHCSR501.LIB: HC-SR501 Simple (HCSR501TEP) and HC-SR501 Advance (HCSR501ADVTEP), both run byTEPHCSR501.DLL. - The BISS0001 behaviour: the time delay, jumper H and L, the block time and the warm-up.
- A live board with PWR, OUT and TRIG LEDs (a TEP addition), turning pots, a moving jumper cap, a glowing dome and an animated PIR VIEW screen.
- A room scene: a person or a cat walks in, paces, stands still or walks out.
- An event log with measured times and four measured test tools on the Advance.
- A two-UNO demo with the TEP Serial Monitor instead of the Virtual Terminal, with a lamp on A0 and five commands.
- A fast sheet: the panels animate at 10 Hz and redraw only what changes. In our Proteus run, the whole demo runs at about 0.71 x real time (22.0 s simulated in 30.8 s, with the pop-up open, U1 animating and both monitors running); our first V4.0 build reached only about 0.35 x.
- A small package: about 1.52 MB, without the C++ source code.
PIR Sensor Library for Proteus: Simple vs Advance
Both devices run the same model with the same properties; only the panel differs:
| Feature | Simple | Advance |
|---|---|---|
| Full HC-SR501 model (BISS0001 timing, jumper, block time, warm-up, 110 degree cone, range) | ✔ | ✔ |
| Green board: PWR / OUT / TRIG LEDs, turning pots, jumper, glowing dome, PIR VIEW screen | ✔ | ✔ |
| PIR ROOM SCENE panel on the schematic (the room, the OUT timeline, scene and module buttons) | ✔ | ✘ |
| Pop-up window you can move, resize and minimise | ✘ | ✔ |
| Room page with THE SENSOR card (measured times) and the EVENT LOG | ✘ | ✔ |
| OUT check, Retrigger H / L, Warm-up & block and Range sweep | ✘ | ✔ |
| TEP Dark / Light theme, text size, Help page with Copy diagnostics | ✘ | ✔ |
| Close the panel and open it again from the board | ✔ | ✔ |
Choose Simple when you want to see the room next to your circuit, and Advance when your sheet is full or you want measured numbers about your sensor. The demo has one of each.
Download PIR Sensor Library for Proteus
Click the button below to download PIR-Sensor-Library-for-Proteus-v4.0.zip (about 1.52 MB, without the C++ source code):
PIR Sensor Library for Proteus V4.0- README.txt: a detailed guide to the files, the wiring, the model, the test tools and real hardware.
- Proteus Library Files:
TEPHCSR501.LIB(both devices),TEPSERIALMON.LIBand our Arduino UNO libraryArduinoV3TEP.LIB/ArduinoV3TEP.IDX. - Proteus Model Files:
TEPHCSR501.DLLandTEPSERIALMON.DLL. - Proteus Simulation:
HCSR501-PIR-ArduinoUnoV3.pdsprj,HCSR501_Motion.hex(both UNOs run it) and copies of both DLLs. - Arduino Code:
HCSR501_Motion.ino, the demo sketch. It needs no Arduino library.
No Proteus yet? Read How to Download and Install Proteus 7 and 8. New to libraries? Follow How to Install a New Library in Proteus.
How to Install PIR Sensor Library for Proteus
- Close Proteus and extract the whole zip file.
- Copy the four files from Proteus Library Files into the LIBRARY folder, usually
C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY(on some PCsC:\ProgramData\Labcenter Electronics\Proteus 8 Professional\LIBRARY). - Copy
TEPHCSR501.DLLandTEPSERIALMON.DLLinto the MODELS folder. - Start Proteus, press P and search for HC-SR501 or PIR. You get the Simple and the Advance device (category Sensors > Motion).
Updating from an earlier version? Replace its LIB and DLL files, and delete TEPHCSR501.IDX if there is one in the LIBRARY folder. Tested in Proteus 8.5; Proteus 7 is not supported.
The HC-SR501 Board in Proteus
We drew the sensor as a clean TEP board in the green of the real module: the white faceted Fresnel dome in the middle, the orange TIME and SENS pots, the BISS0001 chip, the L / H jumper with its yellow cap and the VCC OUT GND header. The real module has the dome on one side and the parts on the other; we put them all on one face, so you see everything at once. Here is U1, the Simple device, right after Run:
The PIR VIEW Screen
Above the board, on two posts, sits the PIR VIEW - TOP screen. It shows the sensor's cone from above with the zone arcs at 1.5, 3.5 and 6 m, the detection range as an arc in the state's colour (green = ready, orange = OUT HIGH, violet = blocked, amber = warming up) and the warm body as a dot. While the PIR sees the body, a halo and heat ripples run from the body to the sensor.
Pinout
The three pins have the real order, left to right with the dome up and the header at the bottom: VCC, OUT and GND. Some clones swap them, so on a real board, check the print under the dome.
| Pin | What it does | Demo connection |
|---|---|---|
| VCC | Power (4.5 to 20 V on the real module) | Power terminal |
| OUT | Digital output: HIGH while motion was seen, LOW when the time delay is over | Arduino D2 |
| GND | Ground | Ground |
LEDs and Indicators
| Indicator | What it shows |
|---|---|
| PWR LED (red) | Lit while the board has power |
| OUT LED (green) | Lit while OUT is HIGH |
| TRIG LED (amber) | Lights for 0.3 s on every trigger pulse from the PIR, also on the ones the BISS0001 ignores |
| Dome ring | Grey when idle, amber blinking while warming up, orange-red while OUT is HIGH, a yellow flash on each accepted trigger, violet while blocked |
| TIME and SENS pots | Their slots turn with the settings |
| Jumper cap | Sits on H or on L |
| PIR VIEW screen | The cone, the range in the state's colour, the body, the halo and the heat ripples |
| PANEL / OPEN PANEL, SIMPLE / ADVANCE | The panel button and the device badge |
The PWR, OUT and TRIG LEDs are a TEP addition: the real HC-SR501 has no LED at all. The board also reacts to the mouse: click the jumper to move its cap, and click the left or right half of a pot to turn it down or up.
Component Properties
| Property | Meaning | Default |
|---|---|---|
| TRIGGER | The jumper: H (repeat) or L (single) | H |
| TIMEDELAY | The time delay in s (the TIME pot: 3 to 300 on the real board; 1 to 600 accepted) | 5 |
| SENSITIVITY | The range in m (the SENS pot), 3 to 7 | 5 |
| BLOCKTIME | The block time after OUT falls, in s, 0 to 10 | 2.5 |
| WARMUP | SKIP, REAL (60 s) or a number of seconds, 0 to 300 | SKIP |
| BODY | PERSON or CAT | PERSON |
| ZONE | NEAR (1.5 m), MID (3.5 m) or FAR (6 m) | MID |
| START | The body at Run: STILL, WALKING, OUTSIDE or AUTO | STILL |
| PANEL | Simple only: the panel at Run, OPEN or CLOSED | OPEN |
A bad value is written to the Simulation Log, and the default is used. The panel style comes from the device (Simple or Advance), not from a property; the Advance window has its own "open at Run" setting. There is one more property, for emergencies: if a part of a panel ever looks stale in your Proteus, add REDRAW=FULL under Edit Properties > Other Properties. The sensor then redraws everything on every frame, like our first V4.0 build. It is slower, but it is the fallback.
HC-SR501 Simple: The PIR Room Scene on the Sheet
Beside the Simple board sits the HC-SR501 PIR ROOM SCENE panel (on the right of the image above). On its left, a room of 9.1 x 8.2 m seen from above: the sensor in the bottom wall, its cone, the detection area cut at the SENS range (RANGE 5 m), the zone arcs NEAR 1.5 m, MID 3.5 m and FAR 6 m, a sofa, a plant and the door in the right wall. On its right:
| Part | What it does |
|---|---|
| Header, red X | HC-SR501 PIR ROOM SCENE; the X closes the panel |
| Banner | The state in words and in its colour |
| OUT, TIME LEFT, BLOCK LEFT, DETECTIONS | OUT now, the time delay and the block time still to run, and the detections since power-on (without the warm-up's false pulses) |
| OUT TIMELINE - LAST 30 s | Green = OUT HIGH, violet = blocked, amber = warm-up, ticks = PIR pulses |
| PERSON (OR CAT) | WALK IN, STAND STILL, WALK OUT, AUTO DEMO |
| WARM BODY, DISTANCE ZONE | PERSON or CAT; NEAR 1.5 m, MID 3.5 m or FAR 6 m |
| SENSITIVITY POT (3 - 7 m), TIME DELAY POT (3 s - 5 min) | The SENS and TIME pots with - / + |
| TRIGGER JUMPER | L SINGLE or H REPEAT |
| WARM-UP AFTER POWER ON | SKIP, or REAL 60 s |
| HOW A PIR SENSOR SEES | Six short tips on how a PIR works |
| Button | What the warm body does |
|---|---|
| WALK IN | Walks from the door to the zone, then paces across the cone |
| STAND STILL | Stops where it is (from outside: walks in and stops) |
| WALK OUT | Walks back to the door and out |
| AUTO DEMO | Outside 4 s, in and pacing 6 s, still 12 s, out, and again |
| PERSON / CAT | A cat is seen only up to half of the SENS range |
| NEAR / MID / FAR | The pacing zone: 1.5, 3.5 or 6 m from the sensor |
At Run: Standing Still Is Invisible
Look at the image above again. The demo starts with START = STILL: the person stands at MID 3.5 m, inside the cone and the range, and yet the banner says NO MOTION - A STILL BODY IS INVISIBLE TO THE PIR. OUT is LOW, DETECTIONS is 0, and only the PWR LED is lit, just like a real PIR.
WALK IN: Motion Detected
Click WALK IN. The person walks in and paces across the cone at MID 3.5 m, and 0.2 s after the motion starts, OUT goes HIGH. The banner turns green, MOTION DETECTED - OUT HIGH, the detection area turns orange and the person gets an orange halo. On the board, all three LEDs are lit, the dome's ring flashes yellow with the accepted trigger, and the PIR VIEW shows heat ripples running to the sensor.
TIME LEFT says 4.9 s: with jumper H, every new trigger restarts the 5 s time delay. Now click STAND STILL: the banner says OUT HIGH - TIME DELAY RUNNING, NO MOTION NOW, and 5 s after the last trigger, OUT falls. The area turns violet for the 2.5 s block, then green again, and U3 prints the "Motion ended" line with the HIGH time.
Jumper L: OUT Drops While You Keep Walking
Now click L SINGLE while the person keeps pacing, and the jumper cap on the board moves to L. New triggers no longer restart the time delay, so OUT falls when it runs out, although the person is still walking. Then the sensor is blocked: the banner turns violet, BLOCKED (RE-ARMING) - OUT LOW, MOTION IGNORED, BLOCK LEFT shows 0.3 s, and the dome ring and the detection area are violet.
The PIR still sees the person: the ticks on the timeline go on, and the TRIG LED still flashes. But the BISS0001 ignores those triggers until the block ends. This is why a light with jumper L can switch off while you are still in the room.
A Cat at MID 3.5 m: Too Far
Click CAT. A cat is smaller and warms fewer zones, so our model sees it only up to half of the SENS range: 2.5 m with SENS 5 m. At MID 3.5 m, the cat walks and walks, but OUT stays LOW, and the banner turns orange: NO MOTION SEEN - TOO FAR FOR THE SENSITIVITY. On the PIR VIEW screen, the green range arc has moved in to half the distance, with the cat's dot beyond it. The timeline still shows the person's two detections, each followed by the violet block.
To catch the cat, click NEAR 1.5 m, or press SENS + twice: at 7 m, a cat counts up to 3.5 m.
Closing the Panel
Click the red X in the panel's header: the panel disappears, the board button says PANEL: CLOSED, and the sensor keeps running. The PIR VIEW screen stays, so you still see what the sensor sees; here, the cat beyond its range. Click PANEL to bring the panel back. The PANEL property decides whether the panel is open at Run.
HC-SR501 Advance: The Pop-Up Room Window
The Advance device keeps only the board on the schematic. Here is U2:
At Run, the "TEP HC-SR501 Advance" pop-up opens with the look of our TEP Serial Monitor and no Windows title bar: move it by its header, resize or minimise it, and open it again with OPEN PANEL after you close it. The header shows the state (for example U2 · OUT HIGH), the Room and Test tabs, and the palette (theme), gear (Settings) and ? (Help) icons.
The Room Page
- Toolbar chips: OUT HIGH, Jumper H, TIME 5 s, Range 5 m and Detections 12.
- ROOM - TOP VIEW: the same room with the cone, the range in the state's colour and the person with the halo.
- THE SENSOR: the state, OUT "HIGH (3.3 V)", time left 5.0 s of 5 s, Detections 12 (208 PIR pulses), the measured Last HIGH 20.2 s, After last pulse 5.0 s, Last block 2.5 s and Response 0.10 s, the jumper, the range and the warm body: person at 3.5 m, -11 degrees.
- SCENE AND MODULE SETTINGS and OUT - THE LAST 30 SECONDS: the buttons and the timeline of the Simple panel.
- EVENT LOG - NEWEST FIRST: every event with its simulation time.
Read the event log from the bottom up. At 272.554 s, the person stopped. At 277.501 s: "OUT LOW - HIGH for 20.2 s, 5.0 s after the last trigger", and at 280.001 s: "Ready again - blocked for 2.5 s". Then the person started moving at 367.301 s, the PIR saw it at 3.5 m at 367.401 s, and at 367.501 s came "OUT HIGH - motion #12 at 3.5 m, 0.10 s after it was seen". The model measures these times itself, so they are exactly what OUT did.
The Test Page: Four Measured Sensor Test Tools
The four tools on the Test tab only move the warm body, set the jumper or restart the warm-up, and then read the model's event log. So every time they show is what OUT really did, measured with the simulation clock. Each tool ends with a bold "Good for:" line and puts the scene back when it ends. A tool refuses to start, with the reason, when the sensor has no power, is warming up, another test runs, or (for Retrigger and Warm-up) TIME is above 30 s. All results below come from U2 in our Proteus run.
1. OUT Check: Does OUT Stay HIGH for the TIME Pot?
Good for: "checking that OUT stays HIGH for the TIME pot after the last motion - what your sketch reads on D2." Choose 20, 40 or 60 s and the motion: As set (the scene as it is), Walk in + out (in, pace 4 s, out, 3 s outside, and again) or Auto demo. Then click Run test. The chart shows the body moving (blue), the PIR pulses (the green tick started OUT) and OUT (green HIGH, violet block).
| # | Rise | Fall | HIGH for | After last pulse | Restarts | Response |
|---|---|---|---|---|---|---|
| 1 | 0.20 s | 11.20 s | 11.0 s | 5.0 s | 12 | 0.10 s |
| 2 | 17.00 s | 29.50 s | 12.5 s | 5.0 s | 15 | 0.10 s |
| 3 | 35.35 s | still HIGH | - | - | 9 | 0.10 s |
Every pulse is longer than 5 s, because each PIR pulse restarts the time delay (12 and 15 restarts). But every pulse ends exactly 5.0 s after its last trigger: the TIME pot. After each fall, the sensor is blind for 2.5 s, and every pulse started 0.10 s after the PIR first saw the body. The third pulse was still HIGH when the 40 s ended.
2. Retrigger H / L: Why Does OUT Drop While I Keep Moving?
Good for: "seeing why OUT drops while you keep moving (jumper L) or stays HIGH all along (jumper H)." The tool makes the same motion twice, first with jumper L and then with jumper H: 10.5 s of moving in place at 3.0 m (60 % of the range), which is TIME 5 s + block 2.5 s + 3 s. Choose 1 or 3 bursts; each burst starts after a flat lead-in (OUT LOW and the sensor ready for 1 s).
| Jumper | Pulses | HIGH times | Gaps (block) | OUT fell after the motion |
|---|---|---|---|---|
| L | 2 | 5.0 s, 5.0 s | 2.5 s | 2.2 s later |
| H | 1 | 15.0 s | - | 4.7 s later |
With jumper L, OUT is HIGH for exactly 5.0 s and falls although the body keeps moving, stays blind for the 2.5 s block, and then the next trigger starts a second pulse of 5.0 s. With jumper H, every PIR pulse restarts the time. The first trigger came 0.2 s after the motion started and the last one 0.3 s before it ended, so OUT was HIGH from 0.2 s to 15.2 s: one pulse of 15.0 s, falling 4.7 s after the motion, which is 5.0 s after the last trigger. For a light that must stay on while people move, use H.
3. Warm-Up & Block: How Long Is the Sensor Blind?
Good for: "knowing how long to wait after power-on, and how long the sensor is blind after OUT falls." Choose a warm-up of 10 s, 30 s or 60 s (real); the tool reminds you that "a real HC-SR501 needs 30 - 60 s". It restarts the warm-up like a fresh power-on while the person keeps moving. After the first detection, the person stands still until OUT falls and then moves again at once.
| Time | Event (as the tool lists it) |
|---|---|
| 0.00 s | warm-up 30 s starts (like a fresh power-on) |
| 6.00 s | OUT HIGH - false pulse 1 (the sketch would see motion!) |
| 7.80 s | OUT LOW - the false pulse lasted 1.8 s |
| 16.50 s | OUT HIGH - false pulse 2 (the sketch would see motion!) |
| 18.30 s | OUT LOW - the false pulse lasted 1.8 s |
| 30.00 s | warm-up over after 30.0 s (60 triggers ignored) |
| 30.20 s | OUT HIGH - motion detected |
| 35.20 s | OUT LOW after 5.0 s HIGH - the block starts |
| 37.70 s | ready again after a 2.5 s block (5 pulses ignored) |
| 37.90 s | OUT HIGH - motion detected |
The two false pulses come at 20 % and 55 % of the warm-up (6.0 and 16.5 s of 30 s), and to your sketch they look exactly like motion. The person moved all through the warm-up, but all 60 triggers were ignored; the first real detection came 0.2 s after the warm-up ended. Then the block: OUT fell at 35.20 s, the sensor ignored 5 pulses for 2.5 s, and the next detection came at 37.90 s, so OUT was LOW for 2.7 s between two detections. The demo sketch has the cure for the false pulses: the GUARD command.
4. Range Sweep: Where Does the Sensor See You?
Good for: "finding where the sensor sees a moving body - the SENS range straight ahead and the 110 deg cone." Choose Straight ahead, Across the cone or Both. At each point, the body stands still for 0.3 s and then moves in place for 0.8 s; a point counts when the PIR gives a pulse. Straight ahead, the points go from 0.5 to 8 m; across the cone, from -70 to +70 degrees at 60 % of the range (3.0 m here).
- Seen up to 5.0 m straight ahead and not seen from 5.5 m: the SENS pot.
- Cone -55 .. +55 degrees: 110 degrees in total; at -60 and +60 degrees, nothing.
- The first pulse 0.20 s after the motion started, at every point that was seen.
On the map, green dots are points with pulses, grey rings are points without, and the orange arc and lines are the range and the cone you set. For a cat, the range is half as far.
Settings and Help
The gear opens Settings: theme (TEP Dark or Light), text size (Small, Normal or Large), open the panel at Run, and the window size, saved for your Windows user.
The ? icon opens Help & Support: eight cards with their links (the PIR sensor forum board for bugs and ideas, this article, updates, donate, our website and the forum), Check for updates, and Copy diagnostics, which copies the scene, the counts, the measured values, the events and the test results for a bug report.
PIR Motion Sensor with Arduino in Proteus
Open HCSR501-PIR-ArduinoUnoV3.pdsprj from the Proteus Simulation folder, with HCSR501_Motion.hex and both DLLs beside it. Its two Arduino UNOs from our Arduino Library for Proteus V3.0 run the same HEX file:
- NODE 1 - SIMPLE: UNO 1 (ARD1) with the HC-SR501 Simple (U1), the lamp LED D1 with R1 (220 Ω) on A0, and Serial Monitor U3.
- NODE 2 - ADVANCE: UNO 2 (ARD2) with the HC-SR501 Advance (U2), the lamp LED D2 with R2 on A0, and Serial Monitor U4.
Wiring
| From | To | Why |
|---|---|---|
| HC-SR501 VCC / GND | Power terminal / ground | Power (the PWR LED lights) |
| HC-SR501 OUT | Arduino D2 | Read with digitalRead(): HIGH = motion |
| LED + 220 Ω (the lamp) | A0 to GND | The motion lamp |
| Serial Monitor RXD / TXD / GND | Arduino D1 / D0 / ground | Shows what the Arduino prints, sends what you type |
| Serial Monitor RXD2 | Not connected | OUT is one logic line, and the sketch prints what it sees |
On the real module, OUT is 3.3 V when HIGH, and an UNO at 5 V reads anything above 3.0 V as HIGH, so no level shifter is needed (see our Introduction to Arduino UNO). The sketch also lights the UNO's own LED on D13 ("L") while OUT is HIGH.
The Arduino Code
The sketch needs no library. It reads D2 every 10 ms and prints a line only when something happens. First the pins:
const int PIR_PIN = 2; // HC-SR501 OUT
const int LED_PIN = 13; // the UNO's built-in LED
const int LAMP_PIN = A0; // the lamp (LED + 220R)
In setup(), D2 is a plain input, because the sensor drives OUT itself, and the sketch prints its three start lines:
void setup() {
pinMode(PIR_PIN, INPUT); // the sensor drives OUT itself, no pull-up needed
pinMode(LED_PIN, OUTPUT);
pinMode(LAMP_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
setLamp(false);
Serial.begin(9600);
Serial.println("HC-SR501 PIR Motion Sensor demo - The Engineering Projects");
Serial.println("Move in front of the sensor (Proteus: WALK IN on the panel)...");
Serial.println("PIR Sensor Library for Proteus V4.0 - type HELP for the commands.");
}
The loop reads OUT, lets the UNO's LED follow it, and reads the commands from the Serial Monitor:
int state = digitalRead(PIR_PIN); // HIGH = motion, LOW = no motion
digitalWrite(LED_PIN, state); // the LED simply follows OUT
unsigned long now = millis();
readCommands();
A rising edge, where OUT was LOW and is HIGH now, is a new motion. The counter goes up, the time is stored, the lamp goes on, and the sketch prints the motion number and the time since the Arduino started:
if (state == HIGH && lastState == LOW) { // OUT just went HIGH: motion started
motionCount++;
highSince = now;
setLamp(true);
Serial.print("Motion detected! #");
Serial.print(motionCount);
Serial.print(" at ");
printSeconds(highSince);
Serial.println();
}
A falling edge means that the time delay is over. The sketch measures how long OUT was HIGH and keeps the shortest and the longest time for STATUS:
if (state == LOW && lastState == HIGH) { // OUT just went LOW: motion ended (time delay over)
lowSince = now;
lastHigh = now - highSince;
if (shortestHigh == 0 || lastHigh < shortestHigh) shortestHigh = lastHigh;
if (lastHigh > longestHigh) longestHigh = lastHigh;
Serial.print("Motion ended #");
Serial.print(motionCount);
Serial.print(" at ");
printSeconds(now);
Serial.print(" (OUT was HIGH for ");
printSeconds(now - highSince);
Serial.println(")");
}
printSeconds() prints milliseconds as seconds with one decimal, rounded to 0.1 s. The panels round their times the same way, so both show the same numbers:
void printSeconds(unsigned long ms) {
ms += 50;
Serial.print(ms / 1000);
Serial.print('.');
Serial.print((ms % 1000) / 100);
Serial.print(" s");
}
The lamp on A0 stays on for LAMP seconds after OUT goes LOW, like a motion-activated light in a corridor. With LAMP 0, the start value, it simply follows OUT:
if (lampOn && state == LOW && now - lowSince >= lampSeconds * 1000UL) {
setLamp(false); // no motion for LAMP seconds (LAMP 0: at once)
if (lampSeconds > 0) {
Serial.print("Lamp OFF after ");
Serial.print(lampSeconds);
Serial.println(" s without motion.");
}
}
GUARD is the answer to the warm-up's false pulses. While the guard runs, the sketch counts the OUT changes but ignores them; when it ends, it says how many it ignored and starts watching OUT:
if (guarding && (long)(now - guardUntil) >= 0) { // the guard time is over
guarding = false;
Serial.print("Guard over - watching OUT (");
Serial.print(guardIgnored);
Serial.println(" changes ignored).");
if (state == HIGH) highSince = now;
lastState = state;
}
if (guarding) { // sitting out the warm-up: no counting, no lamp
if (state != lastState) guardIgnored++;
lastState = state;
delay(10);
return;
}
The GUARD command takes 0 to 300 seconds; 0 switches the guard off:
if (s == 0) {
guarding = false;
Serial.println("Guard off - watching OUT.");
} else {
guarding = true;
guardUntil = millis() + (unsigned long)s * 1000UL;
Serial.print("Guard: OUT ignored for the next ");
Serial.print(s);
Serial.println(" s (warm-up).");
}
HELP prints three short lines, so they fit the Serial Monitor's Simple interface:
void printHelp() {
Serial.println("Commands: HELP, STATUS, RESET, LAMP s, GUARD s");
Serial.println(" LAMP s: the A0 lamp stays on s s after the motion (0-600)");
Serial.println(" GUARD s: ignore OUT for s s - sit out the warm-up (0-300)");
}
The loop ends with a short pause; 100 looks a second are plenty for a PIR:
lastState = state;
delay(10); // look 100 times a second - plenty for a PIR
To change the sketch, export a new HEX file and load it into both UNOs; see How to get the HEX file from Arduino. New to Arduino? Start with our Arduino Tutorial for Beginners.
Serial Monitor Commands
| Command | What it does | The sketch answers |
|---|---|---|
| HELP | The command list | Three lines, from "Commands: HELP, STATUS, RESET, LAMP s, GUARD s" |
| STATUS | OUT now, the motions counted, how long ago the last one ended; the last, shortest and longest HIGH time, the lamp and the guard | Two lines, "Status: ..." and " HIGH: ..." |
| RESET | The motion counter back to 0 | "Counter reset: 0 motions." |
| LAMP s | The A0 lamp stays on s seconds after OUT goes LOW (0 to 600; 0 = it follows OUT) | "Lamp: A0 stays on 10 s after the motion." for LAMP 10 |
| GUARD s | Ignore OUT for s seconds (0 to 300; 0 = off) | "Guard: OUT ignored for the next 30 s (warm-up)." for GUARD 30 |
Any other text gets "Unknown command: FOO - type HELP" (with your text in place of FOO). The README shows what STATUS prints after one motion with a HIGH time of 7.5 s:
Status: OUT LOW, 1 motion, last ended 4.2 s ago
HIGH: last 7.5 s, shortest 7.5 s, longest 7.5 s; lamp 0 s; guard off
How to Run the Demo
- Press Run. Both Serial Monitors (9600 baud) and U2's pop-up open, U3 and U4 print the three start lines, and the PWR LEDs light.
- On U1's panel, click WALK IN (the lamp D1 lights, U3 prints "Motion detected!"), then STAND STILL (5 s after the last trigger, U3 prints "Motion ended").
- Try CAT, FAR 6 m (press SENS + twice), L SINGLE, AUTO DEMO and WARM-UP REAL 60 s, whose two false pulses the sketch counts as motions.
- Use the quick buttons: STATUS, LAMP 10 (the lamp stays on 10 s after the motion), RESET and HELP on U3; STATUS, GUARD 30 (sit out the warm-up), LAMP 0 and HELP on U4.
- On U2, watch THE SENSOR card and the EVENT LOG on the Room page, then try the four tools on the Test tab.
- Close U2's window and open it again with OPEN PANEL; close U1's panel with its red X and open it with PANEL.
PIR Sensor Proteus Simulation Results
The Serial Monitor in Its Simple Interface
Both monitors in this demo run in the Simple interface of our TEP Serial Monitor, as in every monitor screenshot here. Only the log, the send box and one slim toolbar row stay visible (baud rate, follow, pause, search and clear), so the window stays small.
- Switch to it: right-click the log and choose Simple interface, or press Ctrl+Shift+U.
- Back to the full view: click the corner button (the expand arrows at the top right), press Esc or Ctrl+Shift+U, or right-click and choose Full interface.
- Your choice is remembered.
Type commands such as STATUS or LAMP 10 in the send box and press Enter; the quick buttons come back with the full view. Every line of the sketch is shorter than 80 characters (the longest has 71), so it fits this small window. Read all about the monitor in TEP Serial Monitor Advance for Proteus.
Start-Up
After Run, U3 prints its three lines, and then nothing until OUT changes: the sketch never prints anything periodically.
HC-SR501 PIR Motion Sensor demo - The Engineering Projects
Move in front of the sensor (Proteus: WALK IN on the panel)...
PIR Sensor Library for Proteus V4.0 - type HELP for the commands.
The Motion Log
Motion detected! #8 at 182.9 s
Motion ended #8 at 184.7 s (OUT was HIGH for 1.8 s)
Motion detected! #9 at 193.4 s
Motion ended #9 at 195.2 s (OUT was HIGH for 1.8 s)
Motion detected! #10 at 207.1 s
Motion ended #10 at 212.1 s (OUT was HIGH for 5.0 s)
Motion detected! #11 at 214.8 s
Motion ended #11 at 221.5 s (OUT was HIGH for 6.7 s)
Motion detected! #12 at 236.3 s
Motion ended #12 at 251.7 s (OUT was HIGH for 15.4 s)
Motion detected! #13 at 257.2 s
Motion ended #13 at 277.4 s (OUT was HIGH for 20.2 s)
Motion detected! #14 at 367.4 s
These lines come from U4 in our run, after the four tests. Look at #8 and #9: two pulses of 1.8 s, 10.5 s apart. They are the two false pulses of the Warm-up & block test, at 6.00 and 16.50 s of its warm-up. #10 at 207.1 s is that test's first real detection, 30.2 s after its warm-up started; it was HIGH for 5.0 s while the person stood still, and #11 followed 2.7 s after it ended: the 2.5 s block plus the 0.2 s response.
The sketch counts every rising edge of OUT, the false pulses too, while the model's Detections counter leaves them out. That is why U2 says Detections 12 while U4 is at #14: a warm-up guard matters in a real project. And look at #13: HIGH for 20.2 s. The Room page measured the same, "OUT LOW - HIGH for 20.2 s, 5.0 s after the last trigger", so the sketch and the model agree.
Troubleshooting
- Nothing is printed while the person stands in the room: correct; a PIR sees only moving warm bodies. Click WALK IN.
- "Motion detected!" right after Run without anyone moving: the warm-up's false pulses (WARMUP REAL or a number). Use GUARD in the sketch, or wait.
- OUT goes LOW although the person keeps walking: jumper L (single trigger), or the person is too far (FAR 6 m with SENS 5 m) or outside the cone.
- No new detection right after OUT went LOW: the block time (2.5 s).
- A cat at MID 3.5 m is not detected with SENS 5 m: correct; try NEAR 1.5 m or SENS 7 m.
- The part is not simulated, no panel or no monitor window: TEPHCSR501.DLL or TEPSERIALMON.DLL is missing from MODELS and the project folder; click OPEN MONITOR on a closed monitor.
- The Advance pop-up does not appear: click OPEN PANEL on the board, use Proteus's Debug menu, or turn "Open the panel at Run" back on in Settings.
- The red X does not close the Simple panel: the design holds an older symbol; replace TEPHCSR501.LIB, delete TEPHCSR501.IDX and re-pick the part.
- A part of a panel looks stale: add
REDRAW=FULLto the sensor (Edit Properties > Other Properties), and please tell us in the forum.
Things to Know Before Using a Real HC-SR501
The demo sketch uses no library, so it runs unchanged on a real UNO and HC-SR501. Keep in mind:
- Supply: 4.5 to 20 V; 5 V from the UNO is fine. OUT is 3.3 V when HIGH, which an UNO reads as HIGH.
- Pins: some clones swap VCC, OUT and GND: check the print under the dome.
- Jumper: its factory position varies; most projects use H.
- Warm-up: wait 30 to 60 s after power-on (or use GUARD 60 in the demo) before you trust OUT.
- What it sees: a body moving across its zones is seen best, a body walking straight at it is seen later (not simulated), and glass blocks it.
Limitations of the Simulation
- Not modelled: the analog signal of the pyroelectric element, the direction of motion (motion towards the sensor is seen as well as motion across it), temperature effects, the board's pads for a daylight sensor (LDR) and a thermistor, the retrigger glitches of real boards, and the exact false-pulse pattern of a real warm-up (it varies).
- The model is our own implementation, written from the published BISS0001 and HC-SR501 data; it contains no third-party code. The way the PIR looks every 100 ms, the cat's half range and the two false pulses are model choices.
- Licences: the demo sketch uses no Arduino library. The HEX file contains the Arduino AVR core 1.8.6, which includes LGPL-licensed code; its source code is on GitHub.
- Tested in Proteus 8.5 in October 2026: the demo on two UNOs, both panels, the four tools, the fixes after the first run (re-checked the same day) and every screenshot here; and with 1,435 automatic PC checks, all passed, 29 of them with the real demo sketch on two UNOs. Proteus 7 is not supported.
Want to know how far away the person is? See our Ultrasonic Sensor Library for Proteus V2.0. For short-range obstacles, try our Infrared Sensor Library for Proteus V2.0, and to switch your motion lamp on only at night, add our LDR Sensor Library for Proteus. To send a motion alarm to another Arduino by radio, add our HC-12 Library for Proteus.
So, that was all about the PIR Sensor Library for Proteus V4.0. I hope the walking person, the H / L jumper, the block time, the warm-up guard and the four test tools make the HC-SR501 much easier to understand, so your motion project works the first time you wire a real module. If you use the PIR Sensor Library for Proteus in a project, please share your feedback in the comments or in our forum, and if you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!