INEMA.SOLUÇÕES
Solução 7 · Controle da casa

Luz e ventilador que desligam sozinhos quando a sala esvazia

Um ESP32 com dois relés liga e desliga uma luz e um ventilador pelo celular, por horário ou quando alguém entra. Um sensor de presença apaga a luz depois de 10 minutos sem ninguém. Com IA, você manda "desliga tudo da sala" em texto ou por voz.

Kit R$ 70–120Dificuldade: fácilCargas só em 12 V

Como funciona

Três jeitos de ligar, um jeito de desligar

Celular Horário Presença ESP32 decide Relé 1 Relé 2 botões 22 h apaga sensor PIR guarda o estado de cada canal e responde o painel luz (fita LED) ventilador tudo em 12 V, com fonte pronta
O horário vem da internet (NTP), então o ESP32 não precisa de relógio. Os 10 minutos e as 22 h são pontos de partida: ajuste depois dos testes.

O ESP32 cria uma página com botões que abre no celular, na mesma rede Wi-Fi. Cada relé é uma chave controlada pelo ESP32: fecha o contato e a fita de LED ou o ventilador liga. O sensor PIR percebe o calor de uma pessoa se mexendo. Enquanto houver movimento, a luz fica acesa; depois de 10 minutos parados, ela apaga. Às 22 h, tudo desliga, mesmo que alguém tenha esquecido.

Peças

Lista de compras

PeçaPara que servePreço aprox.
ESP32 DevKit V1 (30 pinos)O cérebro, com Wi-FiR$ 28–40
Módulo relé 2 canais 5 V com optoacopladorLiga e desliga as duas cargas. Compre um que aceite sinal de 3,3 VR$ 8–14
Sensor de presença PIR HC-SR501Percebe pessoa se mexendo, até uns 5 mR$ 7–12
Fonte 12 V 1 A com plugue P4Alimenta a fita e o ventiladorR$ 12–20
Fita de LED 12 V (50 cm)A "luz da sala" do projetoR$ 6–12
Cooler 12 V (8 cm, de computador)O "ventilador" do projetoR$ 6–10
Protoboard, jumpers, borne P4Ligações sem soldaR$ 8–12
TotalR$ 75–120

Preços aproximados de loja online brasileira em outubro de 2026, a conferir antes de comprar. Não inclui caixa de acabamento.

Ligação

O circuito, pino por pino

ESP32 VIN 5V GND GPIO 26 GPIO 25 GPIO 27 Relé 2 canais PIR · OUT IN1 (cima) · IN2 VCC no VIN · GND VCC no VIN · GND Lado das cargas (12 V, contatos do relé) Fonte12 V K1COM · NO K2COM · NO Fita LED Cooler − da fonte volta direto nas cargas
Fio vermelho: + da fonte 12 V → COM de K1 e de K2; NO de K1 → + da fita; NO de K2 → + do cooler. Fio cinza: − da fonte → − da fita e − do cooler. Os 12 V nunca passam pelo ESP32.
ComponentePino do componenteLiga no ESP32
Relé 2 canaisVCC · GND · IN1 · IN2VIN (5 V do USB) · GND · GPIO 26 · GPIO 25
PIR HC-SR501VCC · OUT · GNDVIN · GPIO 27 · GND (a saída já é 3,3 V, liga direto)
Fita e cooler+ e −Nada no ESP32: só nos contatos COM/NO dos relés e na fonte 12 V
Por que não os pinos 0, 2, 12 e 15? Eles decidem como o ESP32 liga. Um relé neles pode clicar sozinho no boot ou travar a placa. O 25, o 26 e o 27 não têm esse problema.

Passo a passo

Do pacote ao primeiro clique

  1. Prepare a Arduino IDE. Instale a Arduino IDE 2 e, em Gerenciador de Placas, instale "esp32" (Espressif). Este projeto não precisa de biblioteca extra: WiFi, WebServer e o relógio já vêm com a placa.
  2. Teste a placa sozinha. Escolha "ESP32 Dev Module" e a porta, e grave o exemplo Blink. Se não gravar, segure o botão BOOT quando aparecer "Connecting...".
  3. Ligue o relé, sem as cargas. Siga a tabela. Grave o código e aperte os botões no painel: o LED de cada canal do relé acende e você ouve o clique.
  4. Ligue o PIR. Gire o trimpot de tempo (Tx) todo para a esquerda, o mínimo, e deixe o jumper em H. Espere 1 minuto depois de ligar: é o tempo de o sensor estabilizar.
  5. Ligue as cargas de 12 V. Fonte desligada da tomada. Faça a ligação do desenho de baixo, confira o + e o − e só então ligue a fonte.
  6. Abra o painel. O Monitor Serial (115200) mostra o IP (ex.: 192.168.0.50). Digite no navegador do celular, na mesma rede Wi-Fi.
  7. Teste o horário. Troque HORA_DESLIGA para a hora atual + 1 minuto, grave e veja tudo desligar sozinho. Depois volte para 22.

Código

Arduino IDE para ESP32

Troque o nome e a senha da rede e grave. No painel, cada canal tem um botão liga e um desliga. O canal 0 quer dizer "todos".

// Controle da casa — ESP32, Arduino IDE
// Sem bibliotecas extras.
#include <WiFi.h>
#include <WebServer.h>
#include <time.h>

const char* REDE  = "NOME_DA_REDE";
const char* SENHA = "SENHA_DA_REDE";

// GPIO 26: relé canal 1 (luz, fita LED)
// GPIO 25: relé canal 2 (ventilador)
const int RELE[2] = {26, 25};
const char* NOME[2] = {"Luz", "Ventilador"};
// GPIO 27: saída (OUT) do sensor PIR
const int PINO_PIR = 27;

// A maioria dos relés liga com LOW.
// Se o seu ligar com HIGH, troque os dois.
const int LIGA = LOW, DESLIGA = HIGH;

// apaga a luz após 10 min sem movimento
const unsigned long SEM_GENTE_MS =
  10UL * 60 * 1000;
// hora em que tudo desliga
const int HORA_DESLIGA = 22;

WebServer servidor(80);
bool ligado[2] = {false, false};
unsigned long ultimoMovimento = 0;
int diaDesligou = -1;

void aciona(int c, bool liga) {
  ligado[c] = liga;
  digitalWrite(RELE[c], liga ? LIGA : DESLIGA);
}

// lê ?c= e confere: 0 = todos, 1 ou 2
int canal() {
  int c = servidor.arg("c").toInt();
  if (c < 0 || c > 2) return -1;
  return c;
}

void comando(bool liga) {
  int c = canal();
  if (c < 0) {
    servidor.send(400, "text/plain", "canal?");
    return;
  }
  for (int i = 0; i < 2; i++) {
    if (c == 0 || c == i + 1) aciona(i, liga);
  }
  // volta para o painel
  servidor.sendHeader("Location", "/");
  servidor.send(303);
}
void rotaLiga()    { comando(true); }
void rotaDesliga() { comando(false); }

// /dados: JSON para o painel e para a IA
void dados() {
  String j = "{\"luz\":";
  j += ligado[0] ? "true" : "false";
  j += ",\"ventilador\":";
  j += ligado[1] ? "true" : "false";
  unsigned long s =
    (millis() - ultimoMovimento) / 1000;
  j += ",\"sem_movimento_s\":" + String(s);
  j += "}";
  servidor.send(200, "application/json", j);
}

// /: página com botões para o celular
void painel() {
  String h = "<meta name=viewport "
    "content='width=device-width'>"
    "<h2>Sala</h2>";
  for (int i = 0; i < 2; i++) {
    String n = String(i + 1);
    h += "<p>" + String(NOME[i]) + ": ";
    h += ligado[i] ? "ligado" : "desligado";
    h += "<br><a href=/liga?c=" + n;
    h += ">Liga</a> | <a href=/desliga?c=";
    h += n + ">Desliga</a></p>";
  }
  h += "<p><a href=/desliga?c=0>";
  h += "Desligar tudo</a></p>";
  servidor.send(200, "text/html", h);
}

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 2; i++) {
    // relé desligado antes de virar saída
    digitalWrite(RELE[i], DESLIGA);
    pinMode(RELE[i], OUTPUT);
  }
  pinMode(PINO_PIR, INPUT);
  WiFi.begin(REDE, SENHA);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("\nPainel em http://");
  Serial.println(WiFi.localIP());
  // relógio pela internet, fuso -3 h
  configTime(-3 * 3600, 0, "pool.ntp.org");
  servidor.on("/", painel);
  servidor.on("/liga", rotaLiga);
  servidor.on("/desliga", rotaDesliga);
  servidor.on("/dados", dados);
  servidor.begin();
}

void loop() {
  servidor.handleClient();

  // presença: movimento acende a luz
  if (digitalRead(PINO_PIR) == HIGH) {
    ultimoMovimento = millis();
    if (!ligado[0]) aciona(0, true);
  }
  // 10 min sem ninguém: apaga a luz
  unsigned long parado =
    millis() - ultimoMovimento;
  if (ligado[0] && parado > SEM_GENTE_MS) {
    aciona(0, false);
  }

  // horário: às 22 h desliga tudo, 1 vez/dia
  struct tm t;
  if (getLocalTime(&t, 10) &&
      t.tm_hour == HORA_DESLIGA &&
      t.tm_mday != diaDesligou) {
    aciona(0, false);
    aciona(1, false);
    diaDesligou = t.tm_mday;
  }
}
Versão 1 tem um furo de propósito. Depois das 22 h, se alguém passar na frente do PIR, a luz acende de novo. Na versão 2, faça a presença só valer entre 6 h e 22 h. É um bom primeiro ajuste para anotar no caderno de testes.

A camada de IA

O que a IA faz neste projeto

Comando em texto

Você escreve "desliga tudo da sala" ou "liga só o ventilador". A IA traduz a frase para um comando curto que o ESP32 entende.

Comando por voz

Use o ditado do teclado do celular ou do computador: a fala vira texto e o resto é igual ao comando em texto.

Lista fechada de ações

A IA só sugere. O script confere se a resposta é "liga" ou "desliga" e se o canal existe. Qualquer outra coisa é recusada.

Script em Python, rodando no computador na mesma rede. Na versão 1, você mesmo cola o pedido no chat da IA e cola a resposta de volta. Funciona sem chave nenhuma.

# comando.py — frase em português vira
# comando para o ESP32
import json, urllib.request

# troque pelo IP do seu ESP32
ESP = "http://192.168.0.50"
CANAIS = {0: "todos", 1: "luz da sala",
          2: "ventilador"}
ACOES = {"liga", "desliga"}

def perguntar_ia(prompt):
    # Versão 1: cole o prompt no chat da IA
    # e cole aqui a resposta.
    # Versão 2: troque pela biblioteca do
    # serviço que você usa, com a SUA chave
    # numa variável de ambiente (nunca no
    # código), ou por um modelo local no PC.
    print(prompt)
    return input("Resposta da IA: ")

frase = input("Comando: ")
prompt = (
    "Você controla uma sala. Canais: "
    + json.dumps(CANAIS, ensure_ascii=False)
    + '. Responda SÓ um JSON assim: '
    '{"canal": 1, "acao": "desliga"}. '
    "acao é liga ou desliga. Comando: "
    + frase
)
resposta = perguntar_ia(prompt)

# confere ANTES de acionar
try:
    cmd = json.loads(resposta)
    c, a = int(cmd["canal"]), cmd["acao"]
except Exception:
    c, a = -1, ""
if a in ACOES and c in CANAIS:
    urllib.request.urlopen(f"{ESP}/{a}?c={c}")
    print("Feito:", a, CANAIS[c])
else:
    print("Comando recusado:", resposta)
Chave de IA é como senha. Nunca escreva a chave dentro do código do ESP32 nem em arquivo que vai para o GitHub. Guarde numa variável de ambiente do computador e siga a documentação do serviço que você escolheu.

Teste e melhore

Confira antes de mostrar para alguém

Checklist
  • Ao ligar a placa, nenhum relé clica sozinho.
  • Cada botão do painel liga e desliga o canal certo; "Desligar tudo" apaga os dois.
  • Passando a mão na frente do PIR, a luz acende; parado por 10 min, apaga.
  • Com HORA_DESLIGA na hora atual, tudo desliga e não volta a desligar no mesmo dia.
  • O script de IA recusa uma resposta inventada, como canal 5 ou "pisca".
Erro comumCausa provávelComo resolver
Relé fica ligado diretoRelé liga com HIGH, não com LOWTroque LIGA e DESLIGA no código
Relé não clica, só o LED acende fracoMódulo não aceita sinal de 3,3 VUse um módulo que aceite 3,3 V, ou com jumper de nível alto/baixo
Luz acende sozinha toda horaPIR aquecendo, sensível demais ou mirando janela e ar-condicionadoEspere 1 min ao ligar, baixe o trimpot de sensibilidade (Sx) e mude a mira
Desligar às 22 h não funcionaSem internet, o relógio não acertaConfira o Wi-Fi; imprima a hora no Monitor Serial com Serial.println(&t, "%H:%M")
Cooler não gira+ e − invertidos ou fio no NC em vez do NOConfira as cores e use o borne NO de cada relé

Caderno de testes. Cada vez que mudar alguma coisa, anote numa linha. Depois de uma semana na sala, você sabe quantas horas a luz ficaria acesa à toa, e isso vira argumento de venda.

DataVersãoO que mudouResultado
20/10v1Botões, PIR com 10 min, desliga às 22 hLuz acendeu às 23 h quando o gato passou
21/10v2Presença só vale entre 6 h e 22 hNoite toda apagada
…v3Contar quantos minutos cada canal ficou ligado no diaAnote aqui

Segurança

Tomada não entra no kit

No kit, só 12 V. Relé ligado em lâmpada ou aparelho de tomada (127/220 V), em portão eletrônico ou dentro do quadro de energia: só um eletricista ou adulto responsável faz, com a energia desligada e tudo em caixa fechada. Módulo de relé barato não é feito para carga alta, como chuveiro, aquecedor ou ar-condicionado. Desligue a fonte de 12 V da tomada antes de mexer nos fios.

Ficha de negócio

Como vender o controle

Quem compraEscola com sala que fica com luz e ventilador ligados depois da aula, pequeno comércio que esquece a vitrine acesa, vizinho que quer apagar a luz da garagem pelo celular
Custo do kitR$ 70–120 (lista acima, a conferir)
Preço sugeridoR$ 200–350 o controle montado, testado, em caixa (sugestão)
Mão de obra1 a 2 horas para configurar o Wi-Fi, os horários e ensinar o painel. A ligação na rede de 127/220 V é do eletricista do cliente
Assinatura opcionalR$ 10–25 por mês: ajuste de horários, relatório de horas ligadas e comando por texto (sugestão)
Argumento de economiaMostre a conta: potência (W) × horas ligadas à toa por dia × 30 ÷ 1000 = kWh no mês; × tarifa da conta de luz do cliente (R$/kWh). Ex.: 400 W × 2 h × 30 = 24 kWh por mês, vezes a tarifa
Meça antes de prometer. Deixe o controle uma semana na sala só registrando o PIR, sem desligar nada. As horas sem ninguém com a luz acesa são o número que você mostra ao diretor.

Para ir além

Próximos passos

Para entender como o modelo transforma uma frase em comando, comece pelo curso IA do zero. Para usar um agente de IA que ajuda a escrever e corrigir o código, siga para o OSWork. Todos os cursos são abertos e gratuitos no INEMA.CLUB.