{"id":175393,"date":"2025-11-20T14:12:47","date_gmt":"2025-11-20T14:12:47","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=175393"},"modified":"2025-11-20T14:27:55","modified_gmt":"2025-11-20T14:27:55","slug":"esp32-freertos-software-timers-interrupts","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-freertos-software-timers-interrupts\/","title":{"rendered":"ESP32 with FreeRTOS: Software Timers\/Timer Interrupts (Arduino IDE)"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to use software timers (timer interrupts) with the ESP32 using FreeRTOS programming on Arduino IDE. We&#8217;ll take a look at auto-reload (periodic) timers and one-shot timers, and provide simple examples so that you can apply software timers easily to your own projects. You&#8217;ll see that using FreeRTOS software timers will make things much easier in your projects to schedule different tasks.<\/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\/2025\/10\/ESP32-FreeRTOS-Software-Timers.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 FreeRTOS Software Timers, Timer Interrupts\" class=\"wp-image-180756\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers.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><strong>New to FreeRTOS?<\/strong> Here are other FreeRTOS tutorials with the ESP32 that we recommend following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-arduino-tasks\/\" title=\"\">ESP32 with FreeRTOS (Arduino IDE) \u2013 <strong>Getting Started<\/strong>: Create Tasks<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-queues-inter-task-arduino\/\" title=\"\">ESP32 with FreeRTOS<strong> Queues<\/strong>: Inter-Task Communication (Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-semaphores-arduino\/\">ESP32 with FreeRTOS: Getting Started with <strong>Semaphores<\/strong> (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Table of Contents<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#timer-interrupts\" title=\"\">Timer Interrupts \/ Software Timers<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#timers-basics\" target=\"_blank\" rel=\"noopener\" title=\"\">FreeRTOS Timers Basics<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#periodic-timer\" title=\"\">FreeRTOS Periodic Timer with the ESP32 (Auto-Reload)<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#led-blink-periodic-timer\" title=\"\">1) Blinking an LED with a Periodic Timer<\/a><\/li>\n\n\n\n<li><a href=\"#blinking-led-multiple-timers\" title=\"\">2) Blinking Multiple LEDs at Different Frequencies<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#one-shot-timers\" title=\"\">FreeRTOS One-Shot Timers with the ESP32<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#toggle-led-with-pushbutton\" title=\"\">1) Toggle an LED with a Pushbutton (with a delay)<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"timer-interrupts\">Timer Interrupts\/Software Timers<\/h2>\n\n\n\n<p>Using timer interrupts is especially useful to make something happen periodically or after a predefined period without constantly checking the elapsed time.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><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=\"Timer Interrupts and Software Timers\" 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<p>A software timer lets you schedule a function to run at a specific time later on. The function that the timer calls is known as its <em>callback function<\/em>, and the interval from when the timer starts until the callback executes is the<em> timer&#8217;s period<\/em>.<\/p>\n\n\n\n<p>In FreeRTOS with the ESP32, we have two types of timers available:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Periodic Timer<\/strong> (auto-reload timer): a timer that will trigger indefinitely every x number of seconds you define. This allows you to run a task periodically. For example, blinking an LED every second.<\/li>\n\n\n\n<li><strong>One-shot Timer<\/strong>: a timer that will trigger once after a predefined period. This allows you to run a specific task after a predefined time. For example, turn on an LED five seconds after pressing a pushbutton.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"timers-basics\">FreeRTOS Timers Basics<\/h3>\n\n\n\n<p>Here are some basic concepts about creating and handling FreeRTOS timers with the ESP32 on Arduino IDE:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Creating a Timer<\/h4>\n\n\n\n<p>To create a timer, you use the <span class=\"rnthl rntliteral\"><strong>xTimerCreate<\/strong>()<\/span> function and pass the following parameters as arguments in this order:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>timer name<\/li>\n\n\n\n<li>period<\/li>\n\n\n\n<li>autoReload (<span class=\"rnthl rntliteral\">pdTRUE<\/span> for periodic timer, or <span class=\"rnthl rntliteral\">pdFALSE<\/span> for one-shot timer)<\/li>\n\n\n\n<li>timerID (a user-defined value passed to the callback)<\/li>\n\n\n\n<li>callback function<\/li>\n<\/ul>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>xTimerCreate(\n    \"BlinkTimer\",                   \/\/ Timer name\n    1000 \/ portTICK_PERIOD_MS,      \/\/ 1s period\n    pdTRUE,                         \/\/ Auto-reload (periodic timer)\n    NULL,                           \/\/ Timer ID\n    BlinkCallback                   \/\/ Callback function\n);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Starting a Timer<\/h4>\n\n\n\n<p>To start a timer use <span class=\"rnthl rntliteral\"><strong>xTimerStart<\/strong>(timer, blockTime)<\/span>. The first argument is the timer handler, and the second argument is the number of seconds to wait before starting the timer.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Stopping a Timer<\/h4>\n\n\n\n<p>To stop a running timer, you just need to call <span class=\"rnthl rntliteral\"><strong>xTimerStop<\/strong>(timer, blockTime)<\/span>. The arguments are the same as the previous function.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Resetting a Timer<\/h4>\n\n\n\n<p>To reset a timer, which means restarting a timer&#8217;s countdown, even if it is already running, call <span class=\"rnthl rntliteral\"><strong>xTimerReset<\/strong>(timer, blockTime)<\/span>. The arguments are the same as the previous functions.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Starting a Timer in ISRs (interrupt service routines)<\/h4>\n\n\n\n<p>If you want to start a timer from an ISR (interrupt service routine function), you should call <span class=\"rnthl rntliteral\"><strong>xTimerStartFromISR<\/strong>(timer, &amp;higherPriorityTaskWoken)<\/span>.<\/p>\n\n\n\n<p><span class=\"rnthl rntliteral\">higherPriorityTaskWoken<\/span> can be <span class=\"rnthl rntliteral\">pdTRUE<\/span> or <span class=\"rnthl rntliteral\">pdFALSE<\/span>. Set to <span class=\"rnthl rntliteral\">pdTRUE<\/span> if the task is of higher priority and we should switch to it immediately. In this case, we should call <span class=\"rnthl rntliteral\">portYIELD_FROM_ISR()<\/span> from the ISR to switch to that task immediately for real-time responsiveness.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"periodic-timer\">FreeRTOS Periodic Timer with the ESP32<\/h2>\n\n\n\n<p>Now that we&#8217;ve learned the basics of software timers, we&#8217;ll start by testing some simple examples to show you how to create and handle periodic timers (auto-reload) with the ESP32 using FreeRTOS in Arduino IDE.<\/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=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers-Examples.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Two LEDs connected to the ESP32 to test FreeRTOS software timers\" class=\"wp-image-180757\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers-Examples.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers-Examples.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<h3 class=\"wp-block-heading\" id=\"led-blink-periodic-timer\">1) Blinking an LED with a Periodic Timer<\/h3>\n\n\n\n<p>The first example we&#8217;ll take a look at is a simple Blink LED sketch. This sketch creates a FreeRTOS periodic timer to toggle the state of an LED every second.<\/p>\n\n\n\n<p>This is a simple and easy example to show you how to actually use the timers. Here&#8217;s how it works:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Starting a timer with a one-second period.<\/li>\n\n\n\n<li>After the timer period, its callback function runs.<\/li>\n\n\n\n<li>The callback function toggles the state of an LED (first, it turns it on).<\/li>\n\n\n\n<li>After the timer period (one second), the callback function will run again, toggling the state of the LED (this time, it turns it off).<\/li>\n\n\n\n<li>This will be repeated forever, until the program is stopped or until you stop timer. This will create a blinking effect.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Circuit Diagram<\/h4>\n\n\n\n<p>For this example, we&#8217;ll be blinking the ESP32 onboard LED. In our case, it&#8217;s connected to GPIO 2. Other ESP32 boards might have the built-in LED connected to a different GPIO.<\/p>\n\n\n\n<p>Alternatively, you can actually wire a physical LED via a 220 Ohm resistor to your board.<\/p>\n\n\n\n<p><strong>Parts Required:<\/strong><\/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\" title=\"\">ESP32 board<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener\" title=\"\">1x LED<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noopener\" title=\"\">1x 220 Ohm resistor<\/a> (or similar values)<\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Jumper wires<\/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<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"751\" height=\"825\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-LED_circuit-diagram.png?resize=751%2C825&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Circuit Diagram of an ESP32 connected to GPIO 2\" class=\"wp-image-180761\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-LED_circuit-diagram.png?w=751&amp;quality=100&amp;strip=all&amp;ssl=1 751w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-LED_circuit-diagram.png?resize=273%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 273w\" sizes=\"(max-width: 751px) 100vw, 751px\" \/><\/figure><\/div>\n\n\n<h4 class=\"wp-block-heading\">Code<\/h4>\n\n\n\n<p>The following code uses periodic FreeRTOS timers to blink the ESP32 onboard LED. You can upload it to your ESP32 board.<\/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-freertos-software-timers-interrupts\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*\/\n#include &lt;Arduino.h&gt;\n\n#define LED_PIN 2\n\nTimerHandle_t blinkTimer = NULL;\n\nbool ledState = false;\n\nvoid BlinkCallback(TimerHandle_t xTimer) {\n  ledState = !ledState;\n  \n  if (ledState) {\n    digitalWrite(LED_PIN, HIGH);\n    Serial.print(&quot;LED is &quot;);\n    Serial.println(&quot;ON&quot;);\n  } else {\n    digitalWrite(LED_PIN, LOW);\n    Serial.print(&quot;LED is &quot;);\n    Serial.println(&quot;OFF&quot;);\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  delay(1000);\n  Serial.println(&quot;Starting FreeRTOS&quot;);\n  Serial.println(&quot;Periodic Timer for LED Blink&quot;);\n\n  pinMode(LED_PIN, OUTPUT);\n\n  blinkTimer = xTimerCreate(\n    &quot;BlinkTimer&quot;,                   \/\/ Timer name\n    1000 \/ portTICK_PERIOD_MS,      \/\/ 1s period\n    pdTRUE,                         \/\/ Auto-reload (periodic timer)\n    NULL,                           \/\/ Timer ID\n    BlinkCallback                   \/\/ Callback function\n  );\n  if (blinkTimer == NULL) {\n    Serial.println(&quot;Failed to create timer!&quot;);\n    while (1);\n  }\n\n  xTimerStart(blinkTimer, 0); \/\/ Start timer immediately\n}\n\nvoid loop() {\n  \/\/ Empty\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\/FreeRTOS\/Periodic_Timer_Blink_LED.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">How Does the Code Work?<\/h4>\n\n\n\n<p>Start by defining the GPIO connected to the LED. Change if you&#8217;re using a different GPIO pin.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED_PIN 2<\/code><\/pre>\n\n\n\n<p>Create a handler for the timer. A handler is like a name that we use to refer to the timer. At first, we set it to <span class=\"rnthl rntliteral\">NULL<\/span> because we haven&#8217;t created the actual timer yet. We&#8217;ll call the timer handler <span class=\"rnthl rntliteral\">blinkTimer<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>TimerHandle_t blinkTimer = NULL;<\/code><\/pre>\n\n\n\n<p>Create a variable called <span class=\"rnthl rntliteral\">ledState<\/span> to hold the current state of the LED. When the program first runs, the LED is turned off (<span class=\"rnthl rntliteral\">false<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>bool ledState = false;<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Timer Callback Function<\/strong><\/h5>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">BlinkCallback<\/span> is the function we&#8217;ll want to run periodically. It should accept a parameter of type <span class=\"rnthl rntliteral\">TimerHandle_t<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void BlinkCallback(TimerHandle_t xTimer) {\n  ledState = !ledState;\n  \n  if (ledState) {\n    digitalWrite(LED_PIN, HIGH);\n    Serial.print(\"LED is \");\n    Serial.println(\"ON\");\n  } else {\n    digitalWrite(LED_PIN, LOW);\n    Serial.print(\"LED is \");\n    Serial.println(\"OFF\");\n  }\n}<\/code><\/pre>\n\n\n\n<p>We first invert the current LED state:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ledState = !ledState;<\/code><\/pre>\n\n\n\n<p>Then, we turn the LED on or off accordingly using the <span class=\"rnthl rntliteral\">digitalWrite()<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (ledState) {\n  digitalWrite(LED_PIN, HIGH);\n  Serial.print(\"LED is \");\n  Serial.println(\"ON\");\n} else {\n  digitalWrite(LED_PIN, LOW);\n  Serial.print(\"LED is \");\n  Serial.println(\"OFF\");\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>setup()<\/strong><\/h5>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the Serial Monitor and set up the LED as an <span class=\"rnthl rntliteral\">OUTPUT<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void setup() {\n  Serial.begin(115200);\n  delay(1000);\n  Serial.println(\"Starting FreeRTOS\");\n  Serial.println(\"Periodic Timer for LED Blink\");\n\n  pinMode(LED_PIN, OUTPUT);<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Creating the Timer<\/strong><\/h5>\n\n\n\n<p>Then, create the timer, <span class=\"rnthl rntliteral\">blinkTimer<\/span>, using the <span class=\"rnthl rntliteral\">xTimeCreate()<\/span> function we&#8217;ve seen in the introduction section. This timer, once started, will call the <span class=\"rnthl rntliteral\">BlinkCallback<\/span> function every 1000 milliseconds (1 second).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>blinkTimer = xTimerCreate(\n  \"BlinkTimer\",                   \/\/ Timer name\n  1000 \/ portTICK_PERIOD_MS,      \/\/ 1s period\n  pdTRUE,                         \/\/ Auto-reload (periodic timer)\n  NULL,                           \/\/ Timer ID\n  BlinkCallback                   \/\/ Callback function\n);<\/code><\/pre>\n\n\n\n<p>We also check if the timer was successfully created. If it fails to be created, it will return <span class=\"rnthl rntliteral\">NULL<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (blinkTimer == NULL) {\n    Serial.println(\"Failed to create timer!\");\n    while (1);\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Starting the Timer<\/strong><\/h5>\n\n\n\n<p>Finally, we can start our <span class=\"rnthl rntliteral\">blinkTimer<\/span> by calling the <span class=\"rnthl rntliteral\">xTimerStart()<\/span> function. The timer will start immediately (the second argument of the function is <span class=\"rnthl rntliteral\">0<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>xTimerStart(blinkTimer, 0); \/\/ Start timer immediately<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>loop()<\/strong><\/h5>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">loop()<\/span> is empty because the FreeRTOS scheduler takes care of keeping the program running, waiting for the timer interrupts and tasks. However, if it is required for your project, you can add any code you need to the <span class=\"rnthl rntliteral\">loop()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\n  \/\/ Empty\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Demonstration<\/h4>\n\n\n\n<p>Upload the code to your ESP32 board.<\/p>\n\n\n\n<p>Then, open the Serial Monitor at a baud rate of 115200.<\/p>\n\n\n\n<p>The ESP32 on-board LED will start blinking every second (or the LED connected to GPIO 2).<\/p>\n\n\n\n<div class=\"wp-block-jetpack-tiled-gallery aligncenter is-style-rectangular\"><div class=\"\"><div class=\"tiled-gallery__gallery\"><div class=\"tiled-gallery__row\"><div class=\"tiled-gallery__col\" style=\"flex-basis:50.00000%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"ESP32 board Built in LED turned on HIGH\" data-height=\"422\" data-id=\"96167\" data-link=\"https:\/\/randomnerdtutorials.com\/esp32-board-built_in-led-turned-on-high\/\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><div class=\"tiled-gallery__col\" style=\"flex-basis:50.00000%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"ESP32 board Built in LED turned off LOW\" data-height=\"422\" data-id=\"96166\" data-link=\"https:\/\/randomnerdtutorials.com\/esp32-board-built_in-led-turned-off-low\/\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<p>The Serial Monitor will show the current state of the LED (note that the built-in LED of the ESP32 works with inverted logic).<\/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=\"749\" height=\"318\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/Blink-LED-freertos-periodic-timer-demonstration-serial-monitor.png?resize=749%2C318&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Serial Monitor showing the current state of an LED - testing FreeRTOS periodic timers\" class=\"wp-image-179922\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/Blink-LED-freertos-periodic-timer-demonstration-serial-monitor.png?w=749&amp;quality=100&amp;strip=all&amp;ssl=1 749w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/Blink-LED-freertos-periodic-timer-demonstration-serial-monitor.png?resize=300%2C127&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 749px) 100vw, 749px\" \/><\/figure><\/div>\n\n\n<p>As you can see, using FreeRTOS periodic timers is quite simple, useful, and practical to use in your projects. For example, besides blinking an LED, you can use it for periodic tasks like getting data from a sensor, sending data to a server, logging data to a microSD card, checking the state of an input, and much more.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"blinking-led-multiple-timers\">2) Blinking Multiple LEDs at Different Frequencies<\/h3>\n\n\n\n<p>After understanding how to create a periodic timer, it is quite simple to create multiple timers if you need to run multiple tasks periodically with the same or different intervals.<\/p>\n\n\n\n<p>To show you how to do that, we&#8217;ll create a new example that blinks two LEDs at different frequencies. We&#8217;ll create two periodic timers, one to control each LED.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Circuit Diagram<\/h4>\n\n\n\n<p>For this example, connect two LEDs to your ESP32 board via a 220 Ohm resistor. We&#8217;re connecting the LEDs to GPIOs 2 and 4, but you can use any other suitable pins. Just make sure to modify the code accordingly.<\/p>\n\n\n\n<p><strong>Parts Required:<\/strong><\/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\" title=\"\">ESP32 board<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener\" title=\"\">2x LED<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noopener\" title=\"\">2x 220 Ohm resistor<\/a> (or similar values)<\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"709\" height=\"826\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-two-LEDs_bb.png?resize=709%2C826&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Circuit Diagram of an ESP32 connected to GPIO 2 and GPIO 4\" class=\"wp-image-180765\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-two-LEDs_bb.png?w=709&amp;quality=100&amp;strip=all&amp;ssl=1 709w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-two-LEDs_bb.png?resize=258%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 258w\" sizes=\"(max-width: 709px) 100vw, 709px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgreen\">Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pinout-reference-gpios\/\">ESP32 Pinout Reference: Which GPIO pins should you use?<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Code<\/h4>\n\n\n\n<p>Upload the following code to your ESP32 board.<\/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-freertos-software-timers-interrupts\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*\/\n#define LED_PIN_RED 2\n#define LED_PIN_BLUE 4\n\nTimerHandle_t blinkTimerRed = NULL;\nTimerHandle_t blinkTimerBlue = NULL;\n\nbool ledStateRed = false;\nbool ledStateBlue = false;\n\nvoid BlinkRedCallback(TimerHandle_t xTimer) {\n  ledStateRed = !ledStateRed;\n  \n  if (ledStateRed) {\n    digitalWrite(LED_PIN_RED, HIGH);\n    Serial.print(&quot;Red LED is &quot;);\n    Serial.println(&quot;ON&quot;);\n  } else {\n    digitalWrite(LED_PIN_RED, LOW);\n    Serial.print(&quot;Red LED is &quot;);\n    Serial.println(&quot;OFF&quot;);\n  }\n}\n\nvoid BlinkBlueCallback(TimerHandle_t xTimer) {\n  ledStateBlue = !ledStateBlue;\n  \n  if (ledStateBlue) {\n    digitalWrite(LED_PIN_BLUE, HIGH);\n    Serial.print(&quot;Blue LED is &quot;);\n    Serial.println(&quot;ON&quot;);\n  } else {\n    digitalWrite(LED_PIN_BLUE, LOW);\n    Serial.print(&quot;Blue LED is &quot;);\n    Serial.println(&quot;OFF&quot;);\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  delay(1000);\n  Serial.println(&quot;Starting FreeRTOS&quot;);\n  Serial.println(&quot;Periodic Timers for Two LEDs&quot;);\n\n  pinMode(LED_PIN_RED, OUTPUT);\n  pinMode(LED_PIN_BLUE, OUTPUT);\n\n  blinkTimerRed = xTimerCreate(\n    &quot;BlinkTimerRed&quot;,               \/\/ Timer name\n    700 \/ portTICK_PERIOD_MS,      \/\/ 1s period\n    pdTRUE,                        \/\/ Auto-reload (periodic timer)\n    NULL,                          \/\/ Timer ID\n    BlinkRedCallback               \/\/ Callback function\n  );\n  if (blinkTimerRed == NULL) {\n    Serial.println(&quot;Failed to create blinkTimerRed timer!&quot;);\n    while (1);\n  }\n\n  blinkTimerBlue = xTimerCreate(\n    &quot;BlinkTimerBlue&quot;,               \/\/ Timer name\n    1100 \/ portTICK_PERIOD_MS,      \/\/ 1s period\n    pdTRUE,                         \/\/ Auto-reload (periodic timer)\n    NULL,                           \/\/ Timer ID\n    BlinkBlueCallback               \/\/ Callback function\n  );\n  if (blinkTimerBlue == NULL) {\n    Serial.println(&quot;Failed to create blinkTimerBlue timer!&quot;);\n    while (1);\n  }\n\n  xTimerStart(blinkTimerRed, 0); \/\/ Start timer immediately\n  xTimerStart(blinkTimerBlue, 0); \/\/ Start timer immediately\n}\n\nvoid loop() {\n  \/\/ Empty\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\/FreeRTOS\/Periodic_Timer_Blink_Two_LEDs.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">How Does the Code Work?<\/h4>\n\n\n\n<p>If you&#8217;ve understood how to create a timer in the previous example, you&#8217;ll see that it is quite simple to create multiple timers.<\/p>\n\n\n\n<p>We define the GPIOs to control each of the LEDs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED_PIN_RED 2\n#define LED_PIN_BLUE 4<\/code><\/pre>\n\n\n\n<p>Then, we create a time handler for each timer. Each timer will control a different LED.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>TimerHandle_t blinkTimerRed = NULL;\nTimerHandle_t blinkTimerBlue = NULL;<\/code><\/pre>\n\n\n\n<p>We create a callback function that will be called after each timer to control each of the LEDs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void BlinkRedCallback(TimerHandle_t xTimer) {\n  ledStateRed = !ledStateRed;\n  \n  if (ledStateRed) {\n    digitalWrite(LED_PIN_RED, HIGH);\n    Serial.print(\"Red LED is \");\n    Serial.println(\"ON\");\n  } else {\n    digitalWrite(LED_PIN_RED, LOW);\n    Serial.print(\"Red LED is \");\n    Serial.println(\"OFF\");\n  }\n}\n\nvoid BlinkBlueCallback(TimerHandle_t xTimer) {\n  ledStateBlue = !ledStateBlue;\n  \n  if (ledStateBlue) {\n    digitalWrite(LED_PIN_BLUE, HIGH);\n    Serial.print(\"Blue LED is \");\n    Serial.println(\"ON\");\n  } else {\n    digitalWrite(LED_PIN_BLUE, LOW);\n    Serial.print(\"Blue LED is \");\n    Serial.println(\"OFF\");\n  }\n}<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, we can actually create the timers to blink each of the LEDs. The following timer will call the <span class=\"rnthl rntliteral\">BlinkRedCallback<\/span> function every 700 milliseconds, which will result in the Red LED toggling its state every 700 milliseconds.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>blinkTimerRed = xTimerCreate(\n  \"BlinkTimerRed\",                   \/\/ Timer name\n  700 \/ portTICK_PERIOD_MS,      \/\/ 1s period\n  pdTRUE,                         \/\/ Auto-reload (periodic timer)\n  NULL,                           \/\/ Timer ID\n  BlinkRedCallback                   \/\/ Callback function\n);\nif (blinkTimerRed == NULL) {\n  Serial.println(\"Failed to create blinkTimerRed timer!\");\n  while (1);\n}<\/code><\/pre>\n\n\n\n<p>We also create a timer to control the other LED. This timer will call the <span class=\"rnthl rntliteral\">BlinkBlueCallback<\/span> function every 1100 milliseconds.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>blinkTimerBlue = xTimerCreate(\n  \"BlinkTimerBlue\",                   \/\/ Timer name\n  1100 \/ portTICK_PERIOD_MS,      \/\/ 1s period\n  pdTRUE,                         \/\/ Auto-reload (periodic timer)\n  NULL,                           \/\/ Timer ID\n  BlinkBlueCallback                   \/\/ Callback function\n);\nif (blinkTimerBlue == NULL) {\n  Serial.println(\"Failed to create blinkTimerBlue timer!\");\n  while (1);\n}<\/code><\/pre>\n\n\n\n<p>Finally, we can start the timers by calling the <span class=\"rnthl rntliteral\">xTimerStart()<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>xTimerStart(blinkTimerRed, 0); \/\/ Start timer immediately\nxTimerStart(blinkTimerBlue, 0); \/\/ Start timer immediately<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">loop()<\/span> is empty because the FreeRTOS scheduler will take care of running the timers at the appropriate time. If you need, you can add code to the <span class=\"rnthl rntliteral\">loop()<\/span> for any other tasks you need for your project.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\n  \/\/ Empty\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Demonstration<\/h4>\n\n\n\n<p>Upload the previous code to your ESP32 board.<\/p>\n\n\n\n<p>This will result in two LEDs blinking at different frequencies.<\/p>\n\n\n\n<div class=\"wp-block-jetpack-tiled-gallery aligncenter is-style-rectangular\"><div class=\"\"><div class=\"tiled-gallery__gallery\"><div class=\"tiled-gallery__row\"><div class=\"tiled-gallery__col\" style=\"flex-basis:50.00000%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Timers-Blink-LEDs-at-different-frequencies.jpg?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Timers-Blink-LEDs-at-different-frequencies.jpg?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"ESP32 connected to two LEDs blinking at different frequencies using software timers\" data-height=\"421\" data-id=\"180767\" data-link=\"https:\/\/randomnerdtutorials.com\/?attachment_id=180767#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Timers-Blink-LEDs-at-different-frequencies.jpg\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Timers-Blink-LEDs-at-different-frequencies.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><div class=\"tiled-gallery__col\" style=\"flex-basis:50.00000%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers-Examples.jpg?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers-Examples.jpg?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"\" data-height=\"421\" data-id=\"180757\" data-link=\"https:\/\/randomnerdtutorials.com\/?attachment_id=180757#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers-Examples.jpg\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-FreeRTOS-Software-Timers-Examples.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<p>You can also open the Serial Monitor to check the results.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/Blink-Two-LEDs-different-frequencies-freertos-timers-serial-monitor-demonstration.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"666\" height=\"315\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/Blink-Two-LEDs-different-frequencies-freertos-timers-serial-monitor-demonstration.png?resize=666%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Serial Monitor showing the state of two different LEDs - testing multiple FreeRTOS timers with the ESP32\" class=\"wp-image-179933\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/Blink-Two-LEDs-different-frequencies-freertos-timers-serial-monitor-demonstration.png?w=666&amp;quality=100&amp;strip=all&amp;ssl=1 666w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/Blink-Two-LEDs-different-frequencies-freertos-timers-serial-monitor-demonstration.png?resize=300%2C142&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 666px) 100vw, 666px\" \/><\/a><\/figure><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"one-shot-timers\">FreeRTOS One-Shot Timers with the ESP32<\/h2>\n\n\n\n<p>One-shot timers will trigger a callback function once after a predefined period. This allows you to run a specific task after a predefined time.<\/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\/2025\/10\/ESP32-connected-to-led-and-pushbutton.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 connected to a pushbutton and an LED to test an example of FreeRTOS one-shot timer\" class=\"wp-image-180768\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-connected-to-led-and-pushbutton.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-connected-to-led-and-pushbutton.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"toggle-led-with-pushbutton\">1) Toggle an LED with a Pushbutton (with a delay)<\/h3>\n\n\n\n<p>To show you how one-shot timers work, we&#8217;ll create a simple example in which we&#8217;ll toggle the state of an LED five seconds after pressing a pushbutton.<\/p>\n\n\n\n<p>Here&#8217;s how it works:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>LED is off.<\/li>\n\n\n\n<li>Press the pushbutton.<\/li>\n\n\n\n<li>After 5 seconds, the LED turns on.<\/li>\n\n\n\n<li>LED stays on.<\/li>\n\n\n\n<li>Press the pushbutton.<\/li>\n\n\n\n<li>After 5 seconds, the LED turns off.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Circuit Diagram<\/h4>\n\n\n\n<p>For this example, connect an LED and a pushbutton to the ESP32 GPIOs. We&#8217;re connecting the LED to GPIO 2 and the pushbutton to GPIO 4. We&#8217;re not using any resistor with the pushbutton because we&#8217;ll use the ESP32&#8217;s internal pull-up resistor.<\/p>\n\n\n\n<p><strong>Parts Required:<\/strong><\/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\" title=\"\">ESP32 board<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener\" title=\"\">1x LED<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noopener\" title=\"\">1x 220 Ohm resistor<\/a> (or similar values)<\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/pushbuttons-kit\/\" target=\"_blank\" rel=\"noopener\" title=\"\">1x Pushbutton<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"729\" height=\"847\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-LED-and-pushbutton_bb.png?resize=729%2C847&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 connected to a pushbutton and an LED - circuit diagram\" class=\"wp-image-180779\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-LED-and-pushbutton_bb.png?w=729&amp;quality=100&amp;strip=all&amp;ssl=1 729w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-with-LED-and-pushbutton_bb.png?resize=258%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 258w\" sizes=\"(max-width: 729px) 100vw, 729px\" \/><\/figure><\/div>\n\n\n<h4 class=\"wp-block-heading\">Code<\/h4>\n\n\n\n<p>Upload the following code to your ESP32 board.<\/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-freertos-software-timers-interrupts\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*\/\n#define BUTTON_PIN 4\n#define LED_PIN 2\n#define DEBOUNCE_DELAY 200\n#define TIMER_DELAY 5000\n\nTimerHandle_t toggleTimer = NULL;\nvolatile uint32_t lastInterruptTime = 0;\nvolatile bool ledState = false;\n\nvoid IRAM_ATTR buttonISR() {\n  uint32_t currentTime = millis();\n  if (currentTime - lastInterruptTime &gt; DEBOUNCE_DELAY) {\n    BaseType_t higherPriorityTaskWoken = pdFALSE;\n    xTimerStartFromISR(toggleTimer, &amp;higherPriorityTaskWoken);\n    Serial.print(&quot;buttonISR: LED will &quot;);\n    if (ledState) {\n      Serial.print(&quot;turn OFF&quot;);\n    } else {\n      Serial.print(&quot;turn ON&quot;);\n    }\n    Serial.print(&quot; in 5 seconds&quot;);\n    Serial.println();\n    lastInterruptTime = currentTime;\n    if (higherPriorityTaskWoken) {\n      portYIELD_FROM_ISR();\n    }\n  }\n}\n\nvoid ToggleCallback(TimerHandle_t xTimer) {\n  ledState = !ledState;\n  if (ledState) {\n    digitalWrite(LED_PIN, HIGH);\n    Serial.println(&quot;LED is ON&quot;);\n  } else {\n    digitalWrite(LED_PIN, LOW);\n    Serial.println(&quot;LED is OFF&quot;);\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  delay(1000);\n  Serial.println(&quot;Starting FreeRTOS&quot;);\n\n  pinMode(BUTTON_PIN, INPUT_PULLUP);\n  pinMode(LED_PIN, OUTPUT);\n  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);\n\n  toggleTimer = xTimerCreate(\n    &quot;ToggleTimer&quot;,                    \/\/ Timer name\n    TIMER_DELAY \/ portTICK_PERIOD_MS, \/\/ 5s delay\n    pdFALSE,                          \/\/ One-shot\n    NULL,                             \/\/ Timer ID\n    ToggleCallback                   \/\/ Callback\n  );\n  if (toggleTimer == NULL) {\n    Serial.println(&quot;Failed to create timer!&quot;);\n    while (1);\n  }\n}\n\nvoid loop() {\n  \/\/ Empty\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\/FreeRTOS\/One_Shot_Timer.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">How Does the Code Work<\/h4>\n\n\n\n<p>Start by defining the GPIOs for the LED and for the pushbutton. We&#8217;re using GPIOs 2 and 4, respectively. You can use any other suitable GPIOs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define BUTTON_PIN 4\n#define LED_PIN 2<\/code><\/pre>\n\n\n\n<p>Define the debounce delay for the pushbutton in milliseconds.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define DEBOUNCE_DELAY 200<\/code><\/pre>\n\n\n\n<p>Define the delay time for the one-shot timer (time between pressing the pushbutton and changing the state of the LED).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define TIMER_DELAY 5000<\/code><\/pre>\n\n\n\n<p>Create a handle for our one-shot timer. We&#8217;re calling it <span class=\"rnthl rntliteral\">toggleTimer<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>TimerHandle_t toggleTimer = NULL;<\/code><\/pre>\n\n\n\n<p>Create a variable to check how much time has passed since the last button press (to prevent false positives).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>volatile uint32_t lastInterruptTime = 0;<\/code><\/pre>\n\n\n\n<p>Create a variable called <span class=\"rnthl rntliteral\">ledState<\/span> to hold the current LED state.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>volatile bool ledState = false;  \/\/ Made volatile for ISR access<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, we initialize the serial monitor for debugging purposes.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void setup() {\n  Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>We set the pushbutton as an input with an internal pull-up resistor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(BUTTON_PIN, INPUT_PULLUP);<\/code><\/pre>\n\n\n\n<p>The LED is set as an <span class=\"rnthl rntliteral\">OUTPUT<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(LED_PIN, OUTPUT);<\/code><\/pre>\n\n\n\n<p>Then, we set the pushbutton as an interrupt on <span class=\"rnthl rntliteral\">FALLING<\/span> edge. When the pushbutton is pressed, it will call the <span class=\"rnthl rntliteral\">buttonISR<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Creating the One-shot Timer<\/strong><\/h5>\n\n\n\n<p>We create our one-shot timer, <span class=\"rnthl rntliteral\">toggleTimer<\/span>, using the <span class=\"rnthl rntliteral\">xTimerCreate()<\/span> function. Notice that we have the 5-second delay time (second argument), and that the third argument is <span class=\"rnthl rntliteral\">pdFALSE<\/span>, indicating that we want to set a one-shot timer to trigger after 5 seconds of its initialization. As you can see, it&#8217;s quite simple to set up a one-shot timer.<\/p>\n\n\n\n<p>In this case, it will call the <span class=\"rnthl rntliteral\">ToggleCallback<\/span> function when triggered.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>toggleTimer = xTimerCreate(\n  \"ToggleTimer\",                  \/\/ Timer name\n  TIMER_DELAY \/ portTICK_PERIOD_MS,  \/\/ 5s delay\n  pdFALSE,                        \/\/ One-shot\n  NULL,                           \/\/ Timer ID\n  ToggleCallback                  \/\/ Callback\n);\nif (toggleTimer == NULL) {\n  Serial.println(\"Failed to create timer!\");\n  while (1);\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>buttonISR() Function<\/strong><\/h5>\n\n\n\n<p>The ISR (callback function) for the pushbutton is the <span class=\"rnthl rntliteral\">buttonISR()<\/span> function. We first check if we have a valid pushbutton press.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void IRAM_ATTR buttonISR() {\n  uint32_t currentTime = millis();\n  if (currentTime - lastInterruptTime &gt; DEBOUNCE_DELAY) {<\/code><\/pre>\n\n\n\n<p>Then, we create and set the <span class=\"rnthl rntliteral\">higherPriorityTaskWoken<\/span> variable to <span class=\"rnthl rntliteral\">pdFALSE<\/span>. This variable tells us whether the ISR operation (in this case, starting a timer) has unblocked a higher-priority task that need to run immediately. It starts as false.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>BaseType_t higherPriorityTaskWoken = pdFALSE;<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Starting the Timer<\/strong><\/h5>\n\n\n\n<p>Then, we start our timer by calling the <span class=\"rnthl rntliteral\">xTimerStartFromISR<\/span> function. We pass as arguments the timer handle, <span class=\"rnthl rntliteral\">toggleTimer<\/span>, and the address of higherPriorityTaskWoken (<span class=\"rnthl rntliteral\">&amp;higherPriorityTaskWoken<\/span>) so FreeRTOS can update the flag if the operation unblocks a higher-priority task (like the timer service task), allowing us to check it next (<span class=\"rnthl rntliteral\">if (higherPriorityTaskWoken)<\/span>) and switch to that task right away if needed for real-time responsiveness (<span class=\"rnthl rntliteral\">portYIELD_FROM_ISR()<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>xTimerStartFromISR(toggleTimer, &amp;higherPriorityTaskWoken);<\/code><\/pre>\n\n\n\n<p>By starting our timer, it will run the <span class=\"rnthl rntliteral\">ToggleCallback<\/span> function after five seconds (<span class=\"rnthl rntliteral\">TIMER_DELAY<\/span>). The <span class=\"rnthl rntliteral\">ToggleCallback<\/span> function simply toggles the current state of the LED.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void ToggleCallback(TimerHandle_t xTimer) {\n  ledState = !ledState;\n  if (ledState) {\n    digitalWrite(LED_PIN, HIGH);\n    Serial.println(\"LED is ON\");\n  } else {\n    digitalWrite(LED_PIN, LOW);\n    Serial.println(\"LED is OFF\");\n  }\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Demonstration<\/h4>\n\n\n\n<p>Upload the code to your ESP32 board.<\/p>\n\n\n\n<p>Open the Serial Monitor at a baud rate of 115200.<\/p>\n\n\n\n<p>Press the pushbutton. On the Serial Monitor, you&#8217;ll get the message: &#8220;<em>buttonISR: LED will turn ON in 5 seconds<\/em>&#8220;.<\/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=\"666\" height=\"278\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/one-shot-timer-turn-on-LED-serial-monitor.png?resize=666%2C278&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Turn on LED on button press with a one-shot timer - serial monitor demonstration\" class=\"wp-image-180695\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/one-shot-timer-turn-on-LED-serial-monitor.png?w=666&amp;quality=100&amp;strip=all&amp;ssl=1 666w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/one-shot-timer-turn-on-LED-serial-monitor.png?resize=300%2C125&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 666px) 100vw, 666px\" \/><\/figure><\/div>\n\n\n<p>And after five seconds, the LED will turn on.<\/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=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-connected-to-LED-an-pushbutton-freertos-timers.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 connected to an LED and a pushbutton to test FreeRTOS one-shot timers with the ESP32\" class=\"wp-image-180780\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-connected-to-LED-an-pushbutton-freertos-timers.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/ESP32-connected-to-LED-an-pushbutton-freertos-timers.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<p>Press the pushbutton again, and after 5 seconds, the LED will turn off.<\/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=\"666\" height=\"277\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/one-shot-timer-turn-off-LED-serial-monitor.png?resize=666%2C277&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Turn off LED on button press with a one-shot timer - serial monitor demonstration\" class=\"wp-image-180694\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/one-shot-timer-turn-off-LED-serial-monitor.png?w=666&amp;quality=100&amp;strip=all&amp;ssl=1 666w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/10\/one-shot-timer-turn-off-LED-serial-monitor.png?resize=300%2C125&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 666px) 100vw, 666px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, we&#8217;ve taken a look at how to set up and use FreeRTOS software timers with the ESP32 programmed with Arduino IDE. You learned about periodic and one-shot timers.<\/p>\n\n\n\n<p>For more detailed information about software timers, you can check the official <a href=\"https:\/\/www.freertos.org\/Documentation\/02-Kernel\/02-Kernel-features\/05-Software-timers\/01-Software-timers\" target=\"_blank\" rel=\"noopener\" title=\"\">documentation<\/a>.<\/p>\n\n\n\n<p>If you want to learn more about FreeRTOS programming with the ESP32, check-out our other tutorials:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-arduino-tasks\/\" title=\"\">ESP32 with FreeRTOS (Arduino IDE) \u2013 <strong>Getting Started<\/strong>: Create Tasks<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-queues-inter-task-arduino\/\" title=\"\">ESP32 with FreeRTOS<strong> Queues<\/strong>: Inter-Task Communication (Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-semaphores-arduino\/\">ESP32 with FreeRTOS: Getting Started with Semaphores (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<p><strong>Want to learn more about the ESP32?<\/strong> Check out our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-arduino-tasks\/\">ESP32 with FreeRTOS (Arduino IDE) \u2013 Getting Started: Create Tasks<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">All our ESP32 Projects and Guides<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to use software timers (timer interrupts) with the ESP32 using FreeRTOS programming on Arduino IDE. We&#8217;ll take a look at auto-reload (periodic) timers and &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 with FreeRTOS: Software Timers\/Timer Interrupts (Arduino IDE)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-software-timers-interrupts\/#more-175393\" aria-label=\"Read more about ESP32 with FreeRTOS: Software Timers\/Timer Interrupts (Arduino IDE)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":180756,"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-175393","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\/2025\/10\/ESP32-FreeRTOS-Software-Timers.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\/175393","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=175393"}],"version-history":[{"count":26,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/175393\/revisions"}],"predecessor-version":[{"id":183527,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/175393\/revisions\/183527"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/180756"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=175393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=175393"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=175393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}