{"id":88005,"date":"2019-08-05T13:01:42","date_gmt":"2019-08-05T13:01:42","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=88005"},"modified":"2019-08-06T09:42:19","modified_gmt":"2019-08-06T09:42:19","slug":"interrupts-timers-esp8266-arduino-ide-nodemcu","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/interrupts-timers-esp8266-arduino-ide-nodemcu\/","title":{"rendered":"ESP8266 Interrupts and Timers using Arduino IDE (NodeMCU)"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to use interrupts and timers with the ESP8266 NodeMCU using Arduino IDE. Interrupts allow you to detect changes in the GPIO state without the need to constantly check its current value. With interrupts, when a change is detected, an event is triggered (a function is called).<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-Interrupts.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Interrupts and Timers with ESP8266 using Arduino IDE (NodeMCU)\" class=\"wp-image-88048\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-Interrupts.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-Interrupts.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-Interrupts.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-Interrupts.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<p>As an example, we\u2019ll detect motion using a PIR motion sensor: when motion is detected, the ESP8266 starts a timer and turns an LED on for a predefined number of seconds. When the timer finishes counting down, the LED automatically turns off.<\/p>\n\n\n\n<p class=\"rntbox rntclgreen\">To create an interrupt, call <span class=\"rnthl rntliteral\">attachInterrupt()<\/span> and pass as arguments the GPIO interrupt pin, the ISR (funcion to be called) and mode. The ISR function must have the <span class=\"rnthl rntliteral\">ICACHE_RAM_ATTR<\/span> attribute declared. The mode can be <span class=\"rnthl rntliteral\">CHANGE<\/span>, <span class=\"rnthl rntliteral\">RISING<\/span> or <span class=\"rnthl rntliteral\">FALLING<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);<\/code><\/pre>\n\n\n\n<p>Before proceeding with this tutorial you should have the ESP8266 add-on installed in your Arduino IDE. Follow <a href=\"https:\/\/randomnerdtutorials.com\/how-to-install-esp8266-board-arduino-ide\/\">this tutorial to&nbsp;Install ESP8266 in Arduino IDE<\/a>, if you haven&#8217;t already.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introducing ESP8266 Interrupts<\/h2>\n\n\n\n<p>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 pin value. When a change is detected, an event is triggered &#8211; a function is called. This function is called interrupt service routine (ISR).<\/p>\n\n\n\n<p>When an interrupt happens, the processor stops the execution of the main program to execute a task, and then gets back to the main program as shown in the figure below.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"992\" height=\"291\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/03\/interrupt.png?resize=992%2C291&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Introducing to ESP8266 NodeMCU Interrupts: how it works\" class=\"wp-image-81979\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/03\/interrupt.png?w=992&amp;quality=100&amp;strip=all&amp;ssl=1 992w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/03\/interrupt.png?resize=300%2C88&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/03\/interrupt.png?resize=768%2C225&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 992px) 100vw, 992px\" \/><\/figure><\/div>\n\n\n\n<p>This is especially useful to trigger an action whenever motion is detected or whenever a pushbutton is pressed without the need to constantly check its state.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">attachInterrupt() Function<\/h2>\n\n\n\n<p>To set an interrupt in the Arduino IDE, you use the <span class=\"rnthl rntliteral\">attachInterrupt()<\/span> function, that accepts as arguments: the GPIO interrupt pin, the name of the function to be executed, and mode:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">GPIO interrupt pin<\/h3>\n\n\n\n<p>The first argument is a GPIO interrupt. You should use <span class=\"rnthl rntliteral\">digitalPinToInterrupt(GPIO)<\/span> to set the actual GPIO as an interrupt pin. For example, if you want to use GPIO 14 as an interrupt, use:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>digitalPinToInterrupt(14)<\/code><\/pre>\n\n\n\n<p>The ESP8266 supports interrupts in any GPIO, except GPIO16.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ISR<\/h3>\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 every time the interrupt is triggered \u2013 the interrupt service routine (ISR).<\/p>\n\n\n\n<p>The ISR function should be as simple as possible, so the processor gets back to the execution of the main program quickly. <\/p>\n\n\n\n<p>The best approach is to signal the main code that the interrupt has happened by using a global variable and within the <span class=\"rnthl rntliteral\">loop()<\/span> check and clear that flag, and execute code.<\/p>\n\n\n\n<p>ISRs need to have <span class=\"rnthl rntliteral\">ICACHE_RAM_ATTR<\/span> before the function definition to run the interrupt code in RAM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Interrupt modes<\/h3>\n\n\n\n<p>The third argument is the mode and there are 3 different modes:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>CHANGE:<\/strong> to trigger the interrupt whenever the pin changes value \u2013 for example from HIGH to LOW or LOW to HIGH;<\/li><li><strong>FALLING:<\/strong> for when the pin goes from HIGH to LOW;<\/li><li><strong>RISING:<\/strong> to trigger when the pin goes from LOW to HIGH.<\/li><\/ul>\n\n\n\n<p>For our example, will be using the RISING mode, because when the PIR motion sensor detects motion, the GPIO it is connected to goes from LOW to HIGH.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introducing ESP8266 Timers<\/h2>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" 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=\"Introducing to ESP8266 NodeMCU Timers: how it works\" 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\n<p>For this tutorial, we&#8217;ll use 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\u2019ll use a timer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">delay() vs millis()<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">delay()<\/span> function 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 language-c\"><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. <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>. For most projects you should avoid using delays and use timers instead.<\/p>\n\n\n\n<p>Using a function called <span class=\"rnthl rntliteral\">millis()<\/span> you can return the number of milliseconds that have passed since the program first started.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>millis();<\/code><\/pre>\n\n\n\n<p>Why is that function useful? Because by using some math, you can easily verify how much time has passed without blocking your code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Blinking an LED using millis() (without delay)<\/h3>\n\n\n\n<p>If you&#8217;re not familiar with <span class=\"rnthl rntliteral\">millis()<\/span> function, we recommend reading this section. If you&#8217;re already familiar with timers, you can skip to the PIR motion sensor project.<\/p>\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 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 the <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 >= interval) {\n  \/\/ save the last time you blinked the LED\n  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&nbsp;if&nbsp;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 ESP8266 to test it. The on-board LED should be blinking every second.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-blinking-LED.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 blinking on-board LED (attached to GPIO 2) using Millis\" class=\"wp-image-88063\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-blinking-LED.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-blinking-LED.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">ESP8266 NodeMCU with PIR Motion Sensor<\/h2>\n\n\n\n<p>In this section, you&#8217;ll learn how to detect motion with a PIR motion sensor using interrupts and timers in your code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parts Required<\/h3>\n\n\n\n<p>Here&#8217;s a list of the parts required to complete this tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">ESP8266<\/a> (read <a rel=\"noreferrer noopener\" aria-label=\"Best ESP8266 development boards (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/best-esp8266-wi-fi-development-board\/\" target=\"_blank\">Best ESP8266 development boards<\/a>)<\/li><li><a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/pir-motion-sensor-hc-sr501\/\" target=\"_blank\">PIR motion sensor<\/a> (AM312)<\/li><li><a rel=\"noreferrer noopener\" aria-label=\"5mm LED\u2028 (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\">5mm LED<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"330 Ohm resistor\u2028 (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\">330 Ohm resistor<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"Breadboard (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\">Breadboard<\/a><\/li><li><a rel=\"noreferrer noopener\" aria-label=\"Jumper wires (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\">Jumper wires<\/a><\/li><\/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<h3 class=\"wp-block-heading\">Schematic Diagram<\/h3>\n\n\n\n<p>Assemble the PIR motion sensor and an LED to your ESP8266. We\u2019ll connect the LED to <span class=\"rnthl rntcgreen\">GPIO 12<\/span> (D6) and the PIR motion sensor data pin to <span class=\"rnthl rntcyellow\">GPIO 14<\/span> (D5).<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/esp8266_interrupts_pir_sensor_bb.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/esp8266_interrupts_pir_sensor_bb.png?resize=465%2C862&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Interrupts and Timers with PIR Motion Sensor Schematic Circuit Diagram\" class=\"wp-image-88007\" width=\"465\" height=\"862\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/esp8266_interrupts_pir_sensor_bb.png?w=650&amp;quality=100&amp;strip=all&amp;ssl=1 650w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/esp8266_interrupts_pir_sensor_bb.png?resize=162%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 162w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/esp8266_interrupts_pir_sensor_bb.png?resize=553%2C1024&amp;quality=100&amp;strip=all&amp;ssl=1 553w\" sizes=\"(max-width: 465px) 100vw, 465px\" \/><\/a><\/figure><\/div>\n\n\n\n<p class=\"rntbox rntclblue\"><strong>Recommended reading:<\/strong><a rel=\"noreferrer noopener\" href=\"https:\/\/randomnerdtutorials.com\/esp8266-pinout-reference-gpios\/\" target=\"_blank\"> ESP8266 Pinout Reference Guide<\/a><\/p>\n\n\n\n<p><strong>Important: <\/strong> the Mini AM312 PIR Motion Sensor used in this project operates at 3.3V. However, if you\u2019re using another PIR motion sensor like the HC-SR501, it operates at 5V. You can either modify it to operate at 3.3V or simply power it using the Vin pin.<\/p>\n\n\n\n<p>The following figure shows the AM312 PIR motion sensor pinout.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"292\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/mini-pir-pinout.jpg?resize=750%2C292&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"AM312 PIR motion sensor pinout: GND, Data, 3.3V\" class=\"wp-image-85870\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/mini-pir-pinout.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/08\/mini-pir-pinout.jpg?resize=300%2C117&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Code<\/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\n  Complete project details at https:\/\/randomnerdtutorials.com  \n*********\/\n\n#define timeSeconds 10\n\n\/\/ Set GPIOs for LED and PIR Motion Sensor\nconst int led = 12;\nconst int motionSensor = 14;\n\n\/\/ Timer: Auxiliary variables\nunsigned long now = millis();\nunsigned long lastTrigger = 0;\nboolean startTimer = false;\n\n\/\/ Checks if motion was detected, sets LED HIGH and starts a timer\nICACHE_RAM_ATTR void detectsMovement() {\n  Serial.println(&quot;MOTION DETECTED!!!&quot;);\n  digitalWrite(led, HIGH);\n  startTimer = true;\n  lastTrigger = millis();\n}\n\nvoid setup() {\n  \/\/ Serial port for debugging purposes\n  Serial.begin(115200);\n  \n  \/\/ PIR Motion Sensor mode INPUT_PULLUP\n  pinMode(motionSensor, INPUT_PULLUP);\n  \/\/ Set motionSensor pin as interrupt, assign interrupt function and set RISING mode\n  attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);\n\n  \/\/ Set LED to LOW\n  pinMode(led, OUTPUT);\n  digitalWrite(led, LOW);\n}\n\nvoid loop() {\n  \/\/ Current time\n  now = millis();\n  \/\/ Turn off the LED after the number of seconds defined in the timeSeconds variable\n  if(startTimer &amp;&amp; (now - lastTrigger &gt; (timeSeconds*1000))) {\n    Serial.println(&quot;Motion stopped...&quot;);\n    digitalWrite(led, LOW);\n    startTimer = 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\/ESP8266\/ESP8266_Interrupts_Timers.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 look at the code.<\/p>\n\n\n\n<p>Start by assigning two GPIO pins to the <span class=\"rnthl rntliteral\">led<\/span> and <span class=\"rnthl rntliteral\">motionSensor<\/span> variables.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const int led = 12;\nconst int motionSensor = 14;<\/code><\/pre>\n\n\n\n<p>Then, create variables that will allow you set a timer to turn the LED off after motion is detected.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned long now = millis();\nunsigned long lastTrigger = 0;\nboolean startTimer = false;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">now<\/span> variable holds the current time. The <span class=\"rnthl rntliteral\">lastTrigger<\/span> variable holds the time when the PIR sensor detects motion. The <span class=\"rnthl rntliteral\">startTimer<\/span> is a boolean variable that starts the timer when motion is detected.<\/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>, start by initializing the serial port at 115200 baud rate.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Set the PIR Motion sensor as an <span class=\"rnthl rntliteral\">INPUT_PULLUP<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(motionSensor, INPUT_PULLUP);<\/code><\/pre>\n\n\n\n<p>To set the PIR sensor pin as an interrupt, use the <span class=\"rnthl rntliteral\">attachInterrupt()<\/span> function as described earlier.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);<\/code><\/pre>\n\n\n\n<p>The pin that will detect motion is <span class=\"rnthl rntcyellow\">GPIO 14<\/span> and it will call the function <span class=\"rnthl rntliteral\">detectsMovement()<\/span> on <span class=\"rnthl rntliteral\">RISING<\/span> mode.<\/p>\n\n\n\n<p>The LED is an <span class=\"rnthl rntliteral\">OUTPUT<\/span> whose state starts at <span class=\"rnthl rntliteral\">LOW<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(led, OUTPUT);\ndigitalWrite(led, LOW);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">loop()<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">loop()<\/span> function is constantly running over and over again. In every loop, the <span class=\"rnthl rntliteral\">now<\/span> variable is updated with the current time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>now = millis();<\/code><\/pre>\n\n\n\n<p>Nothing else is done in the <span class=\"rnthl rntliteral\">loop()<\/span>. But, when motion is detected, the <span class=\"rnthl rntliteral\">detectsMovement()<\/span> function is called because we\u2019ve set an interrupt previously in the <span class=\"rnthl rntliteral\">setup()<\/span>. <\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">detectsMovement()<\/span> function prints a message in the Serial Monitor, turns the LED on, sets the <span class=\"rnthl rntliteral\">startTimer<\/span> boolean variable to true and updates the <span class=\"rnthl rntliteral\">lastTrigger<\/span> variable with the current time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ICACHE_RAM_ATTR void detectsMovement() {\n  Serial.println(\"MOTION DETECTED!!!\");\n  digitalWrite(led, HIGH);\n  startTimer = true;\n  lastTrigger = millis();\n}<\/code><\/pre>\n\n\n\n<p>After this step, the code goes back to the <span class=\"rnthl rntliteral\">loop()<\/span>. This time, the <span class=\"rnthl rntliteral\">startTimer<\/span> variable is true. So, when the time defined in seconds has passed (since motion was detected), the following if statement will be true.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(startTimer &amp;&amp; (now - lastTrigger > (timeSeconds*1000))) {\n  Serial.println(\"Motion stopped\u2026\");\n  digitalWrite(led, LOW);\n  startTimer = false;\n}<\/code><\/pre>\n\n\n\n<p>The \u201cMotion stopped\u2026\u201d message will be printed in the Serial Monitor, the LED is turned off, and the <span class=\"rnthl rntliteral\">startTimer<\/span> variable is set to false.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>Upload the code to your ESP8266. Make sure you have the\nright board and COM port selected.<\/p>\n\n\n\n<p>Open the Serial Monitor at a baud rate of 115200.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"745\" height=\"109\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/02\/serial-monitor.png?resize=745%2C109&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE Open Serial Monitor at baud rate 115200\" class=\"wp-image-81671\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/02\/serial-monitor.png?w=745&amp;quality=100&amp;strip=all&amp;ssl=1 745w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/02\/serial-monitor.png?resize=300%2C44&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 745px) 100vw, 745px\" \/><\/figure><\/div>\n\n\n\n<p>Move your hand in front of the PIR sensor. The LED should turn on, and a message is printed in the Serial Monitor saying \u201c<strong>MOTION DETECTED!!!<\/strong>\u201d. After 10 seconds the LED should turn off.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/esp8266-pir-motion-sensor.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Interrupts and Timers with ESP8266 NodeMCU using Arduino IDE Demonstration\" class=\"wp-image-88049\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/esp8266-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\/2019\/08\/esp8266-pir-motion-sensor.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>To sum up, interrupts are useful to detect a change in a GPIO state and instantly trigger a function. You&#8217;ve also learned that you should use timers to write non-blocking code.<\/p>\n\n\n\n<p>We hope you&#8217;ve found this tutorial useful. We have other tutorials on how to handle interrupts using MicroPython and using ESP32:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-interrupts-esp32-esp8266\/\">MicroPython: Interrupts with ESP32 and ESP8266<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-pir-motion-sensor-interrupts-timers\/\">ESP32 with PIR Motion Sensor using Interrupts and Timers<\/a><\/li><\/ul>\n\n\n\n<p>Learn more about the ESP8266 board with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\">Home Automation using EPS8266<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\">Free ESP8266 Projects and Tutorials<\/a><\/li><\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to use interrupts and timers with the ESP8266 NodeMCU using Arduino IDE. Interrupts allow you to detect changes in the GPIO state without the &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP8266 Interrupts and Timers using Arduino IDE (NodeMCU)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/interrupts-timers-esp8266-arduino-ide-nodemcu\/#more-88005\" aria-label=\"Read more about ESP8266 Interrupts and Timers using Arduino IDE (NodeMCU)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":88048,"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":[265,214,246,300,240,264],"tags":[],"class_list":["post-88005","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp8266-project","category-esp8266","category-esp8266-arduino-ide","category-0-esp8266","category-esp8266-projects","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/08\/ESP8266-Interrupts.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/88005","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=88005"}],"version-history":[{"count":0,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/88005\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/88048"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=88005"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=88005"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=88005"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}