ESP32 Dual Core Programming with Arduino IDE

Published  January 16, 2020   0
ESP32 Dual Core Processor

ESP modules are popular for their Wi-Fi functionalities like ESP8266, ESP-12E, etc. These all are powerful Microcontroller modules with Wi-Fi functionalities. There is one more ESP module which is more powerful and versatile than previous ESP modules- its name is ESP32. It has Bluetooth and Wi-Fi connectivity and we already explained BLE capabilities of ESP32 and used ESP32 in many IoT projects. But very few people know that ESP32 is a Dual-core microcontroller.

ESP32 has two 32-bit Tensilica Xtensa LX6 microprocessors which makes it a powerful dual-core (core0 and core1) microcontroller. It is available in two variants single-core and dual-core. But the dual-core variant is more popular because there is no significant price difference.

Espressif ESP32 Diagram

ESP32 can be programmed using Arduino IDE, Espressif IDF, Lua RTOS, etc. While programming with Arduino IDE, the code only runs on Core1 because Core0 is already programmed for RF communication. But here is this tutorial we will show how to use both the cores of ESP32 to perform two operations simultaneously. Here the first task will be to blink the onboard LED and the second task will be to fetch the temperature data from the DHT11 sensor.

Let’s first see the advantages of a multi-core processor over a single core.

Advantages of Multi-core processor

  1. Multi-core processors are useful when there are more than 2 processes to work simultaneously.
  2. As work is distributed among different cores, its speed increases and multiple processes can be finished at the same time.
  3. Power consumption can be reduced because when any core is in idle mode than it can be used to shut down the peripherals that are not in use at that time.
  4. Dual-core processors have to switch between different threads less often than single-core processors because they can handle two at once instead of one at a time.

ESP32 and FreeRTOS

ESP32 board already has FreeRTOS firmware installed on it. FreeRTOS is an open-source Real-time Operating system which is very useful in multitasking. RTOS helps in managing the resources and maximizing the system performance. FreeRTOS has many API functions for different purposes and using these APIs, we can create tasks and make them run on different cores.

Complete documentation of FreeRTOS APIs can be found here. We will try to use some APIs in our code to build a multitasking application that will run on both the cores.

Finding the ESP32 core ID

Here we will use Arduino IDE to upload the code into ESP32. To know the Core ID on which the code is running, there is an API function

xPortGetCoreID()

This function can be called from void setup() and void loop() function to know the core ID on which these functions are running.

You can test this API by uploading the below sketch:

void setup() {
  Serial.begin(115200);
  Serial.print("setup() function running on core: ");
  Serial.println(xPortGetCoreID());
}
void loop() {
  Serial.print("loop() function running on core: ");
  Serial.println(xPortGetCoreID());
}

After uploading the above sketch, open the Serial monitor and you will find that both the functions are running on core1 as shown below.

ESP32 Dual Core Serial Monitor

From the above observations, it can be concluded that the default Arduino sketch always runs on core1.

ESP32 Dual Core Programming

Arduino IDE supports FreeRTOS for ESP32 and FreeRTOS APIs allow us to create tasks that can run independently on both the cores. The task is the piece of code that performs some operation on the board like blinking led, sending temperature, etc.

The below function is used to create tasks that can run on both the cores. In this function, we have to give some arguments like a priority, core id, etc.

Now, follow the below steps to create task and task function.

1.   First, create tasks in the void setup function. Here we will create two tasks, one for blinking LED after every 0.5 seconds and another task is to get temperature reading after every 2 seconds.

xTaskCreatePinnedToCore() function takes 7 arguments:

  1. Function name to implement the task (task1)
  2. Any name given to the task (“task1”, etc)
  3. Stack size allotted to the task in words(1 word=2bytes)
  4. Task input parameter (can be NULL)
  5. Priority of the task  ( 0 is the lowest priority)
  6. Task handle (can be NULL)
  7. Core id where the task will run (0 or 1)

Now, create Task1 for blinking the led by giving all the arguments in xTaskCreatePinnedToCore() function.

xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL,  0); 

Similarly, create Task2 for Task2 and make core id 1 in the 7th argument.

xTaskCreatePinnedToCore(Task2code, "Task2", 10000, NULL, 1, NULL,  1); 

You can change the priority and stack size depending on the complexity of the task.

2.   Now, we will implement Task1code and Task2code function. These functions contain the code for the required task. In our case, the first task will blink the led and another task will fetch the temperature. So make two separate functions for each task outside the void setup function.

Task1code function for blinking on-board led after 0.5 seconds is implemented as shown below.

Void Task1code( void * parameter) {
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;) {//infinite loop
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
​​delay(500);
}
}

Similarly, implement Task2code function for fetching the temperature.

void Task2code( void * pvParameters ){
  Serial.print("Task2 running on core ");
  Serial.println(xPortGetCoreID());
  for(;;){
    float t = dht.readTemperature();
     Serial.print("Temperature: ");
     Serial.print(t);
   delay(2000);
  }
}

3.   Here void loop function will remain empty. As we already know that loop and setup function runs on core1 so you can implement core1 task in void loop function also.

Now the coding part is over, so just upload the code using Arduino IDE by choosing the ESP32 board in Tools menu. Make sure you have connected the DHT11 sensor to pin D13 of ESP32.

ESP32 with DHT11 Circuit Diagram

Now the results can be monitored on Serial Monitor or Arduino IDE as shown below:

ESP32 Dual Core with Arduino IDE

Complex applications like real-time system can be built by running multiple tasks simultaneously using dual cores of ESP32.

Complete code along with a Demo video is given below.

Code

#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11 
const int led = 2;  
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(115200); 
  pinMode(led, OUTPUT);
dht.begin();
xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL,  1); 
  delay(500); 
xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL,  0); 
    delay(500); 
}
void Task1code( void * pvParameters ){
  Serial.print("Task1 running on core ");
  Serial.println(xPortGetCoreID());
  for(;;){
    digitalWrite(led, HIGH);
    delay(300);
    digitalWrite(led, LOW);
    delay(300);
  } 
}
void Task2code( void * pvParameters ){
  Serial.print("Task2 running on core ");
  Serial.println(xPortGetCoreID());
  for(;;){
      float h = dht.readHumidity();
    float t = dht.readTemperature();
     float f = dht.readTemperature(true);
      Serial.print("Temperature: ");
     Serial.print(t);
   Serial.print(" *C \n ");
     if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
    delay(2000);
  }
}
void loop() {
}

Video

Have any question realated to this Article?

Ask Our Community Members