Seu portão eletrônico funciona perfeitamente, mas você sempre sonhou em controlá-lo pelo celular ou por comando de voz? Se o seu portão tem mais de 10 anos e não possui essas funcionalidades, este tutorial vai te mostrar como adicionar inteligência ao sistema existente sem precisar trocar a central.
Por que automatizar um portão antigo?
A maioria dos portões eletrônicos instalados entre 1995-2010 possui apenas controle remoto básico. Automatizar significa:
- Controle remoto ilimitado: Abra de qualquer lugar do mundo
- Integração com Alexa/Google: "Alexa, abra o portão"
- Histórico de acessos: Veja quem entrou e quando
- Múltiplos usuários: Compartilhe acesso com família
- Notificações: Receba alerta quando alguém chegar
Material necessário
Componentes eletrônicos:
- ESP32 DevKit V1 - R$ 30-50
- Módulo relé 5V 1 canal - R$ 12-25
- Sensor magnético reed switch - R$ 15-30
- Fonte 5V 2A - R$ 22-35
- Protoboard e jumpers - R$ 15-25
- Caixa plástica vedada - R$ 15-25
Ferramentas:
- Ferro de solda
- Multímetro
- Furadeira
- Chaves de fenda/phillips
Custo total: R$ 110-190
⚠️ Importante: As marcas mencionadas neste tutorial (Broadlink, Sinric Pro, Home Assistant, etc.) são citadas apenas para fins educativos e informativos. Não possuímos qualquer parceria, vínculo comercial ou patrocínio com essas empresas. As recomendações são baseadas em funcionalidade técnica e disponibilidade no mercado brasileiro.
Como funciona o sistema
O ESP32 atua como um "intermediário inteligente" entre você e a central do portão:
- Detecção: Sensor magnético monitora se portão está aberto/fechado
- Comando: ESP32 recebe comando (app, Alexa, botão)
- Acionamento: Relé simula o botão do controle remoto original
- Feedback: Sistema confirma se portão abriu/fechou
- Histórico: Registra todos os acionamentos com data/hora
Preparando o ambiente de desenvolvimento
1. Instalar Arduino IDE
Baixe em: https://www.arduino.cc/en/software
2. Configurar ESP32 no Arduino IDE
- Vá em Arquivo > Preferências
- Em "URLs Adicionais", adicione:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - Ferramentas > Placa > Gerenciador de Placas
- Procure "esp32" e instale
3. Instalar bibliotecas necessárias
No Arduino IDE: Sketch > Incluir Biblioteca > Gerenciar Bibliotecas
Instale estas bibliotecas:
- WiFi (já incluída no ESP32)
- ESPAsyncWebServer por lacamera
- AsyncTCP por dvarrel
- ArduinoJson por Benoit Blanchon
- NTPClient por Fabrice Weinberg
Montagem do circuito
Conexões ESP32:
| ESP32 | Componente |
|---|---|
| GPIO 2 | LED indicador (opcional) |
| GPIO 4 | Pino IN do módulo relé |
| GPIO 18 | Reed switch (sensor portão) |
| 5V | VCC do relé |
| GND | GND do relé e reed switch |
⚠️ Importante - Segurança:
- NUNCA conecte o ESP32 diretamente na rede elétrica 110V/220V
- Use sempre um relé adequado para isolar os circuitos
- Desligue a energia antes de fazer qualquer conexão
Esquema de ligação na central do portão:
A maioria das centrais antigas possui dois fios para botão externo (normalmente rotulados como "BOTÃO" ou "BT"). O relé vai simular o pressionamento deste botão:
Central do Portão:
- Fio 1 (BOTÃO +) → Terminal COM do relé
- Fio 2 (BOTÃO -) → Terminal NA do relé
Código do ESP32
👀 Ver código completo do ESP32
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// Configurações WiFi
const char* ssid = "SEU_WIFI";
const char* password = "SUA_SENHA";
// Pinos
const int RELAY_PIN = 4;
const int REED_PIN = 18;
const int LED_PIN = 2;
// Servidor web
AsyncWebServer server(80);
// NTP para timestamp
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", -3*3600, 60000);
// Variáveis de estado
bool portaoAberto = false;
unsigned long ultimoAcionamento = 0;
String historicoAcessos = "";
void setup() {
Serial.begin(115200);
// Configurar pinos
pinMode(RELAY_PIN, OUTPUT);
pinMode(REED_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
digitalWrite(LED_PIN, LOW);
// Conectar WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Conectando ao WiFi...");
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Piscar LED
}
digitalWrite(LED_PIN, HIGH); // LED fixo quando conectado
Serial.println("WiFi conectado!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
// Iniciar NTP
timeClient.begin();
// Configurar rotas do servidor web
configurarRotas();
// Iniciar servidor
server.begin();
Serial.println("Servidor iniciado!"
</>);
}
void loop() {
timeClient.update();
// Ler estado do sensor
bool estadoAtual = digitalRead(REED_PIN) == LOW; // LOW = portão aberto
if (estadoAtual != portaoAberto) {
portaoAberto = estadoAtual;
String evento = portaoAberto ? "ABERTO" : "FECHADO";
adicionarHistorico(evento + " (sensor)");
Serial.println("Portão: " + evento);
}
delay(100);
}
void acionarPortao() {
Serial.println("Acionando portão...");
// Pulso no relé (simula pressionar botão)
digitalWrite(RELAY_PIN, HIGH);
delay(500); // 0.5 segundos
digitalWrite(RELAY_PIN, LOW);
ultimoAcionamento = millis();
adicionarHistorico("ACIONADO (comando)");
}
void adicionarHistorico(String evento) {
String timestamp = timeClient.getFormattedTime();
String entrada = timestamp + " - " + evento + "\n";
historicoAcessos = entrada + historicoAcessos;
// Manter apenas últimas 50 entradas
int contadorLinhas = 0;
int posicao = 0;
while ((posicao = historicoAcessos.indexOf('\n', posicao + 1)) != -1) {
contadorLinhas++;
if (contadorLinhas >= 50) {
historicoAcessos = historicoAcessos.substring(0, posicao);
break;
}
}
}
void configurarRotas() {
// Página principal
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
String html = gerarPaginaHTML();
request->send(200, "text/html", html);
});
// Acionar portão
server.on("/acionar", HTTP_POST, [](AsyncWebServerRequest *request){
acionarPortao();
request->send(200, "application/json", "{\"status\":\"ok\",\"message\":\"Portão acionado\"}");
});
// Status do portão
server.on("/status", HTTP_GET, [](AsyncWebServerRequest *request){
StaticJsonDocument<200> doc;
doc["portaoAberto"] = portaoAberto;
doc["ultimoAcionamento"] = ultimoAcionamento;
doc["timestamp"] = timeClient.getFormattedTime();
String response;
serializeJson(doc, response);
request->send(200, "application/json", response);
});
// Histórico
server.on("/historico", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", historicoAcessos);
});
}
String gerarPaginaHTML() {
String html = R"(
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<title>Controle do Portão</title>
<style>
body { font-family: Arial; text-align: center; margin: 20px; }
.button {
background: #4CAF50; color: white; padding: 15px 30px;
border: none; border-radius: 5px; font-size: 18px;
cursor: pointer; margin: 10px;
}
.button:hover { background: #45a049; }
.status {
padding: 10px; margin: 20px 0; border-radius: 5px;
font-weight: bold; font-size: 16px;
}
.aberto { background: #f44336; color: white; }
.fechado { background: #4CAF50; color: white; }
#historico {
text-align: left; background: #f5f5f5;
padding: 10px; border-radius: 5px;
font-family: monospace; white-space: pre-line;
max-height: 300px; overflow-y: auto;
}
</style>
</head>
<body>
<h1>🚪 Controle do Portão Inteligente</h1>
<div id='status' class='status'>
Carregando status...
</div>
<button class='button' onclick='acionarPortao()'>
🔄 Acionar Portão
</button>
<h3>📋 Histórico de Acessos</h3>
<div id='historico'>Carregando histórico...</div>
<script>
function atualizarStatus() {
fetch('/status')
.then(response => response.json())
.then(data => {
const statusDiv = document.getElementById('status');
if (data.portaoAberto) {
statusDiv.textContent = '🔓 PORTÃO ABERTO';
statusDiv.className = 'status aberto';
} else {
statusDiv.textContent = '🔒 PORTÃO FECHADO';
statusDiv.className = 'status fechado';
}
});
}
function acionarPortao() {
fetch('/acionar', { method: 'POST' })
.then(response => response.json())
.then(data => {
alert(data.message);
setTimeout(atualizarStatus, 2000); // Atualizar após 2s
});
}
function atualizarHistorico() {
fetch('/historico')
.then(response => response.text())
.then(data => {
document.getElementById('historico').textContent = data || 'Nenhum histórico ainda.';
});
}
// Atualizar a cada 5 segundos
setInterval(atualizarStatus, 5000);
setInterval(atualizarHistorico, 10000);
// Carregar inicial
atualizarStatus();
atualizarHistorico();
</script>
</body>
</html>
)";
return html;
}Interface Web Completa
O sistema inclui uma interface web responsiva com controle completo do portão:
Funcionalidades da interface:
- 🚪 Status em tempo real: Portão aberto/fechado
- 🔄 Botão de acionamento: Abrir/fechar remotamente
- 📋 Histórico completo: Últimos 50 eventos
- 📱 Design responsivo: Funciona em qualquer dispositivo
- 🔄 Atualização automática: Status a cada 5 segundos
Instalação física
1. Localização do ESP32
Instale próximo à central do portão, em local protegido da chuva:
- Dentro de caixa vedada IP65
- Próximo a tomada 110V/220V
- Com sinal WiFi adequado
2. Instalação do sensor reed switch
O sensor detecta se o portão está aberto/fechado:
- Fixe o ímã na parte móvel do portão
- Fixe o sensor na parte fixa (pilar/muro)
- Distância máxima: 2cm entre ímã e sensor
- Teste antes de fixar definitivamente
3. Conexão na central existente
⚠️ IMPORTANTE: Desligue a energia antes desta etapa
- Localize os terminais "BOTÃO" na sua central
- Desconecte um dos fios do botão existente (se houver)
- Conecte os terminais COM e NA do relé nestes pontos
- O botão original continuará funcionando normalmente
Configuração e teste
1. Upload do código
- Conecte ESP32 no computador via USB
- Selecione a placa: ESP32 Dev Module
- Selecione a porta COM correta
- Altere SSID e senha do WiFi no código
- Faça upload
2. Primeiro teste
- Abra o monitor serial (115200 baud)
- ESP32 deve conectar ao WiFi e exibir o IP
- Acesse o IP no navegador
- Teste o botão "Acionar Portão"
3. Teste do sensor
- Aproxime/afaste o ímã do sensor
- Status deve mudar na interface web
- Histórico deve registrar as mudanças
Integração com Alexa
Para controle por voz, use o serviço Sinric Pro (gratuito para até 3 dispositivos):
1. Criar conta no Sinric Pro
- Acesse: https://sinric.pro/
- Crie conta gratuita
- Adicione dispositivo tipo "Switch"
2. Código adicional para Alexa
Adicione estas linhas no início do código:
#include <SinricPro.h>
#include <SinricProSwitch.h>
#define SINRIC_APP_KEY "SEU_APP_KEY"
#define SINRIC_APP_SECRET "SEU_APP_SECRET"
#define SINRIC_DEVICE_ID "SEU_DEVICE_ID"
bool onPowerState(const String &deviceId, bool &state) {
acionarPortao();
state = true; // Sempre retorna true após acionar
return true;
}
// No setup(), adicione:
SinricProSwitch& mySwitch = SinricPro[SINRIC_DEVICE_ID];
mySwitch.onPowerState(onPowerState);
SinricPro.begin(SINRIC_APP_KEY, SINRIC_APP_SECRET);3. Vincular com Alexa
- Instale skill "Sinric Pro" na Alexa
- Faça login com sua conta
- Descubra dispositivos
- Comando: "Alexa, ligar portão"
Troubleshooting
Problema: ESP32 não conecta ao WiFi
Soluções:
- Verificar SSID e senha no código
- Testar com celular se WiFi está funcionando
- Aproximar ESP32 do roteador
- Verificar se rede é 2.4GHz (ESP32 não suporta 5GHz)
Problema: Portão não aciona
Verificações:
- Relé está energizado? (LED do relé deve acender)
- Conexões na central estão corretas?
- Fios não estão invertidos?
- Central do portão está ligada?
Problema: Sensor não detecta posição
Soluções:
- Aproximar ímã do sensor (máximo 2cm)
- Verificar polaridade do ímã
- Testar sensor com multímetro
- Verificar conexão dos fios
Problema: Interface web não carrega
Verificações:
- ESP32 está conectado ao WiFi?
- IP está correto?
- Firewall não está bloqueando?
- Tentar acessar por outro dispositivo
Melhorias avançadas
1. Notificação push no celular
Integrate com Pushover ou Telegram Bot:
- Receba notificação quando portão abrir
- Alerta se portão ficar aberto por muito tempo
2. Controle por aplicativo dedicado
Use Blynk para criar app personalizado:
- Interface mais bonita
- Widgets customizados
- Histórico com gráficos
3. Backup de configurações
Salve configurações na memória EEPROM:
- WiFi não precisa ser reprogramado
- Configurações via interface web
4. Câmera de segurança
Adicione ESP32-CAM para:
- Ver quem está no portão
- Foto automática quando acionar
- Stream de vídeo
Considerações de segurança
1. Segurança de rede
- Use senha forte no WiFi
- Considere criar rede separada (IoT)
- Atualize firmware do roteador
2. Segurança física
- Proteja ESP32 em caixa vedada
- Dificulte acesso aos fios
- Use fonte com proteção
3. Backup manual
- Mantenha controle remoto original
- Instale botão manual de emergência
- Documente as conexões
Custo-benefício
Investimento e economia:
- Investimento inicial: R$ 110-190
- Economia vs. sistema novo: R$ 800-1500
Funcionalidades adicionais:
- Controle remoto ilimitado
- Integração com Alexa/Google
- Histórico de acessos
- Notificações personalizadas
- Expansão futura (câmeras, sensores)
Conclusão
Automatizar um portão antigo com ESP32 é um projeto gratificante que combina eletrônica básica com programação e resulta em um sistema extremamente útil no dia a dia.
O sistema criado é robusto, confiável e pode ser expandido com diversas funcionalidades. Mais importante: você não precisa descartar seu equipamento antigo - apenas adiciona inteligência a ele.
Próximos passos sugeridos:
- Monte o circuito em protoboard primeiro
- Teste todas as funcionalidades
- Solde em placa perfurada para instalação definitiva
- Documente sua instalação específica
- Compartilhe sua experiência com a comunidade maker!
Tem alguma dúvida ou sugestão? A automação residencial é um mundo fascinante e este é apenas o primeiro passo de uma jornada muito interessante!
💡 Dica: Depois de dominar este projeto, você pode aplicar os mesmos conceitos para automatizar outros equipamentos antigos como interfones, sistemas de irrigação e equipamentos industriais.