Atividade 2 versao 1.0

This commit is contained in:
2026-01-26 18:24:20 -03:00
commit 947dea7851
12 changed files with 1607 additions and 0 deletions

429
src/esp32-ntp-clock.ino Normal file
View File

@@ -0,0 +1,429 @@
// ============================================================================
// Sistema de monitoramento de cozinha com ESP32
// Monitora temperatura, umidade e gás com detecção avançada de incêndio
// Envia dados via MQTT e controla coifa e ar-condicionado
// ============================================================================
// INCLUDES
#include <DHT.h> // Sensor DHT22
#include <PubSubClient.h> // MQTT
#include <RTClib.h> // RTC DS1307
#include <WiFi.h> // WiFi
// ============================================================================
// DEFINES - Pinos GPIO
// ============================================================================
#define DHTPIN 32 // Sensor DHT22 (temperatura/umidade)
#define DHTTYPE DHT22 // Tipo sensor DHT
#define MQ2PIN 33 // Sensor MQ2 (qualidade do ar/gás)
#define ALARME_SONORO 4 // Alarme sonoro
#define COIFA 17 // Coifa (exaustor)
#define AR_CONDICIONADO 16 // Ar-condicionado
// ============================================================================
// ENUMS
// ============================================================================
enum statusCozinha {
NOMINAL, // Sem alerta
GAS, // Detecção de gás
TEMP_ALTA, // Temperatura acima do limite
UMIDADE_ALTA, // Umidade acima do limite
INCENDIO // Possível incêndio (padrão: ΔT > 5°C + Δumidade < -10% em 30s)
};
// ============================================================================
// CONSTANTES - Limiares de alarme
// ============================================================================
const int GAS_ON = 940; // Ativação gás (~1000ppm)
const int GAS_OFF = 916; // Desativação gás (~500ppm)
const float TEMP_ON_DEFAULT = 30.0; // Temperatura máxima padrão (°C)
const float TEMP_HISTERESE = 2.0; // Histerese temperatura
const float UMIDADE_ON_DEFAULT = 70.0; // Umidade máxima padrão (%)
const float UMIDADE_HISTERESE = 5.0; // Histerese umidade
// Detecção de incêndio
const uint32_t JANELA_TEMPO_INCENDIO = 30; // Janela: 30 segundos
const float DELTA_TEMP_INCENDIO = 5.0; // Aumento mínimo: 5°C
const float DELTA_UMIDADE_INCENDIO = -10.0; // Queda mínima: -10%
// ============================================================================
// CONSTANTES - WiFi e MQTT
// ============================================================================
const char* WIFI_SSID = "Wokwi-GUEST";
const char* WIFI_PASSWORD = "";
const char* MQTT_BROKER = "77.37.69.84";
const int MQTT_PORT = 1883;
const char* MQTT_SUB_TOPICS[] = { "cozinha/max_tmp", "cozinha/max_umi" };
const char* MQTT_PUB_TOPIC = "cozinha";
const int MQTT_SUB_COUNT = sizeof(MQTT_SUB_TOPICS) / sizeof(MQTT_SUB_TOPICS[0]);
// ============================================================================
// VARIÁVEIS GLOBAIS - Objetos
// ============================================================================
DHT dht(DHTPIN, DHTTYPE);
RTC_DS1307 RTC;
WiFiClient espClient;
PubSubClient mqtt(espClient);
DateTime now;
// ============================================================================
// VARIÁVEIS GLOBAIS - Estado do sistema
// ============================================================================
int alarmStatus = NOMINAL;
float umidade = 0.0;
float temperatura = 0.0;
int iqAR = 0;
// Variáveis de configuração (atualizáveis via MQTT)
float TEMP_ON = TEMP_ON_DEFAULT;
float TEMP_OFF = TEMP_ON - TEMP_HISTERESE;
float UMIDADE_ON = UMIDADE_ON_DEFAULT;
float UMIDADE_OFF = UMIDADE_ON - UMIDADE_HISTERESE;
// Variáveis para detecção de incêndio
float temp_inicio = 0.0;
float umidade_inicio = 0.0;
uint32_t timestamp_inicio = 0;
// Buffer MQTT
char msg[256];
char MQTT_CLIENTID[32];
// ============================================================================
// FUNÇÕES AUXILIARES - Callbacks MQTT
// ============================================================================
void mqttCallback(char* topic, byte* payload, unsigned int length)
{
Serial.print("[MQTT] Mensagem em [");
Serial.print(topic);
Serial.println("]");
// Copia payload para buffer null-terminated
char buf[64];
int n = (length < (int)sizeof(buf) - 1) ? length : (int)sizeof(buf) - 1;
memcpy(buf, payload, n);
buf[n] = '\0';
Serial.print("[MQTT] payload: ");
Serial.println(buf);
// Processa tópicos
if (strcmp(topic, "cozinha/max_tmp") == 0) {
float v = atof(buf);
if (!isnan(v)) {
TEMP_ON = v;
TEMP_OFF = TEMP_ON - TEMP_HISTERESE;
Serial.print("[MQTT] TEMP_ON = ");
Serial.println(TEMP_ON);
}
} else if (strcmp(topic, "cozinha/max_umi") == 0) {
float v = atof(buf);
if (!isnan(v)) {
UMIDADE_ON = v;
UMIDADE_OFF = UMIDADE_ON - UMIDADE_HISTERESE;
Serial.print("[MQTT] UMIDADE_ON = ");
Serial.println(UMIDADE_ON);
}
}
}
// ============================================================================
// FUNÇÕES AUXILIARES - Conectividade
// ============================================================================
// Conecta o ESP32 à rede WiFi
void connectWiFi()
{
Serial.print("[WiFi] Conectando...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
Serial.println("\r\n[WiFi] Conectado!");
}
// Inscreve em tópicos MQTT para receber atualizações de limiares
void mqttSubscribe()
{
Serial.println("[MQTT] Conectado!");
for (int i = 0; i < MQTT_SUB_COUNT; ++i) {
if (mqtt.subscribe(MQTT_SUB_TOPICS[i])) {
Serial.print("[MQTT] Tópico: ");
Serial.println(MQTT_SUB_TOPICS[i]);
}
}
}
// Conecta ao broker MQTT
void connectMQTT()
{
mqtt.setServer(MQTT_BROKER, MQTT_PORT);
mqtt.setCallback(mqttCallback);
while (!mqtt.connected()) {
Serial.println("[MQTT] Conectando...");
if (mqtt.connect(MQTT_CLIENTID)) {
mqttSubscribe();
break;
} else {
Serial.print("[MQTT] Falha rc=");
Serial.println(mqtt.state());
delay(2000);
}
}
}
// ============================================================================
// FUNÇÕES AUXILIARES - Sensores
// ============================================================================
// Lê valores de temperatura e umidade do sensor DHT22
void read_DHT()
{
umidade = dht.readHumidity();
temperatura = dht.readTemperature();
if (isnan(umidade) || isnan(temperatura)) {
Serial.println("[DHT] Erro na leitura!");
umidade = 0.0;
temperatura = 0.0;
}
}
void read_MQ2()
{
iqAR = analogRead(MQ2PIN);
}
// ============================================================================
// FUNÇÕES - Detecção de alarmes
// ============================================================================
// Detecta padrão de possível incêndio: aumento de temperatura > 5°C + queda de umidade > 10% em 30 segundos
void detect_fire()
{
// Inicializa janela de monitoramento na primeira chamada
if (temp_inicio == 0.0) {
temp_inicio = temperatura;
umidade_inicio = umidade;
timestamp_inicio = now.secondstime();
return;
}
// Calcula tempo decorrido
uint32_t tempo_decorrido = now.secondstime() - timestamp_inicio;
// Verifica padrão de incêndio a cada 30 segundos
if (tempo_decorrido >= JANELA_TEMPO_INCENDIO) {
float delta_temp = temperatura - temp_inicio;
float delta_umidade = umidade - umidade_inicio;
// Debug: exibe deltas
Serial.print("[INCENDIO] ΔT: ");
Serial.print(delta_temp);
Serial.print("°C | ΔUmidade: ");
Serial.print(delta_umidade);
Serial.println("%");
// Verifica condições críticas
if (delta_temp > DELTA_TEMP_INCENDIO && delta_umidade < DELTA_UMIDADE_INCENDIO) {
Serial.println("[ALERTA] INCÊNDIO DETECTADO!");
alarmStatus = INCENDIO;
}
// Reseta janela
temp_inicio = temperatura;
umidade_inicio = umidade;
timestamp_inicio = now.secondstime();
}
}
// Verifica qual alarme deve ser ativado baseado nos limites
void check_alarm()
{
// Atualiza RTC
now = RTC.now();
// Detecção de incêndio (máxima prioridade)
detect_fire();
if (alarmStatus == INCENDIO) {
return;
}
// Verifica gás
if (alarmStatus == GAS) {
if (iqAR <= GAS_OFF) {
alarmStatus = NOMINAL;
}
} else if (iqAR > GAS_ON) {
alarmStatus = GAS;
return;
}
// Verifica umidade
if (alarmStatus == UMIDADE_ALTA) {
if (umidade <= UMIDADE_OFF) {
alarmStatus = NOMINAL;
}
} else if (umidade > UMIDADE_ON) {
alarmStatus = UMIDADE_ALTA;
return;
}
// Verifica temperatura
if (alarmStatus == TEMP_ALTA) {
if (temperatura <= TEMP_OFF) {
alarmStatus = NOMINAL;
}
} else if (temperatura > TEMP_ON) {
alarmStatus = TEMP_ALTA;
return;
}
// Nenhum alarme ativo
if (alarmStatus != GAS && alarmStatus != UMIDADE_ALTA
&& alarmStatus != TEMP_ALTA) {
alarmStatus = NOMINAL;
}
}
// ============================================================================
// FUNÇÕES - Leitura e publicação
// ============================================================================
// Realiza leitura de todos os sensores e publica dados via MQTT
void leitura_sensores()
{
read_DHT();
read_MQ2();
// Formata e publica via MQTT
snprintf(msg, sizeof(msg),
"{\"tmp\": %.2f, \"umi\": %.2f, \"gas\": %d, \"alarme\": %d}",
temperatura, umidade, iqAR, alarmStatus);
Serial.print("[MQTT] Publicando: ");
Serial.println(msg);
mqtt.publish(MQTT_PUB_TOPIC, msg);
// Verifica alarmes
check_alarm();
}
// Processa ativação de periféricos baseado no alarme
void processa_alarme()
{
// Desativa todos antes de processar
digitalWrite(ALARME_SONORO, LOW);
digitalWrite(COIFA, LOW);
digitalWrite(AR_CONDICIONADO, LOW);
if (alarmStatus == NOMINAL) {
return;
}
// Ativa periféricos conforme alarme
switch (alarmStatus) {
case INCENDIO:
digitalWrite(ALARME_SONORO, HIGH);
digitalWrite(COIFA, HIGH);
digitalWrite(AR_CONDICIONADO, HIGH);
Serial.println("[ALARME] INCÊNDIO!");
break;
case GAS:
digitalWrite(ALARME_SONORO, HIGH);
digitalWrite(COIFA, HIGH);
Serial.println("[ALARME] GÁS DETECTADO!");
break;
case UMIDADE_ALTA:
digitalWrite(COIFA, HIGH);
Serial.println("[ALARME] UMIDADE ALTA!");
break;
case TEMP_ALTA:
digitalWrite(AR_CONDICIONADO, HIGH);
Serial.println("[ALARME] TEMPERATURA ALTA!");
break;
default:
break;
}
}
// ============================================================================
// FUNÇÕES - Inicialização
// ============================================================================
void rtc_setup()
{
if (!RTC.begin()) {
Serial.println("[RTC] Erro: não encontrado!");
while (1)
delay(1000);
}
Serial.println("[RTC] Inicializado");
}
// Inicializa o ESP32 e configura os periféricos
void setup()
{
Serial.begin(115200);
delay(100);
Serial.println("\n[SETUP] Iniciando sistema...");
// Inicializa DHT
dht.begin();
Serial.println("[DHT] Inicializado");
// Gera ID único MQTT
snprintf(MQTT_CLIENTID, sizeof(MQTT_CLIENTID), "esp32_%08X",
(uint32_t)(ESP.getEfuseMac() & 0xFFFFFFFF));
// Configura ADC
analogReadResolution(10);
// Configura pinos
pinMode(ALARME_SONORO, OUTPUT);
pinMode(COIFA, OUTPUT);
pinMode(AR_CONDICIONADO, OUTPUT);
pinMode(MQ2PIN, INPUT);
pinMode(DHTPIN, INPUT);
// Desativa todos os atuadores
digitalWrite(ALARME_SONORO, LOW);
digitalWrite(COIFA, LOW);
digitalWrite(AR_CONDICIONADO, LOW);
// Conecta
connectWiFi();
connectMQTT();
rtc_setup();
// Primeira leitura
now = RTC.now();
leitura_sensores();
Serial.println("[SETUP] Pronto!\n");
}
// ============================================================================
// LOOP PRINCIPAL
// ============================================================================
// Loop principal - executa continuamente
void loop()
{
// Verifica MQTT
if (!mqtt.connected()) {
connectMQTT();
}
mqtt.loop();
// Lê sensores
leitura_sensores();
// Processa alarme
processa_alarme();
// Aguarda 2 segundos
unsigned long start = millis();
while (millis() - start < 2000UL) {
mqtt.loop();
delay(10);
}
}