/* -- Queue Macros -- */
#define QUEUE_MAX 5
#define QUEUE_STACK_SIZE 1000
#define QUEUE_NO_WAIT 0
/* -- Estados y eventos del esp-32 -- */
enum states
{
ST_INIT,
ST_IDLE,
ST_IDLE_NIGHT,
ST_LOW_ON_WATER,
ST_DRAWING_WATER,
ST_FEEDING_FISHES,
};
enum events
{
EV_CAPTURED,
EV_MQTT_RESPONSE
};
const String g_states_str[] = {
"ST_INIT", "ST_IDLE", "ST_IDLE_NIGHT",
"ST_LOW_ON_WATER", "ST_DRAWING_WATER", "ST_FEEDING_FISHES",
};
const String g_events_str[] = {
"EV_CAPTURED", "EV_MQTT_RESPONSE"
};
enum states g_current_state = ST_DRAWING_WATER;
enum events g_new_event = EV_CAPTURED;
/* -- FreeRTOS variables -- */
QueueHandle_t queue_to_esp;
QueueHandle_t queue_to_mqtt;
TaskHandle_t xMqttHandle;
void setup()
{
Serial.begin(9600);
// Esto es solo para asegurarnos que se asigne la tarea el core vacio.
byte idle_core = (xPortGetCoreID() + 1) % 2;
// Esta queue le envia los eventos a la esp-32
queue_to_esp = xQueueCreate(QUEUE_MAX, sizeof(enum events));
// Esta queue envia el nuevo estado de la esp-32
queue_to_mqtt = xQueueCreate(QUEUE_MAX, sizeof(enum states));
if (queue_to_esp == NULL || queue_to_mqtt == NULL)
{
Serial.println("[Error] - No se pudieron crear las colas de mensajes.");
}
BaseType_t xReturned = xTaskCreatePinnedToCore(
mqtt_task, // Funcion que utiliza la tarea.
"mqtt task", // Nombre de la tarea.
QUEUE_STACK_SIZE, // Stack size en palabras (en esp-32 las palabras son de 32 bits).
NULL, // Argumentos para la tarea.
tskIDLE_PRIORITY, // Prioridad de la tarea.
&xMqttHandle, // Task handle.
idle_core // Core en el que se ejecuta.
);
if (xReturned != pdPASS)
{
Serial.println("[Error] - No se pudo crear tarea en el otro nucleo.");
}
}
void loop()
{
delay(1050);
BaseType_t xReturned = xQueueReceive(queue_to_esp, &(g_new_event), (TickType_t) QUEUE_NO_WAIT);
if (xReturned != pdPASS)
{
Serial.println("[Warning] - Cola de mensajes del nucleo secundario vacia.");
}
else
{
Serial.print("Mensaje recibido: ");
Serial.println(g_events_str[g_new_event]);
// El nuevo evento va a disparar alguna accion...
}
delay(500);
// Hace otras cosas...
// Cambiamos de estado, por lo cual notificamos al core de mqtt para que envie el nuevo estado.
xReturned = xQueueSend(queue_to_mqtt, (void *) &g_current_state, (TickType_t) QUEUE_NO_WAIT);
if (xReturned != pdPASS)
{
Serial.println("[Error] - No se pudo enviar el mensaje al nucleo secundario.");
}
else
{
Serial.println("Mensaje enviado al nucleo secundario!");
}
}
void mqtt_task(void* pvParameters)
{
enum events tmp_event = EV_MQTT_RESPONSE;
enum states tmp_state = ST_IDLE;
BaseType_t xReturned;
while (true) // Loop infinito a sino la tarea terminaria.
{
delay(500);
// Recibimos un mensaje desde mqtt...
// Notificamos al core del esp-32 sobre este evento.
xReturned = xQueueSend(queue_to_esp, (void *) &tmp_event, (TickType_t) QUEUE_NO_WAIT);
if (xReturned != pdPASS)
{
Serial.println("[Error] - No se pudo enviar el mensaje al nucleo principal.");
}
else
{
Serial.println("Mensaje enviado al nucleo principal!");
}
delay(1000);
xReturned = xQueueReceive(queue_to_mqtt, &(tmp_state), (TickType_t) QUEUE_NO_WAIT);
if (xReturned != pdPASS)
{
Serial.println("[Warning] - Cola de mensajes del nucleo principal vacia.");
}
else
{
Serial.print("Publicando mensaje: ");
Serial.println(g_states_str[tmp_state]);
// Enviamos el nuevo estado al mqtt...
}
}
}
/* -- Bibliografia -- */
// https://esp32tutorials.com/esp32-esp-idf-freertos-queue-tutorial/
// https://www.freertos.org/a00018.html
// https://randomnerdtutorials.com/esp32-dual-core-arduino-ide/