Automação IoT

Detecção de Vazamento de Água com IoT: Sensores ESP32, Alarmes MQTT e Válvula de Corte Automática

Construa sensores de vazamento com ESP32 que publicam alarmes MQTT retidos e um controlador de válvula que corta o abastecimento de água automaticamente e permanece travado até que alguém o rearme.

Sistema IoT de detecção de vazamento de água com uma sonda ESP32 embaixo de uma pia e uma válvula de corte motorizada no cano principal
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

A detecção de vazamento de água com IoT transforma um gotejamento silencioso embaixo da pia em um alarme no seu celular e, melhor ainda, em uma válvula fechada antes que o piso seja arruinado. Neste tutorial você vai construir sensores de vazamento de baixo custo com ESP32 que publicam alarmes via MQTT e um controlador de válvula separado que assina todos os sensores e corta o abastecimento de água automaticamente, permanecendo fechado até que uma pessoa o rearme.

Visão geral do sistema

O design separa deliberadamente a detecção da ação:

  1. Os nós sensores de vazamento ficam onde a água pode aparecer: embaixo das pias, atrás da máquina de lavar, ao lado do aquecedor de água. Cada um publica um estado retido dry ou wet.
  2. O broker distribui os alarmes para todos os interessados.
  3. Um controlador de válvula perto da entrada principal assina todos os topics de vazamento com um único curinga e fecha uma válvula esfera motorizada no primeiro wet.
  4. Seu celular, o Home Assistant ou o Node-RED também assinam, para notificações e histórico.

Separar os papéis permite adicionar sensores sem mexer no código da válvula, e qualquer número de aplicativos pode acompanhar o mesmo alarme. Também significa que o controlador de válvula precisa falhar de forma segura, o que abordamos mais adiante.

Onde instalar os sensores de vazamento

Os vazamentos começam em lugares previsíveis. Coloque os sensores no ponto mais baixo perto de cada um deles, porque a água escorre para baixo e se acumula antes de se espalhar:

Local Causa típica Dica de instalação
Embaixo da pia da cozinha Sifão solto, mangueira flexível rompida No fundo do piso do armário, embaixo dos registros
Atrás da máquina de lavar Mangueira de entrada estourada, ralo entupido No piso, logo abaixo das conexões das mangueiras
Ao lado do aquecedor de água Tanque corroído, descarga da válvula de alívio Dentro da bandeja coletora ou na sua borda mais baixa
Lava-louças Vedação da porta, válvula de entrada Embaixo do rodapé frontal, se for acessível
Vasos sanitários e gabinetes de banheiro Válvula de enchimento, flexível rachado Atrás da base do vaso, dentro do gabinete
Porão ou área de serviço Entrada principal, falha da bomba de drenagem Perto do ralo, no canto mais baixo

Nomeie cada sensor pelo local, não por um número. Quando um alarme chega às 3 da manhã, laundry diz para onde correr; sensor-4, não.

Lista de componentes

Componente Quantidade Finalidade
ESP32 DevKit 1 por sensor + 1 para a válvula Wi-Fi e MQTT
Dois parafusos de aço inox ou uma sonda em PCB 1 par por sensor Eletrodos que a água conecta
Resistor de 100 kΩ 1 por sensor Pull-down para a leitura analógica
Válvula esfera motorizada, 12 V, com fins de curso 1 Corta o abastecimento principal
Módulo de relé de 2 canais 1 Aciona os fios de abrir/fechar da válvula
Fonte de 12 V 1 Alimentação da válvula
Buzzer opcional 1 por sensor Alarme local sem rede

Sondas de vazamento prontas, com duas placas de contato, funcionam tão bem quanto parafusos atravessando uma pequena caixa plástica. O que importa é que os eletrodos fiquem um ou dois milímetros acima do piso, para que uma fina película de água os conecte.

Ligando um sensor de vazamento

A água conduz mal em comparação com um fio, e uma tensão contínua constante nos eletrodos causa corrosão ao longo dos meses. A solução é alimentar a sonda apenas durante a medição:

Conexão Pino do ESP32
Eletrodo A GPIO 25 (excitação, em HIGH apenas durante a amostragem)
Eletrodo B GPIO 34 (entrada ADC)
Resistor de 100 kΩ GPIO 34 ao GND
Buzzer opcional GPIO 26

Seco, o ADC lê perto de zero. Molhado, a corrente passa do GPIO 25 pela água até o GPIO 34 e a leitura sobe. A água da torneira normalmente dá um salto nítido; a água destilada quase não conduz, mas vazamentos reais raramente são de água destilada.

Sketch do sensor para detecção de vazamento de água IoT

O nó faz uma amostragem a cada dois segundos, exige três leituras molhadas consecutivas antes de alarmar (para ignorar um respingo do pano de chão) e publica um estado retido para que novos assinantes o vejam na hora.

#include <WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* BROKER = "broker.connectmq.com";
const char* BASE = "connectmq/demo/w5n8c1/home1";   // seu próprio prefixo aleatório
const char* LOCATION = "kitchen-sink";
const char* CLIENT_ID = "leak-kitchen-sink-w5n8c1";

const int EXCITE_PIN = 25;
const int SENSE_PIN = 34;
const int BUZZER_PIN = 26;
const int WET_THRESHOLD = 600;      // 0..4095, calibre com um pano molhado
const int CONFIRM_SAMPLES = 3;

WiFiClient net;
PubSubClient mqtt(net);
char tState[96], tAvail[96], tRaw[96];
bool wet = false;
int wetCount = 0, dryCount = 0;

int readProbe() {
  digitalWrite(EXCITE_PIN, HIGH);
  delay(5);
  int v = analogRead(SENSE_PIN);
  digitalWrite(EXCITE_PIN, LOW);
  return v;
}

void connectMqtt() {
  while (!mqtt.connected()) {
    if (mqtt.connect(CLIENT_ID, nullptr, nullptr, tAvail, 1, true, "offline")) {
      mqtt.publish(tAvail, "online", true);
      mqtt.publish(tState, wet ? "wet" : "dry", true);
    } else {
      delay(3000);
    }
  }
}

void setup() {
  pinMode(EXCITE_PIN, OUTPUT);
  digitalWrite(EXCITE_PIN, LOW);
  pinMode(BUZZER_PIN, OUTPUT);
  snprintf(tState, sizeof tState, "%s/%s/leak/state", BASE, LOCATION);
  snprintf(tAvail, sizeof tAvail, "%s/%s/leak/availability", BASE, LOCATION);
  snprintf(tRaw, sizeof tRaw, "%s/%s/leak/raw", BASE, LOCATION);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  mqtt.setServer(BROKER, 1883);
}

void loop() {
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();

  static unsigned long last = 0;
  if (millis() - last < 2000) return;
  last = millis();

  int v = readProbe();
  if (v > WET_THRESHOLD) { wetCount++; dryCount = 0; }
  else { dryCount++; wetCount = 0; }

  if (!wet && wetCount >= CONFIRM_SAMPLES) {
    wet = true;
    mqtt.publish(tState, "wet", true);
  } else if (wet && dryCount >= 15) {   // 30 s seco antes de limpar
    wet = false;
    mqtt.publish(tState, "dry", true);
  }
  digitalWrite(BUZZER_PIN, wet ? HIGH : LOW);   // o alarme local funciona offline

  static unsigned long lastRaw = 0;
  if (millis() - lastRaw > 60000) {
    lastRaw = millis();
    char buf[8];
    snprintf(buf, sizeof buf, "%d", v);
    mqtt.publish(tRaw, buf);   // útil para calibração e deriva
  }
}

O buzzer é acionado localmente, então um vazamento é audível mesmo com o Wi-Fi fora do ar. Esse tipo de fallback local é um bom hábito em qualquer projeto relacionado à segurança.

O controlador da válvula

O nó da válvula assina <base>/+/leak/state, que corresponde a todos os sensores de todos os cômodos. No primeiro wet, ele fecha a válvula e trava: a válvula permanece fechada até que alguém envie OPEN e nenhum sensor ainda esteja informando molhado.

#include <WiFi.h>
#include <PubSubClient.h>
#include <set>
#include <string>

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* BROKER = "broker.connectmq.com";
const char* BASE = "connectmq/demo/w5n8c1/home1";
const char* CLIENT_ID = "valve-main-w5n8c1";

const int RELAY_OPEN = 32;
const int RELAY_CLOSE = 33;
const unsigned long TRAVEL_MS = 8000;   // confira o datasheet da sua válvula

WiFiClient net;
PubSubClient mqtt(net);
char tLeakAll[96], tValve[96], tValveSet[96], tAvail[96];
std::set<std::string> wetSensors;
bool closedLatched = false;

void driveValve(bool close) {
  digitalWrite(close ? RELAY_OPEN : RELAY_CLOSE, LOW);
  digitalWrite(close ? RELAY_CLOSE : RELAY_OPEN, HIGH);
  delay(TRAVEL_MS);
  digitalWrite(RELAY_OPEN, LOW);
  digitalWrite(RELAY_CLOSE, LOW);
  mqtt.publish(tValve, close ? "closed" : "open", true);
}

void onMessage(char* topic, byte* payload, unsigned int len) {
  std::string t(topic), p((char*)payload, len);
  if (t == tValveSet) {
    if (p == "CLOSE") { closedLatched = true; driveValve(true); }
    else if (p == "OPEN") {
      if (wetSensors.empty()) { closedLatched = false; driveValve(false); }
      else mqtt.publish(tValve, "closed (sensor still wet)", true);
    }
    return;
  }
  if (p == "wet") {
    wetSensors.insert(t);
    if (!closedLatched) { closedLatched = true; driveValve(true); }
  } else if (p == "dry") {
    wetSensors.erase(t);
  }
}

void connectMqtt() {
  while (!mqtt.connected()) {
    if (mqtt.connect(CLIENT_ID, nullptr, nullptr, tAvail, 1, true, "offline")) {
      mqtt.publish(tAvail, "online", true);
      mqtt.subscribe(tLeakAll, 1);
      mqtt.subscribe(tValveSet, 1);
    } else {
      delay(3000);
    }
  }
}

void setup() {
  pinMode(RELAY_OPEN, OUTPUT);
  pinMode(RELAY_CLOSE, OUTPUT);
  snprintf(tLeakAll, sizeof tLeakAll, "%s/+/leak/state", BASE);
  snprintf(tValve, sizeof tValve, "%s/utility/main-valve/state", BASE);
  snprintf(tValveSet, sizeof tValveSet, "%s/utility/main-valve/state/set", BASE);
  snprintf(tAvail, sizeof tAvail, "%s/utility/main-valve/availability", BASE);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  mqtt.setServer(BROKER, 1883);
  mqtt.setCallback(onMessage);
}

void loop() {
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();
}

Como os estados dos sensores são retidos, o controlador da válvula fica sabendo de qualquer vazamento ocorrido enquanto ele reiniciava no momento em que assina de novo. Esse é o principal motivo para reter os estados de alarme em vez de enviar eventos avulsos.

Testando o sistema

Observe tudo e depois simule um vazamento com um pano molhado ou publicando manualmente:

B=connectmq/demo/w5n8c1/home1
mosquitto_sub -h broker.connectmq.com -p 1883 -i mon-w5n8c1 -t "$B/#" -v
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-w5n8c1 -r -q 1 -t $B/laundry/leak/state -m wet
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-w5n8c1 -r -q 1 -t $B/laundry/leak/state -m dry
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-w5n8c1 -q 1 -t $B/utility/main-valve/state/set -m OPEN

Depois do teste, limpe o topic retido simulado com uma retained message vazia (-r -n). O servidor MQTT público (gratuito) é ideal para essa fase de bancada, mas seus topics podem ser lidos por qualquer pessoa e ele não é feito para dados de produção, então não deixe uma válvula real escutando nele.

Modos de falha para os quais se preparar

  1. O sensor perde a alimentação. Seu last will publica offline. Gere um alerta para isso também; um sensor morto não protege nada.
  2. O controlador da válvula perde o Wi-Fi. Ele não consegue ouvir os alarmes. Considere ligar o sensor mais crítico (aquecedor de água) diretamente a um GPIO do controlador da válvula como backup cabeado.
  3. A válvula trava. Válvulas esfera que nunca se movem podem emperrar. Exercite a válvula mensalmente com um CLOSE/OPEN agendado durante o dia.
  4. Alarmes falsos. Calibre o WET_THRESHOLD usando o topic raw e mantenha a contagem de confirmação.
  5. Queda de energia da rede elétrica. Um pequeno nobreak mantém o roteador e o controlador da válvula funcionando; sensores a bateria podem usar deep sleep com despertar ext0 pela sonda.

Escalonamento de alertas que as pessoas realmente percebem

Um alarme que ninguém vê não é um alarme. Uma escada de escalonamento simples funciona bem:

  1. Buzzer local no sensor, imediatamente e sem nenhuma rede.
  2. Notificação push do Home Assistant, do Node-RED ou de um pequeno subscriber em Python assim que chegar um estado wet.
  3. A válvula fecha automaticamente, e o estado fechado é enviado como uma segunda notificação para você saber que o abastecimento foi cortado.
  4. Lembretes repetidos a cada quinze minutos enquanto algum sensor estiver molhado ou a válvula estiver travada.
  5. Alertas de offline quando um sensor ou o controlador da válvula publicar offline, porque o silêncio pode esconder um problema.

Mantenha a lógica de notificação fora dos sensores. Os dispositivos publicam fatos; os assinantes decidem quem avisar e com que frequência.

Migrando para um broker privado

Para uma instalação real, crie um broker no portal e depois mude os dois sketches para WiFiClientSecure, porta 8883, a CA ISRG Root X1 e os seus YOUR_USERNAME, YOUR_PASSWORD e YOUR_CLIENT_ID gerados. Cada dispositivo precisa do seu próprio client ID. No portal do ConnectMQ, você pode acompanhar todos os topics de vazamento no explorador de topics ao vivo e criar regras de alerta por limite, por exemplo sobre o valor bruto da sonda.

Para notificações no celular, o Home Assistant pode assinar o mesmo curinga; nosso guia de automações MQTT no Home Assistant mostra a sintaxe dos gatilhos. Se também quiser identificar vazamentos ocultos pelo consumo durante a noite, combine isso com um medidor de água via MQTT. O guia de estrutura de topics MQTT para casa inteligente explica as convenções de /set e de estado retido usadas aqui.

Proteja sua casa com o ConnectMQ

Um sistema contra vazamentos precisa estar online quando importa, o que faz de um broker MQTT gerenciado uma base sensata. O ConnectMQ oferece TLS, credenciais geradas e regras de alerta em um único portal. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, e migre seus sensores em minutos. Mais projetos residenciais estão reunidos no guia de automação IoT.

Perguntas frequentes

Por que a válvula continua fechada depois que o piso secou?

Isso é intencional. Um vazamento geralmente significa que algo quebrou, então a válvula fica travada até que uma pessoa verifique e envie OPEN, o que só funciona quando todos os sensores informam seco.

Posso alimentar os sensores de vazamento com bateria?

Sim. Use deep sleep com despertar periódico, ou desperte pela sonda via ext0, e conecte apenas quando o estado mudar. Conte com ajustes no circuito, porque a sonda analógica precisa estar alimentada para detectar água.

Por que usar retained messages para alarmes de vazamento?

Um estado wet retido é entregue a qualquer client no momento em que ele assina, então um controlador de válvula ou um aplicativo que reinicie durante um vazamento fica sabendo dele imediatamente.

A sonda vai corroer?

Manter tensão contínua nos eletrodos o tempo todo acelera a corrosão. Alimentar a sonda apenas por alguns milissegundos por amostra, como o sketch faz, e usar eletrodos de aço inox a mantém funcionando por muito tempo.

Artigos relacionados

Guia de Configuração do Zigbee2MQTT: do Coordenador ao Painel

Instale o Zigbee2MQTT com Docker, configure o coordenador e a conexão MQTT, pareie e renomeie dispositivos, controle-os via MQTT e veja seus estados em um painel, testando primeiro no servidor MQTT público (gratuito).

8 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.