ESP8266: como monitorar temperatura e umidade



No tutorial de hoje vamos utilizar um ESP-01, que é o ESP8266 na configuração 01 (com somente 2 GPIOs), para a leitura de temperatura e umidade de um sensor DHT22. Mostro a vocês um esquema elétrico e a parte da programação do ESP como um arduino. O exemplo é simples, de fácil compreensão, e ainda disponibilizo o PDF utilizado no vídeo para auxiliar na sua montagem.


No projeto temos, então, o ESP01, a fonte que converte 110 ou 220 em 5 volts, um regulador de tensão de 3v3 e o DHT22, que é o sensor. Na tela de um smartphone, você terá o endereço IP local, além do código JavaScript fornecido pelo ESP. Esta tela, portanto, vai receber os parâmetros de temperatura e umidade e vai imprimir esses valores, que serão atualizados a cada cinco segundos. Para este trabalho não será necessário nenhum aplicativo em celulares e tablets tanto do sistema operacional Android quanto do IOS.

Montagem


O esquema elétrico é bastante simples, assim como a parte da montagem, que vai envolver o ESP01 como um servidor, o qual será programado como se ele fosse um arduino, ou seja, através da linguagem C. Destaco que parte do código é de um print do browser. Isso quer dizer que ele manda um código em JavaScript para o browser. Explico melhor mais abaixo como isso funciona.
Voltando ao esquema elétrico, coloquei uma fonte chaveada de 5 volts ligada a um regulador de tensão 3v3 para alimentar o ESP01. Temos ainda o DHT22 com quatro pinos, sendo que um deles, o de dados, não é utilizado, mas leva um resistor de pull up.


Código

O primeiro passo é incluir as libs que iremos utilizar. A lib do DHT pode ser adicionada pela opção Sketch > Incluir Biblioteca > Gerenciar Bibliotecas...
Na janela que abrir procure por DHT sensor library.
Depois disso criamos uma variável do tipo ESP8266WebServer que será o nosso servidor que irá responder as requisições http (porta 80).
Criamos também uma variável do tipo DHT com os parâmetros 0 (que é o pino GPIO 0) e o tipo (no nosso caso DHT22)

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DHT.h>

//Criamos uma variável do tipo ESP8266WebServer que já possui funções
//que auxiliam na criação das rotas que o ESP8266 vai responder
ESP8266WebServer server(80);
//Variável do tipo DHT que possui funções para controlarmos o módulo dht 
//permitindo ler a temperatura e a umidade
DHT dht(0, DHT22);

Setup

No setup, vamos inicializar o Serial apenas para que tenhamos um log, caso o ESP8266 esteja conectado ao computador através da serial para utilizarmos o monitor serial.
Iremos fazer com que o ESP8266 se conecte na nossa rede. No nosso caso, usamos a rede TesteESP com a senha 87654321, mas você terá que alterar de acordo com a rede que irá utilizar.

//Inicialize a Serial apenas caso esteja com o ESP8266 conectado ao computador pela serla queira ter um log 
  //para facilitar saber o que está acontecendo com o ESP8266
  Serial.begin(115200);

  //Instrução para o ESP8266 se conectar à rede. 
  //No nosso caso o nome da rede é TesteESP e a senha é 87654321. 
  //Você deve alterar com as informações da sua rede
  WiFi.begin("TesteESP", "87654321" );

  //Feedback caso esteja usando o Monitor Serial 
  Serial.println("");
  Serial.print("Conectando");

Aguardamos o ESP8266 se conectar à rede e, após ele se conectar, enviamos as configurações da rede. Altere conforme a sua rede.

 //Esperamos até que o módulo se conecte à rede
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  
  //Configurações do IP fixo. Você pode alterar conforme a sua rede
  IPAddress ip(192, 168, 3, 11);
  IPAddress gateway(192, 168, 3, 1);
  IPAddress subnet(255, 255, 255, 0);
  Serial.print("Configurando IP fixo para : ");
  Serial.println(ip);
  //Envia a configuração
  WiFi.config(ip, gateway, subnet);

Os próximos comandos são apenas para caso esteja com o ESP8266 conectado ao computador pela serial para que você tenha um feedback pelo Monitor Serial.
Você pode conferir o IP que o ESP8266 recebeu para ver se é o mesmo que está nas configurações.

 //Mostramos no Monitor Serial o ip com o qual o esp8266 se conectou para ver se está de acordo com o que configuramos
  Serial.println("");
  Serial.println("Connectado");
  Serial.print ("IP: ");
  Serial.println(WiFi.localIP());

Aqui começamos a definir quais funções serão executadas para cada requisição.
Na instrução abaixo, toda vez que o ESP8266 receber uma requisição http do tipo GET no caminho /temperature a função getTemperature irá ser executada.

//Aqui definimos qual a função será executada para o caminho e tipo dado.
  //Nesse caso quando houver uma requisição http do tipo GET no caminho http://192.168.2.8/temperature
  //(pode ser outro ip dependendo da sua configuração) a função getTemperature será executada
  server.on("/temperature", HTTP_GET, getTemperature);


Nessa outra instrução, toda vez que o ESP8266 receber uma requisição http do tipo GET no caminho /humidity a função getHumidity irá ser executada.

//Nesse outo caso quando houver uma requisição http do tipo GET no caminho http://192.168.2.8/humidity
  //(pode ser outro ip dependendo da sua configuração) a função getHumidity será executada
  server.on("/humidity", HTTP_GET, getHumidity);


Nessa instrução, toda vez que o ESP8266 receber uma requisição http do tipo GET no caminho /monitor a função showMonitor irá ser executada.
A função showMonitor é a responsável por retornar o html principal que irá mostrar os valores da temperatura e da umidade.

//Nesse caso quando houver uma requisição http do tipo GET no caminho http://192.168.2.8/monitor
  //(pode ser outro ip dependendo da sua configuração) a função showMonitor será executada. 
  //Esta função retornará a página principal que mostrará os valores
  //da temperatura e da umidade e recarregará essas informações de tempos em tempos
  server.on("/monitor", HTTP_GET, showMonitor);


Aqui é a definição da função que deve ser executada quando o caminho requisitado não for encontrado.

//Aqui definimos qual função será executada caso o caminho que o cliente requisitou não tenha sido registrado
  server.onNotFound(onNotFound);

Aqui inicializamos o nosso servidor que declaramos anteriormente na porta 80.
Com isso terminamos o setup.

//Inicializamos o server que criamos na porta 80
  server.begin();
  Serial.println("Servidor HTTP iniciado");
}

Loop

Graças a lib ESP8266WebServer, não precisamos ficar verificando no loop se há clientes e qual o caminho da requisição. Apenas precisamos chamar handleClient() e o objeto verificará se algum cliente está fazendo alguma requisição e irá redirecionar para a função correspondente que registramos anterirormente.

void loop() 
{
  //Verifica se há alguma requisição de algum cliente
  server.handleClient();
}



Requisição não encontrada

Essa é a função que registramos anteriormente para ser executada quando o cliente fizer alguma requisição que não foi registrada.
A função apenas volta o código 404 (código padrão para quando um recurso não é encontrado), o tipo de dado retornado (no caso texto puro) e um texto com os dizeres “Not Found”.

//Função que definimos para ser chamada quando o caminho requisitado não foi registrado 
void onNotFound() 
{
  server.send(404, "text/plain", "Not Found" );
}


Retornando a temperatura

Essa é a função que retornará um json com os dados da temperatura quando o cliente fizer uma requisição do tipo GET em /temperature.

//Função que definimos que será executada quando o cliente fizer uma requisição
//do tipo GET no caminho http://192.168.2.8/temperature (pode ser outro ip dependendo da sua configuração) 
void getTemperature()
{
  //Fazemos a leitura da temperatura através do módulo dht
  float t = dht.readTemperature();
  //Cria um json com os dados da temperatura
  String json = "{\"temperature\":"+String(t)+"}";
  //Envia o json para o cliente com o código 200, que é o código quando a requisição foi realizada com sucesso
  server.send (200, "application/json", json);
}

Retornando a umidade

Essa é a função que retornará um json com os dados da umidade quando o cliente fizer uma requisição do tipo GET em /humidity.
//Função que definimos que será executada quando o cliente fizer uma requisição
//do tipo GET no caminho http://192.168.2.8/humidity (pode ser outro ip dependendo da sua configuração) 
void getHumidity()
{
  //Fazemos a leitura da umidade através do módulo dht
  float h = dht.readHumidity();
  //Cria um json com os dados da umidade
  String json = "{\"humidity\":"+String(h)+"}";
  //Envia o json para o cliente com o código 200, que é o código quando a requisição foi realizada com sucesso
  server.send(200, "application/json", json);
}

HTML

Essa é a função que retornará o html quando o cliente acessar /monitor. Esta página mostrará os valores da temperatura e umidade e recarregará os dados de tempos em tempos. A parte que está entre <style type=‘text/css’> e </style> definem a aparência da página e você pode alterar conforme queira.

//Função que definimos que será executada quando o cliente fizer uma requisição
//do tipo GET no caminho http://192.168.2.8/monitor (pode ser outro ip dependendo da sua configuração) 
void showMonitor()
{
  String html =
  "<html>"
  "<head>"
    "<meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no'/>"
    "<title>DHT Monitor</title>"
    "<style type='text/css'>"
      "body{"
            "padding: 35px;"
            "background-color: #222222;"
      "}"



Continuação do style do HTML

"h1{"
        "color: #FFFFFF;"
        "font-family: sans-serif;"
      "}"
      "p{"
        "color: #EEEEEE;"
        "font-family: sans-serif;"
            "font-size:18px;"
      "}"
   "</style>"
  "</head>"



Aqui temos a parte principal do html. Nele temos dois parágrafos que irão mostrar a temperatura e a umidade. Atenção para os IDs dos parágrafos, pois é através deles que iremos recuperar estes parágrafos para inserir os valores da temperatura e umidade após as requisições.

 "<body>"
    "<h1>DHT Monitor</h1>"
    "<p id='temperature'>Temperature: </p>"
    "<p id='humidity'>Humidity: </p>"
  "</body>"
Aqui começamos a definir o script que vai de tempos em tempos ler os valores da temperatura e umidade. A função refresh() chama as funções refreshTemperature() e refreshHumdity() e o setInterval chama a função refresh a cada 5000 milisegundos (5 segundos).

 "<script type='text/javascript'>"
    "refresh();"  
    "setInterval(refresh, 5000);"
    "function refresh()"
    "{"
      "refreshTemperature()"
      "refreshHumidity();"
    "}"

A função refreshTemperature() faz uma requisição à /temperature e faz o parse da informação contida no json e adiciona no parágrafo com id temperature.

 "function refreshTemperature()"
    "{"
      "var xmlhttp = new XMLHttpRequest();"
      "xmlhttp.onreadystatechange = function() {"
        "if (xmlhttp.readyState == XMLHttpRequest.DONE && xmlhttp.status == 200){"
          "document.getElementById('temperature').innerHTML = 'Temperature: ' + JSON.parse(xmlhttp.responseText).temperature + 'C';"
        "}"
      "};"
      "xmlhttp.open('GET', 'http://192.168.2.8/temperature', true);"
      "xmlhttp.send();"
    "}"


A função refreshHumidity() faz uma requisição à /humidity e faz o parse da informação contida no json e adiciona no parágrafo com id humidity. E, com isso, finalizamos o html que enviaremos nas requisições em /monitor.

"function refreshHumidity()"
    "{"
      "var xmlhttp = new XMLHttpRequest();"
      "xmlhttp.onreadystatechange = function() {"
        "if (xmlhttp.readyState == XMLHttpRequest.DONE && xmlhttp.status == 200){"
          "document.getElementById('humidity').innerHTML = 'Humidity: ' + JSON.parse(xmlhttp.responseText).humidity + '%';"
        "}"
      "};"
      "xmlhttp.open('GET', 'http://192.168.2.8/humidity', true);"
      "xmlhttp.send();"
    "}"
  "</script>"
  "</html>";

Finalizando showMonitor

Agora que a string com o html que enviaremos está pronta podemos enviar para o cliente. Com isso, finalizamos a função showMonitor e o código.

//Envia o html para o cliente com o código 200, que é o código quando a requisição foi realizada com sucesso
  server.send(200, "text/html", html);
}

Testando

Agora, abra seu navegador e digite http://192.168.2.8/monitor (pode ser outro ip dependendo da sua configuração).




Arquivos para download:



4 comentários:

  1. Boa noite!!! Tenho como colocar mais de um sensor? Se sim até quantos sensores é possível colocar em cada placa?

    ResponderExcluir
  2. Boa noite!!! Tenho como colocar mais de um sensor? Se sim até quantos sensores é possível colocar em cada placa?

    ResponderExcluir
  3. Eu gostaria muito de ver uma rede com vários esp8266 ou esp32 conectada a um servidor central e fazendo a leitura dos sensores espalhados e um ambiente de aplicação.

    ResponderExcluir
  4. Eu gostaria muito de ver uma rede com vários esp8266 ou esp32 conectada a um servidor central e fazendo a leitura dos sensores espalhados e um ambiente de aplicação.

    ResponderExcluir

Tecnologia do Blogger.