The ESP32 is a well-known microcontroller chip that is extensively used in the Internet of Things (IoT) sector because of its cheap price, low power usage, and high performance capabilities. The ESP32’s dual-core CPU, which enables real multitasking, is one of its special characteristics.
Traditional single-core processors can only perform one job at a time, so if the processor is working on one task, it won’t be able to start working on another one until it is done. For some applications, such as those that need real-time performance or those that must manage numerous jobs at once, this may be an issue.
However, the ESP32’s dual-core processor allows the device to carry out two jobs at once. This means that one core can be devoted to operating the primary program, and the other core can take care of background processes like sensor monitoring or network connection management.

The ESP32 supports FreeRTOS, a real-time operating system that offers a method to handle duties and objectives, to take advantage of the dual-core CPU. You can make a number of tasks with FreeRTOS, each with a different importance level, and the operating system will take care of allocating time for these tasks across the two cores.

Overall, the ESP32 is a powerful microcontroller for multitasking apps, especially those in the IoT area where multiple activities must be handled concurrently due to its dual-core CPU and support for FreeRTOS.
In this blog we are not using free RTOS we directly assign tasks to the controller . Further blogs I tell you about using Free RTOS .
Getting started with ESP32 – https://elconics.com/getting-started-withesp32/
Here is a example code
// This code is for Multitasking Servo and Led
TaskHandle_t Task1;
TaskHandle_t Task2;
#include <Servo.h>
// LED pins
const int led1 = 2;
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
Serial.begin(115200);
pinMode(led1, OUTPUT);
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
}
//Task1code: blinks an LED every 1000 ms
void Task1code( void * pvParameters ){
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
while(1){
digitalWrite(led1, HIGH);
delay(1000);
digitalWrite(led1, LOW);
delay(1000);
}
}
//Task2code: Run servo 0-180 degree and 180-0 degree
void Task2code( void * pvParameters ){
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID());
myservo.attach(33); // attaches the servo on pin 13 to the servo object
while(1){
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
}
void loop() {
}
// This code is for servo and led running in one core
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
int led=2;
void setup() {
pinMode(led,OUTPUT);
myservo.attach(33); // attaches the servo on pin 13 to the servo object
}
void loop() {
digitalWrite(led,HIGH);
delay(1000);
digitalWrite(led,LOW);
delay(1000);
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}