3.4 Build : producer-consumer pattern

5. 3.4 Build : producer-consumer pattern

Pattern complet — capteur → queue → affichage avec mutex :

// src/main.c

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_log.h"

typedef struct {
    float    temperature;
    float    humidity;
    uint32_t timestamp_ms;
} sensor_data_t;

static QueueHandle_t     xQueueSensorData;
static SemaphoreHandle_t xMutexDisplay;

// Producteur — simule la lecture DHT22 toutes les 2s
static void task_producer(void *pv) {
    TickType_t    xLastWake = xTaskGetTickCount();
    sensor_data_t data;

    while (1) {
        data.temperature = 22.5f + (rand() % 10) * 0.1f;  // simulé
        data.humidity     = 45.0f + (rand() % 20) * 0.1f;
        data.timestamp_ms = xTaskGetTickCount();

        if (xQueueSend(xQueueSensorData, &data, pdMS_TO_TICKS(10)) != pdTRUE) {
            ESP_LOGW("PRODUCER", "Queue full — data dropped");
        }
        vTaskDelayUntil(&xLastWake, pdMS_TO_TICKS(2000));
    }
    vTaskDelete(NULL);
}

// Consommateur — attend les données, protège l'affichage avec mutex
static void task_consumer(void *pv) {
    sensor_data_t data;

    while (1) {
        if (xQueueReceive(xQueueSensorData, &data, pdMS_TO_TICKS(5000)) == pdTRUE) {
            if (xSemaphoreTake(xMutexDisplay, pdMS_TO_TICKS(50)) == pdTRUE) {
                ESP_LOGI("DISPLAY", "Temp: %.1f C  Hum: %.1f %%  @%" PRIu32 "ms",
                         data.temperature, data.humidity, data.timestamp_ms);
                xSemaphoreGive(xMutexDisplay);
            }
        } else {
            ESP_LOGW("CONSUMER", "No data in 5s — is the sensor task alive?");
        }
    }
    vTaskDelete(NULL);
}

void app_main(void) {
    xQueueSensorData = xQueueCreate(5, sizeof(sensor_data_t));
    xMutexDisplay    = xSemaphoreCreateMutex();

    xTaskCreate(task_producer, "producer", 4096, NULL, 4, NULL);
    xTaskCreate(task_consumer, "consumer", 4096, NULL, 2, NULL);
}

Exercice : Ajouter une tâche task_logger (priorité 1) qui conserve un buffer circulaire de 20 entrées sensor_data_t et affiche l'historique sur xSemaphoreGive(xSemPrintHistory) (sémaphore binaire déclenché par un bouton GPIO).

Soumettez l'implémentation avec une capture série montrant l'historique affiché au moins une fois.

Se connecter pour suivre votre progression.