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

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
97 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Jose Antonio do
Jose Antonio do
22/07/2023 16:21

Boa tarde Igor. É impressão minha ou no esquema das ligações dos fios, não há nenhum conectado a um terra do arduino!! (GND)?

Radija Marques
Radija Marques
16/09/2022 08:43

Gostaria de saber onde você comprou o sensor de material articulado, UV e luminosidade. Poderia me passar os links?

Maicon Douglas Cândido da Silva
Maicon Douglas Cândido da Silva
05/07/2022 11:47

Boa Tarde Igor, tudo bem?
Em um outro momento, tinha criado minha estação metereológica e agora estava procurando alguma atualização para meu projeto, foi quando encontrei seu projeto, e achei muito legal. Então fiquei com uma duvida, é possível alocar os dados obtidos em algum outro local, ou nuvem?
Para o meu projeto pensei em criar um app, para poder monitorar a estação em tempo real

Estudante
Estudante
20/08/2019 23:09

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

Taciano
Taciano
06/08/2018 00:10

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
Taciano
15/07/2018 20:55

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
Afonso
13/05/2018 16:53

Igor projeto maravilhoso

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

Igor
Igor
Reply to  Afonso
18/05/2018 10:07

É 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
Italo Coutinho
Reply to  Igor
02/03/2019 19:09

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

Alex Bilato
Alex Bilato
20/03/2018 01:11

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
Igor
Reply to  Alex Bilato
18/05/2018 10:14

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

Rener
Rener
05/02/2018 10:18

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

Taciano
Taciano
01/02/2018 09:12

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?

Home » Arduino » Estação meteorológica com Arduino

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: