ESP32

ESP32 FreeRTOS, Dual Core Programming, and Multi Tasking

ESP32 Dual Core Programming:

ESP32 FreeRTOS, Dual Core Programming, and Multi Tasking- ESP32 WiFi + Bluetooth module is a great microcontroller made by Espressif Systems. It has a powerful dual-core Xtensa LX6 microprocessor that runs at a fast 240 MHz.

ESP32 Dual Core



But the question is, how many of you have actually used the dual cores of the ESP32? Or have done multi-tasking on the ESP32? I am sure 85% of you have not used the dual cores of the ESP32 or done any multi-tasking.

allpcb circuit

ESP32 Dual Core FreeRTOS programming

First of all, let me tell you that you should not mix up FreeRTOS, dual-core programming, and Multi tasking.

Although Dual core programming and multi tasking in ESP32 are related to FreeRTOS, but not exactly the same thing.

FreeRTOS is a real-time operating system that helps run multiple tasks at the same time, even when they share the same resources. To be more specific; FreeRTOS manages the tasks, schedules them, and provides mechanisms for inter-task communication and synchronization.

Whereas, Dual-core programming in ESP32 means you can run two different tasks or programs on the two cores of the ESP32 processor (Core 0 and Core 1). This way, each core can do its own job at the same time.

Multi-tasking in ESP32, on the other hand, refers to the ability to run multiple tasks concurrently on a single core, using FreeRTOS or other scheduling mechanisms.



So,

  • FreeRTOS is used to manage multiple tasks running on one core.
  • Dual-core programming lets you run two different tasks at the same time on the two cores.
  • Multi-tasking means you can have several tasks running on each core, managed by FreeRTOS or other tools.

I will not make things too complicated so that you can easily understand everything. Today, we will only cover the dual cores (Core 0 and Core 1). In upcoming articles, we will talk about FreeRTOS and multi-tasking.

So, without any further delay, let’s get started!!!

Amazon Links:

ESP32 WiFi + Bluetooth Module (Recommended)

Breadboard

Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.

ESP32 Default Core:

By default, Arduino sketches run on ESP32’s Core 1. We can easily find out which function is running on which core by using the xPortGetCoreID() function. As you can see, I have used this function in both void setup() and void loop().



Check the ESP32 Default Core:

  • Upload this program to confirm the default core of the ESP32.
  • Open the Serial monitor and select the Baud rate.

If you are not able to see the core information for the setup() function then simply press the Reset button.

how to use the default ESP32 Dual Core

You can see both the setup() and loop() functions are running on the ESP32 Core 1.

The ESP32 microcontroller comes with two cores: Core 0 and Core 1. This means you can run two tasks simultaneously on separate cores. This feature is useful when you want to split your workload, such as running time-sensitive tasks on one core while handling less critical tasks on the other.



What is a Task?

A task in the context of programming is a single, independent piece of code that performs a specific function. In FreeRTOS (which is often used for managing tasks on the ESP32), tasks can be thought of as lightweight processes that the operating system schedules and runs. Each task can run on either Core 0 or Core 1.

Single-Core Execution

Let’s start with a basic example where both tasks (blinking an LED and printing a message to the Serial Monitor) run on a single core. Let me tell you, this variant of the ESP32 has its onboard LED connected to GPIO 5.

Code:




Code Explanation:

In this example, both the LED blinking task and the message printing task are executed on Core 1 by default. The loop() function runs these tasks one after the other, meaning that the LED blinks, and then a message is printed to the Serial Monitor.Let’s upload this program.

how to run two tasks on the same time using ESP32 Dual Core

Since both tasks are running on the same core, so; that’s why they are executed sequentially. The microcontroller completes the LED blink, and then moves on to printing the message.

Dual-Core Execution:

I modified the program; and now, the LED blinking task runs on one core and the message printing task runs on the other core.

ESP32 Dual Cores Programming:



ESP32 Dual Cores Code Explanation:

These lines create two variables to keep track of the tasks. Task1 and Task2 will store information about the tasks we create.

The ESP32 onboard Led is connected to the gpio 5.

The setup() function runs once when the ESP32 starts up. Next, I activated the serial communication and selected 115200 as the baud rate. And I set the LED as output.

Next, I created two tasks, each assigned to a different core.

xTaskCreatePinnedToCore(…);: This function creates a new task and assigns it to a core.

Task1Code: This is the function that will run as Task 1.

“Task 1”: This is a name for the task.

2000: This is the amount of memory (stack size) Task 1 will use. It is measured in words.

NULL: This means no extra input is passed to Task 1.

2: This sets Task 1’s priority. A higher number means higher priority.

&Task1: This saves information about Task 1 in the Task1 variable.

0: This tells the ESP32 to run Task 1 on Core 0.



xTaskCreatePinnedToCore(…);: This function creates another task.

Task2Code: This is the function that will run as Task 2.

“Task 2”: This is a name for the task.

2000: This is the amount of memory (stack size) Task 2 will use.

NULL: This means no extra input is passed to Task 2.

2: This sets Task 2’s priority.

These three lines are exactly the same.

&Task2: This saves information about Task 2 in the Task2 variable.

1: This tells the ESP32 to run Task 2 on Core 1.

The loop() function is empty; because the tasks are running on separate cores.

void Task1Code(void * pvParameters) {: This defines what Task 1 does.

for (;;) {: This creates an infinite loop.

digitalWrite(myLed, HIGH);: This turns the LED on.

delay(500);: This waits for 500 milliseconds.

digitalWrite(myLed, LOW);: This turns the LED off.

delay(500);: This waits for another 500 milliseconds.

All these other instructions are used to ON and OFF the Led at 500 millisconds.   



Similarly, task 2 sends the Electronic Clinic message to the Serial monitor at a delay of 1000 milliseconds. Let’s upload this program.

Practical Demonstration:

printing data of ESP32 Dual Core on serial monitor

For the practical demonstration watch the video tutorial given at the end of this article. The LED is blinking on its own, and the message is printing separately. In the previous example, when both tasks were running on the same core, the LED would blink first and then the message would print. This happened because the tasks were executed one after the other. But now, with both tasks running on separate cores, they run independently of each other.

Let’s take a look at another example.




Two LEDs on Core 0 and Core 1:

This time, we will make the two LEDs blink at different speeds. One Led is connected to the ESP32 GPIO 2 and the other LED is connected to the GPIO 4. For the connections you can follow this circuit diagram. 

ESP32 Dual Core led controlling circuit diagram

ESP32 Dual Cores Code:

I have slightly modified the previous code. This time, I am not using the onboard LED; instead, I am using external LEDs that are connected to pins 2 and 4 of the ESP32. The rest of the code is the same. We are just turning one LED ON and OFF every 200 milliseconds and the other LED ON and OFF every 1 second. I have already uploaded this program so let’s go ahead and watch this in action.



Practical Demonstration:

Controlling with ESP32 Dual Core

Now you can see even more clearly how we can run two different tasks on two different cores independently. Watch the video tutorial on my YouTube channel “Electronic Clinc”.

Running tasks independently does not mean we cannot link them together. In fact, we can also make the cores communicate with each other. let’s do it.

Inter Task Communication Between two Cores:

For this example, you can see I have also added a potentiometer. Its middle leg is connected to the ESP32 GPIO 36 which may also be labeled as “A0 or VP”.  Whereas the two LEDs are still connected to the GPIOs 2 and 4.

how to use ESP32 Dual Core core1 and core2

For the Inter Task Communication between the two cores “Core 0 and Core 1”. I want the Led1 and Potentiometer to be on Core 1; and the other LED Led 2 on the Core 0.

So, what I want do is, I want to control the Delay time of Led 2 from Core 1. So, we will read the potentiometer on the Core 1 and then send its value to the Core 0 to increase and decrease the delay time of Led 2. Instead of using Potentiometer, you can use any other Analog or digital sensor.



Inter-core communication Code:

Code Explanation:

This time for inter-core communication, I also defined a Queue Handle which allows Core 1 to send the potentiometer value to core 0.

in the setup() function, I also created a queue that can hold one integer value, which will be used to pass the potentiometer value from Core 1 to Core 0.

This checks if a new potentiometer value is available in the queue. If a new value is available, it updates the delay time.

On core 1 we read the Potentiometer and map its value from 50 to 1000 milliseconds.

Using this line of code, we send the Potentiometer value to Core 0.

I have already uploaded this program, so let’s go ahead and watch the inter task communication between two cores on the ESP32 in action.



Practical Demonstration:

The Led 1 and potentiometer are on Core 1, and the other LED is on Core 0. By using the potentiometer, I can control the ON and OFF time of the Led 2 on Core 0.

how to use inter core in ESP32 Dual Core

Whereas, the Led1 keeps turning ON and OFF every 1 second.

By using Core 0 and Core 1, you can make amazing projects. For example, you can use Bluetooth on one core and WiFi on the other. Or you can use Bluetooth for short-range communication on one core and LoRa transceiver modules for long-range communication on the other core. You can use these cores in a myriad of different ways. So, that’s all for now.

Watch Video Tutorial:

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button