ESP-IDF a fondo: proyectos, tareas, logs y particiones

Guía práctica de ESP-IDF: estructura de proyecto, idf.py, menuconfig, tareas de FreeRTOS, logs, particiones OTA y cuándo merece la pena frente a Arduino.

También disponible en: EN, ES

Serie Introducción al ESP32 Parte 12 Ver la serie →
ESP-IDF sobre el ESP32

Si el core de Arduino esconde el ESP32, ESP-IDF lo enseña todo. Es el SDK oficial de Espressif y la base sobre la que se construye todo lo demás. Tiene más curva, sí, pero también te da el control que un producto necesita.

Vamos con lo importante sin perderse en la documentación.

Estructura de un proyecto

mi-proyecto/
├── CMakeLists.txt          # proyecto (casi siempre igual)
├── sdkconfig               # configuración generada
└── main/
    ├── CMakeLists.txt      # registra el main
    └── main.c

El CMakeLists.txt raíz:

cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mi-proyecto)

Y el de main/:

idf_component_register(SRCS "main.c"
                       INCLUDE_DIRS ".")

Los comandos que vas a usar

idf.py set-target esp32s3   # elige el chip
idf.py menuconfig           # configura (Kconfig)
idf.py build                # compila
idf.py flash monitor        # flashea y abre el monitor

menuconfig es una de las mejores cosas de ESP-IDF: cambias opciones (Wi-Fi, logs, particiones, PSRAM) sin tocar el código, y quedan guardadas en sdkconfig.

Hola mundo con logs

#include "esp_log.h"

static const char *TAG = "app";

void app_main(void) {
    ESP_LOGI(TAG, "Arrancando…");
    ESP_LOGW(TAG, "Esto es un aviso");
    ESP_LOGE(TAG, "Y esto un error");
}

Nada de printf: usa los niveles de log. Puedes subir o bajar el nivel por componente desde menuconfig, y en producción apagarlos casi todos.

Tareas: el corazón de ESP-IDF

Aquí está la gran diferencia con Arduino. En lugar de un loop(), creas tareas de FreeRTOS con prioridad y tamaño de pila propios:

void tarea_sensor(void *arg) {
    while (1) {
        leer_sensor();
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void app_main(void) {
    xTaskCreate(tarea_sensor, "sensor", 4096, NULL, 5, NULL);
}

Ventajas reales:

  • Paralelismo de verdad: una tarea mide, otra publica por MQTT.
  • vTaskDelay no bloquea el resto del sistema.
  • Controlas pila y prioridad, que es lo que evita los reinicios raros.

Particiones y OTA

La flash no es un bloque único: está particionada (tabla partitions.csv). Por defecto hay dos ranuras de aplicación (app0 y app1) para poder hacer OTA (actualización por Wi-Fi) con rollback si algo falla.

# Name,   Type, SubType, Offset,  Size
nvs,      data, nvs,     0x9000,  0x4000
factory,  app,  factory, 0x10000, 1M

Ejemplo de partición con OTA:

# Name,   Type, SubType,  Size
nvs,      data, nvs,      0x4000
otadata,  data, ota,      0x2000
phy_init, data, phy,      0x1000
factory,  app,  factory,  1M
ota_0,    app,  ota_0,    1M
ota_1,    app,  ota_1,    1M

Wire: ¿Arduino o ESP-IDF?

Arduino coreESP-IDF
CurvaBajaAlta
ControlMedioTotal
Tareas1 loopN tareas
MemoriaAutomáticaTú decides
OTAFácilCompleto (rollback)
LogsSerialNiveles por componente

Cuándo merece la pena

  • : producto, batería, timing fino, OTA serio, muchos periféricos.
  • No: si solo quieres leer un sensor y publicar, Arduino te lleva en una tarde y te sobra.

Consejo: puedes mezclar. El core de Arduino es ESP-IDF por debajo, así que desde un sketch puedes llamar a APIs de ESP-IDF cuando las necesites.

Resumen

  • ESP-IDF es el SDK oficial: CMake + idf.py + menuconfig.
  • Usa tareas de FreeRTOS, no un loop().
  • Logs por niveles con ESP_LOGx en lugar de printf.
  • La flash está particionada; el OTA con rollback viene casi gratis.
  • Versión actual: 6.1.

Siguiente paso: MicroPython y Lua para el extremo opuesto: cero compilación. O vuelve al hub de la serie.

Entradas relacionadas

↑↓ navegar ↵ abrir Esc cerrar