Phipps Electronics

Order within the next 

FREE SHIPPING OVER $199

50,000+ ORDERS

WORLDWIDE SHIPPING

SSL SECURED

A Simple ESP32 Multitasking Example

Contents

Want to take a sneak peek at a simple ESP32 multitasking application? Wondering how things are done? See below to find example codes and applications.

Introduction

An ESP32 is a powerful chip that can handle various numbers of tasks. Using this chip for simple applications would be a waste, underutilizing its value. Here you can take a sneak peek of how basic multitasking on an ESP32 works through a simple example.

How Can ESP32 Do Multitasking?

This is through an open-source real-time operating system called FreeRTOS. FreeRTOS is added to ESP-IDF as a Component and can readily be included in your main application through header files. With this, you can run multiple tasks in your programs seemingly simultaneously.

Espressif customized its version of ESP-IDF called ESP-IDF FreeRTOS. If you want to get in-depth with it, browse through these Espressif resources:

Creating Simple Tasks in FreeRTOS

First, make sure to include the necessary FreeRTOS header files. The basic ones to create tasks are:

				
					#include "freeRTOS\freeRTOS.h"
#include "freeRTOS\task.h"
				
			

You’ll also need to use the function xTaskCreate() from the freeRTOS library to create your tasks:

				
					BaseType_t xTaskCreate(TaskFunction_t pxTaskCode, const char * const pcName, const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask)
				
			
  • pxTaskCode – is your task function.
  • pcName – is a text name for your task.
  • usStackDepth – is the size of the stack allocated to your task.
  • pvParamters – are variable or structure pointers that can be passed to your task.
  • uxPriority – is the priority level of your task when it is executed with other tasks.
  • pxCreatedTask – is the task handle to reference your task code easily.

xTaskCreate() has these various parameters. However, pvParameters and pxCreatedTask can be treated as NULL values in the following example below.

Example Code

The last tutorial covered working with GPIO ports. We can continue where we left off and create simple tasks to blink each LED strip. What’s more interesting now is that each strip will be associated with its own task, seemingly running simultaneously with each other.

The entire code is listed below:

				
					#include <stdio.h>
#include "driver\gpio.h"
#include "freeRTOS\freeRTOS.h"
#include "freeRTOS\task.h"

#define LED_STRIP1_G GPIO_NUM_32
#define LED_STRIP1_R GPIO_NUM_33
#define LED_STRIP1_B GPIO_NUM_25

#define LED_STRIP2_G GPIO_NUM_26
#define LED_STRIP2_R GPIO_NUM_27
#define LED_STRIP2_B GPIO_NUM_2

#define LED_STRIP3_G GPIO_NUM_13
#define LED_STRIP3_R GPIO_NUM_14
#define LED_STRIP3_B GPIO_NUM_15

#define LED_STRIP1_BIT_MASK (1ULL << LED_STRIP1_G | 1ULL << LED_STRIP1_R | 1ULL << LED_STRIP1_B)
#define LED_STRIP2_BIT_MASK (1ULL << LED_STRIP2_G | 1ULL << LED_STRIP2_R | 1ULL << LED_STRIP2_B)
#define LED_STRIP3_BIT_MASK (1ULL << LED_STRIP3_G | 1ULL << LED_STRIP3_R | 1ULL << LED_STRIP3_B)

#define PUSH_BUTTON_1 GPIO_NUM_4
#define PUSH_BUTTON_2 GPIO_NUM_35
#define PUSH_BUTTON_3 GPIO_NUM_36

#define PUSH_BUTTON_1_BIT_MASK (1ULL << PUSH_BUTTON_1)
#define PUSH_BUTTON_2_BIT_MASK (1ULL << PUSH_BUTTON_2)
#define PUSH_BUTTON_3_BIT_MASK (1ULL << PUSH_BUTTON_3)


gpio_config_t myGPIOconfig;

void config_ports(void);

void Led_strip_task1(void *parameter);
void Led_strip_task2(void *parameter);
void Led_strip_task3(void *parameter);

void app_main(void)
{
    config_ports();

    xTaskCreate(Led_strip_task1, "led_strip1_task", 2048, NULL, 2, NULL);
    xTaskCreate(Led_strip_task2, "led_strip2_task", 2048, NULL, 2, NULL);
    xTaskCreate(Led_strip_task3, "led_strip3_task", 2048, NULL, 2, NULL);


    while(1)
    {
        // no return from here
    }

}

void config_ports(void)
{
    // Configure Digital I/O for LEDs
    myGPIOconfig.pin_bit_mask = (LED_STRIP1_BIT_MASK | LED_STRIP2_BIT_MASK | LED_STRIP3_BIT_MASK);
    myGPIOconfig.pull_down_en = GPIO_PULLDOWN_DISABLE;
    myGPIOconfig.pull_up_en = GPIO_PULLUP_DISABLE;
    myGPIOconfig.mode = GPIO_MODE_OUTPUT;
    myGPIOconfig.intr_type = GPIO_INTR_DISABLE;

    gpio_config(&myGPIOconfig);

    myGPIOconfig.pin_bit_mask = (PUSH_BUTTON_2_BIT_MASK | PUSH_BUTTON_3_BIT_MASK);
    myGPIOconfig.pull_down_en = GPIO_PULLDOWN_DISABLE;
    myGPIOconfig.pull_up_en = GPIO_PULLUP_DISABLE;
    myGPIOconfig.mode = GPIO_MODE_INPUT;
    myGPIOconfig.intr_type = GPIO_INTR_DISABLE;

    gpio_config(&myGPIOconfig);

    gpio_set_direction(PUSH_BUTTON_1, GPIO_MODE_INPUT);
    gpio_set_pull_mode(PUSH_BUTTON_1, GPIO_PULLUP_ONLY); 

}

void Led_strip_task1(void *parameters)
{
    for(;;)
    {
            gpio_set_level(LED_STRIP1_G, 1);
            vTaskDelay(1);
            gpio_set_level(LED_STRIP1_G, 0);

            gpio_set_level(LED_STRIP1_R, 1);
            vTaskDelay(1);
            gpio_set_level(LED_STRIP1_R, 0);

            gpio_set_level(LED_STRIP1_B, 1);
            vTaskDelay(1);
            gpio_set_level(LED_STRIP1_B, 0);
            vTaskDelay(1);
    }
}

void Led_strip_task2(void *parameters)
{
    for(;;)
    {
            gpio_set_level(LED_STRIP2_G, 1);
            vTaskDelay(100);
            gpio_set_level(LED_STRIP2_G, 0);

            gpio_set_level(LED_STRIP2_R, 1);
            vTaskDelay(100);
            gpio_set_level(LED_STRIP2_R, 0);

            gpio_set_level(LED_STRIP2_B, 1);
            vTaskDelay(100);
            gpio_set_level(LED_STRIP2_B, 0);
            vTaskDelay(100);
    }
}

void Led_strip_task3(void *parameters)
{
    for(;;)
    {
            gpio_set_level(LED_STRIP3_G, 1);
            vTaskDelay(1000);
            gpio_set_level(LED_STRIP3_G, 0);

            gpio_set_level(LED_STRIP3_R, 1);
            vTaskDelay(1000);
            gpio_set_level(LED_STRIP3_R, 0);

            gpio_set_level(LED_STRIP3_B, 1);
            vTaskDelay(1000);
            gpio_set_level(LED_STRIP3_B, 0);
            vTaskDelay(1000);
    }
}
				
			

Code Explanation

				
					void config_ports(void);
				
			

config_ports() puts all the GPIO port initializations into one function. These statements were discussed in working with GPIO ports.

				
					void Led_strip_task1(void *parameter);
void Led_strip_task2(void *parameter);
void Led_strip_task3(void *parameter);
				
			

The functions above are the individual function prototype tasks for each LED strip. They are named accordingly.

				
					void Led_strip_task1(void *parameters)
{
    for(;;)
    {
            gpio_set_level(LED_STRIP1_G, 1);
            vTaskDelay(1);
            gpio_set_level(LED_STRIP1_G, 0);

            gpio_set_level(LED_STRIP1_R, 1);
            vTaskDelay(1);
            gpio_set_level(LED_STRIP1_R, 0);

            gpio_set_level(LED_STRIP1_B, 1);
            vTaskDelay(1);
            gpio_set_level(LED_STRIP1_B, 0);
            vTaskDelay(1);
    }
}
				
			

Above is the body of the code for one of the tasks. You’ll see that it runs in a never-ending loop. The vTaskDelay() sets the delay time for how long each LED turns on. Interestingly, this delay or task-blocking function blocks this current task at a specified time interval so that other tasks may run. Hence, there is no blocking code here. This is that part of freeRTOS where multitasking shines.

				
					    xTaskCreate(Led_strip_task1, "led_strip1_task", 2048, NULL, 2, NULL);
    xTaskCreate(Led_strip_task2, "led_strip2_task", 2048, NULL, 2, NULL);
    xTaskCreate(Led_strip_task3, "led_strip3_task", 2048, NULL, 2, NULL);
				
			

Above, you’ll see that in FreeRTOS, you have to explicitly create a task first for it to run. The three tasks for each LED strip are created or declared here. Led_strip_taskn are the names of the functions. These tasks were allocated a stack depth of 2048. They all have the same priorities (priority level 2). The task handles and parameters have NULL values for now.

See the Code in Action

Below, you can see each individual LED strips running it’s own code and time interval. Hope you’ve learned  a lot in this basic ESP32 multitasking example 🙂

SUBSCRIBE FOR NEW POST ALERTS

Subscribe to be the first to know when we publish a new article!
List Subscriptions(Required)

POPULAR POSTS

Scroll to Top