Tutorial de MQTT com ESP32: Mosquitto, Home Assistant e ESPHome
Tutorial de MQTT com ESP32: instale o Mosquitto, publique dados de sensores e controle um relé com PubSubClient, use o discovery do Home Assistant, veja um exemplo de YAML no ESPHome e entenda o QoS.
Juntar o ESP32 com MQTT é a forma mais comum de fazer os sensores e relés da sua casa conversarem entre si e com um sistema de casa inteligente como o Home Assistant. O MQTT é um protocolo de mensagens leve, criado para dispositivos pequenos: o ESP32 deixa a temperatura que mediu em um tópico como “ev/salon/sicaklik”, e todo programa que está ouvindo esse tópico recebe o valor na hora. Do mesmo jeito, quando você toca em um botão no app do Home Assistant no celular, o comando “ON” chega ao ESP32 em bem menos de um segundo e aciona o relé. Diferente do HTTP, ele não abre uma nova conexão a cada requisição; funciona sobre uma única conexão aberta, com cabeçalhos de apenas dois bytes, por isso é rápido e não sobrecarrega nem o Wi-Fi nem o processador.
Neste guia você vai montar do zero um nó de casa inteligente que funciona de verdade. Primeiro você vai aprender os conceitos de broker, tópico, publicar e assinar do MQTT e depois vai instalar o broker Mosquitto no Home Assistant ou em um Raspberry Pi. Em seguida, vai usar a biblioteca PubSubClient para publicar as leituras de temperatura e umidade do DHT22 a partir de um ESP32, ouvir comandos para o relé e adicionar o MQTT Discovery, para que o dispositivo apareça sozinho no Home Assistant. Também vamos ver o QoS e o retain, a mensagem de last will (LWT) que marca o dispositivo como “indisponível” quando a conexão cai, a alternativa ESPHome, que faz o mesmo trabalho sem uma única linha de C++, as diferenças no ESP8266 e no Raspberry Pi Pico W e, um por um, os erros mais comuns.

O que é MQTT e como funciona?
O MQTT (Message Queuing Telemetry Transport) usa o modelo publicar/assinar (publish/subscribe). No meio fica um servidor chamado broker; o ESP32, o Home Assistant, o seu celular ou um programa no seu computador se conectam a ele como clientes. Os clientes não se conhecem nem sabem o endereço IP uns dos outros: um publica uma mensagem em um tópico, e o broker a repassa a todos que assinam esse tópico. Pense em uma agência dos correios: o ESP32 coloca uma carta na caixa com o endereço “ev/salon/sicaklik”, e o Home Assistant, que está de olho nessa caixa, recebe a carta na hora. Como é sempre o cliente que abre a conexão, o ESP32 não precisa de IP estático nem de uma porta aberta no roteador; a única coisa que ele precisa saber é o endereço do broker.
| Conceito | Para que serve | Exemplo |
|---|---|---|
| Broker | O servidor que recebe as mensagens e as distribui aos assinantes | Mosquitto, o broker Mosquitto do Home Assistant |
| Cliente | Qualquer dispositivo ou programa que se conecta ao broker; cada um tem um ID de cliente (client ID) único | ESP32, Home Assistant, MQTT Explorer |
| Tópico (topic) | O endereço de uma mensagem, formado por níveis separados por barras | ev/salon/sicaklik |
| Publicar (publish) | Enviar uma mensagem para um tópico | Enviar o valor “23.4” para ev/salon/sicaklik |
| Assinar (subscribe) | Registrar-se para receber as mensagens de um tópico | O ESP32 ouvindo ev/salon/role/komut |
| Payload (conteúdo) | O conteúdo de uma mensagem; texto, número ou JSON | ON, 23.4, {"sicaklik":23.4} |
| Retain | O broker guarda a última mensagem de um tópico e a entrega na hora a novos assinantes | Estado do relé: ON |
| LWT (last will) | Uma mensagem que o broker publica em nome de um cliente se ele cair sem avisar | ev/salon/baglanti: offline (tópico e mensagem de último desejo) |
| QoS | O nível de garantia de entrega de uma mensagem (0, 1 ou 2) | QoS 1 para comandos do relé |
Por que MQTT? Comparação com servidor web, Blynk e Telegram
| Método | Vantagens | Desvantagens | Melhor para |
|---|---|---|---|
| MQTT + Home Assistant | Local e rápido, nos dois sentidos; centenas de dispositivos em um único painel, automações | É preciso manter um broker | Gerenciar a casa inteira em um só lugar |
| Servidor web no ESP32 | Sem servidor extra, abre no navegador | Cada dispositivo tem sua própria página, sem automações entre dispositivos | Painel de controle de um único dispositivo |
| Blynk IoT | Painel pronto no celular, acesso pela internet | Depende da nuvem, limites no plano grátis | Protótipos móveis rápidos |
| Bot do Telegram | Notificações instantâneas grátis, sem redirecionamento de portas | Sem gráficos nem painel | Alarmes e comandos simples |
| ESP-NOW | As placas ESP conversam sem roteador nem broker | Só entre placas ESP, não chega direto ao Home Assistant | Levar dados de um sensor a bateria até um gateway |
Resumindo, o MQTT brilha à medida que o número de dispositivos cresce: quando você adiciona um sensor novo, não mexe em nenhum código existente, só começa a publicar em um tópico novo. Se você quer controlar um único dispositivo pelo navegador, o guia ESP32 Async Web Server e WebSocket leva ao resultado mais rápido; para notificações no celular, veja bot do Telegram com ESP32, e para um painel móvel pronto, veja Blynk com ESP32. Para um sensor no jardim, fora do alcance do roteador, uma boa solução é usar o ESP-NOW para levar os dados até um ESP32 gateway conectado ao MQTT.
Estrutura dos tópicos MQTT e curingas
Os tópicos parecem caminhos de pastas: “ev/salon/sicaklik” (em turco, casa/sala/temperatura) tem três níveis e diferencia maiúsculas de minúsculas, então “Ev/Salon” e “ev/salon” são dois tópicos diferentes. Não comece com uma barra (“/ev/salon” cria um primeiro nível vazio) e evite espaços e caracteres acentuados; letras simples, números, hífens e sublinhados bastam. Ao assinar, você pode usar dois curingas: + substitui exatamente um nível (“ev/+/sicaklik” traz a temperatura de todos os cômodos), enquanto # cobre tudo o que vem depois dele e só pode aparecer no final (“ev/#” traz todas as mensagens da casa). Os curingas só valem na assinatura; uma mensagem é sempre publicada em um tópico exato. Tópicos que começam com $ (como $SYS) são reservados para as estatísticas do próprio broker e não entram em uma assinatura com #. Para o projeto deste guia, vamos usar esta organização:
| Tópico | Quem publica | Quem ouve | Retain |
|---|---|---|---|
| ev/salon/sicaklik | ESP32 (a cada 30 segundos) | Home Assistant | Sim |
| ev/salon/nem | ESP32 (a cada 30 segundos) | Home Assistant | Sim |
| ev/salon/role/komut (tópico de comando do relé) | Home Assistant, celular, automações | ESP32 | Não |
| ev/salon/role/durum (tópico de estado do relé) | ESP32 (a cada mudança) | Home Assistant | Sim |
| ev/salon/baglanti | ESP32 (publica online), broker (publica offline) | Home Assistant | Sim |
| homeassistant/status | Home Assistant (online ao iniciar) | ESP32 | Não |
Instalando um broker MQTT: Mosquitto
O broker MQTT gratuito mais popular é o Eclipse Mosquitto; mesmo em um Raspberry Pi ele aguenta tranquilamente centenas de mensagens por segundo. Há três jeitos fáceis de instalar: o app oficial Mosquitto broker, se você usa o Home Assistant OS; o pacote apt, em um Raspberry Pi ou computador Linux separado; ou o instalador do Mosquitto no Windows. Seja qual for a escolha, o broker usa a porta 1883 para MQTT sem criptografia e a 8883 para MQTT criptografado com TLS, e só precisa estar na mesma rede doméstica que o ESP32. No Home Assistant, a instalação é assim:
- No Home Assistant, abra Configurações > Aplicativos (chamada de Complementos / Add-ons em versões antigas), clique em Instalar aplicativo e escolha Mosquitto broker na lista.
- Clique em Instalar; quando terminar, clique em Iniciar e deixe ativada a opção de iniciar com o sistema.
- Crie um usuário separado para o ESP32: em Configurações > Pessoas > Usuários, adicione um usuário chamado “esp32” com uma senha forte. Se não aparecer essa aba, ative o Modo avançado no seu perfil. Os nomes “homeassistant” e “addons” são reservados para o broker, então não os use.
- Na página Configurações > Dispositivos e serviços, a integração MQTT normalmente aparece como “Descoberto”; clique em Configurar e confirme. Se ela não aparecer, use Adicionar integração, busque por MQTT e escolha a opção que configura o Mosquitto automaticamente.
- No código do ESP32, você vai colocar o endereço IP do Home Assistant como endereço do broker (por exemplo 192.168.1.10), 1883 como porta e o usuário que acabou de criar.
Em uma máquina Linux, como um Raspberry Pi ou um Ubuntu, a instalação leva poucos comandos. Instale o broker e as ferramentas de teste com sudo apt install mosquitto mosquitto-clients. Crie o usuário “esp32” com sudo mosquitto_passwd -c /etc/mosquitto/passwd esp32 e digite a senha duas vezes; a opção -c cria o arquivo do zero, então deixe-a de fora quando for adicionar um segundo usuário, senão os usuários existentes serão apagados. Depois crie um arquivo chamado local.conf na pasta /etc/mosquitto/conf.d/, coloque nele as três linhas abaixo e reinicie o serviço com sudo systemctl restart mosquitto. No Windows, adicione as mesmas linhas ao arquivo mosquitto.conf da pasta de instalação do Mosquitto e reinicie o serviço Mosquitto Broker.
| Linha | Significado |
|---|---|
| listener 1883 (porta de escuta) | Escuta na porta 1883 em todas as interfaces de rede; sem essa linha, o Mosquitto 2.x só aceita conexões do próprio computador |
| allow_anonymous false (sem acesso anônimo) | Recusa conexões sem usuário e senha; já é o padrão no 2.x, mas escrever isso explicitamente é um bom hábito |
| password_file /etc/mosquitto/passwd (arquivo de senhas) | Usa o arquivo de senhas criado com mosquitto_passwd; as senhas ficam guardadas nele como hash |
Antes de passar para o ESP32, teste o broker pelo computador; separar logo de cara os problemas do broker dos problemas do código economiza muito tempo. Em um terminal, comece a ouvir todos os tópicos da casa com mosquitto_sub -h 192.168.1.10 -u esp32 -P suasenha -t "ev/#" -v. Em um segundo terminal, digite mosquitto_pub -h 192.168.1.10 -u esp32 -P suasenha -t ev/salon/test -m ola. Se a linha “ev/salon/test ola” aparecer no primeiro terminal, o broker está funcionando e a senha está certa. A opção -v mostra o tópico na frente de cada mensagem, e a opção -r envia a mensagem como retida (retain).
Lista de componentes e esquema de ligação
Para este projeto você precisa de uma placa de desenvolvimento ESP32, um sensor de temperatura e umidade DHT22, um módulo relé que possa ser acionado com 3,3 V, uma protoboard e jumpers. O DHT22 é mais preciso que o DHT11: mede a temperatura com ±0,5 °C e a umidade com cerca de ±2–5% e funciona de -40 a 80 °C; falamos dessa família de sensores em detalhes em Sensor de temperatura e umidade DHT11. Se você tem um DHT11, basta trocar DHT22 por DHT11 no código. Para o primeiro teste de conexão, um ESP32 e um cabo USB bastam; o sensor e o relé podem ser adicionados depois.



| Conexão | ESP32 | ESP8266 (NodeMCU) | Raspberry Pi Pico W |
|---|---|---|---|
| DHT22 VCC | 3V3 | 3V3 | 3V3(OUT) |
| DHT22 DATA | GPIO 4 | D2 (GPIO 4) | GP15 |
| DHT22 GND | GND | GND | GND |
| Relé VCC | VIN (5V) | VIN (5V) | VBUS (5V) |
| Relé IN | GPIO 26 | D1 (GPIO 5) | GP14 |
| Relé GND | GND | GND | GND |
Instalando o PubSubClient na Arduino IDE
- Se o pacote de placas do ESP32 ainda não estiver instalado na Arduino IDE, instale-o primeiro; os passos estão em O que é o ESP32?.
- Abra Ferramentas > Gerenciar Bibliotecas, digite PubSubClient no campo de busca e instale a biblioteca de Nick O'Leary. O código deste guia foi compilado com a versão 2.8.
- Na mesma janela, busque por DHT sensor library e instale a biblioteca da Adafruit; quando ela perguntar sobre as dependências, escolha Instalar tudo para que a Adafruit Unified Sensor também seja instalada.
- Se tiver problemas para instalar bibliotecas, veja o guia Como instalar uma biblioteca no Arduino.
Primeiro teste: conectando o ESP32 ao broker MQTT
Antes de adicionar os sensores, vamos confirmar com o código mais simples possível que os dados do Wi-Fi, o endereço do broker e a senha estão certos. O código abaixo se conecta ao broker, publica “merhaba” (olá) no tópico “test/esp32/durum” e mostra no Monitor Serial toda mensagem que chega em “test/esp32/komut”. Troque o nome e a senha do Wi-Fi, o IP do broker e o usuário MQTT pelos seus, carregue o código e abra o Monitor Serial em 115200 baud:
1#include <WiFi.h>
2#include <PubSubClient.h>
3
4const char* WIFI_SSID = "AgAdi"; // Wi-Fi adın (yalnız 2,4 GHz) / your Wi-Fi name (2.4 GHz only)
5const char* WIFI_PASS = "Sifre123"; // Wi-Fi şifren / your Wi-Fi password
6const char* MQTT_SUNUCU = "192.168.1.10"; // broker'ın IP adresi / broker IP address
7const int MQTT_PORT = 1883; // şifresiz MQTT portu / unencrypted MQTT port
8const char* MQTT_KULLANICI = "esp32"; // broker kullanıcı adı / broker username
9const char* MQTT_SIFRE = "mqttSifre"; // broker şifresi / broker password
10
11WiFiClient wifiIstemci; // TCP bağlantısı / TCP connection
12PubSubClient mqtt(wifiIstemci); // MQTT istemcisi / MQTT client
13
14// Abone olunan konuya mesaj gelince çalışır / runs when a subscribed topic receives a message
15void mesajGeldi(char* topic, byte* payload, unsigned int length) {
16 Serial.print("Mesaj [");
17 Serial.print(topic);
18 Serial.print("] ");
19 for (unsigned int i = 0; i < length; i++) {
20 Serial.print((char)payload[i]); // payload sonunda \0 yoktur / payload is not null-terminated
21 }
22 Serial.println();
23}
24
25void setup() {
26 Serial.begin(115200);
27 WiFi.mode(WIFI_STA);
28 WiFi.begin(WIFI_SSID, WIFI_PASS);
29 while (WiFi.status() != WL_CONNECTED) {
30 delay(500);
31 Serial.print(".");
32 }
33 Serial.print("\nIP: ");
34 Serial.println(WiFi.localIP());
35
36 mqtt.setServer(MQTT_SUNUCU, MQTT_PORT); // broker adresi / broker address
37 mqtt.setCallback(mesajGeldi); // gelen mesaj fonksiyonu / incoming message handler
38}
39
40void loop() {
41 if (!mqtt.connected()) {
42 Serial.print("MQTT baglaniyor... ");
43 if (mqtt.connect("esp32-test", MQTT_KULLANICI, MQTT_SIFRE)) { // istemci kimliği benzersiz olmalı / client ID must be unique
44 Serial.println("baglandi");
45 mqtt.subscribe("test/esp32/komut"); // bu konuyu dinle / listen to this topic
46 mqtt.publish("test/esp32/durum", "merhaba"); // ilk mesaj / first message
47 } else {
48 Serial.print("hata, rc=");
49 Serial.println(mqtt.state()); // hata kodu / error code
50 delay(5000);
51 return;
52 }
53 }
54 mqtt.loop(); // mesajları işle, bağlantıyı canlı tut / process messages, keep the connection alive
55}Quando aparecer “baglandi” (conectado) no Monitor Serial, envie mosquitto_pub -h 192.168.1.10 -u esp32 -P suasenha -t test/esp32/komut -m oi de um terminal no seu computador; em poucos milissegundos a linha “Mesaj [test/esp32/komut] oi” aparece no Monitor Serial. Se a conexão falhar, o código mostra um código de erro com mqtt.state() e tenta de novo depois de 5 segundos. Esses códigos dizem exatamente onde está o problema:
| rc | Nome no PubSubClient | Significado e solução |
|---|---|---|
| -4 | MQTT_CONNECTION_TIMEOUT | O broker não respondeu a tempo; rede fraca ou broker sobrecarregado |
| -3 | MQTT_CONNECTION_LOST | Uma conexão estabelecida caiu; normalmente porque loop() ficou muito tempo sem ser chamado ou o Wi-Fi caiu |
| -2 | MQTT_CONNECT_FAILED | A conexão TCP nem chegou a abrir: IP ou porta errados, broker desligado, Mosquitto em modo só local ou um firewall bloqueando a 1883 |
| -1 | MQTT_DISCONNECTED | A conexão foi fechada normalmente (disconnect foi chamado) ou nunca chegou a conectar |
| 2 | MQTT_CONNECT_BAD_CLIENT_ID | O ID de cliente foi recusado; foi usado um client ID vazio ou inválido |
| 4 | MQTT_CONNECT_BAD_CREDENTIALS | Usuário ou senha errados (alguns brokers devolvem esse código) |
| 5 | MQTT_CONNECT_UNAUTHORIZED | Sem autorização; o Mosquitto devolve esse código tanto para senha errada quanto para uma tentativa de conexão sem credenciais |
Publicando dados de sensor e ouvindo comandos do relé com o ESP32
Agora vamos montar o projeto de verdade. O código abaixo lê o DHT22 a cada 30 segundos e publica a temperatura e a umidade com a flag retain, controla o relé com os comandos ON, OFF e TOGGLE que chegam em “ev/salon/role/komut” e informa o novo estado do relé em “ev/salon/role/durum”. Ao se conectar, ele deixa um last will no broker, se apresenta ao Home Assistant pelo MQTT Discovery e, se a conexão cair, tenta reconectar a cada 5 segundos sem travar o loop(). Graças ao bloco #if defined(ESP8266) no início, o mesmo código também compila em uma NodeMCU sem nenhuma alteração.
1#if defined(ESP8266)
2#include <ESP8266WiFi.h>
3#else
4#include <WiFi.h>
5#endif
6#include <PubSubClient.h>
7#include <DHT.h>
8
9// ---- Ayarlar / Settings ----
10const char* WIFI_SSID = "AgAdi";
11const char* WIFI_PASS = "Sifre123";
12const char* MQTT_SUNUCU = "192.168.1.10"; // broker IP (Home Assistant ya da Raspberry Pi) / broker IP (Home Assistant or Raspberry Pi)
13const int MQTT_PORT = 1883;
14const char* MQTT_KULLANICI = "esp32";
15const char* MQTT_SIFRE = "mqttSifre";
16const char* ISTEMCI_ID = "esp32-salon"; // her cihazda farklı olmalı / must be different on every device
17
18#if defined(ESP8266)
19const int DHT_PIN = 4; // NodeMCU D2
20const int ROLE_PIN = 5; // NodeMCU D1
21#else
22const int DHT_PIN = 4; // ESP32 GPIO 4
23const int ROLE_PIN = 26; // ESP32 GPIO 26
24#endif
25const bool ROLE_AKTIF_LOW = true; // çoğu röle modülü LOW ile çeker / most relay modules switch on LOW
26const unsigned long OLCUM_ARALIGI = 30000; // 30 saniyede bir ölçüm / one reading every 30 s
27
28// ---- Konular (topic) / Topics ----
29const char* T_SICAKLIK = "ev/salon/sicaklik";
30const char* T_NEM = "ev/salon/nem";
31const char* T_KOMUT = "ev/salon/role/komut"; // ON, OFF ya da TOGGLE / ON, OFF or TOGGLE
32const char* T_DURUM = "ev/salon/role/durum";
33const char* T_BAGLANTI = "ev/salon/baglanti"; // online / offline (son vasiyet / last will)
34const char* T_HA_DURUM = "homeassistant/status"; // HA açılınca "online" yayınlar / HA publishes "online" when it starts
35
36WiFiClient wifiIstemci;
37PubSubClient mqtt(wifiIstemci);
38DHT dht(DHT_PIN, DHT22);
39
40bool roleAcik = false;
41unsigned long sonOlcum = 0;
42unsigned long sonDeneme = 0;
43
44// Röleyi sür ve yeni durumu kalıcı (retain) yayınla / drive the relay and publish the new state as retained
45void roleAyarla(bool acik) {
46 roleAcik = acik;
47 bool seviye = ROLE_AKTIF_LOW ? !acik : acik;
48 digitalWrite(ROLE_PIN, seviye ? HIGH : LOW);
49 mqtt.publish(T_DURUM, acik ? "ON" : "OFF", true);
50 Serial.println(acik ? "Role: ON" : "Role: OFF");
51}
52
53// Tek bir Home Assistant keşif mesajı gönder / send one Home Assistant discovery message
54void kesifYayinla(const char* tur, const char* nesne, const char* ad, const char* ekAlanlar) {
55 char konu[96];
56 snprintf(konu, sizeof(konu), "homeassistant/%s/%s/%s/config", tur, ISTEMCI_ID, nesne);
57 char json[600];
58 snprintf(json, sizeof(json),
59 "{\"name\":\"%s\",\"unique_id\":\"%s_%s\",%s,\"availability_topic\":\"%s\","
60 "\"device\":{\"identifiers\":[\"%s\"],\"name\":\"Salon ESP32\",\"model\":\"ESP32 + DHT22\"}}",
61 ad, ISTEMCI_ID, nesne, ekAlanlar, T_BAGLANTI, ISTEMCI_ID);
62 if (!mqtt.publish(konu, json, true)) { // false: tampon küçük ya da bağlantı yok / false: buffer too small or not connected
63 Serial.println("Kesif mesaji gonderilemedi");
64 }
65}
66
67// Sıcaklık, nem ve röleyi Home Assistant'a tanıt / announce temperature, humidity and relay to Home Assistant
68void haKesifGonder() {
69 char ek[200];
70 snprintf(ek, sizeof(ek), "\"state_topic\":\"%s\",\"device_class\":\"temperature\",\"unit_of_measurement\":\"°C\",\"state_class\":\"measurement\"", T_SICAKLIK);
71 kesifYayinla("sensor", "sicaklik", "Sıcaklık", ek);
72 snprintf(ek, sizeof(ek), "\"state_topic\":\"%s\",\"device_class\":\"humidity\",\"unit_of_measurement\":\"%%\",\"state_class\":\"measurement\"", T_NEM);
73 kesifYayinla("sensor", "nem", "Nem", ek);
74 snprintf(ek, sizeof(ek), "\"state_topic\":\"%s\",\"command_topic\":\"%s\"", T_DURUM, T_KOMUT);
75 kesifYayinla("switch", "role", "Röle", ek);
76}
77
78// DHT22'yi oku ve değerleri yayınla / read the DHT22 and publish the values
79void olcumGonder() {
80 float t = dht.readTemperature();
81 float h = dht.readHumidity();
82 if (isnan(t) || isnan(h)) {
83 Serial.println("DHT22 okunamadi");
84 return;
85 }
86 char deger[12];
87 snprintf(deger, sizeof(deger), "%.1f", t); // 23.4 gibi / like 23.4
88 mqtt.publish(T_SICAKLIK, deger, true);
89 snprintf(deger, sizeof(deger), "%.0f", h); // 45 gibi / like 45
90 mqtt.publish(T_NEM, deger, true);
91 Serial.printf("Sicaklik %.1f C, nem %.0f %%\n", t, h);
92}
93
94// Abone olunan konulara mesaj gelince çalışır / runs when a subscribed topic receives a message
95void mesajGeldi(char* topic, byte* payload, unsigned int length) {
96 // Önce kopyala: yayın yapınca kütüphane aynı tamponu kullanır / copy first: publishing reuses the same buffer
97 String konu = topic;
98 String mesaj;
99 for (unsigned int i = 0; i < length; i++) mesaj += (char)payload[i];
100 mesaj.trim();
101
102 if (konu == T_KOMUT) {
103 if (mesaj == "ON") roleAyarla(true);
104 else if (mesaj == "OFF") roleAyarla(false);
105 else if (mesaj == "TOGGLE") roleAyarla(!roleAcik);
106 } else if (konu == T_HA_DURUM && mesaj == "online") {
107 haKesifGonder(); // HA yeniden başladı, tanıtımı yenile / HA restarted, announce again
108 mqtt.publish(T_DURUM, roleAcik ? "ON" : "OFF", true);
109 }
110}
111
112bool mqttBaglan() {
113 Serial.print("MQTT baglaniyor... ");
114 // Bağlantı koparsa broker T_BAGLANTI'ya "offline" yazar / if we drop, the broker publishes "offline" to T_BAGLANTI
115 if (!mqtt.connect(ISTEMCI_ID, MQTT_KULLANICI, MQTT_SIFRE, T_BAGLANTI, 1, true, "offline")) {
116 Serial.print("hata, rc=");
117 Serial.println(mqtt.state());
118 return false;
119 }
120 Serial.println("baglandi");
121 mqtt.publish(T_BAGLANTI, "online", true);
122 mqtt.subscribe(T_KOMUT, 1); // komutları QoS 1 ile dinle / listen to commands with QoS 1
123 mqtt.subscribe(T_HA_DURUM);
124 haKesifGonder();
125 mqtt.publish(T_DURUM, roleAcik ? "ON" : "OFF", true);
126 return true;
127}
128
129void setup() {
130 Serial.begin(115200);
131 pinMode(ROLE_PIN, OUTPUT);
132 roleAyarla(false); // güvenli başlangıç: röle kapalı / safe start: relay off
133 dht.begin();
134
135 WiFi.mode(WIFI_STA);
136 WiFi.begin(WIFI_SSID, WIFI_PASS);
137 Serial.print("Wi-Fi");
138 while (WiFi.status() != WL_CONNECTED) {
139 delay(500);
140 Serial.print(".");
141 }
142 Serial.print(" IP: ");
143 Serial.println(WiFi.localIP());
144
145 mqtt.setServer(MQTT_SUNUCU, MQTT_PORT);
146 mqtt.setCallback(mesajGeldi);
147 mqtt.setBufferSize(1024); // keşif JSON'u varsayılan 256 bayta sığmaz / discovery JSON doesn't fit the default 256 bytes
148}
149
150void loop() {
151 if (!mqtt.connected()) {
152 unsigned long simdi = millis();
153 if (sonDeneme == 0 || simdi - sonDeneme >= 5000) { // 5 sn'de bir dene, loop'u kilitleme / retry every 5 s without blocking
154 sonDeneme = simdi;
155 if (mqttBaglan()) sonOlcum = simdi - OLCUM_ARALIGI; // bağlanınca hemen ölç / measure right after connecting
156 }
157 return;
158 }
159 mqtt.loop(); // gelen komutlar ve keep-alive / incoming commands and keep-alive
160
161 if (millis() - sonOlcum >= OLCUM_ARALIGI) {
162 sonOlcum = millis();
163 olcumGonder();
164 }
165}| Linha | O que faz |
|---|---|
| mqtt.connect(ISTEMCI_ID, ..., T_BAGLANTI, 1, true, "offline") (conexão com last will) | Registra o last will durante a conexão: se o ESP32 cair sem avisar, o broker grava um “offline” retido em ev/salon/baglanti |
| mqtt.publish(T_BAGLANTI, "online", true) (estado online) | Muda o estado para “online” logo após conectar; o Home Assistant volta a mostrar o dispositivo como disponível |
| mqtt.subscribe(T_KOMUT, 1) (assinatura) | Ouve os comandos do relé com QoS 1; o PubSubClient só suporta QoS 0 e 1 nas assinaturas |
| mqtt.setBufferSize(1024) (tamanho do buffer) | Aumenta o buffer de pacotes dos 256 bytes padrão; o maior pacote de discovery tem cerca de 355 bytes |
| mqtt.loop() (ciclo do MQTT) | Lê as mensagens recebidas e envia os pacotes de keep-alive (PINGREQ); precisa ser chamado a cada ciclo do loop |
| ROLE_AKTIF_LOW (relé ativo em LOW) | A maioria dos módulos relé aciona com sinal LOW; mude para false se o seu acionar com HIGH |
| OLCUM_ARALIGI (intervalo de medição) | Com que frequência medir; o DHT22 pode ser lido no máximo a cada 2 segundos, e 30–60 segundos é o ideal para temperatura ambiente |
Alguns detalhes do código são propositais. A função mesajGeldi() copia primeiro o tópico e o payload para Strings, porque o PubSubClient usa um único buffer para as mensagens que chegam e as que saem: no momento em que você chama publish() dentro do callback, os dados para os quais os ponteiros de tópico e payload apontam são sobrescritos. O payload também não termina com \0 como uma string em C, por isso lemos exatamente length caracteres. Usamos retain nas leituras e no estado do relé para que o Home Assistant veja o último valor logo depois de reiniciar, em vez de esperar 30 segundos. A temporização também é feita com millis(): um delay() longo dentro do loop() seguraria os pacotes de keep-alive, e o broker derrubaria a conexão. Explicamos essa técnica em detalhes em Arduino: millis() em vez de delay().
Como fica no Home Assistant: MQTT Discovery
O Home Assistant ouve o tempo todo os tópicos que começam com o prefixo homeassistant/. Quando um dispositivo publica uma configuração em JSON em um tópico no formato homeassistant/[componente]/[nó]/[objeto]/config, o Home Assistant cria essa entidade automaticamente; isso se chama MQTT Discovery. Nosso código envia três mensagens: duas para os sensores (temperatura e umidade) em homeassistant/sensor/esp32-salon/... e uma para o relé em homeassistant/switch/esp32-salon/role/config. Como elas são retidas, sobrevivem a uma reinicialização do Home Assistant. O código também assina homeassistant/status: o Home Assistant escreve “online” ali quando inicia, e o ESP32 se apresenta de novo. Se você tiver muitos dispositivos, a documentação do Home Assistant recomenda acrescentar um pequeno atraso aleatório antes dessa nova apresentação.
| Campo JSON | Significado | Nosso valor |
|---|---|---|
| name | O nome de exibição da entidade; o nome do dispositivo é colocado na frente | Sıcaklık (aparece como Salon ESP32 Sıcaklık) |
| unique_id | O ID permanente da entidade; sem ele, o nome e a área da entidade não podem ser editados pela interface | esp32-salon_sicaklik |
| state_topic | O tópico de onde o valor é lido | ev/salon/sicaklik |
| command_topic | O tópico para onde vão os comandos do interruptor (switch) | ev/salon/role/komut (tópico de comando do relé) |
| device_class | Define o ícone, as opções de unidade e o tipo de gráfico | temperature, humidity |
| unit_of_measurement | Unidade de medida | °C e % |
| state_class | O valor measurement ativa estatísticas e gráficos de longo prazo | measurement |
| availability_topic | O tópico de onde o estado online/offline é lido; os payloads padrão são online e offline | ev/salon/baglanti |
| device | Agrupa as entidades em um único cartão de dispositivo | identifiers, name, model (identificadores, nome, modelo) |
Poucos segundos depois de carregar o código, um dispositivo chamado “Salon ESP32” aparece em Configurações > Dispositivos e serviços > MQTT. O cartão do dispositivo traz os sensores de temperatura e umidade e um interruptor para o relé; clique na temperatura para abrir o gráfico de histórico, acione o interruptor e o relé estala. Você pode adicionar essas entidades a um painel (dashboard), liberá-las para assistentes de voz ou usá-las em automações: por exemplo, uma regra como “se a sala passar de 27 °C, ligue o relé em que o ventilador está conectado, e desligue abaixo de 25 °C” sai em poucos cliques. Se você tirar o ESP32 da tomada, as entidades passam para “Indisponível” depois de no máximo uns 22 segundos, o que mostra que a mensagem de last will está funcionando. Se preferir não usar o discovery, você também pode definir as mesmas entidades à mão no configuration.yaml, como entradas sensor e switch dentro de mqtt:.
QoS e retain: qual usar e quando?
O QoS (Quality of Service) define o quanto você quer ter certeza de que uma mensagem chega ao outro lado. Um detalhe importante: o QoS vale separadamente em dois trechos. Entre quem publica e o broker vale o QoS de quem publica, e entre o broker e um assinante vale o QoS da assinatura; a garantia que o assinante recebe é a menor das duas. O PubSubClient só suporta QoS 0 para publicar e QoS 0 e 1 para assinar. No Wi-Fi de casa, perder uma mensagem com QoS 0 é muito raro, mas deixar a assinatura dos comandos em QoS 1 ainda é um seguro barato.
| QoS | Garantia | Como funciona | Quando usar |
|---|---|---|---|
| 0 | No máximo uma vez | A mensagem é enviada uma vez, sem confirmação; pode se perder se a conexão cair naquele momento | Leituras de sensor frequentes |
| 1 | Pelo menos uma vez | O receptor confirma com PUBACK, e a mensagem é reenviada se a confirmação não chegar; pode chegar duas vezes | Comandos do relé, alarmes |
| 2 | Exatamente uma vez | Um handshake de quatro etapas com PUBREC, PUBREL e PUBCOMP; o nível mais lento | Coisas como contadores, em que duplicatas atrapalham; não suportado pelo PubSubClient |
A flag retain tem a ver com memória, e não com entrega: o broker guarda só a última mensagem retida de cada tópico e a envia na hora para quem assinar. Ela é ideal para mensagens de “estado atual”, como valores de sensores, estado do relé e status online, mas perigosa para comandos e eventos pontuais. O last will (LWT) a complementa: se o broker não receber nenhum pacote de um cliente durante 1,5 vez o período de keep-alive, ele conclui que a conexão caiu e publica a mensagem de last will. O keep-alive padrão do PubSubClient é de 15 segundos, então um ESP32 desconectado da tomada aparece como “offline” depois de no máximo uns 22 segundos. Você pode mudar isso com uma linha como mqtt.setKeepAlive(30), mas quanto maior o valor, mais tarde você vai perceber uma queda.
A alternativa sem código: ESPHome
O ESPHome é uma ferramenta gratuita que transforma um dispositivo descrito em um arquivo YAML em um firmware para ESP32 pronto para gravar; você não escreve uma única linha de C++. No Home Assistant, instale o ESPHome Device Builder em Configurações > Aplicativos, abra a interface dele e crie uma configuração com o assistente Novo dispositivo. O primeiro carregamento é feito uma vez pelo USB: o Chrome ou o Edge conseguem programar a placa diretamente e, se isso não funcionar, você pode gravar o arquivo que o assistente baixa usando a página ESPHome Web. Todas as atualizações seguintes vão pelo Wi-Fi, sem fio (OTA). A configuração abaixo é igual ao projeto Arduino acima: lê o DHT22 no GPIO 4 a cada 30 segundos e expõe o relé ativo em LOW do GPIO 26 como um interruptor. Os dados do Wi-Fi e as senhas são lidos de um arquivo secrets.yaml separado com !secret:
1esphome:
2 name: salon-sensor # küçük harf, rakam ve tire / lowercase, digits and hyphens
3 friendly_name: Salon Sensör
4
5esp32:
6 board: esp32dev
7
8logger:
9
10api: # Home Assistant ile doğrudan bağlantı / direct link to Home Assistant
11 encryption:
12 key: !secret api_anahtari
13
14ota:
15 - platform: esphome
16 password: !secret ota_sifresi
17
18wifi:
19 ssid: !secret wifi_ssid
20 password: !secret wifi_sifresi
21 ap: # Wi-Fi yoksa kendi ağını açar / opens its own network if Wi-Fi fails
22 ssid: "Salon-Sensor"
23 password: "yedek1234"
24
25captive_portal:
26
27sensor:
28 - platform: dht
29 pin: GPIO4
30 model: DHT22
31 update_interval: 30s
32 temperature:
33 name: "Sıcaklık"
34 humidity:
35 name: "Nem"
36
37switch:
38 - platform: gpio
39 name: "Röle"
40 pin:
41 number: GPIO26
42 inverted: true # aktif LOW röle / active-LOW relay
43 restore_mode: ALWAYS_OFF # açılışta kapalı / off at boot
44
45# MQTT ile kullanmak için api: bloğunu sil, bunu aç / to use MQTT, delete api: and uncomment this
46# mqtt:
47# broker: 192.168.1.10
48# username: esp32
49# password: !secret mqtt_sifresiHá uma diferença importante: por padrão, o ESPHome não usa MQTT, e sim sua própria native API criptografada. O Home Assistant encontra o dispositivo na rede sozinho e nem precisa de broker. Escolha MQTT só se quiser que outros sistemas, como o Node-RED, leiam os mesmos dados, ou se você não usa o Home Assistant. Para isso, descomente as linhas mqtt: no fim do arquivo e apague o bloco api:; se não fizer isso, o dispositivo se reinicia sozinho sempre que ninguém se conectar à native API por 15 minutos (essa é a configuração reboot_timeout). No modo MQTT, o ESPHome envia sozinho as mensagens de discovery do Home Assistant e as mensagens online/offline em salon-sensor/status, ou seja, faz automaticamente tudo o que fizemos à mão no código Arduino.
| Característica | PubSubClient (código Arduino) | ESPHome (YAML) |
|---|---|---|
| Escrever código | Você escreve tudo em C++ | Só YAML; o firmware é compilado automaticamente |
| Adicionar ao Home Assistant | Você mesmo envia os JSON de discovery | Descoberto automaticamente |
| Flexibilidade | Ilimitada; dá para usar qualquer biblioteca e lógica | Limitada a componentes prontos, mas centenas de sensores são suportados; dá para adicionar C++ com lambdas |
| Atualizações sem fio | Você mesmo adiciona o ArduinoOTA ao código | Já vem integrado |
| Precisa de broker | Sim | Não, com a native API |
| Valor de aprendizado | Ensina o protocolo MQTT e programação | Resultado rápido, esconde o que acontece por baixo |
MQTT com o ESP8266 e o Raspberry Pi Pico W
O código completo acima roda sem alterações nas placas ESP8266 NodeMCU e Wemos D1 Mini: quando você seleciona NodeMCU 1.0 em Ferramentas > Placa, o bloco #if defined(ESP8266) escolhe automaticamente ESP8266WiFi.h no lugar de WiFi.h, junto com os pinos D2 e D1. Do lado do Raspberry Pi Pico W, usamos o módulo umqtt.simple do MicroPython. Ele não vem no firmware MicroPython do Pico W; instale-o no Thonny buscando umqtt.simple em Ferramentas > Gerenciar pacotes, ou digite import mip; mip.install("umqtt.simple") no REPL com a placa conectada ao Wi-Fi. Já o módulo dht, necessário para o DHT22, vem com o firmware. O código abaixo faz um Pico W na cozinha fazer o mesmo trabalho de medição e relé. Para deixá-lo curto, deixamos de fora as mensagens de discovery; para ver o Pico W no Home Assistant, publique os mesmos JSON de discovery do código do ESP32 com os tópicos ev/mutfak, ou defina as entidades à mão dentro de mqtt: no configuration.yaml. Salve o arquivo como main.py e ele roda toda vez que a placa ligar:
1import network, time, dht
2from machine import Pin
3from umqtt.simple import MQTTClient # önce mip ile kur / install with mip first
4
5WIFI_SSID = "AgAdi" # Wi-Fi adın / your Wi-Fi name
6WIFI_PASS = "Sifre123" # Wi-Fi şifren / your Wi-Fi password
7MQTT_SUNUCU = "192.168.1.10" # broker IP / broker IP
8ISTEMCI_ID = "pico-mutfak" # benzersiz olmalı / must be unique
9
10T_SICAKLIK = b"ev/mutfak/sicaklik"
11T_NEM = b"ev/mutfak/nem"
12T_KOMUT = b"ev/mutfak/role/komut"
13T_DURUM = b"ev/mutfak/role/durum"
14T_BAGLANTI = b"ev/mutfak/baglanti"
15
16sensor = dht.DHT22(Pin(15)) # DHT22 DATA -> GP15
17role = Pin(14, Pin.OUT, value=1) # aktif LOW röle kapalı başlar / active-LOW relay starts off
18led = Pin("LED", Pin.OUT) # Pico W dahili LED / Pico W onboard LED
19
20wlan = network.WLAN(network.STA_IF)
21wlan.active(True)
22wlan.connect(WIFI_SSID, WIFI_PASS)
23while not wlan.isconnected():
24 time.sleep(0.5)
25print("IP:", wlan.ifconfig()[0])
26
27def mesaj_geldi(konu, mesaj): # ikisi de bytes gelir / both arrive as bytes
28 if konu == T_KOMUT and mesaj in (b"ON", b"OFF"):
29 acik = mesaj == b"ON"
30 role.value(0 if acik else 1)
31 led.value(1 if acik else 0)
32 istemci.publish(T_DURUM, mesaj, retain=True)
33
34istemci = MQTTClient(ISTEMCI_ID, MQTT_SUNUCU, user="esp32", password="mqttSifre", keepalive=60) # Mosquitto kullanıcısı / Mosquitto user
35istemci.set_callback(mesaj_geldi)
36istemci.set_last_will(T_BAGLANTI, b"offline", retain=True) # son vasiyet / last will
37
38def baglan():
39 while True:
40 try:
41 if not wlan.isconnected(): # Wi-Fi koptuysa yeniden bağlan / reconnect Wi-Fi if it dropped
42 wlan.connect(WIFI_SSID, WIFI_PASS)
43 time.sleep(5)
44 istemci.connect()
45 istemci.publish(T_BAGLANTI, b"online", retain=True)
46 istemci.publish(T_DURUM, b"OFF" if role.value() else b"ON", retain=True)
47 istemci.subscribe(T_KOMUT)
48 print("MQTT baglandi")
49 return
50 except Exception as e: # MQTTException(5): yetki yok / not authorized
51 print("MQTT hatasi:", e)
52 time.sleep(5)
53
54baglan()
55son = time.ticks_add(time.ticks_ms(), -30000) # ilk ölçüm hemen / first reading right away
56while True:
57 try:
58 istemci.check_msg() # bekleyen komut var mı? / any pending command?
59 if time.ticks_diff(time.ticks_ms(), son) >= 30000:
60 son = time.ticks_ms()
61 try:
62 sensor.measure()
63 except OSError:
64 print("DHT22 okunamadi")
65 istemci.ping() # veri yoksa da bağlantıyı canlı tut / keep the link alive without data
66 else:
67 istemci.publish(T_SICAKLIK, "{:.1f}".format(sensor.temperature()).encode(), retain=True)
68 istemci.publish(T_NEM, "{:.0f}".format(sensor.humidity()).encode(), retain=True)
69 except OSError:
70 print("Baglanti koptu, yeniden baglaniliyor")
71 time.sleep(5)
72 baglan()
73 time.sleep_ms(100)Ideias de projetos com ESP32 e MQTT
- Mapa de temperatura cômodo por cômodo: coloque um ESP32 com DHT22 ou BME280 em cada cômodo e acompanhe a casa inteira em um único gráfico com uma assinatura ev/+/sicaklik.
- Lâmpada e tomada inteligentes: ligue o relé a uma automação do Home Assistant que o acende ao pôr do sol e o desliga à meia-noite.
- Sensor de porta e janela: use uma chave reed para enviar uma mensagem MQTT quando uma porta abrir e receba uma notificação no celular quando não houver ninguém em casa.
- Luz do corredor acionada por movimento: deixe um sensor PIR publicar o movimento e uma automação do Home Assistant acender a luz.
- Estação de irrigação de plantas: publique o valor do sensor de umidade do solo e ligue a bomba com um comando MQTT quando o solo ficar seco.
- Monitoramento de energia: meça a corrente que um aparelho consome com um sensor de corrente ACS712 e faça um gráfico do consumo diário.
- Sensor alimentado por bateria: monte um nó que faz uma leitura, envia por MQTT e volta a dormir; detalhes em ESP32 Deep Sleep.
Erros comuns de MQTT no ESP32 e soluções
| Sintoma ou mensagem | Causa | Solução |
|---|---|---|
| rc=-2 o tempo todo | IP ou porta do broker errados, broker desligado ou Mosquitto em modo só local | Confira o IP, adicione listener 1883 à configuração, libere a porta 1883 no firewall |
| rc=5 | Usuário ou senha errados, ou tentativa de conexão sem credenciais | Teste a senha pelo computador com mosquitto_sub; recrie o usuário se precisar |
| Conecta, cai depois de alguns segundos e fica nesse ciclo | Dois dispositivos usam o mesmo client ID; o Mosquitto grava no log “Client esp32-salon already connected, closing old connection.” | Dê a cada dispositivo um ISTEMCI_ID único |
| As mensagens de discovery não chegam, publish() devolve false | O buffer do PubSubClient tem 256 bytes por padrão e o JSON não cabe | Chame mqtt.setBufferSize(1024) no setup() |
| rc=-3 com frequência | Um delay() longo dentro do loop() impede os pacotes de keep-alive, ou o sinal do Wi-Fi está fraco | Faça a temporização com millis() e aproxime a placa do roteador |
| Os comandos nunca chegam ao ESP32 | O nome do tópico difere em maiúsculas/minúsculas ou na grafia, ou o subscribe() não é repetido após reconectar | Confira o tópico com mosquitto_sub; coloque as linhas de subscribe() dentro da função de conexão |
| O relé liga sozinho ao iniciar | Há uma mensagem retida antiga no tópico de comando | Apague-a com mosquitto_pub -r -n -t ev/salon/role/komut |
| As entidades aparecem como “Indisponível” no Home Assistant | O tópico de disponibilidade diz offline ou online está escrito de outro jeito | Ouça ev/salon/baglanti e verifique se o código publica online depois de conectar |
| Caracteres estranhos no lugar do valor | O payload não termina com \0 e foi lido sem usar length | Copie o payload com um laço até length |
| O dispositivo ESPHome reinicia a cada 15 minutos | No modo MQTT, o bloco api: continua lá, mas o Home Assistant nunca se conecta | Apague o bloco api: ou adicione reboot_timeout: 0s |
Com um broker, alguns tópicos e o PubSubClient, o seu ESP32 virou um dispositivo de casa inteligente que fala a mesma língua que o resto da casa. Você pode adicionar novos sensores, outros cômodos e placas diferentes, como o Pico W, à mesma estrutura e gerenciar tudo em um único painel do Home Assistant. No app BlueGrays você encontra projetos como conexão Wi-Fi com ESP32, medição de temperatura e umidade com DHT22, iluminação inteligente com PIR e relé, controle em tempo real com WebSocket e irrigação inteligente de plantas, passo a passo, com esquemas do circuito e código.
Perguntas frequentes
Para que serve o MQTT?
O MQTT é um protocolo de mensagens leve em que os dispositivos enviam e recebem mensagens por meio de um broker, usando nomes de tópicos. Como consome pouca banda e pouca energia, é ideal para dispositivos pequenos como o ESP32 enviarem dados de sensores e receberem comandos. O Home Assistant, o Node-RED e a maioria dos sistemas de IoT industrial falam MQTT.
Qual porta o MQTT usa?
O MQTT sem criptografia usa a porta 1883 por padrão, e o MQTT criptografado com TLS usa a porta 8883. A porta WebSocket, usada para conexões pelo navegador, depende do broker; no broker Mosquitto do Home Assistant ela é a 1884. Em uma rede doméstica, o ESP32 normalmente se conecta à 1883.
O MQTT precisa de conexão com a internet?
Não. Se o broker roda em um Raspberry Pi ou no Home Assistant em casa, o tráfego entre o ESP32 e o broker fica todo na sua rede local; sensores e relés continuam funcionando mesmo se a internet cair. Você só precisa de internet para acessar o sistema de fora de casa ou para usar um broker na nuvem.
Por que meu ESP32 não aparece no Home Assistant?
As causas mais comuns são uma mensagem de discovery que não cabe no buffer de 256 bytes do PubSubClient, um tópico config escrito errado ou um erro de aspas no JSON. Ouça homeassistant/# com mosquitto_sub para ver se a mensagem chega ao broker e confirme que o código tem a linha mqtt.setBufferSize(1024). A integração MQTT do Home Assistant também precisa estar conectada ao mesmo broker.
Devo usar ESPHome ou MQTT com Arduino?
Se o seu objetivo é colocar rapidamente um dispositivo de casa inteligente para funcionar, o ESPHome dá menos trabalho: você escreve YAML, o dispositivo aparece sozinho no Home Assistant e se atualiza sem fio. Se você quer aprender o protocolo MQTT, escrever sua própria lógica ou trabalhar com sistemas além do Home Assistant, Arduino com PubSubClient é mais flexível. Os dois convivem sem problemas na mesma casa.
Qual é a diferença entre QoS 0, 1 e 2 no MQTT?
O QoS 0 envia a mensagem uma vez sem esperar confirmação, o QoS 1 reenvia até receber a confirmação, mas a mensagem pode chegar duas vezes, e o QoS 2 usa um handshake de quatro etapas para garantir que ela chegue exatamente uma vez. O QoS 0 basta para leituras de sensores, e o QoS 1 para comandos. O PubSubClient só consegue publicar com QoS 0 e assinar com QoS 0 ou 1.
Projetos para montar depois desta leitura
Ver todos os projetos
LED piscando com ESP32
Ensina o uso básico de uma saída GPIO no ESP32. Fazemos um LED piscar ligando e desligando um pino digital. É a versão para ESP32 do clássico projeto blink do Arduino UNO: os comandos básicos de blink no ambiente Arduino são os mesmos, mas a disposição dos pinos e os níveis de 3,3 V dos GPIOs do ESP32 diferem dos do Arduino UNO.

Conexão Wi-Fi STA com ESP32 e display LCD
Neste projeto, conectamos o ESP32 à rede Wi-Fi de casa no modo estação (STA), de forma segura e tolerante a falhas. Guardamos o SSID e a senha em um arquivo secrets.h separado para evitar que sejam expostos no Git, configuramos um mecanismo de reconexão automática e exibimos o nível de sinal RSSI e o endereço IP em um display LCD I2C. O LED integrado funciona como indicador de status. É um gerenciador de conexão pronto para uso em produção.

Temperatura e umidade com ESP32 e DHT22 (com display LCD)
Este projeto mede a temperatura e a umidade do ambiente com um sensor DHT22 e exibe os dados em tempo real em um LCD I2C 16x2. Os dados são lidos do sensor pelo protocolo de um fio (one-wire) com a biblioteca Adafruit DHT. Este projeto serve de base para estações meteorológicas IoT, automação residencial ou sistemas de monitoramento ambiental em estufas. A comunicação com o DHT22 é feita pelo pino GPIO 4 do ESP32.

Iluminação inteligente com ESP32 (PIR + LDR + relé + OLED)
Transforme a iluminação do corredor, banheiro ou despensa em iluminação inteligente com ESP32! Com um sensor de movimento PIR, um sensor de luz LDR e um módulo relé, montamos o cenário clássico de "acender a luz ao detectar movimento no escuro" — se o ambiente já estiver claro, o movimento NÃO aciona a luz, economizando energia durante o dia. A luz fica acesa por 30 segundos; se o movimento continuar, o temporizador reinicia e a luz permanece acesa por mais tempo.

Contador WebSocket com ESP32 (2 botões + LCD + web em tempo real)
Neste projeto, dois botões conectados ao ESP32 (GPIO 5 aumenta, GPIO 4 diminui) alteram um contador. O valor é atualizado instantaneamente no LCD I2C 16x2 e, com o suporte a WebSocket do ESPAsyncWebServer, em todos os navegadores conectados, sem recarregar a página. Em vez de consultas periódicas por HTTP, usamos uma única conexão persistente, e o ESP32 envia o novo valor a todos com ws.textAll().

ESP32 mDNS: acesso via bluegrays-esp.local (com display LCD)
Neste projeto, adicionamos o serviço mDNS (Multicast DNS) ao ESP32 para acessar o dispositivo por um nome de host fácil de ler, como bluegrays-esp.local, em vez de um endereço IP. Mesmo que o IP atribuído pelo DHCP mude, você pode acessar o dispositivo pelo mesmo nome. Também executamos um pequeno servidor web no dispositivo para enviar comandos de controle do LED pelo navegador no endereço http://bluegrays-esp.local/.

Alarme de movimento com ESP32 (PIR + buzzer + LED + Telegram)
Um sistema de alarme de segurança inteligente que aciona o buzzer e o LED quando o sensor PIR detecta movimento e, ao mesmo tempo, envia uma notificação instantânea ao proprietário pelo Telegram. Inclui um intervalo de espera de 30 segundos para limitar a frequência dos alarmes repetidos; esse mecanismo não valida as detecções do PIR nem elimina disparos falsos. Pode ser usado na segurança de casas, no monitoramento de garagens, depósitos ou salas de trabalho.
Mais artigos
- O que é ESP32? Características, configuração na Arduino IDE e seu primeiro projeto com Wi-Fi
- Servidor web assíncrono no ESP32 com WebSocket: painel de controle em tempo real
- Bot do Telegram com ESP32: alertas, controle de LED e relé
- Projeto de casa inteligente com Arduino: maquete, sensores, código e app
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

