{"id":68479,"date":"2025-10-27T14:41:47","date_gmt":"2025-10-27T14:41:47","guid":{"rendered":"http:\/\/randomnerdtutorials.com\/?p=68479"},"modified":"2025-10-27T16:43:07","modified_gmt":"2025-10-27T16:43:07","slug":"esp32-pir-motion-sensor-interrupts-timers","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-pir-motion-sensor-interrupts-timers\/","title":{"rendered":"ESP32 with PIR Motion Sensor using Interrupts and Timers (Arduino IDE)"},"content":{"rendered":"\n<p>Learn how to use a PIR (Passive Infrared) Motion Sensor with the ESP32 programmed with Arduino IDE to detect motion. We&#8217;ll create a simple example to introduce you to the concepts of <em>timers <\/em>and <em>interrupts<\/em>.<\/p>\n\n\n\n<p>In this example, when motion is detected (an interrupt is triggered), the ESP32 starts a timer and turns an LED on for a predefined number of seconds. When the timer finishes counting down, the LED is automatically turned off.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/ESP32-PIR-Motion-Sensor.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with PIR Motion Sensor using Interrupts and Timers\" class=\"wp-image-182065\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/ESP32-PIR-Motion-Sensor.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/ESP32-PIR-Motion-Sensor.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/ESP32-PIR-Motion-Sensor.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/ESP32-PIR-Motion-Sensor.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/ESP32-PIR-Motion-Sensor.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgray\">Updated October 27, 2025.<\/p>\n\n\n\n<p class=\"rntbox rntclgreen\"><strong>Using MicroPython?<\/strong> Check out this tutorial instead: <a href=\"https:\/\/randomnerdtutorials.com\/micropython-interrupts-esp32-esp8266\/\">MicroPython: Interrupts with ESP32 and ESP8266<\/a>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Table of Contents<\/h2>\n\n\n\n<p>In this tutorial, we&#8217;ll cover the following subjects:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#pir-intro\" title=\"\">Introducing the PIR Motion Sensor<\/a><\/li>\n\n\n\n<li><a href=\"#interrupts-intro\" title=\"\">Introducing Interrupts<\/a><\/li>\n\n\n\n<li><a href=\"#timers-intro\" title=\"\">Introducing Timers<\/a><\/li>\n\n\n\n<li><a href=\"#esp32-pir-motion-example\" title=\"\">ESP32 with PIR Motion Sensor: Detecting Motion (practical example)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before proceeding with this tutorial, you should have the ESP32 boards installed in your Arduino IDE. Follow this next tutorial to install the ESP32 on the Arduino IDE, if you haven\u2019t already.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\">Installing ESP32 Board in Arduino IDE 2 (Windows, Mac OS X, Linux)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Parts Required<\/h2>\n\n\n\n<p>To follow this tutorial, you need the following parts<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noopener noreferrer\">ESP32 DOIT DEVKIT V1 Board<\/a>&nbsp;&#8211;&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noopener noreferrer\">read ESP32 Development Boards Review and Comparison<\/a><\/li>\n\n\n\n<li>1x <a href=\"https:\/\/makeradvisor.com\/tools\/mini-hc-sr505-pir-motion-sensor\/\" target=\"_blank\" rel=\"noopener noreferrer\">Mini PIR motion sensor (AM312)<\/a>&nbsp;or&nbsp;<a href=\"https:\/\/makeradvisor.com\/tools\/pir-motion-sensor-hc-sr501\/\" target=\"_blank\" rel=\"noopener noreferrer\">PIR motion sensor (HC-SR501)<\/a><\/li>\n\n\n\n<li>1x <a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener noreferrer\">5mm LED<\/a><\/li>\n\n\n\n<li>1x <a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noopener noreferrer\">330 Ohm resistor<\/a> or similar value<\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noopener noreferrer\">Jumper wires<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noopener noreferrer\">Breadboard<\/a><\/li>\n<\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"pir-intro\">Introducing the PIR Motion Sensor<\/h2>\n\n\n\n<p>A PIR motion sensor detects changes in infrared light in its field of view caused by movement. This makes it ideal for detecting humans or animals because it will pick up living things (or heat-emitting objects) that move within their range but not inanimate objects.<\/p>\n\n\n\n<p>You can program the ESP32 to react to changes in infrared light by triggering an event such as turning on a light, sounding an alarm, sending a notification, or any other task. In this tutorial, we\u2019ll print a message on the Serial Monitor, and turn on an LED for a predefined number of seconds.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/04\/AM312-PIR-Motion-Sensor.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"AM312 PIR Motion Sensor Pinout labeled\" class=\"wp-image-130668\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/04\/AM312-PIR-Motion-Sensor.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/04\/AM312-PIR-Motion-Sensor.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><figcaption class=\"wp-element-caption\">Mini AM312 PIR Motion Sensor<\/figcaption><\/figure><\/div>\n\n\n<p>There are different PIR motion sensor modules, but all act in a similar way. Usually, they have a power pin, GND, and data.<\/p>\n\n\n\n<p>The PIR motion sensor outputs a\u00a0<strong>HIGH\u00a0<\/strong>signal on the Data pin when it detects movement, or a\u00a0<strong>LOW\u00a0<\/strong>signal if it doesn\u2019t. Usually, they only have three pins:\u00a0<strong>VCC<\/strong>,\u00a0<strong>GND,\u00a0<\/strong>and\u00a0<strong>Data<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"1024\" height=\"358\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/PIR-Motion-Sensor-How-it-works.png?resize=1024%2C358&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"PIR motion sensor how it works\" class=\"wp-image-136745\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/PIR-Motion-Sensor-How-it-works.png?resize=1024%2C358&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/PIR-Motion-Sensor-How-it-works.png?resize=300%2C105&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/PIR-Motion-Sensor-How-it-works.png?resize=768%2C268&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/PIR-Motion-Sensor-How-it-works.png?resize=1536%2C537&amp;quality=100&amp;strip=all&amp;ssl=1 1536w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/PIR-Motion-Sensor-How-it-works.png?resize=2048%2C716&amp;quality=100&amp;strip=all&amp;ssl=1 2048w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/PIR-Motion-Sensor-How-it-works.png?w=2400&amp;quality=100&amp;strip=all&amp;ssl=1 2400w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>An important concept about PIR motion sensors is the\u00a0<em>dwell time\u00a0<\/em>(reset time or <em>sensor delay<\/em>)\u2014it is the duration during which a PIR motion sensor\u2019s output remains HIGH after detecting motion before returning to a LOW state.<\/p>\n\n\n\n<p>Some PIR sensor models, like the HC-SR501, might have two potentiometers (those two orange potentiometers in the picture below) to adjust the sensitivity and the sensor delay:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/HC-SR501-Motion-Sensor.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"HC-SR501 Motion Sensor\" class=\"wp-image-136744\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/HC-SR501-Motion-Sensor.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/HC-SR501-Motion-Sensor.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><figcaption class=\"wp-element-caption\">HC-SR501 PIR Motion Sensor<\/figcaption><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Sensitivity potentiometer:<\/strong>\u00a0this adjusts the sensor\u2019s detection range. Clockwise increases sensitivity, counterclockwise decreases it.<\/li>\n\n\n\n<li><strong>Time delay potentiometer:<\/strong>\u00a0this controls how long the sensor remains triggered after detecting motion. Clockwise increases the delay, and counterclockwise decreases it.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"interrupts-intro\">Introducing Interrupts<\/h2>\n\n\n\n<p>To trigger an event with a PIR motion sensor, you use interrupts. Interrupts are useful for making things happen automatically in microcontroller programs, and can help solve timing problems.<\/p>\n\n\n\n<p>With interrupts you don\u2019t need to constantly check the current value of a pin. With interrupts, when a change is detected, an event is triggered (a function is called).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using Interrupts with the ESP32<\/h3>\n\n\n\n<p>To set an interrupt in the Arduino IDE, you use the&nbsp;<strong>attachInterrupt()<\/strong>&nbsp;function, that accepts as  arguments: the GPIO pin, the name of the function to be executed, and the mode:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>attachInterrupt(GPIO), callback_function, mode);<\/code><\/pre>\n\n\n\n<p>This instruction should be added to the <span class=\"rnthl rntliteral\">setup()<\/span> of your Arduino code.<\/p>\n\n\n\n<p>Let&#8217;s take a look at the arguments you should pass to that function.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">GPIO Interrupt<\/h4>\n\n\n\n<p>The first argument of the <span class=\"rnthl rntliteral\">attachInterrupt()<\/span> function is the GPIO number where we&#8217;ll detect the change.  For example, if you want to use GPIO 27 as an interrupt, you can use:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>digitalPinToInterrupt(27)<\/code><\/pre>\n\n\n\n<p class=\"rntbox rntclgreen\">With an ESP32 board, all the pins that can act as inputs can be set as interrupts. <\/p>\n\n\n\n<p class=\"rntbox rntclgreen\">For example, in the case of the ESP32 DOIT V1 board, all the pins highlighted with a red rectangle in the following figure can be configured as interrupt pins. In this example, we\u2019ll use <span class=\"rnthl rntcyellow\">GPIO 27<\/span> as an interrupt connected to the PIR Motion sensor.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"522\" height=\"676\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pins_used_as_interrupts.png?resize=522%2C676&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-68484\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pins_used_as_interrupts.png?w=522&amp;quality=100&amp;strip=all&amp;ssl=1 522w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pins_used_as_interrupts.png?resize=232%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 232w\" sizes=\"(max-width: 522px) 100vw, 522px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgray\"><strong>Using an ESP32S3 instead?<\/strong> Check this pinout guide: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-s3-devkitc-pinout-guide\/\" title=\"\">ESP32-S3 DevKitC Pinout Reference Guide: GPIOs Explained<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Callback Function (ISR)<\/h4>\n\n\n\n<p>The second argument of the <span class=\"rnthl rntliteral\">attachInterrupt()<\/span> function is the name of the function that will be called when the interrupt is triggered. This function is also called <em>interrupt service routine<\/em> (ISR).<\/p>\n\n\n\n<p>Now, there are a few important rules you should be aware of when defining your ISR (callback function).<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The ISR should not return anything.<\/li>\n\n\n\n<li>ISRs should be as short and fast as possible because they halt the normal execution of the code.<\/li>\n\n\n\n<li>They should have the <span class=\"rnthl rntliteral\">ARDUINO_ISR_ATTR<\/span> attribute, so that they run in the ESP32 Internal RAM and not in Flash. IRAM access is much faster, which is critical for ISRs to run reliably without timing issues or crashes during interrupts.<\/li>\n\n\n\n<li>Variables that are used inside ISRs and throughout the code should preferably be <span class=\"rnthl rntliteral\">volatile<\/span>. This prevents the compiler from caching values in registers (and skipping memory access), so reads\/writes always access the actual memory location and reflect unexpected changes caused by the interrupt.<\/li>\n<\/ol>\n\n\n\n<p>Here&#8217;s an example of an ISR so that you can check its syntax:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void ARDUINO_ISR_ATTR my_callback() {\n    \/\/ Any code you want to run\n}<\/code><\/pre>\n\n\n\n<p class=\"rntbox rntclgray\">Another important thing about ISRs is that you should keep their code as fast and simple as possible and avoid things like complex operations, writing to the Serial Monitor, or using <span class=\"rnthl rntliteral\">delay()<\/span>. Instead, you should use a flag or counter to indicate that the interrupt happened, and then handle whatever you need to do in the main code or <span class=\"rnthl rntliteral\">loop()<\/span> section.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Mode<\/h4>\n\n\n\n<p>The third argument is the mode. There are 5 different modes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">LOW<\/span>: to trigger the interrupt whenever the pin is LOW;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">HIGH<\/span>: to trigger the interrupt whenever the pin is HIGH;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">CHANGE<\/span>: to trigger the interrupt whenever the pin changes value &#8211; for example, from HIGH to LOW or LOW to HIGH;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">FALLING<\/span>: for when the pin goes from HIGH to LOW;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">RISING<\/span>: to trigger when the pin goes from LOW to HIGH.<\/li>\n<\/ul>\n\n\n\n<p>The following picture will help you better understand the different trigger modes.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"438\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/interrupt-modes.png?resize=750%2C438&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Interrupt modes\" class=\"wp-image-169637\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/interrupt-modes.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/interrupt-modes.png?resize=300%2C175&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>For this example we&#8217;ll be using the <span class=\"rnthl rntliteral\">RISING<\/span> mode, because when the PIR motion sensor detects motion, the GPIO it is connected to goes from <span class=\"rnthl rntliteral\">LOW<\/span> to <span class=\"rnthl rntliteral\">HIGH<\/span>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"timers-intro\">Introducing Timers<\/h2>\n\n\n\n<p>In this example we&#8217;ll also introduce timers. We want the LED to stay on for a predetermined number of seconds after motion is detected. Instead of using a <span class=\"rnthl rntliteral\">delay()<\/span> function that blocks your code and doesn\u2019t allow you to do anything else for a determined number of seconds, we should use a timer.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/alarm-clock-1-150x150.png?resize=150%2C150&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-68480\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/alarm-clock-1-150x150.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/alarm-clock-1-150x150.png?resize=80%2C80&amp;quality=100&amp;strip=all&amp;ssl=1 80w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">The delay() function<\/h3>\n\n\n\n<p>You should be familiar with the <span class=\"rnthl rntliteral\">delay()<\/span> function as it is widely used. This function is pretty straightforward to use. It accepts a single int number as an argument. This number represents the time in milliseconds the program has to wait until moving on to the next line of code.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>delay(time in milliseconds)<\/code><\/pre>\n\n\n\n<p>When you call <span class=\"rnthl rntliteral\">delay(1000)<\/span> your program stops on that line for 1 second.<\/p>\n\n\n\n<p><span class=\"rnthl rntliteral\">delay()<\/span> is a blocking function. Blocking functions prevent a program from doing anything else until that particular task is completed. If you need multiple tasks to occur at the same time, you cannot use <span class=\"rnthl rntliteral\">delay()<\/span>.<\/p>\n\n\n\n<p>For most projects, you should avoid using delays and use timers instead.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The millis() function<\/h3>\n\n\n\n<p>Using a function called <span class=\"rnthl rntliteral\">millis()<\/span> is preferred over using delay(). The <span class=\"rnthl rntliteral\">millis()<\/span> function returns the number of milliseconds that have passed since the program first started.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>millis()<\/code><\/pre>\n\n\n\n<p>Why is that function useful? By using some math, you can easily check how much time has passed since a certain event without blocking your code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Blinking an LED with millis()<\/h3>\n\n\n\n<p>The following snippet of code shows how you can use the <span class=\"rnthl rntliteral\">millis()<\/span> function to create a blink LED project. It turns an LED on for 1000 milliseconds, and then turns it off.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos\n  Complete project details at http:\/\/randomnerdtutorials.com  \n*********\/\n\n\/\/ constants won't change. Used here to set a pin number :\nconst int ledPin =  26;      \/\/ the number of the LED pin\n\n\/\/ Variables will change :\nint ledState = LOW;             \/\/ ledState used to set the LED\n\n\/\/ Generally, you should use &quot;unsigned long&quot; for variables that hold time\n\/\/ The value will quickly become too large for an int to store\nunsigned long previousMillis = 0;        \/\/ will store last time LED was updated\n\n\/\/ constants won't change :\nconst long interval = 1000;           \/\/ interval at which to blink (milliseconds)\n\nvoid setup() {\n  \/\/ set the digital pin as output:\n  pinMode(ledPin, OUTPUT);\n}\n\nvoid loop() {\n  \/\/ here is where you'd put code that needs to be running all the time.\n\n  \/\/ check to see if it's time to blink the LED; that is, if the\n  \/\/ difference between the current time and last time you blinked\n  \/\/ the LED is bigger than the interval at which you want to\n  \/\/ blink the LED.\n  unsigned long currentMillis = millis();\n\n  if (currentMillis - previousMillis &gt;= interval) {\n    \/\/ save the last time you blinked the LED\n    previousMillis = currentMillis;\n\n    \/\/ if the LED is off turn it on and vice-versa:\n    if (ledState == LOW) {\n      ledState = HIGH;\n    } else {\n      ledState = LOW;\n    }\n\n    \/\/ set the LED with the ledState of the variable:\n    digitalWrite(ledPin, ledState);\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/Blink_Without_Delay\/Blink_Without_Delay.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">How the code works<\/h4>\n\n\n\n<p>Let\u2019s take a closer look at this blink sketch that works without a <span class=\"rnthl rntliteral\">delay()<\/span> function (it uses the <span class=\"rnthl rntliteral\">millis()<\/span> function instead).<\/p>\n\n\n\n<p>Basically, this code subtracts the previous recorded time (<span class=\"rnthl rntliteral\">previousMillis<\/span>) from the current time (<span class=\"rnthl rntliteral\">currentMillis<\/span>). If the remainder is greater than the interval (in this case, 1000 milliseconds), the program updates the <span class=\"rnthl rntliteral\">previousMillis<\/span> variable to the current time, and either turns the LED on or off.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (currentMillis - previousMillis &gt;= interval) {\n&nbsp; \/\/ save the last time you blinked the LED\n&nbsp; previousMillis = currentMillis;\n  (...)<\/code><\/pre>\n\n\n\n<p>Because this snippet is non-blocking, any code that\u2019s located outside of that first <span class=\"rnthl rntliteral\">if<\/span> statement should work normally.<\/p>\n\n\n\n<p>You should now be able to understand that you can add other tasks to your <span class=\"rnthl rntliteral\">loop()<\/span> function and your code will still be blinking the LED every one second.<\/p>\n\n\n\n<p>You can upload this code to your ESP32 and assemble the following schematic diagram to test it and modify the number of milliseconds to see how it works.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"645\" height=\"631\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/blink_without_delay_bb.png?resize=645%2C631&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-68481\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/blink_without_delay_bb.png?w=645&amp;quality=100&amp;strip=all&amp;ssl=1 645w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/blink_without_delay_bb.png?resize=300%2C293&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 645px) 100vw, 645px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-pir-motion-example\">ESP32 with PIR Motion Sensor: Detecting Motion<\/h2>\n\n\n\n<p>After understanding these concepts: interrupts and timers, let\u2019s continue with the project.<\/p>\n\n\n\n<p>We\u2019ll create a simple example that will light up an LED when motion is detected. After learning how it works, the same way of thinking can be applied to useful applications, such as sending an email or triggering an alarm.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"135\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/03\/pir-motion-sensor-with-micropython-esp32-esp8266.png?resize=750%2C135&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with a PIR Motion Sensor Example Overview\" class=\"wp-image-82033\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/03\/pir-motion-sensor-with-micropython-esp32-esp8266.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/03\/pir-motion-sensor-with-micropython-esp32-esp8266.png?resize=300%2C54&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Here&#8217;s how the example works:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The sensor detects motion.<\/li>\n\n\n\n<li>The ESP32 detects this event.<\/li>\n\n\n\n<li>It prints in the Serial Monitor that motion was detected.<\/li>\n\n\n\n<li>It turns on an LED for 20 seconds.<\/li>\n\n\n\n<li>During those 20 seconds, we don&#8217;t print anything else to the Serial Monitor.<\/li>\n\n\n\n<li>After those 20 seconds and if motion was not detected, we turn off the LED, print a message to the Serial Monitor indicating that motion has stopped.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Circuit Diagram<\/h3>\n\n\n\n<p>For this example, you need to connect the PIR motion sensor and an LED to your board. <\/p>\n\n\n\n<p>The LED is connected to <span class=\"rnthl rntcblue\">GPIO 26<\/span>. <\/p>\n\n\n\n<p>We\u2019ll be using the <a href=\"https:\/\/makeradvisor.com\/tools\/mini-hc-sr505-pir-motion-sensor\/\" target=\"_blank\" rel=\"noopener noreferrer\">Mini AM312 PIR Motion Sensor<\/a> that operates at 3.3V.\u00a0 It will be connected to <span class=\"rnthl rntcyellow\">GPIO 27<\/span>. You can follow the next schematic diagram.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"665\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pir_esp32_interrupts.jpg?resize=1200%2C665&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-68486\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pir_esp32_interrupts.jpg?w=1274&amp;quality=100&amp;strip=all&amp;ssl=1 1274w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pir_esp32_interrupts.jpg?resize=300%2C166&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pir_esp32_interrupts.jpg?resize=768%2C426&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pir_esp32_interrupts.jpg?resize=1024%2C567&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/07\/pir_esp32_interrupts.jpg?resize=750%2C415&amp;quality=100&amp;strip=all&amp;ssl=1 750w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgray\"><span style=\"color: #ff0000;\">Important:<\/span> the <a href=\"https:\/\/makeradvisor.com\/tools\/mini-hc-sr505-pir-motion-sensor\/\" target=\"_blank\" rel=\"noopener noreferrer\">Mini AM312 PIR Motion Sensor<\/a>\u00a0used in this project operates at 3.3V. However, if you&#8217;re using another PIR motion sensor like the\u00a0<a href=\"https:\/\/makeradvisor.com\/tools\/pir-motion-sensor-hc-sr501\/\" target=\"_blank\" rel=\"noopener noreferrer\">HC-SR501<\/a>, it operates at 5V. You can either\u00a0<a href=\"https:\/\/randomnerdtutorials.com\/modifying-cheap-pir-motion-sensor-to-work-at-3-3v\/\" target=\"_blank\" rel=\"noopener noreferrer\">modify it to operate at 3.3V<\/a>\u00a0or simply power it using the Vin pin.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code &#8211; ESP32 with a PIR Motion Sensor: Detect Motion<\/h3>\n\n\n\n<p>After wiring the circuit as shown in the schematic diagram, copy the code provided to your Arduino IDE.<\/p>\n\n\n\n<p>You can upload the code as it is, or you can modify the number of seconds the LED is lit after detecting motion. Simply change the <span class=\"rnthl rntliteral\">timeSeconds<\/span> variable with the number of seconds you want.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-pir-motion-sensor-interrupts-timers\/\n  ESP32 GPIO Interrupts with Arduino IDE: https:\/\/RandomNerdTutorials.com\/esp32-gpio-interrupts-arduino\/\n*********\/\n#include &lt;Arduino.h&gt;\n\n\/\/ Set GPIOs for LED and PIR Motion Sensor\nconst uint8_t led = 26;\nconst uint8_t motionSensor = 27;\n\n\/\/ Timer: Auxiliary variables\nunsigned long now;\nvolatile unsigned long lastTrigger = 0;\nvolatile bool startTimer = false;\n\nbool printMotion = false;\n\nconst unsigned long timeSeconds = 20 * 1000UL;  \/\/20 seconds in milliseconds\n\nvoid ARDUINO_ISR_ATTR motionISR() {\n  lastTrigger = millis();\n  startTimer = true;\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  pinMode(motionSensor, INPUT_PULLUP);\n  attachInterrupt(motionSensor, motionISR, RISING);\n\n  \/\/ Set LED to LOW\n  pinMode(led, OUTPUT);\n  digitalWrite(led, LOW);\n}\n\nvoid loop() {\n  now = millis();\n\n\/\/ Turn LED on immediately on new trigger\n  if (startTimer &amp;&amp; !printMotion) {\n    digitalWrite(led, HIGH);\n    Serial.println(&quot;MOTION DETECTED!!!&quot;);\n    printMotion = true;\n  }\n\n\/\/ Turn off the LED after timeout\n  if (startTimer &amp;&amp; (now - lastTrigger &gt; timeSeconds)) {\n    Serial.println(&quot;Motion stopped...&quot;);\n    digitalWrite(led, LOW);\n    startTimer = false;\n    printMotion = false;\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_Interrupts\/Interrupts_PIR_Motion.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p><strong>Note: <\/strong>if you&#8217;ve experienced any issues uploading code to your ESP32, take a look at the <a href=\"https:\/\/randomnerdtutorials.com\/esp32-troubleshooting-guide\/\">ESP32 Troubleshooting Guide<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>Let&#8217;s take a quick look at the code to better understand how it works.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Defining Variables<\/h4>\n\n\n\n<p>We start by defining the pins for the LED and PIR Motion sensor. Adjust if you&#8217;re using different pins:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const uint8_t led = 26;\nconst uint8_t motionSensor = 27;<\/code><\/pre>\n\n\n\n<p>Create variables to track the duration of the LED in the on state. The <span class=\"rnthl rntliteral\">now<\/span> variable saves the current time (time elapsed since the program has started), the <span class=\"rnthl rntliteral\">lastTrigger<\/span> saves the last time motion was detected, and the <span class=\"rnthl rntliteral\">startTimer<\/span> is a boolean variable to indicate whether the timer to turn on the LED is currently running or not.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned long now;\nvolatile unsigned long lastTrigger = 0;\nvolatile bool startTimer = false;<\/code><\/pre>\n\n\n\n<p>We also have another variable to keep track whether the <em>Motion Detected<\/em> text was already printed to the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>bool printMotion = false;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">timeSeconds<\/span> variable saves how long we want the LED on after motion is detected. You can adjust according to your preferences.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const unsigned long timeSeconds = 20 * 1000UL;  \/\/20 seconds in milliseconds<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">motionISR()<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">motionISR()<\/span> will run when motion is detected. We save the current time on the <span class=\"rnthl rntliteral\">lastTrigger<\/span> variable to keep track when motion was detected, and we set the <span class=\"rnthl rntliteral\">startTimer<\/span> variable to <span class=\"rnthl rntliteral\">true<\/span> to indicate it&#8217;s time to start the timer to turn on the LED.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void ARDUINO_ISR_ATTR motionISR() {\n  lastTrigger = millis();\n  startTimer = true;\n}<\/code><\/pre>\n\n\n\n<p>We&#8217;ll then handle these variables in the <span class=\"rnthl rntliteral\">loop()<\/span> to do the tasks we want.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">setup()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, set the motion sensor as an interrupt on <span class=\"rnthl rntliteral\">RISING<\/span> mode (when motion is detected, the sensor sets its output pin to <span class=\"rnthl rntliteral\">HIGH<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(motionSensor, INPUT_PULLUP);\nattachInterrupt(motionSensor, motionISR, RISING);<\/code><\/pre>\n\n\n\n<p>And set the LED as an <span class=\"rnthl rntliteral\">OUTPUT<\/span> and set it to <span class=\"rnthl rntliteral\">LOW<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Set LED to LOW\npinMode(led, OUTPUT);\ndigitalWrite(led, LOW);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">loop()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, we&#8217;re constantly getting the current time and saving it in the <span class=\"rnthl rntliteral\">now<\/span> variable.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>now = millis();<\/code><\/pre>\n\n\n\n<p>Then, we check whether the LED timer has started and if the motion message has not already been printed. If these conditions are met, we turn the LED on, print a message to the Serial Monitor, and set the printMotion variable to true, because we have now printed the <em>Motion Detected<\/em> message to the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (startTimer &amp;&amp; !printMotion) {\n  digitalWrite(led, HIGH);\n  Serial.println(\"MOTION DETECTED!!!\");\n  printMotion = true;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>Upload the code to your ESP32 board. Make sure you have the right board and COM port selected.<\/p>\n\n\n\n<p>Open the Serial Monitor at a baud rate of 115200. Press the ESP32 RST button so that it starts running the code.<\/p>\n\n\n\n<p>Move your hand in front of the PIR sensor. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"496\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-detect-moton-with-PIR.jpeg?resize=750%2C496&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Moving my hand in front of the PIR motion sensor connected to the ESP32\" class=\"wp-image-181800\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-detect-moton-with-PIR.jpeg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-detect-moton-with-PIR.jpeg?resize=300%2C198&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The LED should turn on, and a message is printed in the Serial Monitor saying <span class=\"rnthl rntliteral\">\u201cMOTION DETECTED!!!\u201d<\/span>. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"691\" height=\"306\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-PIR-Motion-Sensor-Interrupts-Serial-Monitor.png?resize=691%2C306&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 PIR Motion Sensor with Interrupts - Messages on Serial Monitor\" class=\"wp-image-181798\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-PIR-Motion-Sensor-Interrupts-Serial-Monitor.png?w=691&amp;quality=100&amp;strip=all&amp;ssl=1 691w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-PIR-Motion-Sensor-Interrupts-Serial-Monitor.png?resize=300%2C133&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 691px) 100vw, 691px\" \/><\/figure><\/div>\n\n\n<p>After 20 seconds, the LED should turn off (if motion was not detected meanwhile).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"428\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-PIR-Motion-Sensor-and-LED.jpeg?resize=750%2C428&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 on a breadboard connected to an LED and a PIR motion sensor\" class=\"wp-image-181799\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-PIR-Motion-Sensor-and-LED.jpeg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-PIR-Motion-Sensor-and-LED.jpeg?resize=300%2C171&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Now that you understand how to use interrupts to detect motion with a PIR motion sensor, you can easily adjust the code to do any useful tasks instead of controlling an LED.<\/p>\n\n\n\n<p>You can, for example, send notifications to your email or smartphone to indicate that motion was detected. We have a tutorial with seven different ways to send notifications with the ESP32 that you can explore:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/send-notifications-esp32\/\" title=\"\">7 Different Ways to Send Notifications with the ESP32<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Watch the Video Tutorial and Project Demo<\/h2>\n\n\n\n<p><em>This tutorial is also available in video format (watch below).<\/em> Note that the video format might be outdated.<\/p>\n\n\n<p style=\"text-align:center\"><iframe width=\"720\" height=\"405\" src=\"https:\/\/www.youtube.com\/embed\/PcqiKy_rb24?rel=0\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>To wrap up, interrupts are used to detect a change in the GPIO state without the need to constantly read the current GPIO value. With interrupts, when a change is detected, a function is triggered. You\u2019ve also learned how to set a simple timer that allows you to check if a predefined number of seconds have passed without having to block your code.<\/p>\n\n\n\n<p>We have other tutorials related to the ESP32 that you may also like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-arduino-ide\/\">ESP32 Web Server \u2013 Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-data-logging-temperature-to-microsd-card\/\">ESP32 Data Logging Temperature to MicroSD Card<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-i2c-lcd-arduino-ide\/\">How to Use I2C LCD with ESP32 on Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/esp32-vs-esp8266\/\" target=\"_blank\" rel=\"noopener noreferrer\">ESP32 vs ESP8266 \u2013 Pros and Cons<\/a><\/li>\n<\/ul>\n\n\n\n<p><em>This is an excerpt from our course:&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE<\/a>. If you like ESP32 and you want to learn more, we recommend enrolling in&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE course<\/a>.<\/em><\/p>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to use a PIR (Passive Infrared) Motion Sensor with the ESP32 programmed with Arduino IDE to detect motion. We&#8217;ll create a simple example to introduce you to the &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 with PIR Motion Sensor using Interrupts and Timers (Arduino IDE)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-pir-motion-sensor-interrupts-timers\/#more-68479\" aria-label=\"Read more about ESP32 with PIR Motion Sensor using Interrupts and Timers (Arduino IDE)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":182065,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[276,281,277,299,264],"tags":[],"class_list":["post-68479","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32","category-esp32-project","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/ESP32-PIR-Motion-Sensor.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/68479","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=68479"}],"version-history":[{"count":9,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/68479\/revisions"}],"predecessor-version":[{"id":182072,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/68479\/revisions\/182072"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/182065"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=68479"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=68479"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=68479"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}