Transformando seu Hidrômetro em um Dispositivo IoT Inteligente com ESP32-CAM

Você já foi surpreendido por uma conta de água abusiva no final do mês devido a um vazamento invisível? Ou simplesmente esqueceu de verificar o medidor de água na calçada?

Neste exemplo vou mostrar como criar um Leitor Inteligente de Hidrômetro utilizando o microcontrolador de baixo custo ESP32-CAM e o Telegram. Trata-se de uma solução simples, prática e altamente funcional de Internet das Coisas (IoT).

O Conceito do Projeto

A lógica é extremamente simples e eficiente:

  1. Modo Sono Profundo (Deep Sleep): O ESP32-CAM fica desligado a maior parte do tempo, consumindo quase nada de energia.
  2. Despertar Automático: No horário programado (por exemplo, 1x ao dia), ele acorda automaticamente.
  3. Iluminação e Foto: Acende o LED flash por fração de segundo, tira uma foto nítida do visor numérico e se conecta ao Wi-Fi.
  4. Envio da Foto: Transmite a imagem com o registro do consumo direto para o seu aplicativo no Telegram.
  5. Retorno ao Sono: O módulo se desliga novamente para economizar energia.

Materiais Necessários

Para montar este projeto, você não precisa de conhecimentos avançados em eletrônica:

ComponenteQuantidadeFunção no Projeto
ESP32-CAM + Câmera OV26401 un.Cérebro do sistema + sensor de imagem de 2 Megapixels.
Fonte de Alimentação 5V (USB)1 un.Carregador de celular padrão (5V / 2A) para garantir energia suficiente ao Wi-Fi.
Caixa Hermética de Proteção (IP65)1 un.Caixa plástica para proteger os componentes de poeira e umidade no abrigo do medidor.
Fita Dupla Face / Abraçadeiras1 un.Para fixar a câmera alinhada ao visor do hidrômetro.

O Segredo Técnico: Ajustando o Foco Macro

A câmera OV2640 vem ajustada de fábrica para tirar fotos de objetos a partir de 50 cm de distância. Como ela vai ficar instalada a cerca de 10 a 15 cm do visor do hidrômetro, a imagem sairá embaçada se não fizer este ajuste simples:

  1. Localize a cola de silicone amarela travando a rosca da lente.
  2. Com cuidado (usando a ponta dos dedos ou um alicate pequeno), gire a rosca da lente no sentido anti-horário em aproximadamente 1/4 de volta.
  3. Isso ajustará o foco para curtas distâncias (Macro), tornando os números do visor perfeitamente legíveis.

Código Fonte Pronto (Arduino IDE)

Instale as bibliotecas UniversalTelegramBot e ArduinoJson no seu ambiente Arduino IDE, cole o código abaixo, preencha seus dados de Wi-Fi e Telegram, e faça o upload para a placa:

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "esp_camera.h"
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>

// ======================================================
// CONFIGURAÇÕES DE REDE E TELEGRAM
// ======================================================
const char* ssid = "NOME_DA_SUA_REDE_WIFI";
const char* password = "SENHA_DO_SEU_WIFI";
const char* BOTtoken = "SEU_BOT_TOKEN_DO_TELEGRAM";
const char* CHAT_ID = "SEU_CHAT_ID_DO_TELEGRAM";

// Pinagem Padrão da Câmera (Módulo AI-THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22
#define FLASH_LED_PIN      4

WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);

void configCamera() {
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  if(psramFound()){
    config.frame_size = FRAMESIZE_VGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }
  esp_camera_init(&config);
}

void enviarFotoTelegram() {
  digitalWrite(FLASH_LED_PIN, HIGH); // Liga o Flash LED
  delay(500); // Aguarda a luz estabilizar

  camera_fb_t * fb = esp_camera_fb_get();
  digitalWrite(FLASH_LED_PIN, LOW); // Desliga o Flash

  if(!fb) return;

  clientTCP.setInsecure(); // Ignora verificação estrita de SSL
  
  if (clientTCP.connect("api.telegram.org", 443)) {
    String head = "--Boundary\r\nContent-Disposition: form-data; name=\"chat_id\"\r\n\r\n" + String(CHAT_ID) + 
                  "\r\n--Boundary\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"hidrometro.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String tail = "\r\n--Boundary--\r\n";

    size_t totalLen = head.length() + fb->len + tail.length();

    clientTCP.println("POST /bot" + String(BOTtoken) + "/sendPhoto HTTP/1.1");
    clientTCP.println("Host: api.telegram.org");
    clientTCP.println("Content-Type: multipart/form-data; boundary=Boundary");
    clientTCP.println("Content-Length: " + String(totalLen));
    clientTCP.println();
    clientTCP.print(head);

    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    for (size_t n=0; n<fbLen; n+=1024) {
      if (n+1024 < fbLen) {
        clientTCP.write(fbBuf + n, 1024);
      } else {
        clientTCP.write(fbBuf + n, fbLen - n);
      }
    }
    clientTCP.print(tail);
    clientTCP.stop();
  }
  esp_camera_fb_return(fb);
}

void setup() {
  pinMode(FLASH_LED_PIN, OUTPUT);
  digitalWrite(FLASH_LED_PIN, LOW);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

  configCamera();
  enviarFotoTelegram();

  // Configura sono profundo por 24 horas (em microssegundos)
  uint64_t tempoSono = 86400ULL * 1000000ULL;
  esp_sleep_enable_timer_wakeup(tempoSono);
  esp_deep_sleep_start();
}

void loop() {
  // Loop permanece vazio pois o Deep Sleep reinicia o chip a cada ciclo
}

Passo a Passo de Execução

  1. Abra o Telegram e pesquise por @BotFather.
  2. Envie o comando /newbot para criar seu robô e guarde o Token API.
  3. Pesquise por @userinfobot, envie qualquer mensagem e anote seu número de Chat ID.
  4. Abra o código na Arduino IDE, insira seu SSID, Senha do Wi-Fi, Token e Chat ID.
  5. Conecte o ESP32-CAM via módulo MB USB no PC e faça o upload (Selecione a placa AI Thinker ESP32-CAM).
  6. Instale o dispositivo na caixa hermética apontado para o medidor de água e pronto!

Próximos Passos & Automação Avançada

Este projeto pode facilmente evoluir. Com a imagem sendo gerada, você pode integrá-lo ao Home Assistant e utilizar o projeto open-source AI-on-the-edge-device, que aplica OCR (Reconhecimento Óptico de Caracteres) para ler os números da foto automaticamente e gerar gráficos do consumo de água por dia.

Ainda indo mais adiante você pode adicionar baterias, inclusive a Energia solar deixando ainda mais econômica e a prova de falta de energia

Views: 5

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Rolar para cima