/* Sistema de Controle de Iluminação Pública - ESP32 (FreeRTOS)
Autor: Adilson Silva (adaptado)
Pinos obedecem ao seu esquema:
LDR -> GPIO34 (ADC)
PIR -> GPIO2
LEDV -> GPIO23 (vermelho - emergência)
LEDA -> GPIO22 (amarelo - noite)
LEDG -> GPIO21 (verde - dia)
BOTAO-> GPIO19 (INPUT_PULLUP)
*/
#include <Arduino.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
/* --- Pinos --- */
const int LDR_PIN = 34;
const int PIR_PIN = 2;
const int LED_VERMELHO = 23;
const int LED_AMARELO = 22;
const int LED_VERDE = 21;
const int BOTAO_PIN = 19;
/* --- Parâmetros de tempo --- */
const TickType_t PERIODO_LDR_MS = pdMS_TO_TICKS(5000); // 5 s
const TickType_t PIR_POLL_MS = pdMS_TO_TICKS(50);
const TickType_t BUTTON_POLL_MS = pdMS_TO_TICKS(10);
const TickType_t DEBOUNCE_MS = pdMS_TO_TICKS(200);
/* --- Threshold LDR --- */
const int LDR_THRESHOLD = 10;
/* --- Flags globais --- */
volatile bool emergenciaManual = false;
volatile bool pirDetectado = false;
/* --- Mutex --- */
SemaphoreHandle_t xLedMutex;
/* --- Controle de LEDs --- */
void ledsDia() {
digitalWrite(LED_VERDE, HIGH);
digitalWrite(LED_AMARELO, LOW);
digitalWrite(LED_VERMELHO, LOW);
}
void ledsNoite() {
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_AMARELO, HIGH);
digitalWrite(LED_VERMELHO, LOW);
}
void ledsEmergenciaManual() {
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_AMARELO, LOW);
digitalWrite(LED_VERMELHO, HIGH);
}
void ledsEventoNoturno() {
digitalWrite(LED_VERDE, HIGH);
digitalWrite(LED_AMARELO, HIGH);
digitalWrite(LED_VERMELHO, HIGH);
}
/* -----------------------------------------------------------
Task periódica: leitura do LDR a cada 5s (decide dia/noite)
----------------------------------------------------------- */
void vTaskLDR(void* pvParameters) {
(void) pvParameters;
for (;;) {
int valorLDR = analogRead(LDR_PIN); // 0..4095
if (xSemaphoreTake(xLedMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
if (emergenciaManual) {
ledsEmergenciaManual();
} else if (pirDetectado) {
ledsEventoNoturno();
} else {
// Condição explícita pedida:
if (valorLDR > 100) { // DIA
ledsDia();
} else if (valorLDR <= 100) { // NOITE
ledsNoite();
}
}
xSemaphoreGive(xLedMutex);
}
Serial.print("LDR=");
Serial.print(valorLDR);
Serial.print(" | Manual=");
Serial.print(emergenciaManual ? "SIM" : "NAO");
Serial.print(" | PIR=");
Serial.println(pirDetectado ? "SIM" : "NAO");
vTaskDelay(PERIODO_LDR_MS); // 5s
}
}
/* -----------------------------------------------------------
Task esporádica: monitora PIR
----------------------------------------------------------- */
void vTaskPIR(void* pvParameters) {
(void) pvParameters;
for (;;) {
int estado = digitalRead(PIR_PIN);
if (estado == HIGH) {
pirDetectado = true;
if (xSemaphoreTake(xLedMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
if (emergenciaManual) ledsEmergenciaManual();
else ledsEventoNoturno();
xSemaphoreGive(xLedMutex);
}
while (digitalRead(PIR_PIN) == HIGH) {
vTaskDelay(PIR_POLL_MS);
}
pirDetectado = false;
}
vTaskDelay(PIR_POLL_MS);
}
}
/* -----------------------------------------------------------
Task do botão manual
----------------------------------------------------------- */
void vTaskBotao(void* pvParameters) {
(void) pvParameters;
int estadoAnteriorRaw = HIGH;
for (;;) {
int leituraRaw = digitalRead(BOTAO_PIN);
bool botaoAtivo = (leituraRaw == LOW);
if (botaoAtivo && estadoAnteriorRaw == HIGH) {
vTaskDelay(DEBOUNCE_MS);
if (digitalRead(BOTAO_PIN) == LOW) {
emergenciaManual = !emergenciaManual;
Serial.println(emergenciaManual ? "Emergência MANUAL ATIVADA" : "Emergência MANUAL DESATIVADA");
if (xSemaphoreTake(xLedMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
if (emergenciaManual) ledsEmergenciaManual();
else {
if (pirDetectado) ledsEventoNoturno();
else {
int ldrNow = analogRead(LDR_PIN);
if (ldrNow > 10) ledsDia();
else ledsNoite();
}
}
xSemaphoreGive(xLedMutex);
}
}
}
estadoAnteriorRaw = leituraRaw;
vTaskDelay(BUTTON_POLL_MS);
}
}
void setup() {
Serial.begin(115200);
pinMode(LDR_PIN, INPUT);
pinMode(PIR_PIN, INPUT);
pinMode(BOTAO_PIN, INPUT_PULLUP);
pinMode(LED_VERMELHO, OUTPUT);
pinMode(LED_AMARELO, OUTPUT);
pinMode(LED_VERDE, OUTPUT);
digitalWrite(LED_VERMELHO, LOW);
digitalWrite(LED_AMARELO, LOW);
digitalWrite(LED_VERDE, LOW);
xLedMutex = xSemaphoreCreateMutex();
if (xLedMutex == NULL) {
Serial.println("Erro: não foi possível criar mutex!");
while (1) delay(1000);
}
xTaskCreatePinnedToCore(vTaskLDR, "LDR_Task", 4096, NULL, 1, NULL, 0);
xTaskCreatePinnedToCore(vTaskPIR, "PIR_Task", 2048, NULL, 2, NULL, 1);
xTaskCreatePinnedToCore(vTaskBotao, "Botao_Task", 2048, NULL, 2, NULL, 1);
Serial.println("Sistema iniciado com FreeRTOS (ESP32)");
}
void loop() {
vTaskDelay(pdMS_TO_TICKS(1000));
}