#include "WiFi.h"
#include <Ticker.h>
#include "mlp_pesos.h"
#include "DHT.h"
#include <ESP32Servo.h>
#include <Callmebot_ESP32.h>
// ==== Pinos ====
#define gasSensorPin 34
#define lightSensorPin 33
#define buttonPin 25
#define dhtPin 32
#define DHTTYPE DHT22
#define servo1Pin 26
#define servo2Pin 27
// ==== Instâncias globais ====
DHT dht(dhtPin, DHTTYPE);
Servo servo1;
Servo servo2;
volatile bool flagParar = false;
bool motorLigado = false;
const char* statusOp = "OK";
enum EstadoSistema { FUNCIONANDO, PARADO };
EstadoSistema estado = FUNCIONANDO;
Ticker ticker;
// ==== Interrupção ====
void IRAM_ATTR handleButton() {
flagParar = true;
}
// ==== Setup ====
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(buttonPin, handleButton, FALLING);
dht.begin();
servo1.setPeriodHertz(50);
servo2.setPeriodHertz(50);
servo1.attach(servo1Pin, 500, 2400); // SG90 padrão
servo2.attach(servo2Pin, 500, 2400);
conectarWiFi();
ticker.attach(2, mostrarDados); // Chama a cada 2s
}
// ==== Loop Principal ====
void loop() {
if (flagParar) {
noInterrupts();
flagParar = false;
estado = PARADO;
interrupts();
}
switch (estado) {
case FUNCIONANDO:
continuarOperacao();
break;
case PARADO:
pararOperacao();
break;
}
}
// ==== Mostrar dados ====
void mostrarDados() {
int rawGas = analogRead(gasSensorPin);
int rawLuz = analogRead(lightSensorPin);
float temp = dht.readTemperature(); // já °C
float umid = dht.readHumidity();
if (isnan(temp) || isnan(umid)) {
Serial.println("Erro ao ler o DHT22!");
return;
}
// Gás: 0.1–100000 ppm
float gasPPM = analogToLogRange(rawGas, 0.1, 100000);
// Luz: 0.1–100000 lux
float luzLux = analogToLogRange(rawLuz, 0.1, 100000);
// Exibição com unidades
Serial.printf("Gás: %.2f ppm | Temp: %.1f °C | Umid: %.1f %% | Luz: %.2f lux | StatsOP: %s\n",
gasPPM, temp, umid, luzLux, statusOp);
float vida = propicioAVida_MLP(gasPPM, temp, umid, luzLux);
const char* classificacao = "Ambiente Hostil";
if (vida >= 80.0) classificacao = "Propício à Vida";
else if (vida >= 50.0) classificacao = "Condição Moderada";
Serial.print("Classificação: "); Serial.println(classificacao);
if (vida >= 80.0) {
enviaZap(gasPPM, temp, umid, luzLux, vida);
}
}
//apenas para os valores ficarem na faixa correta dos sensores
float analogToLogRange(int analogValue, float minVal, float maxVal) {
float norm = analogValue / 4095.0;
return pow(10, log10(minVal) + norm * (log10(maxVal) - log10(minVal)));
}
// ==== Controle de motores ====
void pararOperacao() {
if (motorLigado) {
servo1.write(90); // posição neutra
servo2.write(90);
motorLigado = false;
statusOp = "X";
Serial.println("Operação Parada!");
}
}
void continuarOperacao() {
if (!motorLigado) {
servoMotor(); // Faz os servos se moverem
motorLigado = true;
statusOp = "OK";
}
}
// ==== Movimento dos servos ====
void servoMotor() {
for (int pos = 0; pos <= 180; pos++) {
servo1.write(pos);
servo2.write(180 - pos);
delay(15);
}
for (int pos = 180; pos >= 0; pos--) {
servo1.write(pos);
servo2.write(180 - pos);
delay(15);
}
}
// ==== Conexão WiFi ====
void conectarWiFi() {
WiFi.begin("Wokwi-GUEST", "", 6);
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 5000) {
Serial.print(".");
delay(500);
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Falha na conexão! Reiniciando...");
delay(2000);
ESP.restart();
} else {
Serial.println("WiFi conectado!");
}
}
// ==== WhatsApp ====
void enviaZap(float gas, float temp, float umid, float luz, float vida) {
Serial.println("Enviando mensagem no WhatsApp...");
char mensagem[256];
snprintf(mensagem, sizeof(mensagem),
"Condições Adequadas Para Vida!!\nGases: %.2f ppm\nTemperatura: %.1f °C\nUmidade: %.1f %%\nQtd. Luz: %.2f lux\n%% de Vida: %.2f",
gas, temp, umid, luz, vida);
Callmebot.whatsappMessage("+557182829835", "7301051", mensagem);
}
// ==== Rede Neural MLP ====
float relu(float x) {
return x > 0 ? x : 0;
}
float propicioAVida_MLP(float gas, float temp, float umid, float luz) {
float input[4] = { gas, temp, umid, luz };
float hidden[10];
for (int i = 0; i < 10; i++) {
hidden[i] = 0;
for (int j = 0; j < 4; j++) {
hidden[i] += input[j] * PESOS_INPUT_HIDDEN[j][i];
}
hidden[i] += BIAS_HIDDEN[i];
hidden[i] = relu(hidden[i]);
}
float output = 0;
for (int i = 0; i < 10; i++) {
output += hidden[i] * PESOS_HIDDEN_OUTPUT[i];
}
output += BIAS_OUTPUT;
if (output < 0) output = 0;
if (output > 100) output = 100;
return output;
}