#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h> // Necessário para usar Mutex
// --- [1] Pinos dos LEDs e Botões ---
const byte ledPins[] = {13, 12, 14, 27}; // Simulação do PORTB
const byte buttonPins[] = {32, 33, 25, 26}; // Simulação do PORTD
const byte NUM_LEDS = 4;
// --- [2] Variável compartilhada e Mutex ---
volatile byte indice_led = 255; // valor inválido inicial
SemaphoreHandle_t xMutex; // identificador do Mutex
// --- [3] Protótipos das tarefas ---
void Ler_botoes(void *pvParameters); // Produtora
void LED_acende(void *pvParameters); // Consumidora
void setup() {
Serial.begin(115200);
Serial.println("Experimento 3 - Atividade 2: Comunicação com Mutex");
for (byte i = 0; i < NUM_LEDS; i++) {
pinMode(ledPins[i], OUTPUT);
pinMode(buttonPins[i], INPUT_PULLDOWN); // botões ligados ao 3V3
}
// --- [4] Criação do Mutex ---
xMutex = xSemaphoreCreateMutex();
if (xMutex != NULL) {
Serial.println("Mutex criado com sucesso.");
// --- [5] Criação das tarefas ---
xTaskCreate(Ler_botoes, "Leitura_Botoes", 2048, NULL, 1, NULL);
xTaskCreate(LED_acende, "Acionamento_LEDs", 2048, NULL, 1, NULL);
} else {
Serial.println("ERRO: falha ao criar o mutex.");
}
}
void loop() {
vTaskDelete(NULL); // FreeRTOS assume controle
}
// --- [6] Tarefa produtora: detecta botão pressionado ---
void Ler_botoes(void *pvParameters) {
for (;;) {
for (byte i = 0; i < NUM_LEDS; i++) {
if (digitalRead(buttonPins[i]) == HIGH) {
Serial.printf("Botão %d pressionado.\n", i);
// Tenta pegar o mutex por apenas 50 ms
if (xSemaphoreTake(xMutex, pdMS_TO_TICKS(50)) == pdTRUE) {
indice_led = i;
xSemaphoreGive(xMutex); // libera o mutex
} else {
Serial.println("⚠️ Mutex ocupado. Botão ignorado.");
}
// Debounce
while (digitalRead(buttonPins[i]) == HIGH) {
vTaskDelay(pdMS_TO_TICKS(20));
}
vTaskDelay(pdMS_TO_TICKS(50));
}
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
// --- [7] Tarefa consumidora: acende o LED conforme valor protegido ---
void LED_acende(void *pvParameters) {
byte copia_indice;
for (;;) {
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
if (indice_led != 255) {
copia_indice = indice_led;
indice_led = 255; // invalida o dado após uso
Serial.printf("LED %d será acionado.\n", copia_indice);
digitalWrite(ledPins[copia_indice], HIGH);
// Simula tarefa longa segurando o mutex (por 2 segundos)
vTaskDelay(pdMS_TO_TICKS(2000));
digitalWrite(ledPins[copia_indice], LOW);
Serial.printf("LED %d apagado.\n", copia_indice);
}
xSemaphoreGive(xMutex); // libera o mutex
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}