Estação meteorológica com Arduino

Estação meteorológica

Este artigo apresenta o projeto de uma mini estação meteorológica utilizando um Arduino UNO, capaz de realizar medição de luminosidade, temperatura, umidade, índice UV, pressão atmosférica e material particulado, além de se comunicar com a internet através de um módulo wi-fi ESP8266 ESP-01 utilizando a plataforma ThingSpeak.

 

Neste artigo são abordados:

  • Montagem do hardware: conexão dos sensores e módulo de comunicação ESP8266 com o Arduino UNO;
  • Desenvolvimento do firmware para leitura dos sensores e postagem dos dados no Thingspeak;
  • Publicação e consulta dos dados através do Thingspeak.

 

Esse projeto foi desenvolvido por Igor Fonseca Albuquerque, e apresentado no Genuino Day – Santos, SP, em 02 de abril de 2016.

 

Apresentação do projeto de estação metereológica com arduino no primeiro Genuino Day de Santos, SP.
Figura 1 - Apresentação do projeto no primeiro Genuino Day de Santos, SP.

 

 

Motivação

 

A Baixada Santista é uma das principais atrações turísticas do estado de São Paulo, atraindo milhares de visitantes às suas praias todos os anos. São comuns as notícias de engarrafamentos quilométricos rumo à região em feriados prolongados e nos finais de semana ensolarados do verão. Conhecidas pelo elevado número de dias nublados, em virtude da proximidade à Serra do Mar, as cidades litorâneas veem sua população se multiplicar em qualquer sinal de dias de sol e calor.

 

A região abriga ainda um dos maiores portos do país, o qual realiza o escoamento de boa parte da produção de grãos das regiões sudeste e centro-oeste do Brasil, além do transporte e armazenamento de produtos químicos, combustíveis e conteiners. O transporte da soja, em particular, é uma das atividades que mais trazem transtornos à população dos bairros próximos aos terminais portuários, devido às emissões de materiais particulados e aos odores exalados pela fermentação dos grãos.

 

Nos últimos anos, notícias envolvendo incêndios de grandes proporções na área portuária têm sido frequentes na mídia, divulgando negativamente a imagem da região, com potencial de dano para a saúde da população e de impactos ao meio ambiente.

 

Todas essas características relacionadas ao clima e qualidade do ar da região serviram de motivação para o desenvolvimento da plataforma aberta de monitoramento do clima apresentada nesse trabalho.

 

Santos na mídia.
Figura 2 - Santos na mídia.

 

 

Montagem do hardware

 

Nesse projeto foi proposto um sistema capaz de coletar dados ambientais de diversos sensores, processar as variáveis medidas e disponibilizá-las publicamente na internet para acesso remoto.

 

Projeto conceitual da mini estação meteorológica.
Figura 3 - Projeto conceitual da mini estação meteorológica.

 

Foram selecionados sensores capazes de realizar a medição de pressão atmosférica, temperatura, umidade relativa do ar, luminosidade, índice UV e material particulado.

 

Os seguintes componentes foram especificados para o projeto: 

  • Arduino UNO: placa de microcontrolador baseado no ATmega328P, com 14 pinos de entrada/saída digital, 6 entradas analógicas, conexão USB (Figura 4);
  • Sensor de luminosidade: módulo baseado em um LDR (light dependent resistor). Apresenta uma saída analógica proporcional à intensidade luminosa do ambiente, sendo que a sua resistência cai quando a intensidade luminosa aumenta (Figura 5);
  • Sensor de intensidade UV: mede a intensidade do sinal luminoso na faixa de 200 a 400 nm, gerando um sinal analógico que pode ser usado para o cálculo de índice UV (Figura 6);
  • Sensor de pressão atmosférica (BMP085): sensor de pressão atmosférica baseado no chip BMP085, para pressão entre 300 e 1100 hPa. Comunicação com microcontrolador através protocolo I2C (Figura 7);
  • Sensor de temperatura e umidade (DHT-22): permite a leitura de temperaturas entre -40 a +80 °C e umidade entre 0 a 100%. Comunicação com o Arduino através de sinal digital (Figura 8);
  • Sensor de material particulado: indica a concentração de material particulado de 1.0 a 2.5 μm (Figura 9);
  • Módulo wi-fi (ESP8266 ESP-01): módulo wi-fi capaz de realizar a interface do microcontrolador, através de comunicação serial, com uma rede 802.11b/g/n (Figura 10).

 

Podem ser utilizados diferentes modelos de sensores, de diferentes fabricantes, desde que respeitados os tipos de sinais trocados entre o controlador (Arduino) e os sensores.

 

Para facilitar a montagem do protótipo, foi utilizado um protoshield (Figura 11), simplificando assim a interligação dos componentes.

 

Arduino Uno.
Figura 4 - Arduino Uno.
Sensor de luminosidade.
Figura 5 - Sensor de luminosidade.
Sensor de Índice UV.
Figura 6 - Sensor de Índice UV.
Sensor de pressão barométrica.
Figura 7 - Sensor de pressão barométrica.
Sensor de material particulado.
Figura 8 - Sensor de material particulado.
 Sensor de umidade e temperatura.
Figura 9 - Sensor de umidade e temperatura.
Módulo wi-fi ESP8266.
Figura 10 - Módulo wi-fi ESP8266.
Protoshield.
Figura 11 - Protoshield.

 

As figuras abaixo ilustram a interligação entre os componentes e uma foto do circuito com todos os sensores conectados.

 

Estação-metereológica-arduino-123
Figura 12 - Interligação dos componentes em protoboard.

 

Montagem dos componentes da estação metereológica com arduino
Figura 13 - Montagem dos componentes.

 

 

Desenvolvimento do firmware

 

O código utilizado foi desenvolvido utilizando-se o Arduino IDE 1.0.5. A figura abaixo apresenta um diagrama de blocos do programa que foi desenvolvido.

 

Após a inicialização dos sensores e da conexão com o módulo wi-fi, na etapa de setup, o Arduino entra em um loop infinito no qual realizada a leitura dos sensores, tratamento e transmissão dos dados.

 

Estação meteorológica
Figura 14 - Diagrama de blocos do firmware

 

 

Leitura dos sensores e tratamento dos dados

 

O projeto utiliza sensores analógicos (de luminosidade e UV) e digitais (de umidade, temperatura, pressão e material particulado).

 

O valor medido nos sensores analógicos deve ser processado para convertê-los para a unidade desejada. O trecho de código abaixo apresenta como é feita a leitura e conversão dos valores lidos de luminosidade e índice UV.

 

//leitura do sensor de luminosidade
float luminance = analogRead(luminancePin);

//leitura do sensor UV
float uv = analogRead(uvPin);
uv = uv * 0.0049; //converter para V
uv = uv * 307; //converter para mW/m²
uv = uv/200; //índice UV

 

A transmissão dos dados entre o sensor de temperatura e umidade DHT22 e o Arduino é realizada através de um protocolo de comunicação digital próprio, utilizando-se a biblioteca existente para Arduino.

 

//leitura do sensor de temperatura e umidade
int chk = DHT.read22(DHT22_PIN);
float humidity = DHT.humidity;
float temperature = DHT.temperature;

 

A leitura do sensor de pressão é realizada através de protocolo I2C, no qual o Arduino solicita os dados ao sensor e aguarda a chegada de um evento (que pode contar os dados de pressão ou temperatura do sensor).

 

//leitura do sensor de pressão
sensors_event_t event;
bmp.getEvent(&event);
float pressure = 0;
if (event.pressure)
{
    pressure = event.pressure;
}

 

Para realizar a leitura da concentração de material particulado é utilizada uma das entradas digitais do Arduino. O sensor é composto por um laser e um fotodetector. Na ausência de material particulado, o laser incide diretamente sobre o detector, levando a saída do sensor para nível lógico alto. A passagem de material particulado faz com que o feixe seja obstruído, levando a saída para zero (Figura 15).

 

A estimativa da concentração de material particulado é feita verificando-se a porcentagem do tempo no qual a entrada digital do Arduino fica em nível lógico baixo, conforme representado abaixo.

 

Estação meteorológica
Figura 15 - Saída digital do sensor de material particulado
Estação meteorológica
Figura 16 - Curva do sensor de material particulado (concentração x tempo de ocupação).

 

 

O trecho de código abaixo ilustra a rotina de estimativa da concentração de material particulado. No exemplo abaixo o controlador calcula o tempo em que a entrada digital ficou em nível lógico baixo durante um período de amostragem de 30 segundos, e calcula a porcentagem de tempo para a qual permaneceu nesse estado.

 

//medição do material particulado
duration = pulseIn(dustPin, LOW);
lowpulseoccupancy = lowpulseoccupancy + duration;
  
//ciclo de amostragem de 30 segundos
if ((millis() - starttime) >= sampletime_ms) //se o sample time == 30s
{
    ratio = lowpulseoccupancy/(sampletime_ms*10.0);  // porcentagem (de 0 a 100%)
    concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // dados do datasheet
    lowpulseoccupancy = 0;
}

 

 

Conexão com wi-fi

 

A conexão com um roteador específico é realizada durante o setup() do Arduino. Para isso, deve ser informado o SSID e a senha para conexão da rede.

 

#define SSID "xxxxx"
#define PASS "xxxxx"

 

Durante a conexão, o módulo wi-fi é colocado no modo station e solicitado para se conectar com o roteador informado. O módulo deverá permanecer conectado indefinidamente.

 

boolean connectWiFi(){
  Serial.println("Conectando wi-fi...");
  String cmd ="AT+CWMODE=1";
  monitor.println(cmd);
  delay(2000);
  monitor.flush(); //clear buffer
  cmd="AT+CWJAP=\"";
  cmd+=SSID;
  cmd+="\",\"";
  cmd+=PASS;
  cmd+="\"";
  monitor.println(cmd);
  delay(5000);
  
  if(monitor.find("OK")){
    Serial.println("Conectado com sucesso!");
    return true;
  }else{
    Serial.println("Falha na conexao!");
    return false;
  }
  Serial.println();
}

 

 

Envio dos dados para o Thingspeak

 

O Thingspeak é uma plataforma de armazenamento de dados na nuvem, ideal para desenvolvimento de dispositivos IoT. Os dados são acessíveis através do site ThingSpeak, por qualquer dispositivo com acesso à internet, podendo ser categorizados como dados públicos ou privados.

 

Os dados enviados pelos dispositivos são organizados em canais, cada um capaz de armazenar os dados históricos de até 8 variáveis medidas, que podem ser consultados ou exportados em formato CSV. É possível ajustar os gráficos de visualização de cada variável, configurando-se título dos gráficos, escala de tempo e tratamento dos dados (cálculo dos valores médios, medianos ou somados).

 

Após a conexão do módulo ESP8266 ao roteador, deve-se abrir uma conexão http com o ThingSpeak (através do IP 184.106.153.149), informar a quantidade de bytes da mensagem que será transmitida e na sequência enviar os dados através de uma instrução GET. Na mensagem enviada deve ser apresentada a chave (API key) do canal (channel) que armazenará os dados, juntamente com os valores medidos para cada campo (field1, field2, …, field8). O trecho de código abaixo ilustra como é feito o envio dos dados lidos para um canal do ThingSpeak. 

 

#define IP "184.106.153.149" // thingspeak.com
String GET = "GET /update?key=xxxxx&field1=";


void updateSensors(String luminanceStr, String humidityStr, String temperatureStr, String uvStr, String dustStr, String pressureStr, String temperature1Str) {

  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  monitor.println(cmd);
  delay(2000);
 
  cmd = GET;
  cmd += luminanceStr;
  cmd += "&field2=";
  cmd += humidityStr;
  cmd += "&field3=";
  cmd += temperatureStr;
  cmd += "&field4=";
  cmd += uvStr;
  cmd += "&field5=";
  cmd += dustStr;
  cmd += "&field6=";
  cmd += pressureStr;
  cmd += "&field7=";
  cmd += temperature1Str;
  cmd += "\r\n";
  delay(1000);
  int strsize = cmd.length();
  monitor.println("AT+CIPSEND=" + String(strsize));
  delay(2000);
  
  monitor.print(cmd);
  if(monitor.find("OK")){
    Serial.println("Dados transmitidos com sucesso");
  }else{
    Serial.println("Falha na transmissao");
  }
}

 

A figura abaixo ilustra os gráficos que podem ser obtidos da estação através do ThingSpeak, o qual teve seus dados definidos como públicos.

 

Estação meteorológica
Figura 17 - Gráficos de temperatura, umidade, pressão e luminosidade no ThingSpeak.

 

 

Código completo

 

#include<stdlib.h>
#include <SoftwareSerial.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#define SSID "xxxxx"
#define PASS "xxxxx"
#define IP "184.106.153.149" // thingspeak.com
#define DHT22_PIN 2
String GET = "GET /update?key=xxxxx&field1=";
SoftwareSerial monitor(10, 11); // Definição de canal serial para módulo ESP8266 (RX, TX)

dht DHT;
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);

//Definição de variáveis
int luminancePin = A0;
int uvPin = A1;
int dustPin = 8;
unsigned long duration;
unsigned long starttime;
unsigned long sampletime_ms = 30000;
unsigned long delay_time = 30000;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;

//setup
void setup()
{
  //iniciar canais seriais
  Serial.begin(9600);
  monitor.begin(9600);
  Serial.println("Inicializando...");

  //configurar pinos
  pinMode(dustPin, INPUT);
  
  //initicializar o sensor de pressão
  Serial.println("Detectando sensor de pressao BMP085...");
  if(!bmp.begin())
  {
    /* Se ocorrer um problema na detecção do BMP085, verificar suas conexões */
    Serial.println("O BMP085 não foi detectado. Verifique suas ligações ou o I2C ADDR!");
    while(1);
   }
   Serial.println("BMP085 detectado!");

    //comunicação com o módulo wifi
    monitor.flush();
    monitor.println("AT");
    delay(2000);
    
    if(monitor.find("OK")){
      Serial.println("Comunicacao com modulo ESP8266: OK");
    }
    else {
      Serial.println("Erro no modulo ESP8266");
    }

  //conectar com roteador  
  connectWiFi(); 
     
  Serial.print("Amostrando (");
  Serial.print(sampletime_ms/1000);
  Serial.println("s)...");
  
  //inicializar timer
  starttime = millis();
}

void loop(){
  //medição do material particulado
  duration = pulseIn(dustPin, LOW);
  lowpulseoccupancy = lowpulseoccupancy + duration;
  
  //ciclo de amostragem de 30 segundos
  if ((millis() - starttime) >= sampletime_ms) //se oe sample time == 30s
  {
    ratio = lowpulseoccupancy/(sampletime_ms*10.0);  // porcentagem (de 0 a 100%)
    concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // dados do datasheet
    lowpulseoccupancy = 0;
    
    //leitura dos sensores
    char buffer[10];
    //luminosidade
    float luminance = analogRead(luminancePin);
    //UV
    float uv = analogRead(uvPin);
    uv = uv * 0.0049; //converter para V
    uv = uv * 307; //converter para mW/m²
    uv = uv/200; //índice UV
    //temperatura e umidade
    int chk = DHT.read22(DHT22_PIN);
    float humidity = DHT.humidity;
    float temperature = DHT.temperature;
    //pressão e temperatura
    sensors_event_t event;
    bmp.getEvent(&event);
    float pressure = 0;
    float temperature1 = 0;
    if (event.pressure)
    {
      pressure = event.pressure;
      bmp.getTemperature(&temperature1);
    }

    //conversão dos dados lidos para strings
    String luminanceStr = dtostrf(luminance, 4, 1, buffer);
    luminanceStr.replace(" ","");
    String uvStr = dtostrf(uv, 4, 1, buffer);
    uvStr.replace(" ","");
    String humidityStr = dtostrf(humidity, 4, 1, buffer);
    humidityStr.replace(" ","");
    String temperatureStr = dtostrf(temperature, 4, 1, buffer);
    temperatureStr.replace(" ","");
    String dustStr = dtostrf(concentration, 4, 1, buffer);
    dustStr.replace(" ","");
    String pressureStr = dtostrf(pressure, 4, 1, buffer);
    pressureStr.replace(" ","");
    String temperature1Str = dtostrf(temperature1, 4, 1, buffer);
    temperature1Str.replace(" ","");
    
    //enviar dados dos sensores para o thingspeak
    updateSensors(luminanceStr, humidityStr, temperatureStr, uvStr, dustStr, pressureStr, temperature1Str);
  
    //esperar até próximo ciclo de amostragem
    Serial.print("Esperar ");
    Serial.print(delay_time/1000);
    Serial.println("s para proxima amostragem");
    Serial.println();
    delay(delay_time);
    
    //iniciar novo ciclo de amostragem
    Serial.println();
    Serial.print("Amostrando (");
    Serial.print(sampletime_ms/1000);
    Serial.println("s)...");
    starttime = millis();
  }
}

//Função para envio dos dados dos sensores para o thingspeak
void updateSensors(String luminanceStr, String humidityStr, String temperatureStr, String uvStr, String dustStr, String pressureStr, String temperature1Str) {

  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  monitor.println(cmd);
  delay(2000);
 
  cmd = GET;
  cmd += luminanceStr;
  cmd += "&field2=";
  cmd += humidityStr;
  cmd += "&field3=";
  cmd += temperatureStr;
  cmd += "&field4=";
  cmd += uvStr;
  cmd += "&field5=";
  cmd += dustStr;
  cmd += "&field6=";
  cmd += pressureStr;
  cmd += "&field7=";
  cmd += temperature1Str;
  cmd += "\r\n";
  delay(1000);
  int strsize = cmd.length();
  monitor.println("AT+CIPSEND=" + String(strsize));
  delay(2000);
  
  monitor.print(cmd);
  if(monitor.find("OK")){
    Serial.println("Dados transmitidos com sucesso");
  }else{
    Serial.println("Falha na transmissao");
  }
}

void sendDebug(String cmd){
  Serial.print("SEND: ");
  Serial.println(cmd);
  monitor.println(cmd);
} 
 
boolean connectWiFi(){
  Serial.println("Conectando wi-fi...");
  String cmd ="AT+CWMODE=1";
  monitor.println(cmd);
  delay(2000);
  monitor.flush(); //clear buffer
  cmd="AT+CWJAP=\"";
  cmd+=SSID;
  cmd+="\",\"";
  cmd+=PASS;
  cmd+="\"";
  monitor.println(cmd);
  delay(5000);
  
  if(monitor.find("OK")){
    Serial.println("Conectado com sucesso!");
    return true;
  }else{
    Serial.println("Falha na conexao!");
    return false;
  }
  Serial.println();
}

 

 

Referências

 

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Igor Albuquerque
Engenheiro eletrônica pela Universidade Federal de Pernambuco (UFPE), engenheiro mecatrônico pela Universidade de Pernambuco (UPE), mestre em controle e automação pela Universidade Federal do Rio de Janeiro (UFRJ), especialista em instrumentação industrial pelo Instituto Brasileiro de Petróleo (IBP) e inventor nas horas vagas.

94
Deixe um comentário

avatar
 
36 Comment threads
58 Thread replies
4 Followers
 
Most reacted comment
Hottest comment thread
21 Comment authors
EstudanteItalo CoutinhoAfonsoRenatoAlex Bilato Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Estudante
Visitante
Estudante

Olá Igor, outras versões do ESP8266 daria certo?

Taciano Santos
Visitante
Taciano

Boa noite Igor na linha 11 codigo eu coloco o que por favor amigo me esclarece ai porfavor. Sobre a linha 9 #define IP qual eu uso corretamente

Taciano Santos
Visitante
Taciano

Boa noite sobre esse projeto como eu faço para configurar o ESP8266 para enviar ao Thingspeak. Qual o procedimento faz alguma mudança no codigo?

Afonso
Visitante
Afonso

Igor projeto maravilhoso

só senti falta de não poder visualizar os dados também em display o que vc acha de implementar

Igor Albuquerque
Visitante
Igor

É uma boa ideia. Estou trabalhando em outros projetos, porém em breve pretendo publicar uma nova versão da estação, com direito a display e outros sensores (anemômetro, por exemplo).

Italo Coutinho
Visitante
Italo Coutinho

Igor, parabens pelo projeto! vc ja implementou o codigo do anemometro?

Alex Bilato
Visitante
Alex Bilato

Boa noite Igor!

Parabéns pelo projeto!
Estou cursando automação industrial e escolhi fazer uma estação meteorológica para meu trabalho semestral, no momento não é necessário eu montar a estação, só preciso apenas conceituar o projeto (funcionamento, onde liga o que, como é feita a coleta de dados, configuração), resumindo um passo a passo descrito do projeto.
É possível vc passar essas informações.
Desde já agradeço.

Igor Albuquerque
Visitante
Igor

Obrigado! 🙂
Acredito que as informações que você precisa se encontram no tutorial.
Fico a disposição caso surjam dúvidas, ok?

Rener
Visitante
Rener

Bom dia.
Qual o valor dos resistores mostrados na sua montagem ?
Obrigado

Taciano Santos
Visitante
Taciano

Igor bom dia! Eu ja comprei tudo mais eu nao estou conseguindo fazer o upload do codigo está dando erro no DHT. Ja fiz o procedimento mais mesmo assim da erro. Quando eu faço o download eu tenho que renomeiar so essa biblioteca?

Taciano Santos
Visitante
Taciano

Quando eu fizer o download eu tenho que renomeiar, Qual o nome que eu coloco? Mais primeiro eu tenho que descompatar.

Taciano Santos
Visitante
Taciano

Amigo me ajuda a montar esse projeto . Eu nao estou conseguindo baixar as bibliotecas . Sobre o codigo eu tenho que copiar o que está no anuncio. Por favor me ajuda ai

Taciano Santos
Visitante
Taciano

Bom dia! Está dando um erro ao eu verificar o codigo na linha 14 dht DHT;
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(1008. Será porque eu nao tinha alterado as linhas 7, 8 e 11?
Na linha 11 eu coloco o meu ID.