ESP32 e Arduino

Projeto de Sensor ESP32 Alimentado por Bateria: Placas, Reguladores e Intervalos de Publicação MQTT

Um guia prático para projetar um sensor ESP32 alimentado por bateria: escolha da placa, reguladores de baixa corrente quiescente, monitoramento da tensão da bateria, reconexões Wi-Fi rápidas e intervalos de publicação MQTT que prolongam a autonomia.

Nó sensor ESP32 alimentado por bateria com célula LiPo e divisor de tensão enviando leituras MQTT para a nuvem
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

Um sensor ESP32 alimentado por bateria pode funcionar por meses com uma única célula, mas só se o hardware e o firmware forem projetados juntos. Este guia passa pela escolha da placa, pelos reguladores, pelo monitoramento da bateria e pelo ciclo de publicação, para que seu nó MQTT acorde, reporte e volte a dormir gastando o mínimo possível de energia.

Por que a autonomia da bateria é sobretudo uma decisão de projeto

O ESP32 não é um chip de baixo consumo no sentido em que um microcontrolador sem rádio é. Com o Wi-Fi ativo ele puxa bastante corrente, e os picos de transmissão são os momentos mais caros da sua vida. Em deep sleep, o chip em si cai para microamperes. A diferença entre um nó que dura uma semana e outro que dura uma estação inteira está em quanto tempo ele passa em cada estado e em quanto o circuito ao redor desperdiça enquanto o chip dorme.

Isso dá a você três alavancas: corrente em sleep (normalmente dominada pelo regulador, pelo chip USB-serial e pelos LEDs, não pelo ESP32), tempo acordado (boot, Wi-Fi, DHCP, conexão MQTT, publicação) e frequência de despertar (reduzir o intervalo pela metade praticamente dobra a energia do rádio). A placa costuma ser a maior alavanca, então comece por ela.

Escolhendo a placa para um sensor ESP32 alimentado por bateria

Placas de desenvolvimento são feitas para a comodidade na bancada. Normalmente incluem uma ponte USB-UART sempre ligada, um LED de alimentação e um regulador linear escolhido pelo preço, e não pela corrente quiescente. Cada um desses itens pode consumir em sleep muito mais do que o próprio ESP32.

Opção Comportamento em sleep Indicada para
DevKit genérico (ESP32-WROOM + AMS1117 + ponte USB) Ruim: regulador e chip USB consomem miliamperes continuamente Apenas prototipagem de firmware
Placas vendidas como de baixo consumo (carregador LiPo, LDO de baixo Iq, USB comutável) Bom: projetadas para deep sleep, muitas vezes com conector de bateria Pequenas tiragens e pilotos em campo
Módulo puro (ESP32-WROOM / ESP32-C3 / ESP32-C6) em PCB própria Melhor: você escolhe cada componente Produtos e implantações longas
Placas baseadas em ESP32-C3 ou C6 Bom, núcleo único, corrente ativa menor que a do ESP32 clássico em muitas cargas Sensores simples que só precisam de Wi-Fi

Ao avaliar uma placa, remova o LED de alimentação, verifique se o chip USB-serial está na linha de 3,3 V e consulte a corrente quiescente do regulador. Depois meça a corrente em sleep com um multímetro em série com a bateria ou com um analisador de corrente; um medidor USB não tem sensibilidade suficiente.

Reguladores e química da bateria

O ESP32 precisa de aproximadamente 3,0–3,6 V e pode puxar picos curtos de várias centenas de miliamperes durante a transmissão Wi-Fi. Seu caminho de alimentação precisa entregar esses picos sem brownout e desperdiçar quase nada em repouso.

Uma célula LiPo / Li-ion (3,0–4,2 V). A escolha mais comum. Use um regulador de baixa queda (LDO) com corrente quiescente na faixa de poucos microamperes e folga suficiente para os picos de transmissão. À medida que a célula descarrega rumo a 3,3 V, o LDO perde a regulação, então planeje que o nó deixe de reportar com confiabilidade por volta de 3,4–3,5 V na célula, e envie um alerta de bateria fraca bem antes disso.

Célula LiFePO4 (cerca de 3,2–3,3 V nominais). Sua tensão fica dentro da faixa de operação do ESP32 na maior parte da curva de descarga, por isso alguns projetos dispensam o regulador; antes, compare a tensão máxima de carga com os limites absolutos máximos.

Pilhas AA. Pilhas alcalinas cedem sob os picos de transmissão, principalmente no frio. Combine-as com um conversor buck-boost de baixa corrente quiescente ou use pilhas primárias de lítio.

Adicione um capacitor de reserva (algumas centenas de microfarads) perto do módulo. Ele fornece os picos de transmissão e impede que o detector de brownout reinicie o chip, uma das causas mais comuns de loops misteriosos de reboot em nós a bateria.

Monitorando a tensão da bateria

Um sensor que morre em silêncio é pior do que um que morre avisando. Meça a célula com um divisor de tensão ligado a um pino ADC e inclua o valor em todo payload MQTT.

Um divisor com dois resistores iguais de valor alto (por exemplo, 2 × 1 MΩ) reduz a tensão da célula à metade, dentro da faixa do ADC, consumindo apenas microamperes. Divisores de valor alto têm impedância de fonte alta, então adicione um pequeno capacitor (em torno de 100 nF) entre o pino ADC e o terra para dar ao ADC uma amostra estável. Se até essa fuga importar, comute o lado baixo do divisor com um MOSFET acionado por um GPIO.

No core Arduino do ESP32 2.x e 3.x, analogReadMilliVolts() aplica a calibração de fábrica e retorna milivolts diretamente, o que é muito mais preciso do que escalar você mesmo os valores brutos de analogRead(). Faça a média de várias amostras, porque leituras isoladas são ruidosas. No ESP32 clássico, use um pino ADC1 (GPIO 32–39), já que o ADC2 fica indisponível enquanto o Wi-Fi está ativo.

Um padrão de firmware acordar–publicar–dormir

O firmware abaixo é um sketch Arduino completo para um nó a bateria. Ele acorda do deep sleep, reconecta ao Wi-Fi usando o canal e o BSSID guardados na memória RTC, publica uma mensagem JSON com a tensão da bateria, desconecta de forma limpa e dorme de novo. Ele usa o servidor MQTT público (gratuito) broker.connectmq.com, então escolha um prefixo de tópico único e não envie nada sensível.

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

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* TOPIC = "connectmq/demo/7f3a91/garden-node/telemetry";

const uint64_t SLEEP_SECONDS = 600;     // publish every 10 minutes
const int BATTERY_PIN = 34;             // ADC1 pin, divider 2 x 1 MOhm
const float DIVIDER_RATIO = 2.0;

RTC_DATA_ATTR uint32_t bootCount = 0;
RTC_DATA_ATTR uint8_t savedBssid[6];
RTC_DATA_ATTR int32_t savedChannel = 0;

WiFiClient net;
PubSubClient mqtt(net);

float readBatteryVolts() {
  uint32_t sum = 0;
  for (int i = 0; i < 16; i++) sum += analogReadMilliVolts(BATTERY_PIN);
  return (sum / 16.0f) * DIVIDER_RATIO / 1000.0f;
}

bool connectWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.persistent(false);
  if (savedChannel > 0) {
    WiFi.begin(WIFI_SSID, WIFI_PASS, savedChannel, savedBssid);
  } else {
    WiFi.begin(WIFI_SSID, WIFI_PASS);
  }
  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED) {
    if (millis() - start > 10000) {
      savedChannel = 0;                 // force a full scan next time
      return false;
    }
    delay(20);
  }
  savedChannel = WiFi.channel();
  memcpy(savedBssid, WiFi.BSSID(), 6);
  return true;
}

void goToSleep() {
  mqtt.disconnect();
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * 1000000ULL);
  esp_deep_sleep_start();
}

void setup() {
  bootCount++;
  float battery = readBatteryVolts();   // read before the radio loads the cell

  if (!connectWifi()) goToSleep();

  String clientId = "esp32-batt-" + String((uint32_t)ESP.getEfuseMac(), HEX);
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setSocketTimeout(5);
  if (!mqtt.connect(clientId.c_str())) goToSleep();

  char payload[96];
  snprintf(payload, sizeof(payload),
           "{\"battery\":%.2f,\"boot\":%lu,\"rssi\":%d}",
           battery, (unsigned long)bootCount, WiFi.RSSI());
  mqtt.publish(TOPIC, payload);
  mqtt.loop();
  delay(50);                            // let the TCP stack flush
  goToSleep();
}

void loop() {}

Alguns detalhes importam aqui:

  • A bateria é lida antes de o Wi-Fi iniciar. Sob carga de transmissão a tensão da célula cai, então uma leitura feita depois parece mais baixa do que a realidade.
  • Todo caminho de falha termina em sleep. Se o Wi-Fi ou o broker estiverem inacessíveis, o nó não fica tentando para sempre e drenando a célula. Ele tenta de novo no próximo despertar.
  • Canal e BSSID em cache permitem que o rádio pule a varredura completa, o que encurta cada despertar. Se o ponto de acesso mudar, o timeout limpa o cache e o próximo boot faz a varredura normalmente.
  • Um IP estático (via WiFi.config()) também elimina a ida e volta do DHCP. Use-o quando você controlar a rede.

Para se aprofundar em modos de sleep, fontes de despertar e preservação de estado entre despertares, veja o guia de ESP32 deep sleep MQTT.

Escolhendo o intervalo de publicação

O intervalo certo depende da rapidez com que o valor muda e de quão desatualizada uma leitura pode ficar.

Medição Intervalo útil típico Observações
Temperatura de ambiente ou estufa 5–15 minutos Muda devagar; faça a média de várias amostras por despertar
Umidade do solo 30–60 minutos Muito lenta; considere amostrar com mais frequência, mas publicar só na mudança
Nível de caixa d'água 10–30 minutos Adicione uma publicação imediata ao cruzar um limite
Porta ou movimento Por evento Acorde por GPIO (ext0/ext1), não por timer
Tensão da bateria Todo despertar Barato de incluir; essencial para a manutenção

Duas técnicas esticam ainda mais o orçamento. Agrupamento: acorde rapidamente sem Wi-Fi para fazer uma leitura, guarde-a na memória RTC e só conecte a cada N despertares para publicar o lote como um único array JSON. Reporte na mudança: compare o novo valor com o último publicado guardado na memória RTC e pule o rádio por completo quando ele não tiver saído de uma banda morta. Sempre publique pelo menos um heartbeat periódico, para distinguir um sensor quieto de um sensor morto.

Configurações MQTT que economizam energia

As escolhas de protocolo no lado do dispositivo têm custo direto em tempo de rádio:

  • QoS 0 para telemetria de rotina. O QoS 1 adiciona uma ida e volta de PUBACK e mantém o rádio ligado por mais tempo. Use-o só para leituras que você não pode perder; níveis de QoS MQTT explicados aborda essa troca.
  • Mensagens retidas para o valor mais recente. Publique a telemetria com a flag retain e um dashboard que conecte entre os despertares ainda verá a última leitura imediatamente.
  • Sessões limpas e curtas. Um nó que dorme não precisa de inscrição persistente. Conecte com clean session, publique e desconecte.
  • Payloads compactos. Chaves JSON curtas bastam para algumas leituras por hora.
  • TLS custa um handshake. Conexões criptografadas na porta 8883 levam visivelmente mais tempo para se estabelecer do que TCP simples na 1883 e mantêm o rádio ligado por mais tempo. Em produção essa troca vale a pena, e ESP32 MQTT com SSL/TLS mostra como deixar o handshake o mais barato possível.

Checklist de campo antes da implantação

  1. Meça a corrente em deep sleep da placa finalizada.
  2. Registre o tempo acordado por ciclo e procure valores fora da curva causados por novas tentativas de Wi-Fi.
  3. Confirme que o nó sobrevive a uma partida a frio na menor tensão de célula esperada sem loops de brownout.
  4. Publique a tensão da bateria e um contador de boots em toda mensagem.
  5. Configure um alerta no dashboard para tensão de bateria baixa e para mensagens ausentes.
  6. Vede o gabinete, mas mantenha a antena longe de metal e das baterias.
  7. Saia do servidor MQTT público para credenciais privadas antes de instalar qualquer coisa fora da sua bancada.

Do servidor MQTT público para a produção

O servidor MQTT público em broker.connectmq.com é ideal enquanto você ajusta os intervalos, porque dá para ver as mensagens chegando com mosquitto_sub sem se cadastrar. Para implantações reais, mude para um broker privado, para que ninguém mais possa ler seus dados. O ConnectMQ dá a cada broker credenciais geradas e um client ID vinculado a elas; só a chamada de conexão muda:

mqtt.setServer("broker.connectmq.com", 8883);   // with WiFiClientSecure and the ISRG Root X1 CA
mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD");

No portal do ConnectMQ, o explorador de tópicos ao vivo e as regras de alerta por limite permitem acompanhar a tensão das baterias em toda a frota e ser notificado quando um nó cair abaixo do seu limite de troca. Se você está construindo muitos nós, o tutorial de IoT com ESP32, mais abrangente, mostra como o lado do dispositivo se encaixa em um projeto completo, e o guia de broker MQTT na nuvem explica o que um broker MQTT gerenciado tira das suas mãos.

Comece com o ConnectMQ

Prototipe seu nó a bateria contra o broker.connectmq.com hoje mesmo e depois crie um broker privado no plano Serverless gratuito em app.connectmq.com, sem cartão de crédito. É um broker MQTT gerenciado, então você investe seu tempo no orçamento de energia em vez de na manutenção do broker.

Perguntas frequentes

Quanto tempo um sensor ESP32 alimentado por bateria dura com uma célula LiPo?

Depende da corrente em sleep da placa, da duração de cada despertar e do intervalo de publicação. Uma placa com regulador de baixa corrente quiescente e sem chip USB sempre ligado, acordando a cada poucos minutos para uma publicação curta, pode funcionar por meses; um DevKit comum com a mesma célula pode durar apenas dias.

Devo usar deep sleep ou light sleep em um sensor MQTT?

Use deep sleep quando o nó reporta periodicamente e não precisa manter uma conexão. O light sleep preserva a RAM e pode manter a associação Wi-Fi, mas sua corrente em repouso é muito maior, então ele serve para nós que precisam reagir rapidamente a comandos.

Por que meu ESP32 a bateria reinicia quando o Wi-Fi liga?

Normalmente é o detector de brownout reagindo à queda de tensão durante os picos de transmissão. Adicione um capacitor de reserva perto do módulo, use um regulador capaz de fornecer a corrente de pico e verifique a resistência interna da bateria, principalmente no frio.

Posso medir a tensão da bateria sem desperdiçar corrente?

Sim. Use um divisor de valor alto com um pequeno capacitor no pino ADC, ou desligue o divisor com um MOSFET entre as leituras, e leia com analogReadMilliVolts() em um pino ADC1.

Artigos relacionados

Exemplo de MQTT com ESP-IDF: Monte um Cliente esp-mqtt do Zero

Monte um projeto ESP-IDF a partir de uma pasta vazia com o componente esp-mqtt: configuração do Wi-Fi em modo station, o handler de eventos MQTT, publicação e inscrição, propriedades do MQTT 5 e TLS com o bundle de certificados.

8 min de leitura

Usando os Recursos do MQTT 5 do esp-mqtt no ESP32 com ESP-IDF

Um projeto ESP-IDF prático que ativa o MQTT 5.0 no esp-mqtt e usa user properties, expiração de mensagens, topic aliases, expiração de sessão e response topics com um broker MQTT 5 real.

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.