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 ESP3 */

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.