Automação Residencial

Controle de Nível WiFi Utilizando o ESP32

Eletrogate 17 de novembro de 2021

Introdução

Nos últimos 22 anos, após ser proposto o termo “Internet das Coisas”, tendo como referência a interconexão digital de quaisquer objetos físicos com a internet, podendo esses objetos receber ou enviar informações para a rede. Neste projeto será exposto em detalhes como criar um dispositivo para medir o nível de um reservatório de água com graduação de 20% em 20%, de forma a apresentar os resultados por um Web Server, e também tornar automático o processo de enchimento do reservatório d’água sempre que estiver abaixo de 20% da capacidade máxima.

Esta proposta além de possibilitar diversas aplicações para sistemas hidráulicos contando com o monitoramento de tal processo de forma síncrona, se torna de grande viabilidade pelo preço dos materiais necessários para a construção do projeto, se diferenciando de outros processos existentes no mercado.


Materiais Necessários para o Projeto Controle de Nível WiFi Utilizando o ESP32


Alguns dos Componentes do Projeto

Módulo WiFi ESP32 Bluetooth 30 pinos

Esta é a placa de desenvolvimento que será usada no projeto, utilizando a programação mais usual para placas de desenvolvimento: a Arduino IDE. Esta placa foi escolhida pelas atribuições que a torna essencial para o projeto, tais como:

  • Sensores touch capacitivos integrados aos pinos da placa, possibilitando o uso dos pinos como sensores para a medição do nível da água;
  • WiFi nativo, possibilitando a construção de um Web Server para monitorar o sistema;

Módulo Relé 1 Canal

Tem a função de receber um sinal digital do sistema para atuar como chave, fazendo com que o microcontrolador ligue ou desligue uma carga de maior potência, ou seja, um dispositivo responsável pelo enchimento do reservatório, como uma bomba hidráulica ou uma válvula solenoide de modo a não permitir que o reservatório fique abaixo de 20% (e esvazie) ou acima de 100% (e transborde).

Este módulo pode realizar o chaveamento de duas formas, sendo normalmente aberto (NA), desta forma quando recebe o sinal ele realiza a conexão para que que funcione o atuador desejado. Também há o normalmente fechado (NF), que é o oposto do funcionamento anterior, quando há sinal ele realiza a interrupção do circuito, fazendo com que o atuador se desligue.

Para este projeto é necessário que haja um relé de atuação por 3,3V, pois o sinal enviado pela placa ESP32 é de 3.3V, ou se já tiver um relé de atuação a 5V é necessário um Conversor de Nível Lógico 3.3V-5V Bidirecional – 4 Canais para converter o sinal do ESP32 para 5V, possibilitando a atuação do módulo de relé de 5V.


Execução do Projeto

Conexão do ESP32 com a Arduino IDE

O primeiro passo para o projeto é a configuração da placa ESP32 na plataforma Arduino IDE. Essa ação só é necessária no primeiro uso do módulo no Arduino IDE, se você ainda não tem sua placa configurada na plataforma, clique aqui para aprender a configurar.

Após a conexão entre o ESP32 e o Arduino IDE, basta copiar e colar o código deste post, configurar o usuário e a senha do seu WiFi conforme explicado ao longo dos comentários no programa.

Após incluir os passos anteriores, deve-se carregar no módulo ESP32 o programa, que quando reiniciar e obtiver sucesso na conexão com a rede WiFi, o usuário deve abrir o navegador de internet da sua preferência, tanto no computador ou no celular e digitar o número do endereço IP configurado no Arduino IDE, para que seja exibido o Web Server, que após a montagem do circuito e o posicionamento dos sensores capacitivos de toque, exibirá na tela a porcentagem de líquido existente no reservatório.


Código

Cabeçalhos utilizados para o funcionamento WiFi e do servidor WEB no ESP32:

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

Parâmetros de rede com a configuração da rede WIFI e número IP:

const char* WIFISSID = "sua_rede";
const char* senha = "sua_senha";

IPAddress local_IP(192, 168, 1, 50); //Defina o IP de acesso
IPAddress gateway(192, 168, 1, 1);   //Defina o IP do roteador de internet
IPAddress subnet(255, 255, 255, 0);  //Defina a máscara de sub-rede
IPAddress primaryDNS(192, 168, 1, 1);//opcional - DNS primário
IPAddress secondaryDNS(8, 8, 8, 8);  //opcional - DNS secundário

As variáveis de controle da programação e GPIOs utilizadas:

const int bomba = 15;
const int led = 14;
int per = 0;
String bombastatus = "Desligada";

A configuração de programa (setup) que roda uma única vez ao inicializar o microcontrolador

void setup() {

  Serial.begin(115200);
  delay(400);
  // ip fixo
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }// fim ip fixo
  Serial.println("Conectando a rede:  ");
  Serial.println(WIFISSID);
  WiFi.begin(WIFISSID , senha);

  while (WiFi.status() != WL_CONNECTED)   {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("Sucesso ao conectar-se a rede WiFi");
  Serial.print("endereço de IP para o web server: ");
  Serial.println(WiFi.localIP());
  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP servidor está funcionando");
  pinMode(bomba , OUTPUT);
  pinMode(led , OUTPUT);

}

O programa que roda infinitamente (loop) verificando o nível de líquido para determinar o estado do atuador (ligado ou desligado) e chamada das subrotinas do servidor WEB.

void loop() {

  server.handleClient();
  if (touchRead(T4) <= 60 && touchRead(T5) <= 60 && touchRead(T6) <= 60 && touchRead(T7) <= 60 && touchRead(T8) <= 60) {
    per = 100;

  } else if (touchRead(T4) <= 60 && touchRead(T5) <= 60 && touchRead(T6) <= 60 && touchRead(T7) <= 60 ) {
    per = 80;

  } else if (touchRead(T4) <= 60 &&  touchRead(T5) <= 60 && touchRead(T6) <= 60  ) {
    per = 60;

  } else  if (touchRead(T4) <= 60 && touchRead(T5) <= 60 ) {
    per = 40;

  } else if (touchRead(T4) <= 60) {
    per = 20;
  } else {
    per = 0;
  }
  if (per <= 20)   {
    // Aciona o relé e o led indicativo
    digitalWrite(bomba, HIGH);  // Considerando o acionamento do relé com nível alto
    digitalWrite(led, HIGH);
    bombastatus = "Ligada";
    Serial.println("Bomba ligada");
  }
  else if (per == 100)   {
    // Desliga o relé e o led indicativo
    digitalWrite(bomba, LOW);  // Considerando o desacionamento do relé com nível baixo
    digitalWrite(led, LOW);
    bombastatus = "Desligada";
    Serial.println("Bomba desligada");
  }

  delay(400);

  Serial.println(per);

}

E as subrotinas do servidor WEB responsáveis pelas informações que aparecem na página do navegador

void handle_OnConnect() {
  server.send(200, "text/html", SendHTML(per));
}

void handle_NotFound() {
  server.send(404, "text/plain", "Pagina não existente");
}

String SendHTML(int per) {

  String ptr = "<!DOCTYPE html> <html>\n";

  ptr += "<head><meta http-equiv=\"refresh\" content=\"0.5\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";

  ptr += "<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
  ptr += "<title>MEDIDOR NÍVEL E AUTOMATIZADOR DO RESERVATÓRIO</title>\n";
  ptr += "<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
  ptr += "body{margin-top: 50px;}\n";
  ptr += "h1 {margin: 50px auto 30px;}\n";
  ptr += ".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
  ptr += ".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
  ptr += ".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
  ptr += ".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
  ptr += ".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
  ptr += ".data{padding: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";

  ptr += "<div id=\"webpage\">\n";

  ptr += "<h1>MEDIDOR DE NÍVEL E AUTOMATIZADOR DO RESERVATÓRIO</h1>\n";

  ptr += "</div>\n";
  ptr += "<div class=\"data\">\n";
  ptr += "<div class=\"side-by-side humidity-icon\">\n";
  ptr += "<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
  ptr += "<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
  ptr += "c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
  ptr += "</svg>\n";
  ptr += "</div>\n";
  ptr += "<div class=\"side-by-side humidity-text\">Nivel da agua</div>\n";
  ptr += "<div class=\"side-by-side humidity\">";
  ptr += (int)per;
  ptr += "<span class=\"superscript\">%</span></div>\n";
  ptr += "</div>\n";

  ptr += "</div>\n";
  ptr += "</body>\n";
  ptr += "</html>\n";

  return ptr;
}

Ao digitar em um navegador web o endereço IP do ESP32, o servidor web abrirá com o nível do líquido medido, como aparece na figura abaixo:

Logo abaixo está o código completo:

/*  IFMAKER - Itumbiara
  Autores: Henrique Xavier
           Josemar Junior
  APRESENTAÇÃO
  Projeto sensor de nível com controlador automático (para bomba elétríca ou solenoide)
  Nesta configuação o relé para acionamento de carga liga quando medir 20% do nível e desliga ao atingir 100%.
  Pinos utilizados (conexões com o ESP32):
  IO14 - led indidicativo de operação do relé
  IO15 - RELÉ de acionamento da bomba d'água
  IO13 - Sensor de 20%
  IO12 - Sensor de 40%
  IO14 - Sensor de 60%
  IO27 - Sensor de 80%
  IO33 - Sensor de 100%
  Obs.: Os sensores podem ser qualquer peça metálica que terá contato com a água.
*/
#include <WiFi.h>
#include <WebServer.h>
//++++++++++++++++++++++++++++++++++++
// Definições WIFI
//++++++++++++++++++++++++++++++++++++
const char* WIFISSID = "sua_rede";
const char* senha = "sua_senha";
// Pinos I/O
const int bomba = 15;
const int led = 14;
// Variaveis
int per = 0;
String bombastatus = "Desligada";
//++++++++++++++++++++++++++++++++++++
// Definições de rede
//++++++++++++++++++++++++++++++++++++
IPAddress local_IP(192, 168, 1, 50); //Defina o IP de acesso
IPAddress gateway(192, 168, 1, 1);   //Defina o IP do roteador de internet
IPAddress subnet(255, 255, 255, 0);  //Defina a máscara de sub-rede
IPAddress primaryDNS(192, 168, 1, 1);//opcional - DNS primário
IPAddress secondaryDNS(8, 8, 8, 8);  //opcional - DNS secundário
WebServer server(80);
void setup() {
  Serial.begin(115200);
  delay(400);
  // ip fixo
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }// fim ip fixo
  Serial.println("Conectando a rede:  ");
  Serial.println(WIFISSID);
  WiFi.begin(WIFISSID , senha);
  while (WiFi.status() != WL_CONNECTED)   {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("Sucesso ao conectar-se a rede WiFi");
  Serial.print("endereço de IP para o web server: ");
  Serial.println(WiFi.localIP());
  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);
  server.begin();
  Serial.println("HTTP servidor está funcionando");
  pinMode(bomba , OUTPUT);
  pinMode(led , OUTPUT);
}
void loop() {
  server.handleClient();
  if (touchRead(T4) <= 60 && touchRead(T5) <= 60 && touchRead(T6) <= 60 && touchRead(T7) <= 60 && touchRead(T8) <= 60) {
    per = 100;
  } else if (touchRead(T4) <= 60 && touchRead(T5) <= 60 && touchRead(T6) <= 60 && touchRead(T7) <= 60 ) {
    per = 80;
  } else if (touchRead(T4) <= 60 &&  touchRead(T5) <= 60 && touchRead(T6) <= 60  ) {
    per = 60;
  } else  if (touchRead(T4) <= 60 && touchRead(T5) <= 60 ) {
    per = 40;
  } else if (touchRead(T4) <= 60) {
    per = 20;
  } else {
    per = 0;
  }
  if (per <= 20)   {
    // Aciona o relé e o led indicativo
    digitalWrite(bomba, HIGH);  // Considerando o acionamento do relé com nível alto
    digitalWrite(led, HIGH);
    bombastatus = "Ligada";
    Serial.println("Bomba ligada");
  }
  else if (per == 100)   {
    // Desliga o relé e o led indicativo
    digitalWrite(bomba, LOW);  // Considerando o desacionamento do relé com nível baixo
    digitalWrite(led, LOW);
    bombastatus = "Desligada";
    Serial.println("Bomba desligada");
  }
  delay(400);
  Serial.println(per);
}
void handle_OnConnect() {
  server.send(200, "text/html", SendHTML(per));
}
void handle_NotFound() {
  server.send(404, "text/plain", "Pagina não existente");
}
String SendHTML(int per) {
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<head><meta http-equiv=\"refresh\" content=\"0.5\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,600\" rel=\"stylesheet\">\n";
  ptr += "<title>MEDIDOR NÍVEL E AUTOMATIZADOR DO RESERVATÓRIO</title>\n";
  ptr += "<style>html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #333333;}\n";
  ptr += "body{margin-top: 50px;}\n";
  ptr += "h1 {margin: 50px auto 30px;}\n";
  ptr += ".side-by-side{display: inline-block;vertical-align: middle;position: relative;}\n";
  ptr += ".humidity-icon{background-color: #3498db;width: 30px;height: 30px;border-radius: 50%;line-height: 36px;}\n";
  ptr += ".humidity-text{font-weight: 600;padding-left: 15px;font-size: 19px;width: 160px;text-align: left;}\n";
  ptr += ".humidity{font-weight: 300;font-size: 60px;color: #3498db;}\n";
  ptr += ".superscript{font-size: 17px;font-weight: 600;position: absolute;right: -20px;top: 15px;}\n";
  ptr += ".data{padding: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
  ptr += "<div id=\"webpage\">\n";
  ptr += "<h1>MEDIDOR DE NÍVEL E AUTOMATIZADOR DO RESERVATÓRIO</h1>\n";
  ptr += "</div>\n";
  ptr += "<div class=\"data\">\n";
  ptr += "<div class=\"side-by-side humidity-icon\">\n";
  ptr += "<svg version=\"1.1\" id=\"Layer_2\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\"; width=\"12px\" height=\"17.955px\" viewBox=\"0 0 13 17.955\" enable-background=\"new 0 0 13 17.955\" xml:space=\"preserve\">\n";
  ptr += "<path fill=\"#FFFFFF\" d=\"M1.819,6.217C3.139,4.064,6.5,0,6.5,0s3.363,4.064,4.681,6.217c1.793,2.926,2.133,5.05,1.571,7.057\n";
  ptr += "c-0.438,1.574-2.264,4.681-6.252,4.681c-3.988,0-5.813-3.107-6.252-4.681C-0.313,11.267,0.026,9.143,1.819,6.217\"></path>\n";
  ptr += "</svg>\n";
  ptr += "</div>\n";
  ptr += "<div class=\"side-by-side humidity-text\">Nivel da agua</div>\n";
  ptr += "<div class=\"side-by-side humidity\">";
  ptr += (int)per;
  ptr += "<span class=\"superscript\">%</span></div>\n";
  ptr += "</div>\n";
  ptr += "</div>\n";
  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}

Montagem do Circuito e Posicionamento dos Sensores

O próximo passo é a montagem do circuito. É importante ressaltar que existem diversas versões do ESP32, sendo o módulo utilizado no projeto o ESP32 WROOM32 DevKit.

Para montar o circuito é necessário posicionar 6 jumpers no interior do reservatório de água, sendo 5 para a ligação dos sensores de toque no ESP32 até o reservatório.  Os sensores escolhidos para essa tarefa são os presentes nas GPIO 13, 12, 14, 27 e 33, e o jumper restante servirá como GND do reservatório, contudo podem ser modificadas na programação de acordo com as portas disponíveis apresentadas na tabela abaixo.

Fonte: www.randomnerdtutorials.com

Para realizar o contato entre os jumpers e a parte interna do reservatório onde será feito o acionamento (para ilustração deste projeto), foi necessário a perfuração dos locais onde os jumpers serão inseridos e, após a inserção, foi necessária a vedação com massa epóxi bicomponente (Durepoxi), porém há várias outras formas de obter o acionamento de forma interna. A imagem abaixo mostra como ficou o reservatório.

Após esse passo é necessário posicionar o resistor de 220R saindo da GPIO 25 em série com o ânodo do LED difuso para sinalizar a ativação do atuador, feito essa conexão basta ligar o catodo do LED ao GND. O relé de atuação recebe o sinal pela GPIO 26, ativando assim pela ligação normalmente aberta (NA), o atuador que pode ser tanto a eletroválvula, quanto a bomba.

Como apresentado na programação do sistema, o LED ficará no mesmo estado que o atuador, e assim que o sistema apresentar o percentual do nível de líquido no reservatório inferior a 20%, o relé e o LED são simultaneamente ativados até que o reservatório atinja sua capacidade máxima (100%) e desligue.

O sistema completo ficou da seguinte forma:


Pinos Utilizados no ESP32

Para lhe orientar melhor na montagem, abaixo você conta com a lista de GPIOs utilizadas e suas respectivas conexões:

GPIO25 – LED indicativo de operação do relé;
GPIO15 – RELÉ de acionamento da bomba d’água;
GPIO13 – Sensor de 20%;
GPIO12 – Sensor de 40%;
GPIO14 – Sensor de 60%;
GPIO27 – Sensor de 80%;
GPIO33 – Sensor de 100%.


Resultado Final

O resultado final do projeto você pode conferir no vídeo abaixo:


Conclusão

Com este projeto é possível obter êxito em diversas aplicações onde é necessário automatizar ou monitorar o nível de líquidos de um reservatório em tempo real à distância, conectado na mesma rede do ESP32, não sendo necessário conexão com a internet. Esse processo de controle é ideal para sistemas que utilizam bombas hidráulicas, pois aguardam um tempo de esvaziamento antes de religar o sistema.

Para mais materiais como esse, continue acompanhando as postagens semanais do blog e não deixe de visitar nossa loja. Lá você encontra todos os componentes necessários para desenvolver esse e muitos outros projetos!

Um forte abraço e até a próxima!


Referências

Fernando K.; ESP32 com Touch Button Capacitivo. Publicado em 2 de fevereiro de 2021. Disponível em https://www.fernandok.com/2018/02/esp32-com-touch-button-capacitivo.html (último acesso em 09/11/2021).

José Gustavo Abreu Murta (Blog Eletrogate); Conhecendo o ESP32 – Usando Arduino IDE (2). Publicado em 9 de novembro de 2018. Disponível em https://blog.eletrogate.com/conhecendo-o-esp32-usando-arduino-ide-2/ (último acesso em 09/11/2021).

Last Minute ENGINEERS. Interface DHT11 DHT22 w/ ESP8266 NodeMCU Using Web Server, disponível em: https://lastminuteengineers.com/esp8266-dht11-dht22-web-server-tutorial/ (último acesso em 07/11/2021).

Miguel Sena (Blog Eletrogate); Como criar um WebServer com Esp32 e utilizá-lo junto ao BMP280. Publicado em 14 de setembro de 2021, disponível em: https://blog.eletrogate.com/como-criar-um-webserver-com-esp32-e-utiliza-lo-junto-ao-bmp280/ (último acesso em 08/11/2021).

Autores

Henrique Xavier dos Santos (Aluno Engenharia Elétrica / IFG – Itumbiara)
Josemar Alves dos Santos Junior (Professor da área de Indústria / IFG – Itumbiara)

Conheça a Metodologia Eletrogate e ofereça aulas de robótica em sua escola!


Sobre o Autor


IFMaker Itumbiara

O IFMaker Itumbiara é um espaço para ensino de desenvolvimento de projetos voltados à cultura Maker. As publicações e projetos são realizados por professores e alunos do Instituto Federal de Goiás – Campus Itumbiara (Goiás).


Eletrogate

17 de novembro de 2021

A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.

Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!

Eletrogate Robô

Cadastre-se e fique por
dentro de novidades!