{"id":173475,"date":"2025-08-15T13:46:02","date_gmt":"2025-08-15T13:46:02","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=173475"},"modified":"2025-11-20T14:29:26","modified_gmt":"2025-11-20T14:29:26","slug":"esp32-freertos-arduino-tasks","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-freertos-arduino-tasks\/","title":{"rendered":"ESP32 with FreeRTOS (Arduino IDE) &#8211; Getting Started: Create Tasks"},"content":{"rendered":"\n<p>In this tutorial, we\u2019ll introduce the basic concepts of FreeRTOS and show you how to use it with the ESP32 and the Arduino IDE. You\u2019ll learn how to create single and multiple tasks, suspend and resume tasks, run code on the ESP32&#8217;s two cores, and calculate the appropriate stack size needed (memory) for each task.<\/p>\n\n\n\n<p>FreeRTOS is a real-time operating system that allows the ESP32 to manage and run multiple tasks simultaneously in a smooth and efficient way. It&#8217;s built into the ESP32 and fully integrated with both the Arduino core and the Espressif IoT Development Framework (IDF).<\/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\/07\/ESP32-FreeRTOS-Getting-Started.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with FreeRTOS - Getting Started Guide Create Tasks\" class=\"wp-image-173607\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-FreeRTOS-Getting-Started.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-FreeRTOS-Getting-Started.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-FreeRTOS-Getting-Started.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-FreeRTOS-Getting-Started.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-FreeRTOS-Getting-Started.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>In this tutorial, we&#8217;ll cover the following topics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#what-is-freertos\" title=\"\">What is FreeRTOS<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#freertos-and-esp32\" title=\"\">Why is FreeRTOS useful with the ESP32?<\/a><\/li>\n\n\n\n<li><a href=\"#freertos-basic-concepts\" title=\"\">FreeRTOS Basic Concepts<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><a href=\"#create-freertos-tasks\" title=\"\">1) Creating Tasks<\/a><\/li>\n\n\n\n<li><a href=\"#suspend-resume-tasks\" title=\"\">2) Suspend and Resume Tasks<\/a><\/li>\n\n\n\n<li><a href=\"#creating-running-multiple-tasks\" title=\"\">3) Creating and Running Multiple Tasks<\/a><\/li>\n\n\n\n<li><a href=\"#two-cores\" title=\"\">4) Creating and Running Multiple Tasks (Dual Core)<\/a><\/li>\n\n\n\n<li><a href=\"#memory-usage\" title=\"\">5) Tasks Memory Usage<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>This tutorial focuses on programming the ESP32 using the Arduino core. Before proceeding, you should have the ESP32 Arduino core installed in your Arduino IDE. Follow the 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 the ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux instructions)<\/a><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-freertos\">What is FreeRTOS?<\/h2>\n\n\n\n<p>FreeRTOS is a lightweight, open-source real-time operating system (RTOS). It provides a framework for <strong>running multiple tasks concurrently<\/strong>, each with its own <strong>priority <\/strong>and <strong>execution schedule<\/strong>. Instead of running code line by line, FreeRTOS lets you create independent tasks that the ESP32 can switch between quickly based on the task priority.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"413\" height=\"157\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/Logo_freeRTOS.png?resize=413%2C157&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"FreeRTOS Logo\" class=\"wp-image-173608\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/Logo_freeRTOS.png?w=413&amp;quality=100&amp;strip=all&amp;ssl=1 413w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/Logo_freeRTOS.png?resize=300%2C114&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 413px) 100vw, 413px\" \/><\/figure><\/div>\n\n\n<p>It also provides tools like <strong>queues <\/strong>and <strong>semaphores <\/strong>so tasks can seamlessly communicate with each other.<\/p>\n\n\n\n<p>This makes your code more organized and responsive, especially when your ESP32 is handling several tasks at the same time, like reading sensors, handling HTTP requests, and displaying information on a screen, while listening to interrupts.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"freertos-and-esp32\">Why is FreeRTOS useful with the ESP32?<\/h3>\n\n\n\n<p>The FreeRTOS real-time operating system is built into the ESP32 and integrated into the Espressif IDF and the Arduino core. It supports:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Task Management<\/strong>: create, suspend, resume, or delete tasks (covered in this tutorial).<\/li>\n\n\n\n<li><strong>Scheduling<\/strong>: allows you to give priority to your tasks, so they run in a specific order (covered in this tutorial).<\/li>\n\n\n\n<li><strong>Inter-Task Communication<\/strong>: using things like queues, semaphores, and mutexes, we can ensure seamless communication between tasks without crashing the ESP32.<\/li>\n\n\n\n<li><strong>Dual-Core Support<\/strong>: it allows you to run your tasks on either core 0 or core 1 of the ESP32 (also covered in this tutorial, but for a more in-depth guide about using dual-core with the ESP32, check this guide: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-dual-core-arduino-ide\/\" title=\"\">How to use ESP32 Dual Core with Arduino IDE<\/a>).<\/li>\n<\/ul>\n\n\n\n<p>So, in summary&#8230;<\/p>\n\n\n\n<p>FreeRTOS is useful with the ESP32 because it enables multitasking, allowing multiple tasks like sensor reading, Wi-Fi, and display updates to run without blocking each other. <\/p>\n\n\n\n<p>It also allows you to take advantage of the ESP32 dual-core processor by letting you assign tasks to specific cores for better performance. <\/p>\n\n\n\n<p>Additionally, with priority-based scheduling, time-critical tasks can run immediately, making it ideal for real-time applications when you need to react quickly to external events detected by the ESP32 GPIOs. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"freertos-basic-concepts\">FreeRTOS Basic Concepts<\/h3>\n\n\n\n<p>Before diving into the practical examples, let&#8217;s cover some basic concepts related to FreeRTOS:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tasks<\/strong>: tasks are independent functions running concurrently, each with its own stack (memory usage allocated) and priority. Tasks can be in states like Running, Ready, Blocked, or Suspended.<\/li>\n\n\n\n<li><strong>Scheduler<\/strong>: the scheduler decides which tasks to run based on their priorities. This is a preemptive scheduler, which means it can interrupt a lower-priority task at any time to run a higher-priority one, ensuring that critical tasks are executed as soon as they&#8217;re ready.<\/li>\n\n\n\n<li><strong>Priorities<\/strong>: higher numbers indicate higher priority (for example: 1 = low, 5 = high).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"create-freertos-tasks\">1) Creating Tasks<\/h2>\n\n\n\n<p>This is the simplest example in which we&#8217;ll show you how to create a FreeRTOS task to blink an LED every second. We&#8217;ll connect the LED to GPIO 2. Instead, you can skip the LED and check the results on the ESP32 built-in LED.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parts Required<\/h3>\n\n\n\n<p>For this example, 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=\"noreferrer noopener\">ESP32 Board<\/a>&nbsp;\u2013 read&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP32 Development Boards<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener\" title=\"\">LED<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noreferrer noopener\">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=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">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\n<h3 class=\"wp-block-heading\">Wiring the Circuit<\/h3>\n\n\n\n<p>Wire an LED to GPIO 2 as shown in the following schematic diagram.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"729\" height=\"846\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-an-LED_bb-edited.png?resize=729%2C846&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with an LED connected to GPIO2 via a 220Ohm resistor\" class=\"wp-image-173647\" style=\"width:540px;height:auto\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-an-LED_bb-edited.png?w=729&amp;quality=100&amp;strip=all&amp;ssl=1 729w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-an-LED_bb-edited.png?resize=259%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 259w\" sizes=\"(max-width: 729px) 100vw, 729px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">ESP32: Creating FreeRTOS Tasks &#8211; Arduino Code<\/h3>\n\n\n\n<p>The following code creates a task that will blink an LED connected to GPIO 2 every second.<\/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-arduino-tasks\/\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 2\n\n\/\/ Declare task handle\nTaskHandle_t BlinkTaskHandle = NULL;\n\nvoid BlinkTask(void *parameter) {\n  for (;;) { \/\/ Infinite loop\n    digitalWrite(LED_PIN, HIGH);\n    Serial.println(&quot;BlinkTask: LED ON&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS); \/\/ 1000ms\n    digitalWrite(LED_PIN, LOW);\n    Serial.println(&quot;BlinkTask: LED OFF&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    Serial.print(&quot;BlinkTask running on core &quot;);\n    Serial.println(xPortGetCoreID());\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  \n  pinMode(LED_PIN, OUTPUT);\n\n  xTaskCreatePinnedToCore(\n    BlinkTask,         \/\/ Task function\n    &quot;BlinkTask&quot;,       \/\/ Task name\n    10000,             \/\/ Stack size (bytes)\n    NULL,              \/\/ Parameters\n    1,                 \/\/ Priority\n    &amp;BlinkTaskHandle,  \/\/ Task handle\n    1                  \/\/ Core 1\n  );\n}\n\nvoid loop() {\n  \/\/ Empty because FreeRTOS scheduler runs the task\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\/Run_Single_Task.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>We start by defining the GPIO that will be connected to the LED.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED_PIN 2<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Task Handle<\/h4>\n\n\n\n<p>Then, declare the task handle. A <span class=\"rnthl rntliteral\">TaskHandle_t<\/span> is a variable that points to a FreeRTOS task, letting you control it, like resuming it, stopping it, or delete it. In this example, we won&#8217;t need the task handle, but we&#8217;re creating it nonetheless to show you how it&#8217;s done.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>TaskHandle_t BlinkTaskHandle = NULL;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Task Function<\/h4>\n\n\n\n<p>Then, we create a task. A task is nothing more than a function that executes whatever commands you want. Here&#8217;s the <span class=\"rnthl rntliteral\">BlinkTask<\/span> function used in this example.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void BlinkTask(void *parameter) {\n  for (;;) { \/\/ Infinite loop\n    digitalWrite(LED_PIN, HIGH);\n    Serial.println(\"BlinkTask: LED ON\");\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS); \/\/ 1000ms\n    digitalWrite(LED_PIN, LOW);\n    Serial.println(\"BlinkTask: LED OFF\");\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    Serial.print(\"BlinkTask running on core \");\n    Serial.println(xPortGetCoreID());\n  }\n}<\/code><\/pre>\n\n\n\n<p>This function is a FreeRTOS task, which is a special kind of function that runs independently under the FreeRTOS scheduler, allowing multitasking on the ESP32.<\/p>\n\n\n\n<p>FreeRTOS tasks must return void and must accept a single argument, which can be used to pass data to the function (not used in our case).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void BlinkTask(void *parameter) {<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">for(;;)<\/span> creates an infinite loop to ensure the task runs indefinitely until explicitly stopped. This is similar to the <span class=\"rnthl rntliteral\">loop()<\/span> function used in Arduino code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>for (;;) { \/\/ Infinite loop<\/code><\/pre>\n\n\n\n<p>Then, we use the <span class=\"rnthl rntliteral\">digitalWrite()<\/span> function to turn the LED on and off. Notice that instead of using the typical <span class=\"rnthl rntliteral\">delay()<\/span> function, we use <span class=\"rnthl rntliteral\">vTaskDelay()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>digitalWrite(LED_PIN, HIGH);\nSerial.println(\"BlinkTask: LED ON\");\nvTaskDelay(1000 \/ portTICK_PERIOD_MS); \/\/ 1000ms\ndigitalWrite(LED_PIN, LOW);\nSerial.println(\"BlinkTask: LED OFF\");\nvTaskDelay(1000 \/ portTICK_PERIOD_MS);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">vTaskDelay()<\/h4>\n\n\n\n<p><span class=\"rnthl rntliteral\">vTaskDelay()<\/span> is a FreeRTOS function that pauses a task for a specified number of ticks, allowing other tasks to run during that time. It doesn&#8217;t block your code like <span class=\"rnthl rntliteral\">delay()<\/span>. The <span class=\"rnthl rntliteral\">vTaskDelay()<\/span> function accepts ticks. On the ESP32, each tick is typically 1ms (defined by <span class=\"rnthl rntliteral\">portTICK_PERIOD_MS<\/span>), so <span class=\"rnthl rntliteral\">vTaskDelay(1000 \/ portTICK_PERIOD_MS)<\/span> pauses the task for 1000ms (1 second).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>vTaskDelay(1000 \/ portTICK_PERIOD_MS);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Get Core IDE<\/h4>\n\n\n\n<p>For demonstration purposes, we also print in which core the task is running. We can get that information by calling the <span class=\"rnthl rntliteral\">xPortGetCoreID()<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.print(\"BlinkTask running on core \");\nSerial.println(xPortGetCoreID());<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">setup()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, we initialize the Serial Monitor and set the LED as an output.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void setup() {\n  Serial.begin(115200);\n  \n  pinMode(LED_PIN, OUTPUT);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Create a Task<\/h4>\n\n\n\n<p>Now, to actually create a FreeRTOS task and assign it to a specific core, we need to use the <span class=\"rnthl rntliteral\">xTaskCreatePinnedToCore()<\/span> function. This function also specifies the task function, name, stack size, parameters, priority, and task handle.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>xTaskCreatePinnedToCore(\n  BlinkTask,      \/\/ Task function\n  \"BlinkTask\",   \/\/ Task name\n  10000,           \/\/ Stack size (bytes)\n  NULL,            \/\/ Parameters\n  1,                   \/\/ Priority\n  &amp;BlinkTaskHandle,  \/\/ Task handle\n  1                  \/\/ Core 1\n);<\/code><\/pre>\n\n\n\n<p>The task function is <span class=\"rnthl rntliteral\">BlinkTask<\/span> that we defined earlier. We can also give a name to the task. In this case, <span class=\"rnthl rntliteral\">&#8220;BlinkTask&#8221;<\/span>. <\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>BlinkTask,     \/\/ Task function\n\"BlinkTask\",   \/\/ Task name<\/code><\/pre>\n\n\n\n<p>We set the task stack size to 10000 bytes. The task stack size is the amount of memory allocated for the task to store its variables, function calls, and temporary data while it runs, ensuring it has enough space to operate without crashing the ESP32. It is defined in bytes. In a later example, we&#8217;ll see how to get the stack size of a task.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>10000,    \/\/ Stack size (bytes)<\/code><\/pre>\n\n\n\n<p>In this case, our task doesn&#8217;t have any parameters, so we set that parameter to <span class=\"rnthl rntliteral\">NULL<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>NULL,     \/\/ Parameters<\/code><\/pre>\n\n\n\n<p>We give the task priority <span class=\"rnthl rntliteral\">1<\/span>. The higher the number, the higher the priority. In this case, it doesn&#8217;t matter much because we only have one task.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>1,    \/\/ Priority<\/code><\/pre>\n\n\n\n<p>We also define the task handle for the task that we created at the beginning of the code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>&amp;BlinkTaskHandle,  \/\/ Task handle<\/code><\/pre>\n\n\n\n<p>And finally, we define in which core we want to run the task. The ESP32 has two cores, designated core 0 and core 1. In this example, we&#8217;re using core 1.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>1   \/\/ Core 1<\/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> is empty because the FreeRTOS scheduler will run the task. However, it is possible to add code to the <span class=\"rnthl rntliteral\">loop()<\/span> to run any other commands you want.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\n  \/\/ Empty because FreeRTOS scheduler runs the task\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. After uploading, open the Serial Monitor at a baud rate of 115200. You should get a similar result.<\/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=\"748\" height=\"369\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-Running-single-task-demonstration-serial-monitor.png?resize=748%2C369&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 running a single task using freertos - Serial Monitor demonstration\" class=\"wp-image-173648\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-Running-single-task-demonstration-serial-monitor.png?w=748&amp;quality=100&amp;strip=all&amp;ssl=1 748w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-Running-single-task-demonstration-serial-monitor.png?resize=300%2C148&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 748px) 100vw, 748px\" \/><\/figure><\/div>\n\n\n<p>At the same time, the LED should be blinking every second.<\/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\/07\/ESP32-with-an-LED-off.jpg?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-an-LED-off.jpg?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"ESP32 blinking LED (led off)\" data-height=\"422\" data-id=\"173649\" data-link=\"https:\/\/randomnerdtutorials.com\/?attachment_id=173649#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-an-LED-off.jpg\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-an-LED-off.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\/07\/ESP32-with-an-LED-on.jpg?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-an-LED-on.jpg?strip=info&#038;w=750&#038;ssl=1 750w\" alt=\"ESP32 blinking LED (led on)\" data-height=\"422\" data-id=\"173650\" data-link=\"https:\/\/randomnerdtutorials.com\/?attachment_id=173650#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-an-LED-on.jpg\" data-width=\"750\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-an-LED-on.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"suspend-resume-tasks\">2) Suspend and Resume Tasks<\/h2>\n\n\n\n<p>In this example, you\u2019ll learn how to suspend and resume a FreeRTOS task on the ESP32. We\u2019ll create a task that blinks an LED, and use a pushbutton to control it. When the button is pressed, the task will be suspended to stop the blinking, and pressing it again will resume the task.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parts Required<\/h3>\n\n\n\n<p>For this example, 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=\"noreferrer noopener\">ESP32 Board<\/a>&nbsp;\u2013 read&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP32 Development Boards<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener\" title=\"\">LED<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noreferrer noopener\">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=\"\">Pushubutton<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Wiring the Circuit<\/h3>\n\n\n\n<p>Add a pushbutton to your previous circuit. We&#8217;re connecting the pushbutton to GPIO 23, but you can use any other suitable GPIO.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"771\" height=\"857\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-an-LED-and-pushbutton_bb.png?resize=771%2C857&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 connected to an LED on GPIO 2 and a pushbutton on GPIO 23\" class=\"wp-image-173651\" style=\"width:622px;height:auto\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-an-LED-and-pushbutton_bb.png?w=771&amp;quality=100&amp;strip=all&amp;ssl=1 771w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-an-LED-and-pushbutton_bb.png?resize=270%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 270w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-an-LED-and-pushbutton_bb.png?resize=768%2C854&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 771px) 100vw, 771px\" \/><\/figure><\/div>\n\n\n<p>Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pinout-reference-gpios\/\" title=\"\">ESP32 Pinout Reference: Which GPIO pins should you use? <\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ESP32: Suspend and Resume FreeRTOS Tasks &#8211; Arduino Code<\/h3>\n\n\n\n<p>The following code listens to the press of a pushbutton to either suspend or resume the blinking FreeRTOS task.<\/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-arduino-tasks\/\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 LED1_PIN 2\n#define BUTTON_PIN 23\n\n\/\/ Task handle\nTaskHandle_t BlinkTaskHandle = NULL;\n\n\/\/ Volatile variables for ISR\nvolatile bool taskSuspended = false;\nvolatile uint32_t lastInterruptTime = 0;\nconst uint32_t debounceDelay = 100; \/\/ debounce period\n\nvoid IRAM_ATTR buttonISR() {\n  \/\/ Debounce\n  uint32_t currentTime = millis();\n  if (currentTime - lastInterruptTime &lt; debounceDelay) {\n    return;\n  }\n  lastInterruptTime = currentTime;\n\n  \/\/ Toggle task state\n  taskSuspended = !taskSuspended;\n  if (taskSuspended) {\n    vTaskSuspend(BlinkTaskHandle);\n    Serial.println(&quot;BlinkTask Suspended&quot;);\n  } else {\n    vTaskResume(BlinkTaskHandle);\n    Serial.println(&quot;BlinkTask Resumed&quot;);\n  }\n}\n\nvoid BlinkTask(void *parameter) {\n  for (;;) { \/\/ Infinite loop\n    digitalWrite(LED1_PIN, HIGH);\n    Serial.println(&quot;BlinkTask: LED ON&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS); \/\/ 1000ms\n    digitalWrite(LED1_PIN, LOW);\n    Serial.println(&quot;BlinkTask: LED OFF&quot;);\n    Serial.print(&quot;BlinkTask running on core &quot;);\n    Serial.println(xPortGetCoreID());\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n\n\n  \/\/ Initialize pins\n  pinMode(LED1_PIN, OUTPUT);\n  pinMode(BUTTON_PIN, INPUT_PULLUP); \/\/ Internal pull-up resistor\n\n  \/\/ Attach interrupt to button\n  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);\n\n  \/\/ Create task\n  xTaskCreatePinnedToCore(\n    BlinkTask,         \/\/ Task function\n    &quot;BlinkTask&quot;,       \/\/ Task name\n    10000,             \/\/ Stack size (bytes)\n    NULL,              \/\/ Parameters\n    1,                 \/\/ Priority\n    &amp;BlinkTaskHandle,  \/\/ Task handle\n    1                  \/\/ Core 1\n  );\n}\n\nvoid loop() {\n  \/\/ Empty because FreeRTOS scheduler runs the task\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\/Suspend_Resume_Task.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>We already covered how to create tasks in the previous example. So, we&#8217;ll just cover the relevant parts for this section.<\/p>\n\n\n\n<p>We define the GPIOs for the LED and the pushbutton.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED1_PIN 2\n#define BUTTON_PIN 23<\/code><\/pre>\n\n\n\n<p>We create volatile variables that will be used in the ISR (interrupt service routine for the pushbutton). The <span class=\"rnthl rntliteral\">taskSuspended<\/span> variable is used to determine whether the task is suspended or not, and the <span class=\"rnthl rntliteral\">lastInterruptTime<\/span> and <span class=\"rnthl rntliteral\">debounceDelay<\/span> are needed to debounce the pushbutton.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Volatile variables for ISR\nvolatile bool taskSuspended = false;\nvolatile uint32_t lastInterruptTime = 0;\nconst uint32_t debounceDelay = 100; \/\/ debounce period<\/code><\/pre>\n\n\n\n<p>To detect pushbutton presses, we&#8217;re using interrupts. When we use interrupts, we need to define an interrupt service routine (a function that runs on the ESP32 RAM). In this case, we create the <span class=\"rnthl rntliteral\">buttonISR()<\/span> function. We must add <span class=\"rnthl rntliteral\">IRAM_ATTR<\/span> to the function definition to run it on RAM.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void IRAM_ATTR buttonISR() {<\/code><\/pre>\n\n\n\n<p class=\"rntbox rntclgreen\">Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pir-motion-sensor-interrupts-timers\/\">ESP32 with PIR Motion Sensor using Interrupts and Timers<\/a>.<\/p>\n\n\n\n<p>First, we debounce the pushbutton, and if a button press is detected, we toggle the state of the <span class=\"rnthl rntliteral\">taskSuspended<\/span> flag variable.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Debounce\nuint32_t currentTime = millis();\nif (currentTime - lastInterruptTime &lt; debounceDelay) {\n  return;\n}\nlastInterruptTime = currentTime;\n\n\/\/ Toggle task state\ntaskSuspended = !taskSuspended;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Suspend and Resume Tasks<\/h4>\n\n\n\n<p>Then, if the <span class=\"rnthl rntliteral\">taskSuspended<\/span> variable is <span class=\"rnthl rntliteral\">true<\/span>, we call the <span class=\"rnthl rntliteral\">vTaskSuspend()<\/span> function and pass the task handle as an argument. Here, you can see one of the uses of the Task Handle. It is a way to refer to the task to control it.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (taskSuspended) {\n  vTaskSuspend(BlinkTaskHandle);<\/code><\/pre>\n\n\n\n<p>If the <span class=\"rnthl rntliteral\">taskSuspended<\/span> variable is false, we call the <span class=\"rnthl rntliteral\">vTaskResume()<\/span> function to resume the execution of the task.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>} else {\n  vTaskResume(BlinkTaskHandle);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">setup()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, we must declare our pushbutton as an interrupt as follows:<\/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<p>The rest of the code remains similar to the previous example.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>Upload the code to your ESP32 board.<\/p>\n\n\n\n<p>The LED will start blinking. If you press the pushbutton, the LED will stop blinking. Press again and the LED will start blinking again.<\/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\/07\/Pause-Resume-Task-with-pushbutton.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with an LED blinking with a pushbutton to suspend and resume the task\" class=\"wp-image-173652\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/Pause-Resume-Task-with-pushbutton.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/Pause-Resume-Task-with-pushbutton.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>You can check how it works by watching the following video.<\/p>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/1110287470?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<p>At the same time, you should get all the information on the Serial Monitor.<\/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=\"745\" height=\"385\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-suspend-resume-task-serial-monitor-demonstration.png?resize=745%2C385&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 suspend and resume FreeRTOS tasks - serial monitor demonstration\" class=\"wp-image-173654\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-suspend-resume-task-serial-monitor-demonstration.png?w=745&amp;quality=100&amp;strip=all&amp;ssl=1 745w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-suspend-resume-task-serial-monitor-demonstration.png?resize=300%2C155&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 745px) 100vw, 745px\" \/><\/figure><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"creating-running-multiple-tasks\">3) Creating and Running Multiple Tasks<\/h2>\n\n\n\n<p>In this section, you&#8217;ll learn how to create and run multiple FreeRTOS tasks simultaneously. As an example, we&#8217;ll create two tasks to blink two different LEDs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parts Required<\/h3>\n\n\n\n<p>For this example, 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=\"noreferrer noopener\">ESP32 Board<\/a>&nbsp;\u2013 read&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP32 Development Boards<\/a><\/li>\n\n\n\n<li>2x <a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener\" title=\"\">LED<\/a><\/li>\n\n\n\n<li>2x <a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noreferrer noopener\">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=\"\">Pushbutton<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Wiring the Circuit<\/h3>\n\n\n\n<p>We&#8217;ll wire two LEDs to the ESP32. We&#8217;ll use GPIOs 2 and 4. You can use any other suitable GPIOs as long as you modify the code accordingly.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"751\" height=\"837\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-two-LEDs_bb-edited.png?resize=751%2C837&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Two LEDs connected to the ESP32 - one LED connected to GPIO2 and another connected to GPIO4\" class=\"wp-image-173657\" style=\"width:651px;height:auto\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-two-LEDs_bb-edited.png?w=751&amp;quality=100&amp;strip=all&amp;ssl=1 751w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-connected-to-two-LEDs_bb-edited.png?resize=269%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 269w\" sizes=\"(max-width: 751px) 100vw, 751px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">ESP32: Creating and Running Multiple Tasks &#8211; Arduino Code<\/h3>\n\n\n\n<p>The following code creates two separate FreeRTOS tasks, each blinking an LED at a different rate. With FreeRTOS, it&#8217;s easy to run both tasks independently without blocking each other. This approach is much cleaner and more efficient than using delays or complex timing logic in traditional Arduino code.<\/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-arduino-tasks\/\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 LED1_PIN 2\n#define LED2_PIN 4\n\nTaskHandle_t Task1Handle = NULL;\nTaskHandle_t Task2Handle = NULL;\n\nvoid Task1(void *parameter) {\n  pinMode(LED1_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED1_PIN, HIGH);\n    Serial.println(&quot;Task1: LED1 ON&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED1_PIN, LOW);\n    Serial.println(&quot;Task1: LED1 OFF&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n  }\n}\n\nvoid Task2(void *parameter) {\n  pinMode(LED2_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED2_PIN, HIGH);\n    Serial.println(&quot;Task2: LED2 ON&quot;);\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED2_PIN, LOW);\n    Serial.println(&quot;Task2: LED2 OFF&quot;);\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n\n  xTaskCreatePinnedToCore(\n    Task1,             \/\/ Task function\n    &quot;Task1&quot;,           \/\/ Task name\n    10000,             \/\/ Stack size (bytes)\n    NULL,              \/\/ Parameters\n    1,                 \/\/ Priority\n    &amp;Task1Handle,      \/\/ Task handle\n    1                  \/\/ Core 1\n  );\n\n  xTaskCreatePinnedToCore(\n    Task2,            \/\/ Task function\n    &quot;Task2&quot;,          \/\/ Task name\n    10000,            \/\/ Stack size (bytes)\n    NULL,             \/\/ Parameters     \n    1,                \/\/ Priority\n    &amp;Task2Handle,     \/\/ Task handle\n    1                 \/\/ Core 1\n  );\n}\n\nvoid loop() {\n  \/\/ Empty because FreeRTOS scheduler runs the task\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\/Run_Two_Tasks.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>Creating and running multiple tasks is as simple as creating and running a single task.<\/p>\n\n\n\n<p>First, you need to define your tasks. In our case, we have two different tasks to blink two different LEDs at different rates. We call them <span class=\"rnthl rntliteral\">Task1<\/span> and <span class=\"rnthl rntliteral\">Task2<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void Task1(void *parameter) {\n  pinMode(LED1_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED1_PIN, HIGH);\n    Serial.println(\"Task1: LED1 ON\");\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED1_PIN, LOW);\n    Serial.println(\"Task1: LED1 OFF\");\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n  }\n}\n\nvoid Task2(void *parameter) {\n  pinMode(LED2_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED2_PIN, HIGH);\n    Serial.println(\"Task2: LED2 ON\");\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED2_PIN, LOW);\n    Serial.println(\"Task2: LED2 OFF\");\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n  }\n}<\/code><\/pre>\n\n\n\n<p>Then, in the <span class=\"rnthl rntliteral\">setup()<\/span>, we just need to create the tasks using the <span class=\"rnthl rntliteral\">xTaskCreatePinnedToCore<\/span>. In this example, we&#8217;re running both tasks on core 1 of the ESP32 and both have the same priority.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>xTaskCreatePinnedToCore(\n  Task1,             \/\/ Task function\n  \"Task1\",           \/\/ Task name\n  10000,             \/\/ Stack size (bytes)\n  NULL,              \/\/ Parameters\n  1,                 \/\/ Priority\n  &amp;Task1Handle,      \/\/ Task handle\n  1                  \/\/ Core 1\n);\n\nxTaskCreatePinnedToCore(\n  Task2,            \/\/ Task function\n  \"Task2\",          \/\/ Task name\n  10000,            \/\/ Stack size (bytes)\n  NULL,             \/\/ Parameters     \n  1,                \/\/ Priority\n  &amp;Task2Handle,     \/\/ Task handle\n  1                 \/\/ Core 1\n);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>Upload the code to your board. After uploading, press the ESP32 RST button so that it starts running the code. You&#8217;ll have two different LEDs blinking at different rates. <\/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\/07\/ESP32-Two-Tasks.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 running two FreeRTOS tasks- blinking two LEDs at different rates\" class=\"wp-image-173658\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-Two-Tasks.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-Two-Tasks.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<p>In the following video, you can better understand how it works.<\/p>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/1110287107?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<p>As you can see, it is super simple to achieve this by creating FreeRTOS tasks instead of using delays or other complex timing calculations.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"two-cores\">4) Creating and Running Multiple Tasks On Different Cores (ESP32 Dual-Core)<\/h2>\n\n\n\n<p>Most ESP32 models come with two cores, designated core 0 and core 1. By default, when we run code on the Arduino IDE, the code runs on core 1. In this section, we&#8217;ll show you how to run different tasks on different ESP32 cores.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Wiring the Circuit<\/h3>\n\n\n\n<p>Maintain the circuit from the previous example with two LEDs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tasks on Multiple Cores<\/h3>\n\n\n\n<p>The following code is similar to the previous example, but each task is running on a different core. Additionally, we also add a line to each task to double-check in which core it is running.<\/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-arduino-tasks\/\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 LED1_PIN 2\n#define LED2_PIN 4\n\nTaskHandle_t Task1Handle = NULL;\nTaskHandle_t Task2Handle = NULL;\n\nvoid Task1(void *parameter) {\n  pinMode(LED1_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED1_PIN, HIGH);\n    Serial.println(&quot;Task1: LED1 ON&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED1_PIN, LOW);\n    Serial.println(&quot;Task1: LED1 OFF&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    Serial.print(&quot;Task 1 running on core &quot;);\n    Serial.println(xPortGetCoreID());\n  }\n}\n\nvoid Task2(void *parameter) {\n  pinMode(LED2_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED2_PIN, HIGH);\n    Serial.println(&quot;Task2: LED2 ON&quot;);\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED2_PIN, LOW);\n    Serial.println(&quot;Task2: LED2 OFF&quot;);\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n    Serial.print(&quot;Task 2 running on core &quot;);\n    Serial.println(xPortGetCoreID());\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n\n  xTaskCreatePinnedToCore(\n    Task1,             \/\/ Task function\n    &quot;Task1&quot;,           \/\/ Task name\n    10000,             \/\/ Stack size (bytes)\n    NULL,              \/\/ Parameters\n    1,                 \/\/ Priority\n    &amp;Task1Handle,      \/\/ Task handle\n    1                  \/\/ Core 1\n  );\n\n  xTaskCreatePinnedToCore(\n    Task2,            \/\/ Task function\n    &quot;Task2&quot;,          \/\/ Task name\n    10000,            \/\/ Stack size (bytes)\n    NULL,             \/\/ Parameters     \n    1,                \/\/ Priority\n    &amp;Task2Handle,     \/\/ Task handle\n    0                 \/\/ Core 0\n  );\n}\n\nvoid loop() {\n  \/\/ Empty because FreeRTOS scheduler runs the task\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\/Run_Two_Cores.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Does the Code Work?<\/h3>\n\n\n\n<p>The only difference in this example is that we define <span class=\"rnthl rntliteral\">Task2<\/span> to run on core 0 as shown below.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>xTaskCreatePinnedToCore(\n  Task2,            \/\/ Task function\n  \"Task2\",          \/\/ Task name\n  10000,            \/\/ Stack size (bytes)\n  NULL,             \/\/ Parameters     \n  1,                \/\/ Priority\n  &amp;Task2Handle,     \/\/ Task handle\n  0                 \/\/ Core 0\n);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>If you upload the code to your ESP32, the result will be the same as the previous example. Two LEDs are blinking at different rates.<\/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\/07\/ESP32-Two-Tasks.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 running two FreeRTOS tasks- blinking two LEDs at different rates\" class=\"wp-image-173658\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-Two-Tasks.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-Two-Tasks.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<p>In the Serial Monitor, you can actually check that each task is running in a different core.<\/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=\"425\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-running-on-two-cores.png?resize=751%2C425&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 running tasks on two cores - Serial Monitor Demonstration\" class=\"wp-image-173659\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-running-on-two-cores.png?w=751&amp;quality=100&amp;strip=all&amp;ssl=1 751w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-running-on-two-cores.png?resize=300%2C170&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 751px) 100vw, 751px\" \/><\/figure><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"memory-usage\">5) Tasks Memory Usage<\/h2>\n\n\n\n<p>In this section, we&#8217;ll cover how to measure stack and heap usage for your tasks so that you can optimize memory allocation.<\/p>\n\n\n\n<p><strong>Stack <\/strong>and <strong>heap <\/strong>are two types of memory used by FreeRTOS tasks on the ESP32, each serving a unique role in managing a program\u2019s memory needs.<\/p>\n\n\n\n<p><strong>What exactly is the Stack Usage?<\/strong> The stack is a dedicated memory area for each FreeRTOS task, used to store temporary data like local variables, function call information, and task state during execution. Each task has its own stack, allocated when the task is created. You&#8217;ve seen that in previous examples, we&#8217;re allocating a 10000-byte stack to each task.<\/p>\n\n\n\n<p>There is a function that you can call inside your task to determine the stack usage: the <span class=\"rnthl rntliteral\">uxTaskGetStackHighWaterMark()<\/span> function. That function determines the allocated stack size that is not being used.<\/p>\n\n\n\n<p><strong>What is the Heap Usage?<\/strong> The heap is a shared memory pool in the ESP32\u2019s SRAM, used for dynamic memory allocation, including task stacks, buffers, and other runtime data allocated by FreeRTOS or the Arduino core. We can call the <span class=\"rnthl rntliteral\">xPortGetFreeHeapSize()<\/span> function in our code to determine the free heap.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Task Stack Size and Free Heap &#8211; Code<\/h3>\n\n\n\n<p>The following code is similar to the one in previous projects, with two functions to blink two different LEDs. We determine the free stack and free heap.<\/p>\n\n\n\n<p>Upload the following code to your 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-arduino-tasks\/\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 LED1_PIN 2\n#define LED2_PIN 4\n\nTaskHandle_t Task1Handle = NULL;\nTaskHandle_t Task2Handle = NULL;\n\nvoid Task1(void *parameter) {\n  pinMode(LED1_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED1_PIN, HIGH);\n    Serial.println(&quot;Task1: LED1 ON&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED1_PIN, LOW);\n    Serial.println(&quot;Task1: LED1 OFF&quot;);\n    vTaskDelay(1000 \/ portTICK_PERIOD_MS);\n    Serial.printf(&quot;Task1 Stack Free: %u bytes\\n&quot;, uxTaskGetStackHighWaterMark(NULL));\n  }\n}\n\nvoid Task2(void *parameter) {\n  pinMode(LED2_PIN, OUTPUT);\n  for (;;) {\n    digitalWrite(LED2_PIN, HIGH);\n    Serial.println(&quot;Task2: LED2 ON&quot;);\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n    digitalWrite(LED2_PIN, LOW);\n    Serial.println(&quot;Task2: LED2 OFF&quot;);\n    vTaskDelay(333 \/ portTICK_PERIOD_MS);\n    Serial.printf(&quot;Task2 Stack Free: %u bytes\\n&quot;, uxTaskGetStackHighWaterMark(NULL));\n  }\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  delay(1000);\n  Serial.printf(&quot;Starting FreeRTOS: Memory Usage\\nInitial Free Heap: %u bytes\\n&quot;, xPortGetFreeHeapSize());\n\n  xTaskCreatePinnedToCore(\n    Task1,\n    &quot;Task1&quot;,\n    10000,\n    NULL,\n    1,\n    &amp;Task1Handle,\n    1\n  );\n\n  xTaskCreatePinnedToCore(\n    Task2,\n    &quot;Task2&quot;,\n    10000,\n    NULL,\n    1,\n    &amp;Task2Handle,\n    1\n  );\n}\n\nvoid loop() {\n  static uint32_t lastCheck = 0;\n  if (millis() - lastCheck &gt; 5000) {\n    Serial.printf(&quot;Free Heap: %u bytes\\n&quot;, xPortGetFreeHeapSize());\n    lastCheck = millis();\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\/Get_Task_Stack_Size.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>After uploading the code to your board, you should get something similar on your Serial Monitor.<\/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=\"747\" height=\"376\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-FreeRTOS-tasks-free-stack.png?resize=747%2C376&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with FreeRTOS determine task stack high watermark\" class=\"wp-image-173666\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-FreeRTOS-tasks-free-stack.png?w=747&amp;quality=100&amp;strip=all&amp;ssl=1 747w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP32-with-FreeRTOS-tasks-free-stack.png?resize=300%2C151&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 747px) 100vw, 747px\" \/><\/figure><\/div>\n\n\n<p>The <span class=\"rnthl rntliteral\">uxTaskGetStackHighWaterMark<\/span> reports 8556 bytes free for Task1 and 8552 bytes free for Task2, meaning each task uses 1444\u20131448 bytes of its 10000-byte stack at peak. So, we can greatly reduce the allocated stack size to each task.<\/p>\n\n\n\n<p>A good stack size should cover the task\u2019s peak usage (1444 bytes) plus a safety margin of 500\u20131000 bytes to handle unexpected increases<\/p>\n\n\n\n<p>In the case of free heap, in my case, the <span class=\"rnthl rntliteral\">xPortGetFreeHeapSize()<\/span> reports 247616 bytes free (not shown in the screenshot), indicating the remaining heap after allocating stacks (20000 bytes for two tasks) and other system resources.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>This tutorial was a detailed introduction to FreeRTOS with the ESP32. You learned how to create single and multiple tasks, assign a core to each task, suspend and resume tasks, and even calculate the task stack.<\/p>\n\n\n\n<p>Using FreeRTOS with the ESP32 is a great choice because it allows you to perform multiple tasks simultaneously in a simple way, with priorities to run the most critical tasks first. <\/p>\n\n\n\n<p>More FreeRTOS tutorials with the ESP32:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-queues-inter-task-arduino\/\">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\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-software-timers-interrupts\/\" title=\"\">ESP32 with FreeRTOS: <strong>Software Timers\/Timer Interrupts<\/strong> (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<p>We hope you&#8217;ve found this guide useful. <\/p>\n\n\n\n<p>Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\" title=\"\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\" title=\"\">All our ESP32 Projects and Guides<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we\u2019ll introduce the basic concepts of FreeRTOS and show you how to use it with the ESP32 and the Arduino IDE. You\u2019ll learn how to create single &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 with FreeRTOS (Arduino IDE) &#8211; Getting Started: Create Tasks\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-freertos-arduino-tasks\/#more-173475\" aria-label=\"Read more about ESP32 with FreeRTOS (Arduino IDE) &#8211; Getting Started: Create Tasks\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":173607,"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-173475","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\/07\/ESP32-FreeRTOS-Getting-Started.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\/173475","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=173475"}],"version-history":[{"count":20,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/173475\/revisions"}],"predecessor-version":[{"id":183530,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/173475\/revisions\/183530"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/173607"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=173475"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=173475"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=173475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}