Exibindo Dados de Sensores em Tempo Real no Navegador

Imagine poder acompanhar em tempo real a temperatura da sua sala diretamente pelo navegador do seu smartphone ou computador. Com o ESP32, isso é totalmente possível! Neste artigo, vamos explorar como exibir dados de sensores em tempo real no navegador, transformando seu ESP32 em uma central de monitoramento acessível de qualquer lugar.

Introdução🔗

O ESP32 é uma poderosa ferramenta para projetos de IoT (Internet das Coisas). Com ele, é possível ler dados de sensores e transmiti-los de forma eficiente. Nosso objetivo aqui é criar uma interface web que mostre, em tempo real, os valores lidos por um sensor conectado ao ESP32.

Materiais Necessários🔗

  • ESP32
  • Sensor de Temperatura e Umidade DHT11 ou DHT22
  • Cabos Jumper
  • Computador com Arduino IDE instalado
  • Conexão Wi-Fi

Conectando o Sensor ao ESP32🔗

Primeiramente, precisamos conectar o sensor DHT ao ESP32. O DHT11 e o DHT22 são sensores populares para medir temperatura e umidade.

Esquema de Ligações

  • VCC do DHT: Conectar ao pino 3.3V do ESP32
  • GND do DHT: Conectar ao pino GND do ESP32
  • Data do DHT: Conectar ao pino GPIO 4 do ESP32
Nota: Certifique-se de usar resistores pull-up se necessário, conforme especificações do sensor.

Configurando o Ambiente de Desenvolvimento🔗

Antes de começar a codificar, precisamos garantir que o Arduino IDE esteja configurado para programar o ESP32. Caso ainda não tenha feito isso, siga os passos abaixo:

1. Adicionar o URL do Gerenciador de Placas

Abra o Arduino IDE e vá em Arquivo > Preferências. No campo URLs Adicionais para Gerenciadores de Placas, adicione:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

2. Instalar as Placas ESP32

Vá em Ferramentas > Placa > Gerenciador de Placas. Busque por ESP32 e instale a opção esp32 by Espressif Systems.

3. Instalar Bibliotecas Necessárias

Instale as bibliotecas para o sensor DHT e para a conexão Wi-Fi. Vá em Sketch > Incluir Biblioteca > Gerenciar Bibliotecas e pesquise por:
  • "DHT sensor library" por Adafruit
  • "Adafruit Unified Sensor" por Adafruit

Desenvolvendo o Código🔗

Agora que o ambiente está pronto, vamos ao código. Nosso objetivo é:

  • Conectar o ESP32 à rede Wi-Fi
  • Ler os dados do sensor periodicamente
  • Criar um servidor web que disponibilize esses dados
  • Atualizar os dados em tempo real no navegador

Importando Bibliotecas

#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"

Definindo Constantes e Variáveis

#define DHTPIN 4      // Pino onde o sensor DHT está conectado
#define DHTTYPE DHT22 // Tipo de sensor: DHT11 ou DHT22
const char* ssid = "Seu_SSID";
const char* password = "Sua_Senha";
DHT dht(DHTPIN, DHTTYPE);
WebServer server(80);
float temperatura;
float umidade;

Configurando a Conexão Wi-Fi

void setup()
{
  Serial.begin(115200);
  dht.begin();
  // Conectando ao Wi-Fi
  WiFi.begin(ssid, password);
  Serial.print("Conectando-se ao Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConectado!");
  Serial.print("Endereço IP: ");
  Serial.println(WiFi.localIP());
  // Configurando as rotas do servidor
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Servidor HTTP iniciado");
}

Função para Ler os Dados do Sensor

void lerSensor()
{
  umidade = dht.readHumidity();
  temperatura = dht.readTemperature();
  if (isnan(umidade) || isnan(temperatura))
  {
    Serial.println("Falha ao ler do sensor DHT!");
    return;
  }
}

Manipulador da Página Inicial

Vamos criar uma página web que exibe os dados e atualiza em tempo real usando JavaScript.

void handleRoot()
{
  lerSensor();
  String pagina = "<!DOCTYPE html><html>";
  pagina += "<head><meta http-equiv='refresh' content='5'/>";
  pagina += "<title>Monitoramento de Temperatura e Umidade</title>";
  pagina += "<style>body { font-family: Arial; text-align: center; margin-top: 50px; }</style>";
  pagina += "</head><body>";
  pagina += "<h1>Dados do Sensor DHT</h1>";
  pagina += "<p>Temperatura: ";
  pagina += String(temperatura);
  pagina += " °C</p>";
  pagina += "<p>Umidade: ";
  pagina += String(umidade);
  pagina += " %</p>";
  pagina += "</body></html>";
  server.send(200, "text/html", pagina);
}

Loop Principal

No loop, apenas mantemos o servidor em execução.

void loop()
{
  server.handleClient();
}

Código Completo

Para facilitar, segue o código completo:

#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT22
const char* ssid = "Seu_SSID";
const char* password = "Sua_Senha";
DHT dht(DHTPIN, DHTTYPE);
WebServer server(80);
float temperatura;
float umidade;
void setup()
{
  Serial.begin(115200);
  dht.begin();
  WiFi.begin(ssid, password);
  Serial.print("Conectando-se ao Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConectado!");
  Serial.print("Endereço IP: ");
  Serial.println(WiFi.localIP());
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Servidor HTTP iniciado");
}
void lerSensor()
{
  umidade = dht.readHumidity();
  temperatura = dht.readTemperature();
  if (isnan(umidade) || isnan(temperatura))
  {
    Serial.println("Falha ao ler do sensor DHT!");
    return;
  }
}
void handleRoot()
{
  lerSensor();
  String pagina = "<!DOCTYPE html><html>";
  pagina += "<head><meta http-equiv='refresh' content='5'/>";
  pagina += "<title>Monitoramento de Temperatura e Umidade</title>";
  pagina += "<style>body { font-family: Arial; text-align: center; margin-top: 50px; }</style>";
  pagina += "</head><body>";
  pagina += "<h1>Dados do Sensor DHT</h1>";
  pagina += "<p>Temperatura: ";
  pagina += String(temperatura);
  pagina += " °C</p>";
  pagina += "<p>Umidade: ";
  pagina += String(umidade);
  pagina += " %</p>";
  pagina += "</body></html>";
  server.send(200, "text/html", pagina);
}
void loop()
{
  server.handleClient();
}

Explicando o Funcionamento do Código🔗

Conexão Wi-Fi

Utilizamos a biblioteca WiFi.h para conectar o ESP32 à rede Wi-Fi. No setup(), iniciamos a conexão e aguardamos até que o status seja WL_CONNECTED.

Leitura do Sensor DHT

A função lerSensor() lê os valores de temperatura e umidade. Verificamos se a leitura foi bem-sucedida com isnan().

Servidor Web

Com a biblioteca WebServer.h, criamos um servidor HTTP que escuta na porta 80. A função handleRoot() é responsável por montar a página web que será exibida no navegador.

Atualização dos Dados

Para atualizar os dados em tempo real, usamos a meta tag de atualização no HTML:

<meta http-equiv='refresh' content='5'/>

Isso faz com que a página seja recarregada a cada 5 segundos, atualizando os valores exibidos.

Melhorando a Experiência do Usuário🔗

Recarregar a página inteira pode não ser a melhor experiência. Podemos melhorar utilizando técnicas de atualização parcial da página, como AJAX.

Implementando AJAX para Atualização em Tempo Real

Vamos modificar nosso código para que apenas os dados sejam atualizados, sem recarregar toda a página.

Modificando o Manipulador da Página Inicial

Criamos duas rotas: uma para servir a página principal e outra para fornecer os dados em formato JSON.

void setup()
{
  // ... Código anterior ...
  server.on("/", handleRoot);
  server.on("/dados", handleDados);
  // ... Resto do código ...
}

Função para Fornecer Dados em JSON

void handleDados()
{
  lerSensor();
  String json = "{";
  json += "\"temperatura\":";
  json += String(temperatura);
  json += ",";
  json += "\"umidade\":";
  json += String(umidade);
  json += "}";
  server.send(200, "application/json", json);
}

Atualizando a Página HTML

No HTML, adicionamos um script JavaScript que faz requisições periódicas ao servidor para obter os dados:

void handleRoot()
{
  String pagina = "<!DOCTYPE html><html>";
  pagina += "<head>";
  pagina += "<title>Monitoramento de Temperatura e Umidade</title>";
  pagina += "<style>body { font-family: Arial; text-align: center; margin-top: 50px; }</style>";
  pagina += "<script>";
  pagina += "function atualizarDados() {";
  pagina += "var xhttp = new XMLHttpRequest();";
  pagina += "xhttp.onreadystatechange = function() {";
  pagina += "if (this.readyState == 4 && this.status == 200) {";
  pagina += "var dados = JSON.parse(this.responseText);";
  pagina += "document.getElementById('temperatura').innerHTML = dados.temperatura + ' °C';";
  pagina += "document.getElementById('umidade').innerHTML = dados.umidade + ' %';";
  pagina += "}";
  pagina += "};";
  pagina += "xhttp.open('GET', '/dados', true);";
  pagina += "xhttp.send();";
  pagina += "}";
  pagina += "setInterval(function() { atualizarDados(); }, 2000);";
  pagina += "</script>";
  pagina += "</head><body onload='atualizarDados()'>";
  pagina += "<h1>Dados do Sensor DHT</h1>";
  pagina += "<p>Temperatura: <span id='temperatura'>-- °C</span></p>";
  pagina += "<p>Umidade: <span id='umidade'>-- %</span></p>";
  pagina += "</body></html>";
  server.send(200, "text/html", pagina);
}

Código Completo com AJAX

#include <WiFi.h>
#include <WebServer.h>
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT22
const char* ssid = "Seu_SSID";
const char* password = "Sua_Senha";
DHT dht(DHTPIN, DHTTYPE);
WebServer server(80);
float temperatura;
float umidade;
void setup()
{
  Serial.begin(115200);
  dht.begin();
  WiFi.begin(ssid, password);
  Serial.print("Conectando-se ao Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConectado!");
  Serial.print("Endereço IP: ");
  Serial.println(WiFi.localIP());
  server.on("/", handleRoot);
  server.on("/dados", handleDados);
  server.begin();
  Serial.println("Servidor HTTP iniciado");
}
void lerSensor()
{
  umidade = dht.readHumidity();
  temperatura = dht.readTemperature();
  if (isnan(umidade) || isnan(temperatura))
  {
    Serial.println("Falha ao ler do sensor DHT!");
    return;
  }
}
void handleDados()
{
  lerSensor();
  String json = "{";
  json += "\"temperatura\":";
  json += String(temperatura);
  json += ",";
  json += "\"umidade\":";
  json += String(umidade);
  json += "}";
  server.send(200, "application/json", json);
}
void handleRoot()
{
  String pagina = "<!DOCTYPE html><html>";
  pagina += "<head>";
  pagina += "<title>Monitoramento de Temperatura e Umidade</title>";
  pagina += "<style>body { font-family: Arial; text-align: center; margin-top: 50px; }</style>";
  pagina += "<script>";
  pagina += "function atualizarDados() {";
  pagina += "var xhttp = new XMLHttpRequest();";
  pagina += "xhttp.onreadystatechange = function() {";
  pagina += "if (this.readyState == 4 && this.status == 200) {";
  pagina += "var dados = JSON.parse(this.responseText);";
  pagina += "document.getElementById('temperatura').innerHTML = dados.temperatura + ' °C';";
  pagina += "document.getElementById('umidade').innerHTML = dados.umidade + ' %';";
  pagina += "}";
  pagina += "};";
  pagina += "xhttp.open('GET', '/dados', true);";
  pagina += "xhttp.send();";
  pagina += "}";
  pagina += "setInterval(function() { atualizarDados(); }, 2000);";
  pagina += "</script>";
  pagina += "</head><body onload='atualizarDados()'>";
  pagina += "<h1>Dados do Sensor DHT</h1>";
  pagina += "<p>Temperatura: <span id='temperatura'>-- °C</span></p>";
  pagina += "<p>Umidade: <span id='umidade'>-- %</span></p>";
  pagina += "</body></html>";
  server.send(200, "text/html", pagina);
}
void loop()
{
  server.handleClient();
}

Entendendo a Atualização com AJAX🔗

AJAX (Asynchronous JavaScript and XML) permite que o navegador comunique-se com o servidor sem recarregar a página inteira. No nosso script, utilizamos o objeto XMLHttpRequest para fazer requisições assíncronas.
  • Função atualizarDados(): É chamada a cada 2 segundos pelo setInterval(). Faz uma requisição GET para a rota /dados.
  • Processamento da Resposta: Quando a resposta chega, os dados em JSON são parseados e atualizam o conteúdo dos elementos HTML com os IDs temperatura e umidade.

Testando o Projeto🔗

Após carregar o código no ESP32:

1. Abra o Monitor Serial: Verifique se o ESP32 conectou-se ao Wi-Fi e anote o endereço IP exibido.

2. Acesse pelo Navegador: No navegador de seu computador ou smartphone, digite o endereço IP do ESP32.

3. Visualize os Dados: Você deverá ver a página com os valores de temperatura e umidade atualizando a cada 2 segundos.

Expandindo o Projeto🔗

Com a base estabelecida, é possível expandir o projeto para incluir:

  • Múltiplos Sensores: Adicionar outros tipos de sensores, como luminosidade, pressão, etc.
  • Controle Remoto: Implementar botões na interface web para controlar dispositivos conectados ao ESP32.
  • Estilização Avançada: Usar CSS para melhorar a aparência da página.
  • Gráficos em Tempo Real: Integrar bibliotecas JavaScript como Chart.js para exibir gráficos dos dados.

Considerações Finais🔗

Neste artigo, exploramos como exibir dados de sensores em tempo real no navegador utilizando o ESP32. Aprendemos a:

  • Conectar e ler dados de um sensor DHT
  • Configurar um servidor web no ESP32
  • Atualizar dados em tempo real usando AJAX

Essa é uma poderosa aplicação para projetos de automação e monitoramento remoto. Com criatividade, é possível adaptar esse conhecimento para inúmeras outras finalidades, tornando suas ideias em realidade no mundo da IoT.

Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

Referências🔗

Artigos Relacionados