INEMA.SOLUÇÕES
Solução 6 · Água

Painel de água que acha o vazamento de madrugada

Um sensor no cano conta cada litro que passa e outro, na tampa da caixa d'água, mede o nível. O ESP32 mostra no celular quantos litros a casa gastou hoje e avisa quando a água corre às 3 h da manhã, hora em que ninguém usa. Serve para vizinhos, condomínios e sítios com caixa d'água.

Kit R$ 80–140Dificuldade: médiaTudo em 3,3 V e 5 V

Como funciona

Conta litros, mede a caixa, avisa

distância Ultrassônico na tampa caixa d'água Sensor de vazão 450 pulsos = 1 litro para a casa ESP32 conta e compara Painel litros, nível, alerta Água correndo de 2 h a 5 h por 10 min: vazamento Caixa abaixo de 20%: alerta de caixa baixa
Os limites (10 minutos, 20%) são pontos de partida. Ajuste para a casa depois de uma semana de testes.

O sensor de vazão tem uma hélice com um ímã: cada volta gera um pulso, e o YF-S201 dá cerca de 450 pulsos por litro. O ESP32 conta os pulsos e calcula os litros do dia e a vazão em litros por minuto. Na tampa, o sensor ultrassônico mede a distância até a água como um morcego: manda um som e cronometra o eco. Água vazia = distância grande. De madrugada quase ninguém abre torneira, então água correndo por muito tempo nessa hora quase sempre é descarga ou cano vazando.

Peças

Lista de compras

PeçaPara que servePreço aprox.
ESP32 DevKit V1 (30 pinos)O cérebro, com Wi-FiR$ 30–40
Sensor de vazão YF-S201 (rosca 1/2")Conta os litros que passam no canoR$ 25–35
Sensor ultrassônico HC-SR04Mede a distância até a água. Bom para o teste na bancadaR$ 8–12
Resistores 10 kΩ e 20 kΩ (2 de cada)Dois divisores que baixam o sinal de 5 V para 3,3 V. Sem 20 kΩ, use dois de 10 kΩ em sérieR$ 1–3
Adaptadores de rosca 1/2" e fita veda-roscaEncaixam o sensor de vazão no canoR$ 5–10
Caixa plástica com tampaProtege o ESP32 da umidadeR$ 8–15
Fonte 5 V (carregador de celular serve) + cabo USBAlimenta o ESP32 e os sensoresR$ 0–15
Protoboard e jumpersLigações sem soldaR$ 10–15
TotalR$ 80–140
Opcional: JSN-SR04TUltrassônico à prova d'água, para ficar na caixa de vez. Troca o HC-SR04, mesmos pinosR$ 35–55

Preços aproximados de loja online brasileira em outubro de 2026, a conferir antes de comprar. Não inclui cano, conexões extras nem o trabalho de encanador.

Ligação

O circuito, pino por pino

ESP32 VIN 5V GND GPIO 27 GPIO 19 GPIO 18 10k 20k 10k 20k GND GND YF-S201 Ultrassônico sinal (amarelo) 5V verm. · GND TRIG ECHO VCC 5V · GND VCC dos dois sensores no VIN; GND tudo junto.
Os dois sensores trabalham em 5 V e devolvem sinal de 5 V. O divisor (10 kΩ em cima, 20 kΩ para o GND) entrega cerca de 3,3 V ao pino, o máximo que o ESP32 aguenta. O TRIG vai direto: 3,3 V já basta para ele.
ComponentePino do componenteLiga no ESP32
YF-S201Vermelho · preto · amareloVIN (5 V) · GND · 10 kΩ → nó → GPIO 27; do nó, 20 kΩ ao GND
Ultrassônico (HC-SR04 ou JSN-SR04T)VCC · GND · TRIG · ECHOVIN (5 V) · GND · GPIO 19 · 10 kΩ → nó → GPIO 18; do nó, 20 kΩ ao GND
Por que o divisor? Os pinos do ESP32 aguentam até 3,3 V. Um sinal de 5 V direto no pino pode queimar a placa aos poucos. A conta: 5 V × 20k ÷ (10k + 20k) = 3,3 V.

Passo a passo

Da bancada à caixa d'água

  1. Prepare a Arduino IDE. Instale a Arduino IDE 2 e, no Gerenciador de Placas, "esp32" (Espressif). Este projeto não precisa de biblioteca extra.
  2. Teste a placa sozinha. Ligue o ESP32 no USB, 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. Monte os divisores na protoboard. Siga a tabela. Antes de ligar no pino, meça com multímetro: no nó tem que dar perto de 3,3 V quando o sinal está em 5 V.
  4. Teste o nível na bancada. Grave o código, abra o Monitor Serial (115200) e aponte o ultrassônico para a mesa a 30 cm e a 60 cm. A distância tem que acompanhar.
  5. Calibre o sensor de vazão com um balde. Ligue o sensor numa mangueira, respeitando a seta do corpo (sentido da água). Encha um balde de 10 litros e compare com os litros do painel. Se der 9 litros, ajuste PULSOS_LITRO na mesma proporção.
  6. Instale na casa, com um adulto. O lugar certo é a saída da caixa d'água, antes de chegar nas torneiras. Feche o registro, corte o cano ou use uma conexão pronta, rosqueie o sensor com veda-rosca e a seta no sentido da água. Abra o registro e procure vazamento na rosca.
  7. Coloque o ultrassônico na tampa da caixa, virado para baixo, longe da boia e da entrada de água. Meça com trena a distância da tampa até a água com a caixa cheia e anote em ALTURA_CHEIA; até o fundo, em ALTURA_VAZIA.
  8. Abra o painel. O Monitor Serial mostra o IP (ex.: 192.168.0.50). Digite no navegador do celular, na mesma rede Wi-Fi.

Código

Arduino IDE para ESP32

Troque o nome e a senha da rede, as alturas da sua caixa e grave. O relógio vem da internet (NTP), no horário de Brasília, para o ESP32 saber o que é madrugada.

// Painel de água — ESP32, Arduino IDE
// Sem biblioteca extra: WiFi, WebServer
// e time.h já vêm com a placa ESP32
#include <WiFi.h>
#include <WebServer.h>
#include <time.h>

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

// GPIO 27: sinal do YF-S201 (pelo divisor)
const int PINO_VAZAO = 27;
// GPIO 19: TRIG do ultrassônico
const int PINO_TRIG = 19;
// GPIO 18: ECHO do ultrassônico (divisor)
const int PINO_ECHO = 18;

// YF-S201: cerca de 450 pulsos por litro.
// Ajuste depois do teste do balde.
float PULSOS_LITRO = 450.0;
// Distância da tampa até a água, em cm,
// com a caixa vazia e com a caixa cheia
const float ALTURA_VAZIA = 120.0;
const float ALTURA_CHEIA = 20.0;
// Vazão de madrugada que conta como
// vazamento (L/min) e por quanto tempo (s)
const float LIMITE_LMIN = 0.2;
const int TEMPO_VAZAMENTO = 600;
// Caixa baixa abaixo de 20%
const int NIVEL_BAIXO = 20;

volatile unsigned long pulsos = 0;
unsigned long pulsosAntes = 0;
unsigned long ultimoSegundo = 0;
float litrosHoje = 0, vazao = 0;
int nivel = 0, segundosCorrendo = 0;
int diaAtual = -1;
bool vazamento = false, caixaBaixa = false;
WebServer servidor(80);

// Roda sozinha a cada pulso da hélice.
// IRAM_ATTR deixa a função na memória rápida.
void IRAM_ATTR contaPulso() {
  pulsos++;
}

// Mede a distância até a água, em cm
float medirDistancia() {
  digitalWrite(PINO_TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(PINO_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(PINO_TRIG, LOW);
  // espera o eco por até 30 ms
  unsigned long us = pulseIn(PINO_ECHO, HIGH, 30000);
  if (us == 0) return -1;
  // som: 0,0343 cm por microssegundo, ida e volta
  return us * 0.0343 / 2;
}

void medirNivel() {
  float d = medirDistancia();
  if (d < 0) return;
  float faixa = ALTURA_VAZIA - ALTURA_CHEIA;
  float pct = (ALTURA_VAZIA - d) / faixa * 100;
  nivel = constrain((int)pct, 0, 100);
  caixaBaixa = nivel < NIVEL_BAIXO;
}

void medirVazao() {
  // copia o contador sem a interrupção mexer
  noInterrupts();
  unsigned long p = pulsos;
  interrupts();
  unsigned long novos = p - pulsosAntes;
  pulsosAntes = p;
  float litros = novos / PULSOS_LITRO;
  litrosHoje += litros;
  // litros em 1 s × 60 = litros por minuto
  vazao = litros * 60;
}

void conferirHora() {
  struct tm t;
  if (!getLocalTime(&t, 10)) return;
  // virou o dia: zera os litros
  if (t.tm_mday != diaAtual) {
    diaAtual = t.tm_mday;
    litrosHoje = 0;
  }
  bool madrugada = t.tm_hour >= 2 && t.tm_hour < 5;
  if (madrugada && vazao > LIMITE_LMIN) {
    segundosCorrendo++;
  } else {
    segundosCorrendo = 0;
  }
  if (segundosCorrendo > TEMPO_VAZAMENTO) {
    vazamento = true;
  }
}

// /dados: JSON para o painel e para a IA
void dados() {
  String j = "{\"litros_hoje\":" + String(litrosHoje, 1);
  j += ",\"vazao_lmin\":" + String(vazao, 2);
  j += ",\"nivel\":" + String(nivel);
  j += ",\"vazamento\":" + String(vazamento ? "true" : "false");
  j += ",\"caixa_baixa\":" + String(caixaBaixa ? "true" : "false");
  j += "}";
  servidor.send(200, "application/json", j);
}

// /: página que abre no celular (5 em 5 s)
void painel() {
  String h = "<meta name=viewport "
    "content='width=device-width'>"
    "<meta http-equiv=refresh content=5>";
  h += "<h2>Água</h2><p>Hoje: " + String(litrosHoje, 1);
  h += " L<br>Agora: " + String(vazao, 1) + " L/min";
  h += "<br>Caixa: " + String(nivel) + "%</p>";
  if (vazamento) h += "<p><b>ALERTA: vazamento</b></p>";
  if (caixaBaixa) h += "<p><b>ALERTA: caixa baixa</b></p>";
  servidor.send(200, "text/html", h);
}

// /zera: apaga o alerta depois do conserto
void zera() {
  vazamento = false;
  servidor.send(200, "text/plain", "ok");
}

void setup() {
  Serial.begin(115200);
  pinMode(PINO_TRIG, OUTPUT);
  pinMode(PINO_ECHO, INPUT);
  pinMode(PINO_VAZAO, INPUT);
  attachInterrupt(digitalPinToInterrupt(PINO_VAZAO),
                  contaPulso, FALLING);
  WiFi.begin(REDE, SENHA);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // horário de Brasília: UTC -3 h
  configTime(-3 * 3600, 0, "pool.ntp.org");
  Serial.print("\nPainel em http://");
  Serial.println(WiFi.localIP());
  servidor.on("/", painel);
  servidor.on("/dados", dados);
  servidor.on("/zera", zera);
  servidor.begin();
}

void loop() {
  servidor.handleClient();
  if (millis() - ultimoSegundo < 1000) return;
  ultimoSegundo = millis();
  medirVazao();
  medirNivel();
  conferirHora();
  Serial.printf("hoje=%.1f L vazao=%.2f nivel=%d%%\n",
                litrosHoje, vazao, nivel);
}
Limite da versão 1: os litros do dia ficam na memória e zeram se o ESP32 reiniciar ou faltar luz. Na versão 2, guarde o total na memória flash (biblioteca Preferences, que já vem com a placa) ou deixe o script do computador registrar o histórico.

A camada de IA

O que a IA faz neste projeto

Quanto gastei esta semana?

Um script no computador guarda os litros de cada hora num arquivo. A IA lê o histórico e responde em português, com o dia que mais gastou.

Vazamento explicado

Quando o alerta acende, a IA olha o horário e a vazão e sugere onde procurar: "fluxo baixo e constante parece descarga; fluxo alto parece cano".

Comparar dias

"Domingo gastou o dobro de segunda, o que mudou?" A IA cruza os horários de pico e aponta banho longo, máquina de lavar ou mangueira.

Script em Python, rodando no computador na mesma rede. Rode python agua_ia.py guarda e deixe aberto; depois python agua_ia.py pergunta.

# agua_ia.py — roda no computador,
# na mesma rede do ESP32
import csv, json, sys, time
import urllib.request
from datetime import datetime

# troque pelo IP do seu ESP32
URL = "http://192.168.0.50/dados"
ARQ = "agua.csv"

def guarda():
    # uma linha por hora: data, litros, nível
    while True:
        d = json.load(urllib.request.urlopen(URL))
        agora = datetime.now().strftime("%Y-%m-%d %H:00")
        with open(ARQ, "a", newline="") as f:
            csv.writer(f).writerow(
                [agora, d["litros_hoje"], d["nivel"]])
        time.sleep(3600)

def pergunta():
    # últimas 7 x 24 linhas = uma semana
    linhas = open(ARQ).read().splitlines()[-168:]
    q = input("Pergunta: ")
    prompt = (
        "Você analisa o consumo de água de uma casa. "
        "Cada linha: data e hora, litros do dia "
        "até aquela hora, nível da caixa em %.\n"
        + "\n".join(linhas)
        + "\nResponda em português, em até 4 frases: "
        + q
    )
    print(prompt)
    # Mande o prompt ao modelo que você usa:
    # - cole no chat do serviço de IA; ou
    # - use a biblioteca oficial do serviço,
    #   com a SUA chave numa variável de
    #   ambiente (nunca escrita no código); ou
    # - rode um modelo local no PC, sem chave.

if sys.argv[1:] == ["guarda"]:
    guarda()
else:
    pergunta()
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
  • No nó de cada divisor, o multímetro marca no máximo 3,3 V.
  • O teste do balde de 10 litros dá entre 9,5 e 10,5 litros no painel.
  • Com a torneira fechada, a vazão marca 0 L/min.
  • Aproximando a mão do ultrassônico, o nível sobe; afastando, desce.
  • A rosca do sensor de vazão não pinga depois de 1 hora com o registro aberto.
  • Para testar o alerta sem esperar a madrugada, mude por um dia as horas 2 e 5 no código para a hora atual e deixe uma torneira pingando.
Erro comumCausa provávelComo resolver
Litros sempre zeroSensor com a seta ao contrário ou fio amarelo soltoConfira a seta no sentido da água e o divisor até o GPIO 27
Litros a mais ou a menosCada sensor varia um poucoRefaça o teste do balde e ajuste PULSOS_LITRO
Nível pula ou dá 0%Eco batendo na parede, na boia ou condensação no sensorCentralize o sensor, afaste da boia; na caixa, use o JSN-SR04T
Alerta de vazamento sem vazamentoAlguém usou água de madrugada ou a caixa enchendo pela boiaSensor na saída da caixa, não na entrada; aumente TEMPO_VAZAMENTO
Litros zeram do nadaESP32 reiniciou (queda de luz, fonte fraca)Fonte de 5 V boa; na versão 2, salve o total na flash

Caderno de testes. Cada vez que mudar alguma coisa, anote numa linha. O registro da primeira semana vira o argumento de venda.

DataVersãoO que mudouResultado
20/10v1450 pulsos por litro, de fábricaBalde de 10 L marcou 9,2 L
21/10v2PULSOS_LITRO = 414Balde marcou 10,0 L
…v3Total do dia salvo na flashAnote aqui

Segurança

Água, cano e altura

Encanamento e caixa d'água: com um adulto. Cortar cano, mexer no registro ou subir na caixa d'água só com adulto ou encanador. Feche o registro antes de instalar o sensor de vazão. Escada e telhado: nunca sozinho.
Eletrônica longe da água. Tudo aqui funciona em 5 V, pelo carregador de celular. Deixe o ESP32 numa caixa fechada, acima do cano e longe de respingos, e passe os fios do sensor por baixo, para a água escorrer sem entrar na caixa.

Ficha de negócio

Como vender o painel de água

Quem compraVizinho com conta de água alta, condomínio (um painel por bloco ou por caixa), sítio com caixa d'água ou poço, escola
Custo do kitR$ 80–140 (lista acima, a conferir); mais R$ 35–55 se usar o JSN-SR04T
Preço sugeridoR$ 250–380 o aparelho montado, calibrado e em caixa (sugestão)
Mão de obra2 a 3 horas para instalar com o encanador ou o responsável pela casa, calibrar com o balde e ensinar a ler o painel
Assinatura opcionalR$ 15–25 por mês: histórico, relatório da semana e aviso de vazamento (sugestão)
Argumento de economiaMeça na casa do cliente: litros por hora entre 2 h e 5 h × 24 × 30 = litros perdidos por mês. Divida por 1.000 para ter m³ e multiplique pela tarifa da conta de água dele (a conferir)
Exemplo de conta para mostrar ao cliente: se o painel mostrar 6 litros por hora de madrugada, são 6 × 24 × 30 = 4.320 litros por mês, ou 4,3 m³ que a casa paga sem usar. Faça a conta com o número que o painel mediu de verdade.

Para ir além

Próximos passos

Para entender como o modelo de IA lê o histórico e por que às vezes erra, 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.