Multitarea FreeRTOS en un PLC ESP32 con re-join LoRaWAN periódico
Tres tareas, tres prioridades
vTaskDelayUntil para un periodo de 100 ms sin deriva; la telemetría corre a prioridad 1 porque una transmisión LoRa puede tardar legítimamente segundos con spreading factors altos; la tarea de re-join queda entre ambas. En el ESP32 de doble núcleo esta separación sale gratis — y significa que un comando de módem colgado nunca retrasa un paro de bomba.El re-join horario como watchdog
Compartir estado entre tareas de forma segura
volatile de un solo byte (bomba en marcha, rebose, fallo) y la tarea de telemetría los lee. Las lecturas de un byte son atómicas en el ESP32, así que este patrón no necesita mutex — mantén el estado compartido en bytes sueltos o protégelo, y nunca llames a la radio desde la tarea de control.Un fragmento de la implementación
Tal cual del ejemplo desplegado en el ESP32 PLC 14 / 38AR — cópialo libremente:
void setup() {
Serial.begin(115200);
pinMode(I_FLOAT_MIN, INPUT);
pinMode(I_FLOAT_MAX, INPUT);
pinMode(I_OVERLEVEL, INPUT);
pinMode(I_THERMAL, INPUT);
pinMode(Q_PUMP, OUTPUT);
pinMode(Q_PILOT, OUTPUT);
digitalWrite(Q_PUMP, LOW);
digitalWrite(Q_PILOT, LOW);
lora_init(57600); // RN2xx3 via SerialSC1
lora_join_otaa("APP_EUI", "APP_KEY"); // initial join
// 4096 bytes of stack per task: plenty for digitalRead + AT commands
xTaskCreate(vTaskControl, "control", 4096, NULL, 3, NULL); // 100 ms
xTaskCreate(vTaskLora, "lora", 4096, NULL, 1, NULL); // 60 s
xTaskCreate(vTaskRejoin, "rejoin", 4096, NULL, 2, NULL); // 1 h
}El ejemplo completo es un programa entero — cabecera de conexionado, setup y bucle principal — listo para adaptar a tu aplicación.
Preguntas frecuentes
¿Por qué usar FreeRTOS en lugar de temporizar con millis() en loop()?
Porque una operación de radio bloqueante (join, envío con reintentos) congelaría todo el loop. Con tareas, la lógica de control mantiene su cadencia de 100 ms haga lo que haga el módem.
¿Cada cuánto debería re-hacer el join OTAA?
Una vez por hora es un buen equilibrio para estaciones que envían cada 60 s. Re-hacer el join demasiado a menudo desperdicia airtime y duty cycle; hacerlo demasiado poco significa cortes largos tras una incidencia del gateway.
¿Necesito un mutex para las variables compartidas?
No para flags volatile de un solo byte, que se leen y escriben de forma atómica en el ESP32. Para estructuras de varios bytes, protégelas con un mutex o pásalas por una cola de FreeRTOS.