#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include <DHT.h>
#include <Wire.h>
#include "RTClib.h"
#define MQ2_PIN 35
#define CS_PIN 5
#define DHT_PIN 4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
RTC_DS3231 rtc;
File file;
typedef struct {
float temperatura;
float umidade;
int fumaca;
DateTime timestamp;
} DadosSensor;
typedef struct {
DadosSensor dados;
char statusTemp[64];
char statusUmid[64];
char statusFumaca[64];
} DadosCompletos;
QueueHandle_t filaMQ2;
QueueHandle_t filaDHT;
QueueHandle_t filaLog;
QueueHandle_t filaPrint;
void avaliarFumaca(int valor, char* buffer, size_t size) {
if (valor > 2500) snprintf(buffer, size, "Alerta Critico - Risco de incendio");
else if (valor > 1000) snprintf(buffer, size, "Atencao");
else snprintf(buffer, size, "Normal");
}
void avaliarTemperatura(float valor, char* buffer, size_t size) {
if (valor > 45) snprintf(buffer, size, "Alerta Critico - Risco de incendio");
else if (valor >= 35) snprintf(buffer, size, "Atencao");
else snprintf(buffer, size, "Normal");
}
void avaliarUmidade(float valor, char* buffer, size_t size) {
if (valor > 80) snprintf(buffer, size, "Alerta Critico - Chuva forte");
else if (valor >= 60) snprintf(buffer, size, "Atencao");
else snprintf(buffer, size, "Normal");
}
void setup() {
Serial.begin(115200);
dht.begin();
if (!rtc.begin()) {
Serial.println("Erro no RTC!");
while (true);
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
if (!SD.begin(CS_PIN)) {
Serial.println("Falha no cartão SD!");
while (true);
}
filaMQ2 = xQueueCreate(5, sizeof(DadosSensor));
filaDHT = xQueueCreate(5, sizeof(DadosSensor));
filaLog = xQueueCreate(5, sizeof(DadosCompletos));
filaPrint = xQueueCreate(5, sizeof(DadosCompletos));
if (!filaMQ2 || !filaDHT || !filaLog || !filaPrint) {
Serial.println("Erro ao criar as filas!");
while (true);
}
xTaskCreatePinnedToCore(TaskLeituraMQ2, "LeituraMQ2", 2048, NULL, 3, NULL, 0);
xTaskCreatePinnedToCore(TaskLeituraDHT, "LeituraDHT", 2048, NULL, 3, NULL, 1);
xTaskCreatePinnedToCore(TaskAgregadora, "Agregadora", 4096, NULL, 2, NULL, 1);
xTaskCreatePinnedToCore(TaskLogSD, "LogSD", 4096, NULL, 2, NULL, 1);
xTaskCreatePinnedToCore(TaskPrintSerial, "PrintSerial", 4096, NULL, 1, NULL, 0);
xTaskCreatePinnedToCore(TaskRTC, "RTC", 2048, NULL, 2, NULL, 1);
}
void loop() {}
void TaskLeituraMQ2(void *pvParameters) {
while (true) {
int fumaca = analogRead(MQ2_PIN);
DateTime agora = rtc.now();
DadosSensor dados = {0};
dados.fumaca = fumaca;
dados.timestamp = agora;
xQueueSend(filaMQ2, &dados, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
void TaskLeituraDHT(void *pvParameters) {
while (true) {
float temp = dht.readTemperature();
float umid = dht.readHumidity();
if (!isnan(temp) && !isnan(umid)) {
DateTime agora = rtc.now();
DadosSensor dados = {0};
dados.temperatura = temp;
dados.umidade = umid;
dados.timestamp = agora;
xQueueSend(filaDHT, &dados, portMAX_DELAY);
}
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
void TaskAgregadora(void *pvParameters) {
DadosSensor dadosMQ2;
DadosSensor dadosDHT;
DadosCompletos dadosCompletos;
while (true) {
if (xQueueReceive(filaMQ2, &dadosMQ2, portMAX_DELAY)) {
if (xQueueReceive(filaDHT, &dadosDHT, pdMS_TO_TICKS(1000))) {
dadosCompletos.dados.temperatura = dadosDHT.temperatura;
dadosCompletos.dados.umidade = dadosDHT.umidade;
dadosCompletos.dados.fumaca = dadosMQ2.fumaca;
dadosCompletos.dados.timestamp = dadosDHT.timestamp;
avaliarTemperatura(dadosCompletos.dados.temperatura, dadosCompletos.statusTemp, sizeof(dadosCompletos.statusTemp));
avaliarUmidade(dadosCompletos.dados.umidade, dadosCompletos.statusUmid, sizeof(dadosCompletos.statusUmid));
avaliarFumaca(dadosCompletos.dados.fumaca, dadosCompletos.statusFumaca, sizeof(dadosCompletos.statusFumaca));
xQueueSend(filaLog, &dadosCompletos, portMAX_DELAY);
xQueueSend(filaPrint, &dadosCompletos, portMAX_DELAY);
}
}
}
}
void TaskLogSD(void *pvParameters) {
DadosCompletos dados;
while (true) {
if (xQueueReceive(filaLog, &dados, portMAX_DELAY)) {
file = SD.open("/dados.txt", FILE_APPEND);
if (file) {
char linha[256];
snprintf(linha, sizeof(linha), "%02d/%02d/%04d %02d:%02d:%02d, Temperatura - %.1f, %s, Umidade - %.1f, %s, Fumaca - %d, %s\n",
dados.dados.timestamp.day(), dados.dados.timestamp.month(), dados.dados.timestamp.year(),
dados.dados.timestamp.hour(), dados.dados.timestamp.minute(), dados.dados.timestamp.second(),
dados.dados.temperatura, dados.statusTemp,
dados.dados.umidade, dados.statusUmid,
dados.dados.fumaca, dados.statusFumaca);
file.print(linha);
file.close();
} else {
Serial.println("Erro ao abrir arquivo no SD!");
}
}
}
}
void TaskPrintSerial(void *pvParameters) {
DadosCompletos dados;
while (true) {
if (xQueueReceive(filaPrint, &dados, portMAX_DELAY)) {
char linha[512];
snprintf(linha, sizeof(linha),
"%02d/%02d/%04d %02d:%02d:%02d | Temp: %.1f°C (%s), Umid: %.1f%% (%s), Fumaca: %d (%s)",
dados.dados.timestamp.day(), dados.dados.timestamp.month(), dados.dados.timestamp.year(),
dados.dados.timestamp.hour(), dados.dados.timestamp.minute(), dados.dados.timestamp.second(),
dados.dados.temperatura, dados.statusTemp,
dados.dados.umidade, dados.statusUmid,
dados.dados.fumaca, dados.statusFumaca);
Serial.println(linha);
}
}
}
void TaskRTC(void *pvParameters) {
while (true) {
vTaskDelay(pdMS_TO_TICKS(60000));
}
}