#include <MQUnifiedsensor.h>
#include <DHT.h>
#include <math.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include "elm_modelSuper.h"
#include <Stepper.h>
// Configurações do sensor
#define Board "ESP32"
#define MQ2PIN 32 // pino analógico do ESP32
#define Type "MQ-2" // tipo do sensor
#define Voltage_Resolution 3.3
#define ADC_Bit_Resolution 12 // ESP32 = 12 bits (0-4095)
#define RatioMQ2CleanAir 9.83 // valor típico de R0 para MQ-2 no ar limpo
#define DHTPIN 25
#define DHTTYPE DHT22
#define BOTAOPIN 22
#define RPS 200
DHT dht(DHTPIN, DHTTYPE);
const int ldrPin = 33;
volatile bool solicitacaoTrocaEstado = false;
bool estadoFlipFlop = false;
volatile unsigned long ultimaInterrupcao = 0;
// === CONFIGURAÇÕES WI-FI ===
const char* ssid = "Wokwi-GUEST";
const char* senha = "";
// === CONFIGURAÇÕES CALLMEBOT ===
String phoneNumber = "557181289896";
String apiKey = "1844722";
// === CONTROLE DE TEMPO PARA MENSAGENS ===
unsigned long ultimaMensagem = 0;
const unsigned long intervaloMensagem = 30000; // 30 segundos
// ==== RANGES PARA NORMALIZAÇÃO ====
const float TEMP_MIN = 0;
const float TEMP_MAX = 80;
const float UMID_MIN = 0;
const float UMID_MAX = 100;
const int MQ2_MIN = 0;
const int MQ2_MAX = 23008;
const int LDR_MIN = 0;
const int LDR_MAX = 1100;
// ==== Parâmetros do sensor ====
const int luxPin = 34; // Pino ADC conectado no LDR
const float GAMMA = 0.7; // Coeficiente do LDR (ajuste conforme o sensor)
const float RL10 = 50; // Resistência do LDR em 10 lux (em kOhms)
// Handler da interrupção do botão
void IRAM_ATTR trataInterrupcao() {
unsigned long agora = millis();
static unsigned long ultimaInterrupcaoLocal = 0;
if (agora - ultimaInterrupcaoLocal > 200) { // debounce
solicitacaoTrocaEstado = true;
ultimaInterrupcaoLocal = agora;
}
}
// Conecta no WiFi
void conectarWiFi() {
Serial.print("Conectando-se à rede Wi-Fi: ");
Serial.println(ssid);
WiFi.begin(ssid, senha);
unsigned long tempoInicial = millis();
while (WiFi.status() != WL_CONNECTED && millis() - tempoInicial < 10000) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nConectado com sucesso!");
Serial.print("Endereço IP: ");
Serial.println(WiFi.localIP());
enviarWhatsApp("🤖 ESP32 CONECTADO! Sistema iniciado com sucesso.");
} else {
Serial.println("\nFalha ao conectar no Wi-Fi. Reiniciando em 2 segundos...");
delay(2000);
ESP.restart();
}
}
void enviarWhatsApp(String mensagem) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
mensagem.replace(" ", "%20");
mensagem.replace("°", "%C2%B0");
mensagem.replace("🤖", "%F0%9F%A4%96");
mensagem.replace("📊", "%F0%9F%93%8A");
mensagem.replace("🌡️", "%F0%9F%8C%A1%EF%B8%8F");
mensagem.replace("💧", "%F0%9F%92%A7");
mensagem.replace("💨", "%F0%9F%92%A8");
mensagem.replace("💡", "%F0%9F%92%A1");
String url = "https://api.callmebot.com/whatsapp.php?phone=" + phoneNumber +
"&text=" + mensagem + "&apikey=" + apiKey;
http.begin(url);
int httpResponseCode = http.GET();
if (httpResponseCode == 200) {
Serial.println("✅ Mensagem WhatsApp enviada com sucesso!");
} else {
Serial.print("❌ Erro ao enviar mensagem. Código: ");
Serial.println(httpResponseCode);
}
http.end();
} else {
Serial.println("❌ WiFi desconectado. Não foi possível enviar mensagem.");
}
}
//só depois
void enviarStatusCompleto(float s1, float s2, float s3, float s4, float chanceVida) {
String status = "📊 STATUS ESP32:%0A";
status += "Sistema: " + String(estadoFlipFlop ? "ATIVO" : "INATIVO") + "%0A";
if (estadoFlipFlop) {
// Converte os valores normalizados de volta para as escalas reais para visualização
float tempReal = s1 * TEMP_MAX;
float umidReal = s2 * UMID_MAX;
float gasReal = s3 * MQ2_MAX;
float luzReal = s4 * LDR_MAX;
status += "🌡️ Temperatura: " + String(tempReal, 1) + "°C%0A";
status += "💧 Umidade: " + String(umidReal, 1) + "%%0A";
status += "💨 Gás MQ2: " + String(gasReal, 1) + "%0A";
status += "💡 Luz LDR: " + String(luzReal, 1) + "%0A";
status += "🧠 Chance de Vida (ELM): " + String(chanceVida * 100.0, 1) + "%%0A";
} else {
status += "Sensores desativados";
}
enviarWhatsApp(status);
}
// funçoes para normalizar
float normalizarTemperatura(float temp) {
if (temp < 0) temp = 0;
if (temp > TEMP_MAX) temp = TEMP_MAX;
return temp / TEMP_MAX;
}
float normalizarUmidade(float umid) {
if (umid < 0) umid = 0;
if (umid > UMID_MAX) umid = UMID_MAX;
return umid / UMID_MAX;
}
float normalizarMQ2(float val) {
if (val < 0) val = 0;
if (val > MQ2_MAX) val = MQ2_MAX;
return val / MQ2_MAX;
}
float normalizarLDR(float val) {
if (val < 0) val = 0;
if (val > LDR_MAX) val = LDR_MAX;
return val / LDR_MAX;
}
Stepper stepper1(RPS, 33, 26, 27, 14);
Stepper stepper2(RPS, 4, 0, 2, 15);
MQUnifiedsensor MQ2(Board, Voltage_Resolution, ADC_Bit_Resolution, MQ2PIN, Type);
int valor_gas = 0;
void setup() {
Serial.begin(9600);
pinMode(34, INPUT);
stepper1.setSpeed(60);
stepper2.setSpeed(60);
conectarWiFi();
pinMode(BOTAOPIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BOTAOPIN), trataInterrupcao, FALLING);
dht.begin();
MQ2.setRegressionMethod(1); //_PPM = a*ratio^b
MQ2.setA(574.25); MQ2.setB(-2.222); // Configure the equation to to calculate LPG concentration
MQ2.init();
Serial.println("Aperte o botao para ligar o sistema ");
float calcR0 = 0;
for(int i = 1; i<=10; i ++)
{
MQ2.update(); // Update data, the arduino will read the voltage from the analog pin
calcR0 += MQ2.calibrate(RatioMQ2CleanAir);
Serial.print(".");
}
MQ2.setR0(calcR0/10);
delay(500); //Sampling frequency
}
void loop() {
MQ2.update();
MQ2.readSensor();
valor_gas = analogRead(MQ2PIN);
valor_gas = map(valor_gas, 0, 4095, 0, 300);
if (solicitacaoTrocaEstado) {
estadoFlipFlop = !estadoFlipFlop;
solicitacaoTrocaEstado = false;
Serial.print("Botão pressionado. ");
Serial.println(estadoFlipFlop ? "Leitura dos sensores ATIVADA." : "Leitura dos sensores DESATIVADA.");
}
if (estadoFlipFlop) {
stepper1.step(RPS);
stepper2.step(RPS);
int analogValue = analogRead(luxPin);
float volts = analogValue / 4095.0 * 3.3;
float resistance = 2000 * volts / (3.3 - volts);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1.0 / GAMMA));
lux = lux / 10;
float temperatura = dht.readTemperature();
float umidade = dht.readHumidity();
float s1 = normalizarTemperatura(temperatura);
float s2 = normalizarUmidade(umidade);
float s3 = normalizarMQ2(valor_gas);
float s4 = normalizarLDR(lux);
float entrada[4] = {s1, s2, s3, s4};
float entradaGostosinha[4] = {temperatura, umidade,(float)valor_gas,lux};
float chanceVida = elm_predict(entrada);
Serial.println("=== LEITURAS BRUTAS ===");
Serial.print("Temperatura: ");
Serial.print(temperatura);
Serial.print(" °C | Umidade: ");
Serial.print(umidade);
Serial.println(" %");
Serial.print("MQ2: ");
Serial.print(valor_gas);
Serial.print(" | LDR: ");
Serial.println(lux);
delay(1000);
Serial.println("=== LEITURAS NORMALIZADAS ===");
Serial.print("Temperatura: ");
Serial.print(s1);
Serial.print(" °C | Umidade: ");
Serial.print(s2);
Serial.println(" ");
Serial.print("MQ2: ");
Serial.print(s3);
Serial.print(" | LDR: ");
Serial.println(s4);
delay(1000);
Serial.println("=== PREDIÇÃO ELM ===");
Serial.print("Chance de Vida: ");
Serial.print(chanceVida * 100.0);
Serial.println(" %");
delay(1000);
if(chanceVida * 100 >= 80){
Serial.println("Propicio a vida");
enviarWhatsApp("propicio a vida");
}
else if(chanceVida * 100 >= 50 && chanceVida * 100 < 80 ){
Serial.println("Condicao Moderada");
}
else{
Serial.println("ambiente Hostil");
}
stepper1.step(-RPS);
stepper2.step(-RPS);
}
}