FreeRTOS con ESP32

Clase 15 de 30 • Curso de IoT: Programación de Microcontroladores ESP32

Clase anteriorSiguiente clase
    Andrés González

    Andrés González

    student•
    hace 7 meses

    En C y C++, los archivos con extensión .h son utilizados para definir interfaces, como declaraciones de funciones y estructuras, mientras que los archivos .c contienen la implementación de esas funciones. Usar archivos .h permite una mejor organización del código, y facilita la inclusión de la misma interfaz en múltiples archivos fuente sin duplicar el código. Esto también ayuda en la separación de la lógica de implementación y la definición de la API, promoviendo la reutilización del código.

    Andrés González

    Andrés González

    student•
    hace 7 meses

    No estaría mal el curso de FreeRTOS

    Gabriel Obregón

    Gabriel Obregón

    student•
    hace 8 meses

    Implementación de FreeRTOS en ESP32 con ESP-IDF

    1️⃣ Introducción

    Ahora que conoces los conceptos fundamentales de un sistema operativo y FreeRTOS (un sistema operativo en tiempo real), aprenderemos a implementarlo usando ESP-IDF en el ESP32.

    Nos enfocaremos en: ✅ Crear tareas o procesos que se ejecuten en paralelo. ✅ Asignar tareas a un núcleo específico del ESP32.

    2️⃣ Creación del Proyecto en ESP-IDF

    Para comenzar, debemos crear un nuevo proyecto en ESP-IDF.

    Pasos para crear el proyecto:

    1️⃣ Abrir la terminal y ejecutar:

    idf.py create-project rtos

    Esto creará el proyecto en la ruta:

    c:\users\diana\documents\work\platzi\cursos\latest\esp32\rtos  

    2️⃣ Moverse al directorio del proyecto:

    cd .\rtos\

    3️⃣ Abrir el proyecto en Visual Studio Code:

    code .

    4️⃣ Realizar la primera compilación:

    idf.py build

    3️⃣ Configuración del Código en FreeRTOS

    Una vez creado el proyecto, podemos comenzar a escribir código en rtos.c.

    Librerías necesarias:

    Para trabajar con FreeRTOS en ESP-IDF, importamos:

    #include <stdio.h>

    #include "freertos/FreeRTOS.h"

    #include "freertos/task.h"

    📌 Importante: 🔹 stdio.h → Para printf(). 🔹 freertos/FreeRTOS.h → Funciones y estructuras principales de FreeRTOS. 🔹 freertos/task.h → Gestión de tareas en FreeRTOS.

    4️⃣ Creando una Tarea con FreeRTOS

    Estructura de una tarea en FreeRTOS

    Para crear una tarea, necesitamos definir una función que se ejecutará en un bucle infinito.

    📌 Código de la tarea:

    void task1(void *args) {

        while(1) {

            printf("Task 1\n");

        }

    }

    🔹 void *args permite recibir parámetros, aunque en este caso no se usan. 🔹 while(1) mantiene la tarea en ejecución continua.

    Creación de la tarea con xTaskCreate()

    Para ejecutar la tarea en FreeRTOS, usamos:

    TaskHandle_t taskHandle1 = NULL;

    void app_main(void) {

        xTaskCreate(task1, "task1", 4096, NULL, 10, &taskHandle1);

    }

    📌 Parámetros de xTaskCreate()

    Parámetro

    Descripción

    task1

    Nombre de la función de la tarea

    "task1"

    Nombre en texto plano

    4096

    Memoria reservada

    NULL

    No pasamos argumentos

    10

    Prioridad de la tarea

    &taskHandle1

    Referencia para gestionar la tarea

    5️⃣ Compilación y Ejecución del Programa

    Compilar el código:

    idf.py build

    Subir el código al ESP32:

    idf.py -p COM3 flash

    Monitorear la ejecución:

    idf.py -p COM3 monitor

    📌 Problema detectado: El mensaje Task 1 se imprime sin saltos de línea, dificultando la lectura.

    ✅ Solución: Modificamos printf() agregando un \n:

    printf("Task 1\n");

    Recompilamos y volvemos a subir el código:

    idf.py build

    idf.py -p COM3 flash

    idf.py -p COM3 monitor

    6️⃣ Problema: La tarea se queda colgada

    Después de un tiempo, aparecen warnings en la terminal. Esto sucede porque FreeRTOS detecta que la tarea no se detiene y consume todo el tiempo del procesador.

    🚨 ¿Qué hace FreeRTOS en este caso? 🔹 Reinicia automáticamente el sistema para evitar bloqueos.

    7️⃣ Solución: Controlando la tarea con un contador

    En lugar de ejecutar la tarea indefinidamente, podemos limitar su ejecución usando un contador.

    📌 Código actualizado:

    void task1(void *args) {

        int count = 0;

        while (1) {

            count++;

            printf("Task 1 count: %d\n", count);

            if (count > 5) {

                vTaskDelete(NULL);

            }

        }

    }

    🔹 Se crea una variable count que inicia en 0. 🔹 Cada iteración del while(1), el contador aumenta. 🔹 Si count supera 5, la tarea se elimina con vTaskDelete(NULL).

    ✅ Resultado esperado: La tarea se ejecuta seis veces y luego se detiene.

    8️⃣ Comprobando los cambios en la terminal

    Ahora recompilamos y flasheamos el programa:

    idf.py build

    idf.py -p COM3 flash

    idf.py -p COM3 monitor

    📌 Resultado en la terminal: 🔹 La tarea Task 1 se ejecuta 6 veces. 🔹 No hay warnings ni reinicios inesperados. 🔹 El sistema operativo sigue funcionando correctamente.

    Julian Francisco Pinchao Ortiz

    Julian Francisco Pinchao Ortiz

    student•
    hace 2 años

    Comandos para el IDF Monitor

    https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-monitor.html

    Julian Francisco Pinchao Ortiz

    Julian Francisco Pinchao Ortiz

    student•
    hace 2 años

    Comando para la el IDF Monitor

    https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-monitor.html

    Julio Cardenas

    Julio Cardenas

    student•
    hace 2 años

    Agregue un vTaskDelay de 500 milisegundos

    #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "time.h" TaskHandle_t taskHandle_1; const TickType_t taskDelay = 500 / portTICK_PERIOD_MS; time_t elapsed_time; int counter = 0; void task_1(void *args) { while (true) { time(&elapsed_time); printf("Task 1 counter: %d seconds: %lld\n", counter, elapsed_time); counter++; vTaskDelay(taskDelay); if (counter > 50) { printf("Finalizando la tarea"); vTaskDelete(taskHandle_1); } } } void app_main(void) { xTaskCreate( task_1, //Nombre de la funcion que implementa la tarea "Tarea_1", //Nombre descriptivo de la tarea con fines de debugging 4096, //El tamaño del task stack en bytes NULL, //pointer a un parametro cuando la tarea esta siendo creada 10, //Prioridad de la tarea un numero &taskHandle_1 //apuntador para referenciar la tarea. ); }
    Carlos Andres Betancourt Perez

    Carlos Andres Betancourt Perez

    student•
    hace 2 años

    Les comparto mi código con algunos cambios usando la librería esp_log.h para imprimir los mensajes en diferentes colores:

    //importamos las librerias necesarias #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" //declaramos las variables globales static const char* TAG = "ESP32"; TaskHandle_t task1_handle; void task1(void* args) { int count = 0; while (true) { count++; if (count > 5) { ESP_LOGE(TAG, "task1 deleted!"); vTaskDelete(NULL); } ESP_LOGW(TAG, "task1 executed %u times", count); vTaskDelay(pdMS_TO_TICKS(500)); } } //------------------------------------------- void app_main(void) { xTaskCreate(task1, "task1", 2048, NULL, 5, &task1_handle); } ```//importamos las librerias necesarias#include \<stdio.h>#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "esp\_log.h" //declaramos las variables globalesstatic const char\* TAG = "ESP32";*TaskHandle\_t* task1\_handle; void task1(void\* *args*) {   int count = 0;    while (true) {      count++;      if (count > 5) {         ESP\_LOGE(TAG, "task1 deleted!");         vTaskDelete(NULL);      }      ESP\_LOGW(TAG, "task1 executed %u times", count);      vTaskDelay(pdMS\_TO\_TICKS(500));   }}//------------------------------------------- void app\_main(void) {   xTaskCreate(task1, "task1", 2048, NULL, 5, \&task1\_handle);}
    Carlos Andres Betancourt Perez

    Carlos Andres Betancourt Perez

    student•
    hace 2 años

    para saber cuales son los parámetros de freeRTOS como por ejemplo la máxima longitud en el nombre de una tarea, la frecuencia de los ticks, el mínimo stack de memoria y demás, pueden dar ctrl+click izquierdo sobre la librería de freeRTOS y luego buscar la linea 65 donde se incluye el archivo freeRTOSConfig.h que es indispensable para cualquier proyecto con freeRTOS.

    finalmente dan nuevamente ctrl + click izquierdo para que vs code los lleve a ese archivo de configuración. también les recomiendo ampliamente leer la documentación oficial de freeRTOS para tener mas claro los conceptos de este kernel

    https://www.freertos.org/a00110.html

    Carlos Andres Betancourt Perez

    Carlos Andres Betancourt Perez

    student•
    hace 2 años

    personalmente me gusta usar mas la extensión de vs code que la instalación directa, asi evito usar la consola de comandos.

    algo a tener en cuenta, la ruta donde se aloja el proyecto no debe tener espacio en los nombres ni caracteres especiales, sino la compilación fallara

    Edwin Giovanni Callado Armenta

    Edwin Giovanni Callado Armenta

    student•
    hace 2 años

    Hola, tengo este problema al compilar. C:/Espressif/frameworks/esp-idf-v4.4.5-2/rtos/main/rtos.c:24:16: note: each undeclared identifier is reported only once for each function it appears in ninja: build stopped: subcommand failed. ninja failed with exit code 1

      Diana Martinez

      Diana Martinez

      student•
      hace 2 años

      No te está encontrando la librería, necesitas verificar que tu instalación es correcta, y revisar que para la versión que instalaste, es así como se usa.

    Mario Ruben Hernandez Carmona

    Mario Ruben Hernandez Carmona

    student•
    hace 2 años

    Les comparto mi código, hice una modificación para que se ejecute la tarea solo durante un minuto

    #include <stdio.h> #include <time.h> #include <unistd.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" TaskHandle_t taskHandle1 = NULL; void task1(void *args) { int count = 0; time_t start, current; double elapsed ; // Tiempo transcurrido en segundos int duration = 60; // Duración total de la tarea en segundos // Obtiene el tiempo de inicio time(&start); while(1) { time(&current); // Calcula el tiempo transcurrido elapsed = difftime(current, start); count++; if (elapsed >= duration) { printf("End task1... bye\n"); vTaskDelete(NULL); } // Muestra el tiempo restante cada 10 segundos if ((int)elapsed % 10 == 0) { printf("Tiempo restante: %d segundos\n", duration - (int)elapsed); printf("Ejecuciones: %d veces\n", count); } } } void app_main(void) { xTaskCreate(task1, "Task1", 4096, NULL, 10, &taskHandle1); }
    Joaquín Alejandro Domínguez Lozano

    Joaquín Alejandro Domínguez Lozano

    student•
    hace 2 años

    Tengo la v5.0.2 del ESP IDF y cuándo escribía idf.py build mostraba que tenía un error en el archivo CMakeLists.txt. Esto era porque escribía el comando dentro de la carpeta main, Procuren ejectutar sus comandos de compilación dentro de la carpeta del proyecto ya que ambas carpetas tienen archivos de configuración CMake, uno para el proyecto y otro para el código.

    Marcela Dueñas

    Marcela Dueñas

    student•
    hace 3 años

    Dos tips utiles por si a alguien le hacen falta:

    1. Guardar el archivo en vcode cada vez que hacemos cambios o antes de compilar.

    2. Para salir del modo monitor presionar ctrl +]

      Mario Ruben Hernandez Carmona

      Mario Ruben Hernandez Carmona

      student•
      hace 2 años

      En cuanto al punto 2 (Para salir del modo monitor presionar ctrl +]), les comento que yo tenia mi teclado configurado en español, por lo que la combinación de teclas no funcionaba, debí cambiar la configuración a ingles para que funcionara, espero les sea de utilidad el tip.

      Julio Cardenas

      Julio Cardenas

      student•
      hace 2 años

      control +] Me evitaste muchas desconexiones!!! gracias

    Jesús Ramon

    Jesús Ramon

    student•
    hace 3 años

    Este código en lenguaje C utiliza las librerías FreeRTOS para crear una tarea llamada "task1" que se ejecutará en un microcontrolador o microprocesador que tenga soporte para FreeRTOS.

    La función "task1" es una tarea que incrementa una variable "count" en cada iteración de un bucle while infinito, e imprime el valor de esa variable en la consola utilizando la función "printf" de la librería estándar de C. Después, verifica si la variable "count" ha superado un valor de 5 y en ese caso, elimina la tarea actual utilizando la función "vTaskDelete".

    La función "app_main" es la función principal del programa y es donde se crea la tarea "task1" utilizando la función "xTaskCreate". Esta función toma como argumentos el nombre de la tarea, el tamaño de la pila de la tarea (en este caso 4096 bytes), el argumento que se pasará a la tarea (en este caso NULL), la prioridad de la tarea (en este caso 10), y un puntero a una variable "TaskHandle_t" que se utilizará para hacer referencia a la tarea creada.

    En resumen, este código crea una tarea "task1" que se ejecutará indefinidamente, incrementando una variable "count" y mostrando su valor en la consola hasta que esa variable supera un valor de 5. La tarea se elimina en ese momento y el programa termina.

      Edward John Rodriguez Soto

      Edward John Rodriguez Soto

      student•
      hace 3 años

      Excelente respuesta de ChatGPT : )

      José Alberto Raygada Agüero

      José Alberto Raygada Agüero

      student•
      hace 2 años

      La otra opción para terminar el modo "monitor" es la combinaciòn ctrl + t + x

    Harrison Malagon

    Harrison Malagon

    student•
    hace 3 años

    Comarto mi codigo:

    #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" TaskHandle_t taskHandle1 = NULL; void task1(void *args) { int count = 0; while(1){ count++; printf("Task 1, count %d \n", count); if (count > 5){ vTaskDelete(NULL); } } } void app_main(void) { xTaskCreate(task1, "Task1", 4096, NULL, 10, &taskHandle1); }