Hardware Prototyping

Monitoramento Ambiental com DHT22, ESP32 e InfluxDB

O objetivo aqui é construir um sistema que coleta dados de temperatura e umidade usando o sensor DHT22 e os envia para um servidor InfluxDB para armazenamento e análise juntamente com um servidor Grafana. O ESP32 atua conectando o sensor ao Wi-Fi e gerenciando a comunicação com o InfluxDB.

Hardware Necessário

  • ESP32: Microcontrolador com Wi-Fi e Bluetooth integrados, ideal para projetos IoT de baixo custo e baixo consumo de energia.
  • DHT22: Sensor de temperatura e umidade conhecido por sua precisão adequada, baixo custo e facilidade de uso.
  • Conexão Wi-Fi: Para conectar o ESP32 à internet e enviar dados para o InfluxDB.

Pinagem

Sensor DHT22:

  • VCC: Conectado ao pino 3.3V do ESP32 para alimentação.
  • GND: Conectado ao pino GND do ESP32 para aterramento.
  • DHTPIN: Pino de dados conectado a um pino GPIO do ESP32

Observação: O pino específico do ESP32 usado para DHTPIN será definido no código como 18.

Configuração do Projeto no VSCode com PlatformIO

O arquivo platformio.ini define as bibliotecas necessárias e a configuração do ambiente:

[env:upesy_wroom]
platform = espressif32
board = upesy_wroom
framework = arduino
lib_deps = 
	adafruit/DHT sensor library@^1.4.6
	arduino-libraries/NTPClient@3.1.0
	tobiasschuerg/ESP8266 Influxdb@^3.13.1
INI

Análise do Código Fonte

Neste projeto eu inclui uma biblioteca NTP por puro luxo de querer imprimir na porta Serial a data e hora da leitura, Não há utilizamos para escrever os datapoints no influxdb.

Declaração do DHT22
#include <Adafruit_Sensor.h>
#include <DHT.h>

#define DHTPIN 18
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
C++
Conexão com WIFI
#include <WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "MINHA_WIFI";
const char* password = "MINHA_SENHA";

void setup() {
// CÓDIGO
 
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(2500);
    Serial.println("Conectando à rede WiFi...");
  }
  Serial.println("Conectado à rede WiFi");
// CÓDIGO
}

//CÓDIGO
C++
Declaração do InfluxDB e Inicialização

Aqui iremos iniciar a conexão com o InfluxDB e criar uma váriavel de sensor que aponta para o Banco de dados clima do InfluxDB

#include <InfluxDbClient.h>

#define INFLUXDB_URL "http://influx.mfs.eng.br:8086"
// InfluxDB database name
#define INFLUXDB_DB_NAME "clima"
// InfluxDB user name
#define INFLUXDB_USER "esp32"
// InfluxDB password
#define INFLUXDB_PASSWORD "esp32_password"

InfluxDBClient client(INFLUXDB_URL, INFLUXDB_DB_NAME);

Point sensor("clima");

void setup() {
//CODIGO

  // Configuração do cliente InfluxDB
  client.setConnectionParamsV1(INFLUXDB_URL, INFLUXDB_DB_NAME, INFLUXDB_USER, INFLUXDB_PASSWORD);
}

//CODIGO
C++
Coletando Dados do DHT22
void setup() {
//CODIGO
  dht.begin();
//CODIGO
}

void loop() {
//CODIGO

  float tempValue = dht.readTemperature();
  float humidityValue = dht.readHumidity();
  
  //CODIGO
  
  if (!isnan(tempValue) && !isnan(humidityValue)) {

//CODIGO

    Serial.print(" - Temperatura: ");
    Serial.print(tempValue);
    Serial.print(" °C, Umidade: ");
    Serial.print(humidityValue);
    Serial.println(" %");
  }
  
  delay(60000); // Aguarda 60 segundos antes da próxima leitura
}
C++
Envio de Dados para InfluxDB
//CODIGO

InfluxDBClient client(INFLUXDB_URL, INFLUXDB_DB_NAME);

Point sensor("clima");

//CODIGO

void loop() {

  float tempValue = dht.readTemperature();
  float humidityValue = dht.readHumidity();
  
  if (!isnan(tempValue) && !isnan(humidityValue)) {
    // Limpa os campos do ponto de dados
    sensor.clearFields();

    // Adiciona os campos ao ponto de dados
    sensor.addField("temperature", tempValue);
    sensor.addField("humidity", humidityValue);

    
    // Escreve o ponto de dados no InfluxDB
    if (!client.writePoint(sensor)) {
      Serial.print("InfluxDB write failed: ");
      Serial.println(client.getLastErrorMessage());
    }
  }
  
  delay(60000); // Aguarda 60 segundos antes da próxima leitura
}
C++

Vantagens do InfluxDB

Num outro post no futuro, tentarei explicar as vantagens do InfluxDB. Por hora:

Banco de dados de séries temporais: Perfeito para armazenar e analisar dados que mudam ao longo do tempo.

Escalabilidade: Capacidade de lidar com grandes volumes de dados.

Integração com Grafana: Permite visualizar os dados de forma clara e intuitiva.

Visualização no Grafana

Abaixo o Gráfico criado com Grafana e InfluxDB baseado nos dados enviados pelo DHT22 e o ESP32

https://grafana.mfs.eng.br/dashboard/snapshot/QXbgVFpsYpZJnLCsvEIDQYYMvk0AUt5Z

Código Completo

Este projeto demonstra como o ESP32 e o InfluxDB podem ser usados para criar um sistema de monitoramento climático eficaz. Neste artigo não abordamos como configurar o InfluxDB e o Grafana, isso fica para uma próxima.

https://gitlab.com/mfs.eng.br/hardware-quirks/temperatura_esp32

main.cpp

#include <Arduino.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <InfluxDbClient.h>
#include "config.h"

const char* ssid = WIFI_SSID;
const char* password = WIFI_PASSWORD;

#define DHTPIN 18
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "time-a-g.nist.gov");

InfluxDBClient client(INFLUXDB_URL, INFLUXDB_DB_NAME);

Point sensor("clima");

void setup() {
  Serial.begin(9600);
  
  dht.begin();
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(2500);
    Serial.println("Conectando à rede WiFi...");
  }
  Serial.println("Conectado à rede WiFi");
  
  timeClient.begin();
  timeClient.setTimeOffset(-3*60*60); // Ajuste para o fuso horário de -3 horas (Brasil)

  // Configuração do cliente InfluxDB
  client.setConnectionParamsV1(INFLUXDB_URL, INFLUXDB_DB_NAME, INFLUXDB_USER, INFLUXDB_PASSWORD);
}

void loop() {
  timeClient.update();

  float tempValue = dht.readTemperature();
  float humidityValue = dht.readHumidity();

  unsigned long timestamp = timeClient.getEpochTime();
  time_t timeObj = timestamp;
  struct tm* timeinfo = localtime(&timeObj);

  char dataFormatada[20];
  strftime(dataFormatada, sizeof(dataFormatada), "%d/%m/%Y", timeinfo);
  
  if (!isnan(tempValue) && !isnan(humidityValue)) {
    // Limpa os campos do ponto de dados
    sensor.clearFields();

    // Adiciona os campos ao ponto de dados
    sensor.addField("temperature", tempValue);
    sensor.addField("humidity", humidityValue);

    // Adiciona a timestamp ao ponto de dados
    //sensor.setTime(timestamp);

    // Escreve o ponto de dados no InfluxDB
    if (!client.writePoint(sensor)) {
      Serial.print("InfluxDB write failed: ");
      Serial.println(client.getLastErrorMessage());
    }

    // Escreve os dados no serial com o log de data
    Serial.print(dataFormatada);
    Serial.print(" ");
    Serial.print(timeClient.getFormattedTime());
    Serial.print(" - Temperatura: ");
    Serial.print(tempValue);
    Serial.print(" °C, Umidade: ");
    Serial.print(humidityValue);
    Serial.println(" %");
  }
  
  delay(60000); // Aguarda 60 segundos antes da próxima leitura
}
C++

config.h

#define WIFI_SSID "seu_SSID_wifi"
#define WIFI_PASSWORD "sua_senha_wifi"
#define INFLUXDB_URL "http://seu_servidor_influxdb:8086"
#define INFLUXDB_DB_NAME "nome_do_banco_de_dados"
#define INFLUXDB_USER "usuario_influxdb"
#define INFLUXDB_PASSWORD "senha_influxdb"
C++