#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <RTClib.h>
// --- Definições de pinos ---
#define DHTPIN 15
#define DHTTYPE DHT22
#define MQ2_PIN 34
#define RED_LED 27
#define GREEN_LED 26
#define YELLOW_LED 12
#define BUZZER_PIN 13
// --- Objetos dos dispositivos ---
DHT dht(DHTPIN, DHTTYPE);
RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 20, 4);
// --- Wi-Fi e MQTT ---
const char* SSID = "Wokwi-GUEST"; // Ajuste para seu SSID
const char* PASSWORD = ""; // Ajuste sua senha WiFi
const char* BROKER_MQTT = "20.9.131.82"; // IP do broker MQTT
int BROKER_PORT = 1883;
const char* ID_MQTT = "esp32_nexus_01";
const char* TOPICO_PUBLISH_GAS = "/TEF/NEXUScode/attrs/g";
const char* TOPICO_PUBLISH_HUM = "/TEF/NEXUScode/attrs/h";
const char* TOPICO_PUBLISH_TEMP = "/TEF/NEXUScode/attrs/t";
WiFiClient espClient;
PubSubClient MQTT(espClient);
// --- Variáveis de estado ---
bool estadoPerigo = false;
bool ultimoPerigoGas = false;
bool ultimoPerigoTemp = false;
bool ultimoPerigoUmi = false;
bool estadoAtencao = false;
// --- Cálculo estimado de PPM usando map ---
float calculatePPM(int adcValue) {
// Mapeia ADC (0–4095) para PPM estimado (0–1000)
return ((float)adcValue / 4095.0) * 1000.0;
}
// --- Função para conectar WiFi ---
void conectaWiFi() {
Serial.print("Conectando-se ao WiFi: ");
Serial.println(SSID);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWiFi conectado!");
Serial.println(WiFi.localIP());
}
// --- Função para conectar MQTT ---
void conectaMQTT() {
while (!MQTT.connected()) {
Serial.print("Conectando ao MQTT...");
if (MQTT.connect(ID_MQTT)) {
Serial.println("Conectado!");
} else {
Serial.print("Falha. Código: ");
Serial.println(MQTT.state());
delay(2000);
}
}
}
void setup() {
Serial.begin(9600);
dht.begin();
lcd.init();
lcd.backlight();
if (!rtc.begin()) {
Serial.println("RTC não encontrado!");
while (1);
}
pinMode(MQ2_PIN, INPUT);
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, LOW);
digitalWrite(YELLOW_LED, LOW);
noTone(BUZZER_PIN);
conectaWiFi();
MQTT.setServer(BROKER_MQTT, BROKER_PORT);
}
void loop() {
if (!MQTT.connected()) conectaMQTT();
MQTT.loop();
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
int gasADC = analogRead(MQ2_PIN);
float gasPPM = calculatePPM(gasADC);
DateTime now = rtc.now();
bool perigoGas = gasPPM > 500.0;
bool perigoTemp = temperature > 30.0;
bool perigoUmi = humidity > 80.0;
bool atencaoGas = gasPPM > 300.0 && gasPPM <= 500.0;
bool atencaoTemp = temperature >= 25.0 && temperature <= 30.0;
bool atencaoUmi = humidity >= 70.0 && humidity <= 80.0;
bool mudouTipoPerigo = (
perigoGas != ultimoPerigoGas ||
perigoTemp != ultimoPerigoTemp ||
perigoUmi != ultimoPerigoUmi
);
static bool ultimoAtencaoGas = false;
static bool ultimoAtencaoTemp = false;
static bool ultimoAtencaoUmi = false;
bool mudouTipoAtencao = (
atencaoGas != ultimoAtencaoGas ||
atencaoTemp != ultimoAtencaoTemp ||
atencaoUmi != ultimoAtencaoUmi
);
// Estado de perigo
if (perigoGas || perigoTemp || perigoUmi) {
if (!estadoPerigo || mudouTipoPerigo) {
lcd.clear();
lcd.setCursor(0, 0);
if (perigoGas && perigoTemp && perigoUmi) lcd.print("PERIGO: TEMP UMI GAS!");
else if (perigoGas && perigoTemp) lcd.print("PERIGO: TEMP GAS!");
else if (perigoGas && perigoUmi) lcd.print("PERIGO: UMI GAS!");
else if (perigoTemp && perigoUmi) lcd.print("PERIGO: TEMP UMI!");
else if (perigoTemp) lcd.print("PERIGO TEMP!");
else if (perigoUmi) lcd.print("PERIGO UMIDADE!");
else if (perigoGas) lcd.print("PERIGO DE GAS!");
estadoPerigo = true;
estadoAtencao = false;
}
int linha = 1;
if (perigoTemp) {
lcd.setCursor(0, linha++);
lcd.print("Temp: ");
lcd.print(temperature, 1);
lcd.print(" C ");
}
if (perigoUmi) {
lcd.setCursor(0, linha++);
lcd.print("Umi: ");
lcd.print((int)humidity);
lcd.print("% ");
}
if (perigoGas) {
lcd.setCursor(0, linha++);
lcd.print("Gas: ");
lcd.print(gasPPM, 1);
lcd.print("ppm ");
}
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
digitalWrite(YELLOW_LED, LOW);
tone(BUZZER_PIN, 4000);
// Estado de atenção
} else if (atencaoGas || atencaoTemp || atencaoUmi) {
if (!estadoAtencao || mudouTipoAtencao) {
lcd.clear();
lcd.setCursor(0, 0);
if (atencaoGas && atencaoTemp && atencaoUmi) lcd.print("ATENCAO:TEMP UMI GAS!");
else if (atencaoGas && atencaoTemp) lcd.print("ATENCAO: TEMP GAS!");
else if (atencaoGas && atencaoUmi) lcd.print("ATENCAO: UMI GAS!");
else if (atencaoTemp && atencaoUmi) lcd.print("ATENCAO: TEMP UMI!");
else if (atencaoTemp) lcd.print("ATENCAO TEMP!");
else if (atencaoUmi) lcd.print("ATENCAO UMIDADE!");
else if (atencaoGas) lcd.print("ATENCAO DE GAS!");
estadoAtencao = true;
estadoPerigo = false;
}
int linha = 1;
if (atencaoTemp) {
lcd.setCursor(0, linha++);
lcd.print("Temp: ");
lcd.print(temperature, 1);
lcd.print(" C ");
}
if (atencaoUmi) {
lcd.setCursor(0, linha++);
lcd.print("Umi: ");
lcd.print((int)humidity);
lcd.print("% ");
}
if (atencaoGas) {
lcd.setCursor(0, linha++);
lcd.print("Gas: ");
lcd.print(gasPPM, 1);
lcd.print("ppm ");
}
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, LOW);
digitalWrite(YELLOW_LED, HIGH);
tone(BUZZER_PIN, 2000);
// Estado normal
} else {
if (estadoPerigo || estadoAtencao) {
lcd.clear();
estadoPerigo = false;
estadoAtencao = false;
}
lcd.setCursor(0, 0);
if (now.day() < 10) lcd.print('0');
lcd.print(now.day());
lcd.print('/');
if (now.month() < 10) lcd.print('0');
lcd.print(now.month());
lcd.print(' ');
if (now.hour() < 10) lcd.print('0');
lcd.print(now.hour());
lcd.print(':');
if (now.minute() < 10) lcd.print('0');
lcd.print(now.minute());
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("Gas: ");
lcd.print(gasPPM, 1);
lcd.print("ppm ");
lcd.setCursor(0, 2);
lcd.print("Temp: ");
lcd.print(temperature, 1);
lcd.print(" C ");
lcd.setCursor(0, 3);
lcd.print("Umi: ");
lcd.print((int)humidity);
lcd.print("% ");
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
digitalWrite(YELLOW_LED, LOW);
noTone(BUZZER_PIN);
}
// Publica dados MQTT
char tempStr[8], humStr[8], gasStr[8];
dtostrf(temperature, 4, 2, tempStr);
dtostrf(humidity, 4, 2, humStr);
dtostrf(gasPPM, 4, 2, gasStr);
MQTT.publish(TOPICO_PUBLISH_TEMP, tempStr);
MQTT.publish(TOPICO_PUBLISH_HUM, humStr);
MQTT.publish(TOPICO_PUBLISH_GAS, gasStr);
ultimoPerigoGas = perigoGas;
ultimoPerigoTemp = perigoTemp;
ultimoPerigoUmi = perigoUmi;
ultimoAtencaoGas = atencaoGas;
ultimoAtencaoTemp = atencaoTemp;
ultimoAtencaoUmi = atencaoUmi;
delay(3000);
}