#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ESP32Servo.h>
// ====================================
// CONFIGURAÇÕES DE REDE E MQTT
// ====================================
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
// ====================================
// TÓPICOS MQTT POR AMBIENTE
// ====================================
// ====================================
// TÓPICOS MQTT POR AMBIENTE
// ====================================
// AMBIENTE 1 - GARAGEM
const char* garagem_portao_social = "casaAutomatica/garagem/portao_social";
const char* garagem_portao_basculante = "casaAutomatica/garagem/portao_basculante";
const char* garagem_luz = "casaAutomatica/garagem/luz";
const char* garagem_status = "casaAutomatica/garagem/status";
// AMBIENTE 2 - SALA DE ESTAR
const char* sala_sensor = "casaAutomatica/sala/sensor";
const char* sala_luz = "casaAutomatica/sala/luz";
const char* sala_ac = "casaAutomatica/sala/ac";
const char* sala_umidificador = "casaAutomatica/sala/umidificador";
// AMBIENTE 3 - QUARTO
const char* quarto_luz = "casaAutomatica/quarto/luz";
const char* quarto_tomada = "casaAutomatica/quarto/tomada";
const char* quarto_cortina = "casaAutomatica/quarto/cortina";
// ====================================
// CONFIGURAÇÃO DOS PINOS
// ====================================
// AMBIENTE 1 - GARAGEM
const int PIN_LUZ_GARAGEM = 12;
const int PIN_PIR = 34;
const int PIN_SERVO_SOCIAL = 16;
const int PIN_SERVO_BASCULANTE = 17;
// AMBIENTE 2 - SALA DE ESTAR
const int PIN_DHT = 23;
const int PIN_LUZ_SALA = 14;
const int PIN_RELAY_AC = 19;
const int PIN_RELAY_UMIDIFICADOR = 18;
// AMBIENTE 3 - QUARTO
const int PIN_LUZ_QUARTO = 27;
const int PIN_RELAY_QUARTO = 22;
const int PIN_STEP = 26;
const int PIN_DIR = 25;
// ====================================
// CONFIGURAÇÃO DO DHT22
// ====================================
#define DHTTYPE DHT22
DHT dht(PIN_DHT, DHTTYPE);
// ====================================
// CONFIGURAÇÃO DOS SERVOS
// ====================================
Servo servoSocial;
Servo servoBasculante;
// ====================================
// VARIÁVEIS DE ESTADO DOS AMBIENTES
// ====================================
// AMBIENTE 1 - GARAGEM
bool luzGaragemLigada = false;
bool portaoSocialAberto = false;
bool portaoBasculanteAberto = false;
bool luzPorSensorMovimento = false;
bool luzPorPortaoBasculante = false;
bool luzPorPortaoSocial = false; // Nova variável para controle do portão social
unsigned long tempoSensorPIR = 0;
unsigned long tempoPortaoSocial = 0;
const unsigned long TEMPO_LUZ_PIR = 5000; // 5 segundos
const unsigned long TEMPO_PORTAO_SOCIAL = 5000; // 5 segundos
// AMBIENTE 2 - SALA DE ESTAR
bool acLigado = false;
bool umidificadorLigado = false;
bool luzSalaLigada = false;
const float TEMP_LIGA_AC = 28.0;
const float TEMP_DESLIGA_AC = 20.0;
const float UMID_LIGA_UMIDIFICADOR = 20.0;
const float UMID_DESLIGA_UMIDIFICADOR = 80.0;
// AMBIENTE 3 - QUARTO
bool luzQuartoLigada = false;
bool tomadaQuartoLigada = false;
bool cortinaAberta = false;
// ====================================
// CONFIGURAÇÕES GERAIS
// ====================================
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastSensorReading = 0;
const unsigned long INTERVALO_SENSOR = 3000; // 3 segundos
// ====================================
// FUNÇÃO DE CONEXÃO WI-FI
// ====================================
void setup_wifi() {
delay(10);
Serial.println("🔄 Conectando ao Wi-Fi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("\n✅ Wi-Fi conectado! IP: ");
Serial.println(WiFi.localIP());
}
// ====================================
// FUNÇÕES DO AMBIENTE 1 - GARAGEM
// ====================================
void controlarLuzGaragem() {
bool deveEstarLigada = luzPorSensorMovimento || luzPorPortaoBasculante || luzPorPortaoSocial;
if (deveEstarLigada && !luzGaragemLigada) {
digitalWrite(PIN_LUZ_GARAGEM, HIGH);
luzGaragemLigada = true;
Serial.println("💡 LUZ GARAGEM LIGADA");
} else if (!deveEstarLigada && luzGaragemLigada) {
digitalWrite(PIN_LUZ_GARAGEM, LOW);
luzGaragemLigada = false;
Serial.println("💡 LUZ GARAGEM DESLIGADA");
}
}
void abrirPortaoSocial() {
if (!portaoSocialAberto) {
servoSocial.write(180);
portaoSocialAberto = true;
luzPorPortaoSocial = true; // Liga a luz ao abrir portão social
tempoPortaoSocial = millis();
Serial.println("🚪 PORTÃO SOCIAL ABERTO - LUZ LIGADA");
}
}
void fecharPortaoSocial() {
if (portaoSocialAberto) {
servoSocial.write(0);
portaoSocialAberto = false;
Serial.println("🚪 PORTÃO SOCIAL FECHADO");
}
}
void controlarPortaoBasculante(bool abrir) {
if (abrir && !portaoBasculanteAberto) {
servoBasculante.write(180);
portaoBasculanteAberto = true;
luzPorPortaoBasculante = true;
Serial.println("🚗 PORTÃO BASCULANTE ABERTO");
} else if (!abrir && portaoBasculanteAberto) {
servoBasculante.write(0);
portaoBasculanteAberto = false;
luzPorPortaoBasculante = false;
Serial.println("🚗 PORTÃO BASCULANTE FECHADO");
}
}
void verificarSensorPIR() {
int valorPIR = digitalRead(PIN_PIR);
if (valorPIR == HIGH && !luzPorSensorMovimento) {
luzPorSensorMovimento = true;
tempoSensorPIR = millis();
Serial.println("🚶 MOVIMENTO DETECTADO");
}
// Desligar luz após 5 segundos do sensor PIR
if (luzPorSensorMovimento && (millis() - tempoSensorPIR >= TEMPO_LUZ_PIR)) {
luzPorSensorMovimento = false;
}
}
void verificarPortaoSocial() {
// Fechar portão social automaticamente após 5 segundos e desligar a luz
if (portaoSocialAberto && (millis() - tempoPortaoSocial >= TEMPO_PORTAO_SOCIAL)) {
fecharPortaoSocial();
luzPorPortaoSocial = false; // Desliga a luz quando fecha o portão
Serial.println("💡 LUZ GARAGEM DESLIGADA - PORTÃO FECHADO");
}
}
// ====================================
// FUNÇÕES DO AMBIENTE 2 - SALA DE ESTAR
// ====================================
void controleAutomaticoTemperatura(float temperatura) {
if (temperatura >= TEMP_LIGA_AC && !acLigado) {
digitalWrite(PIN_RELAY_AC, HIGH);
acLigado = true;
Serial.printf("❄️ Temperatura %.1f°C ≥ 28°C → LIGANDO AC\n", temperatura);
}
else if (temperatura < TEMP_DESLIGA_AC && acLigado) {
digitalWrite(PIN_RELAY_AC, LOW);
acLigado = false;
Serial.printf("❄️ Temperatura %.1f°C < 20°C → DESLIGANDO AC\n", temperatura);
}
}
void controleAutomaticoUmidade(float umidade) {
if (umidade <= UMID_LIGA_UMIDIFICADOR && !umidificadorLigado) {
digitalWrite(PIN_RELAY_UMIDIFICADOR, HIGH);
umidificadorLigado = true;
Serial.printf("💨 Umidade %.1f%% ≤ 20%% → LIGANDO UMIDIFICADOR\n", umidade);
}
else if (umidade >= UMID_DESLIGA_UMIDIFICADOR && umidificadorLigado) {
digitalWrite(PIN_RELAY_UMIDIFICADOR, LOW);
umidificadorLigado = false;
Serial.printf("💨 Umidade %.1f%% ≥ 80%% → DESLIGANDO UMIDIFICADOR\n", umidade);
}
}
// ====================================
// FUNÇÕES DO AMBIENTE 3 - QUARTO
// ====================================
void moverCortina(bool abrir) {
digitalWrite(PIN_DIR, abrir ? HIGH : LOW);
Serial.println(abrir ? "🪟 ABRINDO CORTINA..." : "🪟 FECHANDO CORTINA...");
// Movimento limitado a 200 passos
for (int i = 0; i < 200; i++) {
digitalWrite(PIN_STEP, HIGH);
delay(5);
digitalWrite(PIN_STEP, LOW);
delay(5);
}
cortinaAberta = abrir;
Serial.println(abrir ? "🪟 CORTINA ABERTA" : "🪟 CORTINA FECHADA");
}
// ====================================
// CALLBACK MQTT
// ====================================
void callback(char* topic, byte* payload, unsigned int length) {
String msg = "";
for (unsigned int i = 0; i < length; i++) {
msg += (char)payload[i];
}
msg.trim();
Serial.printf("📥 [%s]: %s\n", topic, msg.c_str());
// ===================
// CONTROLES GARAGEM
// ===================
if (String(topic) == garagem_portao_social) {
if (msg == "abrir") {
abrirPortaoSocial();
} else if (msg == "fechar") {
fecharPortaoSocial();
}
}
else if (String(topic) == garagem_portao_basculante) {
if (msg == "abrir") {
controlarPortaoBasculante(true);
} else if (msg == "fechar") {
controlarPortaoBasculante(false);
}
}
else if (String(topic) == garagem_luz) {
if (msg == "ligar" || msg == "on") {
luzPorPortaoBasculante = true; // Usar controle manual
} else if (msg == "desligar" || msg == "off") {
luzPorPortaoBasculante = false; // Usar controle manual
luzPorPortaoSocial = false; // Também desliga se foi ligada pelo portão social
luzPorSensorMovimento = false; // E pelo sensor PIR
}
}
// ===================
// CONTROLES SALA
// ===================
else if (String(topic) == sala_luz) {
if (msg == "ligar" || msg == "on") {
digitalWrite(PIN_LUZ_SALA, HIGH);
luzSalaLigada = true;
Serial.println("💡 LUZ SALA LIGADA (Manual)");
} else if (msg == "desligar" || msg == "off") {
digitalWrite(PIN_LUZ_SALA, LOW);
luzSalaLigada = false;
Serial.println("💡 LUZ SALA DESLIGADA (Manual)");
}
}
else if (String(topic) == sala_ac) {
if (msg == "ligar" || msg == "on") {
digitalWrite(PIN_RELAY_AC, HIGH);
acLigado = true;
Serial.println("❄️ AC LIGADO (Manual)");
} else if (msg == "desligar" || msg == "off") {
digitalWrite(PIN_RELAY_AC, LOW);
acLigado = false;
Serial.println("❄️ AC DESLIGADO (Manual)");
}
}
else if (String(topic) == sala_umidificador) {
if (msg == "ligar" || msg == "on") {
digitalWrite(PIN_RELAY_UMIDIFICADOR, HIGH);
umidificadorLigado = true;
Serial.println("💨 UMIDIFICADOR LIGADO (Manual)");
} else if (msg == "desligar" || msg == "off") {
digitalWrite(PIN_RELAY_UMIDIFICADOR, LOW);
umidificadorLigado = false;
Serial.println("💨 UMIDIFICADOR DESLIGADO (Manual)");
}
}
// ===================
// CONTROLES QUARTO
// ===================
else if (String(topic) == quarto_luz) {
if (msg == "ligar" || msg == "on") {
digitalWrite(PIN_LUZ_QUARTO, HIGH);
luzQuartoLigada = true;
Serial.println("💡 LUZ QUARTO LIGADA");
} else if (msg == "desligar" || msg == "off") {
digitalWrite(PIN_LUZ_QUARTO, LOW);
luzQuartoLigada = false;
Serial.println("💡 LUZ QUARTO DESLIGADA");
}
}
else if (String(topic) == quarto_tomada) {
if (msg == "ligar" || msg == "on") {
digitalWrite(PIN_RELAY_QUARTO, HIGH);
tomadaQuartoLigada = true;
Serial.println("🔌 TOMADA QUARTO LIGADA");
} else if (msg == "desligar" || msg == "off") {
digitalWrite(PIN_RELAY_QUARTO, LOW);
tomadaQuartoLigada = false;
Serial.println("🔌 TOMADA QUARTO DESLIGADA");
}
}
else if (String(topic) == quarto_cortina) {
if (msg == "abrir") {
moverCortina(true);
} else if (msg == "fechar") {
moverCortina(false);
}
}
}
// ====================================
// RECONEXÃO MQTT
// ====================================
void reconnect() {
String clientId = "ESP32_CasaAutomatica_" + String(random(0xffff), HEX);
while (!client.connected()) {
Serial.print("🔄 Conectando ao MQTT...");
if (client.connect(clientId.c_str())) {
Serial.println(" ✅ Conectado!");
// Inscrições nos tópicos
// Garagem
client.subscribe(garagem_portao_social);
client.subscribe(garagem_portao_basculante);
client.subscribe(garagem_luz);
// Sala
client.subscribe(sala_luz);
client.subscribe(sala_ac);
client.subscribe(sala_umidificador);
// Quarto
client.subscribe(quarto_luz);
client.subscribe(quarto_tomada);
client.subscribe(quarto_cortina);
Serial.println("📡 Inscrito em todos os tópicos!");
} else {
Serial.printf(" ❌ Falhou (rc=%d). Tentando em 5s...\n", client.state());
delay(5000);
}
}
}
// ====================================
// PUBLICAR STATUS DOS AMBIENTES
// ====================================
void publicarStatusGaragem() {
String payload = "{";
payload += "\"luz\":" + String(luzGaragemLigada ? "true" : "false") + ",";
payload += "\"portao_social\":" + String(portaoSocialAberto ? "true" : "false") + ",";
payload += "\"portao_basculante\":" + String(portaoBasculanteAberto ? "true" : "false");
payload += "}";
client.publish(garagem_status, payload.c_str());
}
void publicarSensorSala(float temperatura, float umidade) {
String payload = "{";
payload += "\"temperatura\":" + String(temperatura, 1) + ",";
payload += "\"umidade\":" + String(umidade, 1) + ",";
payload += "\"ac\":" + String(acLigado ? "true" : "false") + ",";
payload += "\"umidificador\":" + String(umidificadorLigado ? "true" : "false") + ",";
payload += "\"luz\":" + String(luzSalaLigada ? "true" : "false");
payload += "}";
client.publish(sala_sensor, payload.c_str());
}
// ====================================
// SETUP PRINCIPAL
// ====================================
void setup() {
Serial.begin(115200);
Serial.println("🏠 === SISTEMA AUTOMAÇÃO RESIDENCIAL === 🏠");
// Inicializar DHT22
dht.begin();
// Configurar pinos como saída
// Garagem
pinMode(PIN_LUZ_GARAGEM, OUTPUT);
pinMode(PIN_PIR, INPUT);
// Sala
pinMode(PIN_LUZ_SALA, OUTPUT);
pinMode(PIN_RELAY_AC, OUTPUT);
pinMode(PIN_RELAY_UMIDIFICADOR, OUTPUT);
// Quarto
pinMode(PIN_LUZ_QUARTO, OUTPUT);
pinMode(PIN_RELAY_QUARTO, OUTPUT);
pinMode(PIN_STEP, OUTPUT);
pinMode(PIN_DIR, OUTPUT);
// Inicializar servos
servoSocial.attach(PIN_SERVO_SOCIAL);
servoBasculante.attach(PIN_SERVO_BASCULANTE);
// Estado inicial - tudo desligado
digitalWrite(PIN_LUZ_GARAGEM, LOW);
digitalWrite(PIN_LUZ_SALA, LOW);
digitalWrite(PIN_LUZ_QUARTO, LOW);
digitalWrite(PIN_RELAY_AC, LOW);
digitalWrite(PIN_RELAY_UMIDIFICADOR, LOW);
digitalWrite(PIN_RELAY_QUARTO, LOW);
servoSocial.write(0);
servoBasculante.write(0);
// Conectar Wi-Fi e MQTT
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
Serial.println("✅ Sistema pronto!");
Serial.println("📋 Controles automáticos ativos:");
Serial.println(" 🚶 PIR: Liga luz garagem por 5s");
Serial.println(" 🚪 Portão Social: Liga luz por 5s + fecha automático");
Serial.println(" 🌡️ AC: Liga ≥28°C | Desliga <20°C");
Serial.println(" 💧 Umidificador: Liga ≤20% | Desliga ≥80%");
Serial.println("📱 Controles manuais via MQTT disponíveis!");
}
// ====================================
// LOOP PRINCIPAL
// ====================================
void loop() {
// Manter conexão MQTT
if (!client.connected()) {
reconnect();
}
client.loop();
// Verificar sensores e automações da garagem
verificarSensorPIR();
verificarPortaoSocial();
controlarLuzGaragem();
// Leitura periódica do sensor DHT22 na sala
unsigned long agora = millis();
if (agora - lastSensorReading >= INTERVALO_SENSOR) {
lastSensorReading = agora;
float temperatura = dht.readTemperature();
float umidade = dht.readHumidity();
if (!isnan(temperatura) && !isnan(umidade)) {
// Executar controles automáticos da sala
controleAutomaticoTemperatura(temperatura);
controleAutomaticoUmidade(umidade);
// Publicar dados no MQTT
publicarSensorSala(temperatura, umidade);
publicarStatusGaragem();
Serial.printf("📊 T: %.1f°C | U: %.1f%% | AC: %s | Umid: %s | Garagem: %s\n",
temperatura, umidade,
acLigado ? "ON" : "OFF",
umidificadorLigado ? "ON" : "OFF",
luzGaragemLigada ? "ON" : "OFF");
} else {
Serial.println("❌ Erro ao ler sensor DHT22");
}
}
delay(100); // Pequeno delay para estabilidade
}