#include <WiFi.h>
#include <PubSubClient.h>
// --------- PINAGEM ----------
const int MQ2_PIN = 34; // AOUT do MQ-2
const int LED_GREEN = 23;
const int LED_YELLOW = 22;
const int LED_RED = 21;
const int BUZZER_PIN = 19;
// --------- WIFI ----------
const char* ssid = "Wokwi-GUEST"; // ou sua rede real
const char* password = ""; // se for usar Wokwi-GUEST, deixa vazio
// --------- MQTT ----------
const char* mqttServer = "broker.hivemq.com";
const int mqttPort = 1883;
const char* mqttClientId = "esp32-co-marcelo"; // pode mudar
const char* topicData = "fiap/marcelo/co/data";
const char* topicLevel = "fiap/marcelo/co/level";
// --------- CONTROLE DE LEITURA ----------
unsigned long lastRead = 0;
const unsigned long interval = 20000; // 20 segundos
int lastLevel = -1;
WiFiClient espClient;
PubSubClient client(espClient);
// --------- FUNÇÕES AUXILIARES ----------
void setupWiFi() {
delay(10);
Serial.println();
Serial.print("Conectando ao WiFi: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
int tentativas = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
tentativas++;
if (tentativas > 40) {
Serial.println("\nFalha ao conectar no WiFi. Reiniciando...");
ESP.restart();
}
}
Serial.println("\nWiFi conectado.");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Conectando ao MQTT...");
if (client.connect(mqttClientId)) {
Serial.println("conectado.");
// Se quiser assinar algo, faz aqui.
} else {
Serial.print("falhou, rc=");
Serial.print(client.state());
Serial.println(" - tentando novamente em 5 segundos...");
delay(5000);
}
}
}
int decideLevel(float ppm) {
if (ppm <= 1000.0) return 0; // Bom
else if (ppm <= 2000.0) return 1; // Atenção
else return 2; // Perigoso
}
void setOutputs(int level) {
digitalWrite(LED_GREEN, level == 0 ? HIGH : LOW);
digitalWrite(LED_YELLOW, level == 1 ? HIGH : LOW);
digitalWrite(LED_RED, level == 2 ? HIGH : LOW);
if (level == 2) {
// Alarme sonoro
// Você pode usar tone() se estiver disponível para ESP32 no seu core
// No Wokwi funciona:
ledcAttachPin(BUZZER_PIN, 0);
ledcWriteTone(0, 2000); // 2 kHz
} else {
ledcDetachPin(BUZZER_PIN);
}
}
// --------- SETUP ----------
void setup() {
Serial.begin(115200);
pinMode(MQ2_PIN, INPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_YELLOW, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
setOutputs(0); // começa em "bom"
setupWiFi();
client.setServer(mqttServer, mqttPort);
}
// --------- LOOP ----------
void loop() {
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
unsigned long now = millis();
if (now - lastRead >= interval) {
lastRead = now;
int raw = analogRead(MQ2_PIN); // 0 a 4095
// Simulação tosca de PPM: mapeia 0-4095 para 0-5000 ppm
float ppm = map(raw, 0, 4095, 0, 5000);
int level = decideLevel(ppm);
setOutputs(level);
Serial.print("RAW: ");
Serial.print(raw);
Serial.print(" PPM estimado: ");
Serial.print(ppm);
Serial.print(" Nivel: ");
Serial.println(level);
// Publica dados no MQTT (JSON)
char payload[128];
snprintf(payload, sizeof(payload),
"{\"ppm\":%.1f,\"level\":%d}", ppm, level);
client.publish(topicData, payload);
// Só publica evento de mudança de faixa se o nível mudou
if (level != lastLevel) {
lastLevel = level;
char eventMsg[128];
snprintf(eventMsg, sizeof(eventMsg),
"{\"level\":%d,\"ppm\":%.1f}", level, ppm);
client.publish(topicLevel, eventMsg);
Serial.println("Faixa de qualidade alterada, publicando evento em topicLevel.");
}
}
}