O monitoramento de dados climáticos atua em benefícios da qualidade de vida humana, auxiliando tanto em uma simples prevenção, quanto como ferramenta fundamental em setores agrícolas. A coleta das informações necessárias para a caracterização do clima será realizada através de sensores e instrumentos, com a capacidade de avaliar a temperatura, umidade, pressão atmosférica, radiação solar, possíveis indícios de chuva, entre outras variáveis. Neste post iremos propor a construção de uma estação meteorológica com um ESP32, capaz de expressar os valores coletados pelos sensores em uma plataforma composta por gráficos e ferramentas voltadas a análise climática. O sistema será alocado em um servidor online, armazenando as informações coletadas na rede, através das ferramentas de edição Node-RED e IBM Cloud.


Componentes

          Para concluir as atividades desse post, tenha em mãos os seguintes componentes:

          Você pode compra-los clicando nos links acima ou visitando nosso site: www.curtocircuito.com.br.


Circuito Elétrico

          A construção do circuito elétrico irá exigir um valor de correte elétrica maior do que o fornecido internamente em placas DOIT ESP32, portanto, iremos utilizar uma fonte de Protoboard como meio de fornecer uma alimentação externa para o projeto. A tensão de saída da fonte poderá ser ajustada entre 5V e 3,3V de acordo com a posição dos plugs amarelos, destacados na imagem abaixo, e no caso desse projeto, iremos ajusta-la em 3,3V. Verifique a polaridade da fonte antes de conectá-la ao Protoboard.

Ajuste a tensão de um lado da fonte para 5V e o outro 3,3V.


          LEDs RGB possuem quatro terminais, sendo três responsáveis por emitir as cores e um (o maior entre eles) a polaridade. A alimentação do LED será dividida entre Ánodo ou Catodo comu, se for anodo conecte a fileira positiva, se for catodo na fileira negativa.

LED RGB possui polaridade, se for anodo conecte ao positivo, catodo ao negativo.


          Encaixe o LED no Protoboard, conectando os resistores de 330 Ω entre os pinos do LED e as portas digitais D02, D04 e D23 do ESP32, e alimente o pino maior de acordo com o tipo de LED.


Sensor de Chuva

          Este componente emite leituras analógicas e digitais, ao entrar em contato com água, possibilitando diferenciar um chuvisco de uma tempestade. A leitura digital irá identificar a presença de água sob as hastes metálicas do sensor, alternando entre 0 e 1, enquanto o valor analógico permite analisar a intensidade, variando de 0 á 4095. A pinagem do componente será divida da seguinte maneira:

O sensor de chuva dispões de 4 pinos, sendo dois deles parte do sinal de comunicação.


          Encaixe os pinos GND e VCC nas fileiras de alimentação do Protoboard, o terminal D0 do sensor na porta digital D12 e o A0 na porta D35. A leitura analógica será limitada a alguns terminais ao acionar o módulo Wi-Fi, sendo essas as portas ADC1 32, 33, 34, 35, 36 e 39. Como a largura de um único protoboard mostra-se insuficiente para acoplar um ESP32, recomendamos a junção de duas placas.

O circuito elétrico do sensor de chuva irá utilizar um pino digital, um analógico, e alimentação em 5V.

           Os valores do sensor serão interpretados de forma decrescente, ou seja, quanto menor a leitura analógica, maior será o volume da chuva. O funcionamento do sensor será avaliada através do seguinte exemplo:

// Projeto Curto Circuito - ESP32: Sensor de Chuva
//----Sensor de Chuva----
int pino_d = 12; // Pino D12 do ESP32 ligado ao D0 do sensor
int pino_a = 35; // Pino D35 do ESP32 ligado ao A0 do sensor
int val_d = 0;   // Armazena leitura do pino digital
int val_a = 0;   // Armazena leitura do pino analógico
//---- LED----
int pin = 2;    // RGB Vermelho pino D2 do ESP32
int pin2 = 4;   // RGB Azul pino D4 do ESP32

void setup()
{
  Serial.begin(9600);
  // Sensores INPUT
  pinMode(pino_d, INPUT);
  pinMode(pino_a, INPUT);
  // LEDs OUTPUT
  pinMode(pin, OUTPUT);
  pinMode(pin2, OUTPUT);
}

void loop()
{
  // Armazena os valores de leitura
  val_a = analogRead(pino_a);
  // Se a leitura analógica for menor que 300
  if ( val_a < 1000)
  { // Chuva intensa
    digitalWrite(pin, 0);   // Desliga
    digitalWrite(pin2, 1);  // Liga
    Serial.println("Chuva Intensa");
    Serial.println(val_a );
  }
  // Se a leitura analógica for menor que 500 e maior que 300
  if (val_a <= 3000 && val_a >= 1000)
  { // Chuva moderada
    digitalWrite(pin, 1);    // Liga
    digitalWrite(pin2, 1);   // Liga
    Serial.println("Chuva Moderada ou Chuvisco");
    Serial.println(val_a );
  }
  // Se a leitura analógica for maior que 500
  if ( val_a > 4000)
  { // Sem previsão de Chuva
    digitalWrite(pin, 1);    // Liga
    digitalWrite(pin2, 0);   // Desliga
    Serial.println("Sem previsão de chuva");
    Serial.println(val_a );
  }
}
          A leitura analógica em val_a será inicialmente de 4095, tal valor irá diminuir ao aplicar água sob as hastes do sensor, acima de 3000, irá representar um leve gotejar, até 1000, chuva moderada, e abaixo disso poderá ser considerado como tempestade.

O funcionamento do sensor de chuva poderá ser avaliado ao mergulha-lo em um copo com água, ou gotejar algum líquido sob as hastes de metal.



Sensor BME 280

          O BME 280 lida com leituras referentes à Pressão atmosférica, Altitude, Umidade e Temperatura. Esse sensor opera com um consumo de energia baixo, apenas 3.3 V, sendo uma opção simples e econômica na coleta de dados barométricos e meteorológicos. A pinagem do componente apresenta-se como:

Sensor de Temperatura, Umidade, Pressão e Altitude.


          Conecte o pino SCK na porta digital D21 e SDA na porta digital D22. GND e VCC nos terminais de alimentação do protoboard.

O BME deverá ser alimentado em 3,3V, e utilizar dois pinos para leitura.


          Para auxiliar na construção do projeto recomenda-se adicionar ao menos uma biblioteca, no caso do exemplo a seguir, aderimos a opção 
“Adafruit BME280 Library” , que pode ser facilmente instalada através do Gerenciador de Bibliotecas do Arduino IDE.

A biblioteca da Adafruit irá simplificar o desenvolvimento de programações para esse sensor.

          Os exemplo de programação serão divididos entre dois modelos de interface, o I2C, que utiliza apenas 2 pinos de comunicação, e SPI, com 4 pinos. No caso do componente utilizado nesse post, utilizaremos a interface I2C, com endereço 0x76 ou 0x77.
          Utilize a programação abaixo para testar o funcionamento do sensor, caso haja algum problema com o funcionamento, substitua o valor de endereço (presente na função bme.begin(0x76)), e pressione o botão RST.

// Projeto Curto Circuito - ESP32: Sensor BME280

//----Bibliotecas----
#include <Wire.h>
#include "Adafruit_BME280.h"


//----Configurações Sensores I2C----
Adafruit_BME280 bme;
#define SEALEVELPRESSURE_HPA (1013.25)
void getValues(void);

void setup()
{
  Serial.begin(115200);
  Serial.println("Programa Iniciado");
  bool status;  //Cria uma variável status de funcionamento do sensor

  status = bme.begin(0x76); //Endereço 0x77 ou 0x76
  if (!status)
  { //Caso não seja identificado
    Serial.println("Sensor Inexistente, verifique as configurações!");
    while (1);
  }
  delay(1000);
}

void loop()
{
  getValues();
  delay(3000);
}

void getValues()
{
  //Leitura da Temperatura
  Serial.print("Temperatura = ");
  Serial.print(bme.readTemperature()); // Leitura de temperatura
  Serial.println(" ℃"); // Celsius 
  //Leitura da Pressão
  Serial.print("Pressão = ");
  Serial.print(bme.readPressure() / 100.0F);//Leitura de Pressão
  Serial.println(" Pa"); //Pascal
  //Leitura da Altitude
  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));//Leitura de altitude
  Serial.println(" m"); // Metros 
  //Leitura de Umidade
  Serial.print("Umidade = ");
  Serial.print(bme.readHumidity());//Leitura Umidade
  Serial.println(" %"); // Porcentagem 
  Serial.println();
}

          A função #include "Adafruit_BME280.h" inclui a biblioteca na programação, adicionando alguns comandos como bme.readTemperature(), aplicado a leitura da temperatura, ou bme.readHumidity(), umidade. As leituras de pressão variam de acordo com a altitude e as condições de temperatura no ar, quanto maior for a altitude em relação ao mar, menor será a pressão. A proporção para avaliar a leitura com o nível do mar poderá ser dada por meio da seguinte tabela:

Os valores e pressão e altitude serão inversamente proporcionais.

 
          A leitura da altitude será realizada através do comando bme.readAltitude(SEALEVELPRESSURE_HPA), que irá utilizar o valor armazenado na variável SEALEVELPRESSURE_HPA na realização de um cálculo simples de conversão, exibindo assim os resultados coletados em metros.


Sensor Luminosidade Ultra Violeta

          O sensor Ultravioleta lida com a leitura da tensão de saía, que varia de acordo com a luminosidade UV aplica sob o mesmo. Nesse projeto, será utilizado na analise da intensidade de radiação solar, indicando possíveis riscos a saúde. A pinagem do componente será distribuída da seguinte maneira:

O sensor UV utiliza apenas dois pinos para a análise de luminosidade ultravioleta.

          O terminal VIN deverá manter-se desconectado, o
s pinos de alimentação na fileira 3,3V  e GND do Protoboard, OUT no pino VP, e EN no pino D34.


O sensor UV utiliza apenas dois pinos para a análise de luminosidade ultravioleta.


          A lógica de programação atribuída ao sensor será construía com base no índice Ultravioleta (IUV), padronizado pela Organização Mundial de Saúde em 1994, que refere-se á níveis internacionais de medida, para avaliar a radiação solar na superfície da terra, indicando possíveis riscos e danos a saúde de acordo com os valores que variam de 0 á 11.

índice desenvolvido no Canadá em 1992, e adotado como medidor internacional.


          No exemplo abaixo, utilizaremos a mistura de cores presente em um LED RGB para indicar a intensidade da radiação, juntamente à leitura indicada no Monitor Serial do Arduino IDE.
//Projeto Curto - ESP32 : Sensor UV --------
int UVOUT = 36;   // Pino D36 do ESP32 conetado ao Out do sensor 
int REF   = 34;   // Pino D34 do ESP32 conectado ao EN do sensor
//-------- LEDs e Contador--------
int LED = 2;      // Led do ESP
int RED = 23;     // LED RGB pino vermelho
int BLUE = 5;     // LED RGB pino azul
int GREEN = 4;    // LED RGB pino green


void setup()
{
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(BLUE, OUTPUT);
  pinMode(GREEN, OUTPUT);

}

void loop()
{
  int uvLevel = analogRead(UVOUT);           // Armazena a leitura analógica do pino OUT
  int refLevel = analogRead(REF);            // Armazena a leitura analógica do pino EN
  //Use 3.3V como referencia no calculo de tensão
  float outputVoltage = 3.3 / refLevel * uvLevel; // Indica a tensão de saída do sensor
  float uvIntensity = map(outputVoltage, 0.99, 2.9, 0.0, 15.0); // Intensidade raios UV

  Serial.print(" Intensidade UV: ");
  Serial.println(uvIntensity);

  if (uvIntensity >= 0 && uvIntensity <= 2)
  { // Intensidade Baixa: Verde
    digitalWrite(RED, 0);
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 1);                              
  }
  if (uvIntensity >= 3 && uvIntensity < 5)
  { // Intensidade Moderada: Amarelo
    digitalWrite(RED, 1);
    digitalWrite(BLUE, 0);                               
    digitalWrite(GREEN, 1);                             
  }
  if (uvIntensity == 6 || uvIntensity == 7)
  { // Intensidade Alta: Laranja (branco)
    digitalWrite(RED, 1);                               
    digitalWrite(BLUE, 1);
    digitalWrite(GREEN, 1);                            
  }
  if (uvIntensity >= 8 && uvIntensity < 10)
  { // Intensidade Elevada: Vermelho
    digitalWrite(RED, 1);                    
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 0);
  }
  if (uvIntensity >= 11)
  { // Intensidade Elevada: Violeta
    digitalWrite(RED, 1);                    
    digitalWrite(BLUE, 1);                   
    digitalWrite(GREEN, 0);
  }
}

          A lógica de programação será baseada, principalmente, na leitura da tensão de saída do sensor, por isso, a variável "outputVoltage" irá utilizar 3.3 como referência no calculo, pois a tensão de saída será o valor de alimentação dividido pela leitura analógica nos pinos D36 e D34.

 float outputVoltage = 3.3 / refLevel * uvLevel; 

          O resultado do cálculo será aplicado a função map, presente na variável "uvIntensity", que será utilizado para determinar a intensidade dos raios UV, de acordo com o mapeamento dos valores de "outputVoltage". 

float uvIntensity = map(outputVoltage, 0.99, 2.9, 0.0, 15.0);

          A função map irá avaliar a variável "outputVoltage", mapeando a leitura de acordo com os intervalos determinados, que, no caso da programação  foram definidas em quatro variáveis, 0.99(mínimo) ,2.9 (máximo), 0.0 (mínimo), 15.0 (máximo), sendo  elas duas entradas (in) e duas saídas (out). Segundo o site Arduino.cc, a lógica matemática por trás da função será similar a uma regra de três. Para compreender essa lógica de forma mais simples, observe a fórmula completa no exemplo abaixo: 

long map(long x, long in_min,long in_max, long out_min, long out_max){ return (x - in_min)*(out_max - out_min) / (in_max - in_min)+ out_min; } 

          Suponha que a leitura em outputVoltage seja igual a 2, se aplicarmos a forma apresentada acima: return( 2 - 0,99) * (15,0 - 0,0) / (2,9 - 0,99) + 0,0 =  7,9 , Como o resultado encontra-se acima de 5, a intensidade dos raios UV será considerada como alta. As cores no LED serão equivalentes ao alerta, com exceção da cor Laranja, que será demonstrada como um cor branca. 


IBM Cloud: Conectando ao Servidor

          O armazenamento de informações na nuvem requer uma comunicação entre o ESP32 e um host particular, nesse caso,  o servidor será construído através da IBM Cloud, pois esta ferramenta possui um vinculo direto com o editor de fluxo Node-RED, além de deixar a disposição diversos recursos que facilitam o desenvolvimento de plataformas automatizadas. A construção do servidor requer uma conta de usuário no site bluemix.net, e a escolha de uma plataforma de desenvolvimento em Catálogo, que nesse caso, será a opção "Internet of Things Platform Starter".

A opção internet of things facilita o desenvolvimento de servidores de automação.


          Nomeie o aplicativo, e procure manter o plano selecionado em Lite caso deseje desenvolver o projeto de forma gratuita. Em Conexões, acesse a plataforma Watson IoT Platform, que servirá como ferramenta principal na inclusão de dispositivos eletrônicos, permitindo que a leitura e controle de componentes como o ESP32, sejam armazenadas nos servidores da IBM.

Ferramenta para a conexão de objetos na rede.


          No menu lateral da plataforma Watson procure por "
Aplicativos", e  utilize a opção "Gerar chave API". Esta ferramenta irá prover um Token, que será utilizado como medida de segurança, servindo como um código de autenticação na conexão entre o ESP32 e o IBM.

Gera um token de autenticação para conectar o componente.

          Acesse o menu "Dispositivos", e procure a opção "Incluir Dispositivo". Esta opção irá construir um tipo de objeto virtual, e através de algumas configurações na própria programação, possibilita a coleta de informação diretamente no componente real, no caso desse projeto, irá coletar a transmissão de dados presente no ESP32. Nomeie o tipo, crie uma identificação (ID) exclusiva para o componente, e insira o Token de Autenticação, não será preciso configurar os metadados.

Todos os  componentes a serem inclusos na rede, devem ser declarados.



Programação

          O status do componente será exibido na lista de dispositivos, e permanecerá desconectado até que a programação presente no ESP32 esteja ajustada com os seguintes parâmetros:

 
-------- Parâmetros de Conexão IBM -----------
DEVICE_TYPE: ESP32 (componente adicionado ao IBM)
DEVICE_ID:       test      (ID do componente)
TOKEN:   xxxxxxxxxxxx (Chave API )
ORG:                 ctu10j   (serão os seis primeiros dígitos do link internetofthings). ORG de Conexão do Dispositivo          Configure os parâmetros abaixo antes de transferir ao ESP32, a construção dessa programação será uma junção dos exemplos apresentados anteriormente.

// Projeto Curto Circuito – Estação Meteorológica: IBM Watson

//-------- Bibliotecas -----------
#include <WiFi.h>
#include <Wire.h>
#include <PubSubClient.h> // https://github.com/knolleary/pubsubclient/releases/tag/v2.3
#include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson/releases/tag/v5.0.7
#include "Esp32MQTTClient.h"
// ------ Configurações WiFi --------
const char* ssid     = "Nome_da_rede";
const char* password = "Senha";
//-------- Conexão IBM-ESP32 -----------
#define ORG "ORG" // ID de organização 
#define DEVICE_TYPE "Componente" // Insira o nome do componente
#define DEVICE_ID "ID do componente" // Insira o ID
#define TOKEN "Token de autenticação"// Insira o Token

//-------- Comunicação IOT (Não mexer)--------
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
const char eventTopic[] = "iot-2/evt/status/fmt/json";
const char cmdTopic[] = "iot-2/cmd/led/fmt/json";

//-------- Sensor de Chuva--------
#define pino_d 14 // Pino digital D14 do ESP32
#define pino_a 35 // Pino analógico D35 do ESP32
int  val_a = 0;                 // Chuva leitura analógica
int  val_d = 0;                 // Chuva leitura digital
int result = 0 ;                // Lógica que transforma a leitura do sensor em porcentagem.

//-------- Sensor BME280 --------
#include "Adafruit_BME280.h" // Biblioteca Adafruit BME280
Adafruit_BME280 bme;            // Configuração I2C

//-------- Sensor UV --------
int UVOUT = 36;   // Pino Out D36 do ESP32
int REF   = 34;   // Pino EN D34 do ESP32
//-------- LEDs e Contador--------
int LED = 2;      // Led do ESP
int RED = 23;     // LED RGB pino vermelho
int BLUE = 5;     // LED RGB pino azul
int GREEN = 4;    // LED RGB pino green
int contagem = 0; // Contagem crescente
WiFiClient wifiClient;
void callback(char* topic, byte* payload, unsigned int payloadLength)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");

  if ((char)payload[0] == '0')
  { // Se receber o caractere 0
    digitalWrite(LED, LOW);   // Desliga o LED
    Serial.println("LOW");
  }
  if ((char)payload[0] == '1')
  { // Se receber o caractere 1
    digitalWrite(LED, HIGH);  // Liga LED
    Serial.println("HIGH");
  }
}
PubSubClient client(server, 1883, callback, wifiClient);

void setup()
{
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(BLUE, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(UVOUT, INPUT);
  pinMode(REF, INPUT);
  client.setCallback(callback);
  bool status;
  status = bme.begin(0x76);       // Avalia a conexão do BME
  if (!status)
  { // Se estiver desconectado
    Serial.println("BME280 não localizado, confira a pinagem do sensor!");
    while (1);
  }
  //---------Quando o sensor BME estiver conectado-----------
  wifiConnect();                 // Direciona ao void wifiConnect
  mqttConnect();                 // Direciona ao void mqttConnect
}
void wifiConnect()
{ // Funções conectar ao Wi-Fi
  Serial.print("Conectando a rede:");
  Serial.print(ssid);           // Indica a rede Wi-Fi ao qual irá se conectado
  WiFi.begin(ssid, password);   // Conecta ao ssid e o password configurado
  while (WiFi.status() != WL_CONNECTED)
  { // Enquanto o Wi-Fi estiver desconectado
    delay(500);                 // Aguarda meio segundo
    Serial.print(".");
  }
  Serial.print("Rede Wi-Fi Conectada, Endereço de IP: ");
  Serial.println(WiFi.localIP()); // Indica o endereço de IP
}
void mqttConnect()
{ // Funções conectar ao servidor
  if (!!!client.connected())
  { // Se não houver conexão com o servidor
    Serial.print("Reconectando ao servidor:");
    Serial.println(server);      // Indica o endereço do servidor

    while (!!!client.connect(clientId, authMethod, token) )
    {
      Serial.print(".");
      delay(500);
    }
    if (client.subscribe(cmdTopic))
    { // Se conseguir se Conectar ao cmdTopic
      Serial.println("OK");   // Escreve OK no monitor serial
    }
    else
    {
      Serial.println("Erro"); // Escreve erro no monitor serial
    }
  }
}
void loop()
{
  if (!client.loop())
  { // Se Desconectar do Servidor
    mqttConnect();                     // Retorna a função mqttConnect
  }
  float h = bme.readHumidity();        // Armazena os valor de leitura da Umidade
  float t = bme.readTemperature();     // Armazena os valor de leitura da Temperatura
  float p = bme.readPressure();        // Armazena os valores de leitura da Pressão
  float a = bme.readAltitude(1013.25); // Armazena os valores de leitura da Altitude
  val_a = analogRead(pino_a) ;         // Armazena os valores analógicos do sensor de chuva
  p = p / 100.0F;                      // Realiza um calculo que ajusta o valor de p
  // Cria uma variável que coleta a leitura do sensor de chuva
  int result = 0;                      // Cria uma variável do tipo inteira
  result = (val_a * 100) / 4095;       // Transforma o valor em porcentagem
  // ----- As String abaixo serão responsáveis por enviar mensagens ao servidor ------
  String payload = "{\"d\":{\"adc\":";                 // Inicia Payload
  payload += contagem;                                 // Inclui o valor de contagem
  payload += "}}";                                     // Finaliza a função
  Serial.print("Contagem: "); Serial.println(payload); // Escreve o valor no monitor serial
  client.publish(eventTopic, (char*) payload.c_str() );// Publica Payload
  delay(100);                                          // Aguarda 100 milissegundos
  String payload2 = "{\"d\":{\"umi\":";                // Inicia Payload2
  payload2 += h;                                       // Inclui o valor de h
  payload2 += "}}";                                    // Finaliza a função
  Serial.print(" Umidade: "); Serial.println(payload2); // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload2.c_str() );// Publica Payload2
  delay(100);                                           // Aguarda 100 milissegundos
  String payload3 = "{\"d\":{\"tem\":";                    // Inicia Payload3
  payload3 += t;                                           // Inclui o valor de t
  payload3 += "}}";                                        // Finaliza a função
  Serial.print(" Temperatura: "); Serial.println(payload3);// Escreve no monitor serial
  client.publish(eventTopic, (char*) payload3.c_str() );   // Publica Payload3
  delay(100);                                              // Aguarda 100 milissegundos
  String payload4 = "{\"d\":{\"pre\":";                    // Inicia Payload4
  payload4 += p;                                           // Inclui o valor de p
  payload4 += "}}";                                        // Finaliza a função
  Serial.print(" Pressão: "); Serial.println(payload4);    // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload4.c_str() );   // Publica Payload4
  delay(100);                                              // Aguarda 100 milissegundos
  String payload5 = "{\"d\":{\"alt\":";                    // Inicia Payload5
  payload5 += a;                                           // Inclui o valor de a
  payload5 += "}}";                                        // Finaliza a função
  Serial.print(" Altitude: "); Serial.println(payload5);// Escreve no monitor serial
  client.publish(eventTopic, (char*) payload5.c_str() );   // Publica Payload5
  delay(100);                                              // Aguarda 100 milissegundos
  String payload6 = "{\"d\":{\"chu\":";                    // Inicia Payload6
  payload6 += result;                                      // Inclui o valor de result
  payload6 += "}}";                                        // Finaliza a função
  Serial.print(" Chuva: "); Serial.println(payload6);      // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload6.c_str() );   // Publica Payload5
  delay(100);                                              // Aguarda 100 milissegundos
  contagem ++;                                             // Contagem + 1
  delay(1000);                                             // Aguarda 1 segundo
  uv_test();                                               // Direciona ao void uv_test
}
void uv_test()
{
  int uvLevel = analogRead(UVOUT);           // Armazena a leitura analógica do pino OUT
  int refLevel = analogRead(REF);            // Armazena a leitura analógica do pino EN
  //Use o valor de 3.3V como referencia no calculo de tensão
  float outputVoltage = 3.3 / refLevel * uvLevel; // Indica a tensão de saída do sensor
  float uvIntensity = map(outputVoltage, 0.99, 2.9, 0.0, 15.0); // Intensidade raios UV
  String payload7 = "{\"d\":{\"uvl\":";      // Inicia Payload7
  payload7 += uvLevel;                       // Inclui o valor de uvLevel
  payload7 += "}}";                          // Finaliza a função
  Serial.print(" Level: "); Serial.println(payload7); // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload7.c_str() ); // Publica Payload7
  delay(100);

  String payload8 = "{\"d\":{\"volt\":";                 // Inicia Payload8
  payload8 += outputVoltage;                             // Inclui o valor de outputVoltage
  payload8 += "}}";                                      // Finaliza a função
  Serial.print(" Tensao: "); Serial.println(payload8);   // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload8.c_str() ); // Publica Payload8
  delay(100);

  String payload9 = "{\"d\":{\"uvi\":";                  // Inicia Payload9
  payload9 += uvIntensity;                               // Inclui o valor de uvIntensity
  payload9 += "}}";                                      // Finaliza a função
  Serial.print(" Intensidade UV: "); Serial.println(payload9); // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload9.c_str() ); // Publica Payload8
  Serial.println();                                      // Pula uma linha
  delay(1000);                                           // Aguarda 1 segundo
  if (uvIntensity >= 0 && uvIntensity <= 2)
  { // Intensidade Baixa: Verde
    digitalWrite(RED, 0);
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 1);                              // Liga LED VERDE
  }
  if (uvIntensity >= 3 && uvIntensity < 5)
  { // Intensidade Moderada: Amarelo
    digitalWrite(RED, 0);
    digitalWrite(BLUE, 1);                               // Liga LED AZUL
    digitalWrite(GREEN, 1);                              // Liga LED VERDE
  }
  if (uvIntensity == 6 || uvIntensity == 7)
  { // Intensidade Alta: Laranja
    digitalWrite(RED, 1);                                // Liga LED VERMELHO
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 1);                              // Liga LED VERDE
  }
  if (uvIntensity >= 8 && uvIntensity < 10)
  { // Intensidade Elevada: Vermelho
    digitalWrite(RED, 1);                     // Liga LED VERMELHO
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 0);
  }
  if (uvIntensity >= 11)
  { // Intensidade Elevada: Violeta
    digitalWrite(RED, 1);                     // Liga LED VERMELHO
    digitalWrite(BLUE, 1);                    // Liga LED AZUL
    digitalWrite(GREEN, 0);
  }
}
          Todas as opções presente na programação poderão ser ajustadas, porém, recomendamos que os parâmetros da opção "Comunicação IOT (Não mexer)" sejam mantidos, pois os padrões presente em cada variável terão a serventia exclusiva de conectar-se ao servidor.
          A troca de mensagens entre o Servidor Web e o ESP32 irá exigir uma aplicação mínima de linguagem JSON, por exemplo, na função void loop, as mensagens enviadas ao servidor deverão ser compostas:

 String payload2 = "{\"d\":{\"umi\":";                // Inicia Payload2
  payload2 += h;                                              // Inclui o valor da umidade
  payload2 += "}}";                                           // Finaliza a função
  client.publish
(
eventTopic, (char*) payload2.c_str()
); // Publica Payload2

          A função client.publish será responsável por transmitir as informações coletadas ao servidor, no caso do exemplo será transmitida a leitura da umidade. A mensagem será composta por duas variáveis, o eventTopic[], que foi declarado no inicio da programação com o cógido "iot-2/evt/status/fmt/json", e o payload2, que irá compor a mensagem "{\d:\umi\h}}". A junção das variáveis irá construir um evento para a transmissão da leitura de "h" (leitura da umidade), em formato JSON.


Node-RED: Fluxos
           Volte ao IBM Watson, e observe se componente estará exibido como conectado, caso contrário, acesse a opção Configurações no menu lateral e procure Segurança da Conexão.


Caso o circuito não consiga conectar-se ao IBM, altere as opções de segurança.
          As opções de TSL implicam na segurança do componente, normalmente, alguns pacotes de desenvolvimento gratuito limitam a conexão as opções Autenticação por Token ou Opcional. O modo que certamente irá estabelecer uma conexão rápida será a TSL Opcional, pois este não requer qualquer chave de segurança no circuito, apresentando-se como uma das opções mais inseguras, porém, com total certeza de conexão.


TLS opcional diminui a segurança do projeto, porém, facilita a conexão.

          Após alterar o tipo de TSL, o componente adicionado deverá conectar-se ao servidor, indicando o horário de conexão em "Identidade". Após certificar-se sobre a conexão do componente, acesse o painel de aplicativos e clique na URL do projeto.

A URL  estará localizado ao lado do status do aplicativo.

          O link será direcionado ao editor Node-RED, se este for o primeiro acesso a página, será possível criar um login de acesso, limitando a edição dos fluxos em alguns usuários específicos. O Navegador será dividido em três partes principais:

O navegador de edição do Node-RED poderá ser divido em três partes, sendo elas: Paleta de nós, Área de trabalho e Configurações.

          Ao abrir o Node-RED, clique no botão  e selecione a opção Manage Palette, no menu Install escreva “dashboard”, e instale o conjunto node-red-dasboard.


Conjunto de blocos para o desenvolvimento de ferramentas de controle on-line.


          Um novo conjunto será adicionado as opções de nós, com a finalidade de personalizar a página de controle principal do navegador. A coleta de informações presente no ESP32, será estabelecida por um fluxo de comunicação entre um nó IBM IoT Input e um Debug.

Para testar a comunicação inicial entre o servidor IBM e o ESP32, será necessário configurar o nó IBM e liga-lo ao Debug.

          Nas opções de configuração do nó IBM IoT ajuste os seguintes parâmetros:

Configure o nó de acordo com o exemplo demonstrado na imagem.

          A opção "Device Event" será utilizada no recebimento de mensagens (Payload) provenientes do ESP32, "Event" irá filtrar a leitura do nó, direcionando-a a algum um evento específico da programação, no caso desse exemplo, o sinal "+" será aplicado a coleta de quaisquer informações. As demais opções serão configuradas tal qual fôra apresentado nos parâmetros "Comunicação IOT ".
          Para filtrar a mensagem, visualizando apenas os valores relevantes, adicione um nó Function e escreva: return {payload:msg.payload.d.adc};

O nó função servirá para construir ajustes e programações em linguagem JSON.


          Inclua um nó Numeric (presente em Dashboard) e procure construir o seguinte fluxo.

O fluxo irá exibir uma versão reduzida da mensagem, exibindo apenas uma breve contagem.


          Clique em Deploy, e selecione a opção Debug  
 para visualizar as mensagens recebidas.

A mensagem irá se ajustar, exibindo apenas a numeração enviada.


          Adicione dois nós Gauge (do conjunto Dashboard), aplicados a leitura de Umidade e Temperatura. Nas opções de configuração será necessário ajustar um ponto mínimo e máximo de cada leitura. a Umidade será  0 á 100, pois sua grandeza será demonstrada em porcentagem (%), enquanto a temperatura poderá ser ajustada de forma livre. No caso desse post, por exemplo, avaliamos o tipo de clima da região Sudeste do Brasil, e  determinamos um de mínimo de -10° e máximo de 40°C. As demais variáveis serão opcionais, servindo apenas para configurar a estética da ferramenta.

A ferramenta gauge implanta um monitor por level para o layout do navegador.

          A opção Group servirá para separar os componentes em conjuntos, na versão dashboard do navegador, cada grupo será exibido em colunas individuais, auxiliando na organização visual das ferramentas.

A opção Group possibilita uma organização de componentes em grupos.
          Cada fluxo de leitura será composto por um nó Function, e a função "return" será escrita de forma similar, alterando apenas a última palavra de cada um, como mostra o exemplo abaixo.

A configuração dos nós Function de cada leitura será diferenciado pela última palavra inserida em cada um.


          Conecte os nós ao fluxo configurado anteriormente, demonstrado na imagem abaixo. Como a opção "Event", do nó IBM IoT, não foi direcionada a nenhum evento específico, então, essa ferramenta será capaz de coletar quaisquer informações presente no ESP32.

O Gauge será utilizado para construir uma avaliar as informações de  forma crescente.


          Na avaliação do sensor de chuva utilizaremos outro modelo de nó Gauge, colocando a opção Type como Nível, e, assim como a umidade, configurando os pontos mín/máx de leitura da intensidade em 0 e 100 %. Adicione um nó Function, e configure como mostra a imagem a seguir, alterando apenas a última palavra do comando para "chu". Conecte tudo ao IBM IoT.

Utilize a função return para reduzir a mensagem recebida.

          As leituras de Pressão e Altitude serão impressas em gráficos de linhas, portanto, adicione dois nós Chart, das opções Dashboard.


Ferramenta para a construção de gráficos.


          Nas configurações procure manter os pontos mínimo e máximo em branco, para que os pontos de ajuste do gráfico se ajustem automaticamente aos valores coletados. Escolha o tipo de medição como "Line Chart", e o formato em "x-axis Label" como HH:MM:AA.

Adicione as informações desejadas a serem exibidas no gráfico.


          Configure o nó Function de cada sensor alterando as últimas linhas para "pre" e "alt", e construa um fluxo com as respectivas ferramentas Chart.


Utilize a função return para reduzir a mensagem recebida.


          Na leitura da intensidade de raios Ultravioletas, adicione três blocos Function e configure os seguintes endereços:


Utilize a função return para reduzir a mensagem recebida.


          Conecte três nós Text Imput, do menu Dashboard, conectando-os em cada Function de leitura UV. Não haverá necessidade de configurar as opções desses nós, pois, este irá exibir informação com base nos valores fornecidos pela função Return.

Os valores serão exibidos em forma de texto no layout do aplicativo


           Construa um fluxo conectando todas as variáveis de leitura ao IBM IoT Input.


A leitura de todos os componentes poderá ser ligada em um único nó IBM, separando a leitura através dos nós Function.

          Por fim, a programação possui dois tipos de LED, um RGB que indica a intensidade dos raios UV, e um para controlar o acionamento, o D2 presente no próprio ESP32. O controle do LED de teste será estabelecido por um nó Switch, do conjunto Dashboard.
A ferramente Switch será utilizada para construir um botão de acionamento para o LED da placa ESP32.


          Nas opções do Switch, será necessário ajustar o tipo de mensagem como String, com valores 1 (HIGH) e 0 (LOW), e em Topic escreva “led”.

Utilize valores binários como 0 ou 1 para ligar e desligar componentes.


          O controle de componentes requer a construção de um novo fluxo de comunicação, portanto, adicione um nó IBM IoT Output e um Debug.

Utilizado para enviar comandos ao sistema.


          Nas configurações do nó IBM, a opção Type será alterada para Device Command, utilizada no envio de mensagens ao circuito, controlando funções no ESP32, enquanto o comando Type direciona a leitura através da opção "led".

Configure as informações a serem controladas por essa ferramenta.
          Construa um fluxo entre os blocos, e pressione o botão Deploy para intalar as atualizações do Node-RED.

O fluxo construído será convertido em um botão no layout do aplicativo.


          Caso queira ajustar a paleta de cores do navegador, título, e opções de layout, retorne a página de programação do Node-RED, e clique no botão dashbord 
 


As configurações de Dashboard serão referentes aos ajustes do navegador


          Acesse o navegador “/ui” para visualizar o layout e funcionamento das ferramentas.

https://______.mybluemix.net/ui

Monitoramento contínuo, acesso remoto e armazenamento de dados.



Estação em modo Econômico

Nas postagens anteriores apresentamos o comando Deep Sleep, que possibilita desligar praticamente todas as funções principais de um ESP32, mantendo apenas alguns periféricos de memória e o coprocessador em modo ULP (Ultra Low Power). Manter o sistema em Stand-by torna o consumo de energia consideravelmente menor, e, para tornar o projeto mais sustentável e econômico, iremos adicionar tal função a programação, com o objetivo de determinar horários de descanso para o ESP32 e ajustar o despertar do sistema de forma automática e manual.            A programação abaixo irá coletar as informações de leitura dos sensores, armazenando-as no servidor durante o período de 10 segundos, após esse prazo, entrará em repouso por 30 segundos, e o único meio de interromper esse loop temporal será pressionando o sensor capacitivo T2 (pino D2), para acionar o despertar antes do tempo.

// Projeto Curto Circuito – ESP32: Estação Meteorológica em DEEP SLEEP

// ------ Bibliotecas --------
#include <WiFi.h>
#include <Wire.h>
#include <PubSubClient.h> // https://github.com/knolleary/pubsubclient/releases/tag/v2.3
#include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson/releases/tag/v5.0.7
#include <esp_deepsleep.h>
#include "Esp32MQTTClient.h"

// ------ Configurações WiFi --------
const char* ssid     = "Nome_da_rede";
const char* password = "Senha";

//-------- Conexão IBM-ESP32 -----------
#define ORG " Insira o ORG" // seis primeiros caracteres do servidor 
#define DEVICE_TYPE "Insira o nome do Componente" // Nome dado ao componente no servidor Watson
#define DEVICE_ID "Insira o ID do componente" // ID dado ao componente no servidor Watson
#define TOKEN "Token de autenticação" // Insira a Chave API 

//-------- Comunicação IOT --------
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
const char eventTopic[] = "iot-2/evt/status/fmt/json";
const char cmdTopic[] = "iot-2/cmd/led/fmt/json";

//-------- Sensor de Chuva--------
#define pino_d 14 // Pino digital D14 do ESP32
#define pino_a 35 // Pino analógico D35 do ESP32 
int  val_a = 0;                 // Armazenar leitura analógica
int  val_d = 0;                 // Armazenar leitura digital
int result = 0 ;                // Transforme a leitura do sensor em porcentagem.

//-------- Sensor BME280 --------
#include "Adafruit_BME280.h" // Biblioteca Adafruit BME280
Adafruit_BME280 bme;         // I2C

//-------- Memória RTC--------
RTC_DATA_ATTR int tempo;     //Armazena os valores de tempo no RTC.
RTC_DATA_ATTR int tempo2;    //Armazena os valores de tempo2 no RTC.

//-------- Sensor Capacitivo--------
#define Threshold 40 //Define a sensibilidade do sensor capacitivo.
touch_pad_t touchPin;

//-------- Sensor UV --------
int UVOUT = 36;             // Pino Out D36 (VP) do ESP32
int REF   = 34;             // Pino EN D34 do ESP32
//-------- LEDs e Contador--------
int LED = 2;                // Led D2 do ESP32
int RED = 23;               // RGB pino vermelho D32 do ESP32
int BLUE = 5;               // RGB pino azul D05 do ESP32
int GREEN = 4;              // RGB pino green D4 do ESP32

WiFiClient wifiClient;      // COnfigura WiFi Client
void callback(char* topic, byte* payload, unsigned int payloadLength)
{ // Função de retorno, para controlar o ESP32 por meio da plataforma NODE-RED
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");

  if ((char)payload[0] == '0')
  { // Se receber o caractere 0
    digitalWrite(LED, LOW);   // Desliga o LED
    Serial.println("LOW");
  }
  if ((char)payload[0] == '1')
  { // Se receber o caracter 1
    digitalWrite(LED, HIGH);  // Liga LED
    Serial.println("HIGH");
  }
}
PubSubClient client(server, 1883, callback, wifiClient);
void wakeup_touchpad()
{ // Função para configurar o despertar do ESP32 através de um pino Touch
  touch_pad_t pin;
  touchPin = esp_sleep_get_touchpad_wakeup_status();  // Função touchPin
}
void callback2() {}
void setup()
{
  wakeup_touchpad();       // Chama a função de configuração do touch
  Serial.begin(115200);    // Taxa de transmissão
  pinMode(LED, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(BLUE, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(UVOUT, INPUT);
  pinMode(REF_3V3, INPUT);
  client.setCallback(callback);
  bool status;               // Cria uma variável de leitura bool
  status = bme.begin(0x76);  // Configura o enderelo do BME como 0x76
  if (!status)
  { // Verifiva o status de conexão do sensor BME
    Serial.println("BME280 não localizado, confira a pinagem do sensor!");// se estiver desconectado
    while (1);
  }
  delay(100);
  touchAttachInterrupt(T2, callback2, Threshold); // Determina que o pino touch será o T2, terá o valor de sensibilidade declarado em Threshold.
  esp_sleep_enable_touchpad_wakeup();             // Habilita o despertar do ESP32 por sensor touch
  esp_sleep_enable_timer_wakeup(30000000);        // Determina que a cada 30 segundos o ESP32 irá despertar
  tempo2 += 10;                                   // Aumenta em 10 o valor de tempo2
  wifiConnect();                                  // Chama a função de conexão do Wi-Fi
  mqttConnect();                                  // Chama a função de com o servidor
}
void wifiConnect()
{ // Funções para conectar ao Wi-Fi
  Serial.print("Conectando a rede:");
  Serial.print(ssid);           // Indica a rede Wi-Fi ao qual irá se conectado
  WiFi.begin(ssid, password);   // Conecta ao ssid e o password configurado
  while (WiFi.status() != WL_CONNECTED)
  { // Enquanto o Wi-Fi estiver desconectado
    delay(500);                 // Aguarda meio segundo
    Serial.print(".");
  }
  Serial.print("Rede Wi-Fi Conectada, Endereço de IP: ");
  Serial.println(WiFi.localIP()); // Indica o endereço de IP
}
void mqttConnect()
{ // Funções para conectar ao servidor
  if (!!!client.connected())
  { // Se não houver conexão com o servidor
    Serial.print("Reconectando ao servidor:");
    Serial.println(server);      // Indica o endereço do servidor
    while (!!!client.connect(clientId, authMethod, token) )
    {
      Serial.print(".");
      delay(500);
    }
    if (client.subscribe(cmdTopic))
    { // Se conseguir se Conectar ao cmdTopic
      Serial.println("OK");   // Escreve OK no monitor serial
    }
    else
    {
      Serial.println("Erro"); // Escreve erro no monitor serial
    }
  }
}
void loop() {
  if (!client.loop())
  {
    mqttConnect();            // Tenta reconectar ao servidor
  }
  if (tempo == tempo2)
  { // Se a contagem de tempo for igual a variável tempo2
    delay(1);
    esp_deep_sleep_start();   // Inicia o modo de descanso Deep Sleep
  }
  float h = bme.readHumidity();        // Armazena os valor de leitura da Umidade
  float t = bme.readTemperature();     // Armazena os valor de leitura da Temperatura
  float p = bme.readPressure();        // Armazena os valores de leitura da Pressão
  float a = bme.readAltitude(1013.25); // Armazena os valores de leitura da Altitude
  val_a = analogRead(pino_a) ;         // Armazena os valores analógicos do sensor de chuva
  p = p / 100.0F;                      // Realiza um calculo que ajusta o valor de p
  // Cria uma variável que coleta a leitura do sensor de chuva
  int result = 0;                      // Cria uma variável do tipo inteira
  result = (val_a * 100) / 4095;       // Transforma o valor em porcentagem
  // ----- As String abaixo serão responsáveis por enviar mensagens ao servidor ------
  String payload = "{\"d\":{\"adc\":";                 // Inicia Payload
  payload += contagem;                                 // Inclui o valor de contagem
  payload += "}}";                                     // Finaliza a função
  Serial.print("Contagem: "); Serial.println(payload); // Escreve o valor no monitor serial
  client.publish(eventTopic, (char*) payload.c_str() );// Publica Payload
  delay(100);                                          // Aguarda 100 milissegundos

  String payload2 = "{\"d\":{\"umi\":";                // Inicia Payload2
  payload2 += h;                                       // Inclui o valor de h
  payload2 += "}}";                                    // Finaliza a função
  Serial.print(" Umidade: "); Serial.println(payload2); // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload2.c_str() );// Publica Payload2
  delay(100);                                           // Aguarda 100 milissegundos

  String payload3 = "{\"d\":{\"tem\":";                    // Inicia Payload3
  payload3 += t;                                           // Inclui o valor de t
  payload3 += "}}";                                        // Finaliza a função
  Serial.print(" Temperatura: "); Serial.println(payload3);// Escreve no monitor serial
  client.publish(eventTopic, (char*) payload3.c_str() );   // Publica Payload3
  delay(100);                                              // Aguarda 100 milissegundos

  String payload4 = "{\"d\":{\"pre\":";                    // Inicia Payload4
  payload4 += p;                                           // Inclui o valor de p
  payload4 += "}}";                                        // Finaliza a função
  Serial.print(" Pressão: "); Serial.println(payload4);    // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload4.c_str() );   // Publica Payload4
  delay(100);                                              // Aguarda 100 milissegundos

  String payload5 = "{\"d\":{\"alt\":";                    // Inicia Payload5
  payload5 += a;                                           // Inclui o valor de a
  payload5 += "}}";                                        // Finaliza a função
  Serial.print(" Altitude: "); Serial.println(payload5);// Escreve no monitor serial
  client.publish(eventTopic, (char*) payload5.c_str() );   // Publica Payload5
  delay(100);                                              // Aguarda 100 milissegundos

  String payload6 = "{\"d\":{\"chu\":";                    // Inicia Payload6
  payload6 += result;                                      // Inclui o valor de result
  payload6 += "}}";                                        // Finaliza a função
  Serial.print(" Chuva: "); Serial.println(payload6);      // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload6.c_str() );   // Publica Payload5
  delay(100);                                              // Aguarda 100 milissegundos

  tempo++;
  delay(1000);
  uv_test();
}
void uv_test()
{
  int uvLevel = analogRead(UVOUT);           // Armazena a leitura analógica do pino OUT
  int refLevel = analogRead(REF);            // Armazena a leitura analógica do pino EN
  //Use o valor de 3.3V como referencia para o calculo de tensão
  float outputVoltage = 3.3 / refLevel * uvLevel; // Indica a tensão de saída do sensor
  float uvIntensity = map(outputVoltage, 0.99, 2.9, 0.0, 15.0); // Intensidade raios UV
  String payload7 = "{\"d\":{\"uvl\":";               // Inicia Payload7
  payload7 += uvLevel;                                // Inclui o valor de uvLevel
  payload7 += "}}";                                   // Finaliza a função
  Serial.print(" Level: "); Serial.println(payload7); // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload7.c_str() ); // Publica Payload7
  delay(100);

  String payload8 = "{\"d\":{\"volt\":";                 // Inicia Payload8
  payload8 += outputVoltage;                             // Inclui o valor de outputVoltage
  payload8 += "}}";                                      // Finaliza a função
  Serial.print(" Tensao: "); Serial.println(payload8);   // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload8.c_str() ); // Publica Payload8
  delay(100);

  String payload9 = "{\"d\":{\"uvi\":";                  // Inicia Payload9
  payload9 += uvIntensity;                               // Inclui o valor de uvIntensity
  payload9 += "}}";                                      // Finaliza a função
  Serial.print(" Intensidade UV: "); Serial.println(payload9); // Escreve no monitor serial
  client.publish(eventTopic, (char*) payload9.c_str() ); // Publica Payload8
  Serial.println();                                      // Pula uma linha
  delay(1000);                                           // Aguarda 1 segundo
  if (uvIntensity >= 0 && uvIntensity <= 2)
  { // Intensidade Baixa: Verde
    digitalWrite(RED, 0);
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 1);                              // Liga LED VERDE
  }
  if (uvIntensity >= 3 && uvIntensity < 5)
  { // Intensidade Moderada: Amarelo
    digitalWrite(RED, 0);
    digitalWrite(BLUE, 1);                               // Liga LED AZUL
    digitalWrite(GREEN, 1);                              // Liga LED VERDE
  }
  if (uvIntensity == 6 || uvIntensity == 7)
  { // Intensidade Alta: Laranja
    digitalWrite(RED, 1);                                // Liga LED VERMELHO
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 1);                              // Liga LED VERDE
  }
  if (uvIntensity >= 8 && uvIntensity < 10)
  { // Intensidade Elevada: Vermelho
    digitalWrite(RED, 1);                     // Liga LED VERMELHO
    digitalWrite(BLUE, 0);
    digitalWrite(GREEN, 0);
  }
  if (uvIntensity >= 11)
  { // Intensidade Elevada: Violeta
    digitalWrite(RED, 1);                     // Liga LED VERMELHO
    digitalWrite(BLUE, 1);                    // Liga LED AZUL
    digitalWrite(GREEN, 0);
  }
}

          Ao despertar o sistema do modo Deep Sleep, boa parte das funções como comunicação Wi-F, CPU, e todas as leituras presente no ESP32 serão reiniciadas, e a única forma de manter os dados a salvo será através da construção de uma variável de armazenamento que aloque tais dados em uma memória RTC, como o demonstrado nos comandos RTC_DATA_ATTR int tempo e RTC_DATA_ATTR int tempo2. No caso da programação acima, apenas as variáveis de contagem serão mantidas em RTC, pois, além de as demais leituras já estarem salvas no próprio servidor, o tempo será um ponto importante para o funcionamento do ciclo de descanso do ESP32. O void wakeup_touchpad será utilizado na configuração de um sensor capacitivo, como meio de remover o ESP32 do modo de hibernação. As funções touch_pad_t e esp_sleep_get_touchpad_wakeup_status, irão construir variáveis de leitura aplicada aos pinos capacitivos, determinando que o toque irá influenciar no status da hibernação. O touchAttachInterrupt() configura o pino T2 como um interruptor no processo de despertar do ESP32, utilizando o valor da variável Threshold no ajuste da sensibilidade do sensor. A função esp_sleep_enable_timer_wakeup() determina um intervalo de tempo para despertar o sistema, esse valor será interpretado em microssegundos (1 segundo  = 1.000000 microssegundos). E por fim, esp_deep_sleep_start(), inicia o modo de hibernação do ESP32.

Considerações Finais

          Ao desbloquear a tela de um smartphone, ou acessar uma rede social qualquer, automaticamente serão exibidas informações referentes as condições climáticas do dia, alertas meteorológicos, e análises barométricas. Esse tipo de informações se apresenta de forma tão sutil em nossa rotina diária, que poucos realmente já se perguntaram o que seria necessário para coletar tais informações. O ESP32 mostrou ser uma das melhores opções para a aplicação dessa problemática em um circuito elétrico, afinal com uma rápida comunicação entre o módulo Wi-Fi e um servidor web particular, construímos uma ferramenta meteorológica completa, capaz de fornecer gráficos e bases para estudos de forma acessível, e, graças ao Node-RED e a IBM Watson, conectar componentes em sistemas IoT, além do desenvolvimento de plataformas supervisórias  tornou-se mais simples. E se em algum momento o consumo de energia se apresentou como um problema, o modo de hibernação Deep Sleep estará a disposição, para manter o sistema com um consumo de aproximadamente 150 µA.