Estacao Meteorologica: mudanças entre as edições

De Wiki Cursos IFPR Foz
Ir para navegaçãoIr para pesquisar
Linha 32: Linha 32:
===Produções===
===Produções===


RIBEIRO, T. H. ; OLIVEIRA, B. H. ; SILVA, M. S. ; MOSCHKOWICH, F. N. ; MARTINES, M. M. ; SALLET, J. A. K. ; SILVA, J. M. ; BENACCHIO, A. ; BENEDUZZI, H. M. ; CANTÚ, E. . Estação hidrometeorológica automatizada com microcontrolador Arduíno. I Mostra de Inovação, Pesquisa, Ensino, Extensão e Cultura do IFPR, Foz do Iguaçu, 2016.  
RIBEIRO, T. H. ; OLIVEIRA, B. H. ; SILVA, M. S. ; MOSCHKOWICH, F. N. ; MARTINES, M. M. ; SALLET, J. A. K. ; SILVA, J. M. ; BENACCHIO, A. ; BENEDUZZI, H. M. ; CANTÚ, E. . Estação hidrometeorológica automatizada com microcontrolador Arduíno. '''I Mostra de Inovação, Pesquisa, Ensino, Extensão e Cultura do IFPR''', Foz do Iguaçu, 2016.  


RIBEIRO, T. H. ; OLIVEIRA, B. H. ; SILVA, M. S. ; MARTINES, M. M. ; CANTÚ, E. . Estação hidrometeorológica automatizada com microcontrolador Arduíno. V Seminário de Extensão, Ensino, Pesquisa e Inovação do IFPR, Cascavel, 2016 ([[Mídia:EstacaoMeteorologica.pdf|Poster SEPIN2016]]).
RIBEIRO, T. H. ; OLIVEIRA, B. H. ; SILVA, M. S. ; MARTINES, M. M. ; CANTÚ, E. . Estação hidrometeorológica automatizada com microcontrolador Arduíno. '''V Seminário de Extensão, Ensino, Pesquisa e Inovação do IFPR''', Cascavel, 2016 ([[Mídia:EstacaoMeteorologica.pdf|Poster SEPIN2016]]).


RIBEIRO, T. H. ; OLIVEIRA, B. H.; MARTINES, M. M. Estação hidrometeorológica. Projeto Integrador II, Curso Superior de Tecnologia em Análise e Desenvolvimento de Sistemas, IFPR, Foz do Iguaçu, 2016 ([[Mídia:PI_II_TADS-EstacaoMeteorologica.pdf|Documentação PI-II Estação Meteorológica]]).
RIBEIRO, T. H. ; OLIVEIRA, B. H.; MARTINES, M. M. Estação hidrometeorológica. '''Projeto Integrador II, Curso Superior de Tecnologia em Análise e Desenvolvimento de Sistemas, IFPR''', Foz do Iguaçu, 2016 ([[Mídia:PI_II_TADS-EstacaoMeteorologica.pdf|Documentação PI-II Estação Meteorológica]]).


Esposição Espaço Maker. PTI, Foz do Iguaçu, 2016. [[Arquivo:EspacoMaker.jpg|300px]]
Esposição '''Espaço Maker'''. PTI, Foz do Iguaçu, 2016. [[Arquivo:EspacoMaker.jpg|300px]]


==Estudos sobre Meteorologia==
==Estudos sobre Meteorologia==

Edição das 18h49min de 21 de novembro de 2017

Estação Meteorológica Automatizada com Arduíno

Objetivo

O objetivo deste projeto é construir uma estação hidrometeorológica automatizada no Campus Foz do Iguaçu, com o objetivo de dispor um banco de dados dinâmico de informações para uso em pesquisas e estudos sobre manejo da água, integrando as áreas de conhecimento de Informática, Eletrônica, Física, Hidrologia e Aquicultura.

Projeto da Estação Hidrometeorológica
Aprovado no programa PIBIC/CNPq, IFPR, 2016.

Equipe

Professores
2015
Estudos e testes preliminares
Alunos voluntários
  • Jade Mathias da Silva (CST Análise e Desenvolvimento de Sistemas)
  • José Antonio Kazienko Sallet (CST Análise e Desenvolvimento de Sistemas)
2016
Versão operacional incluindo sensores de campo, transmissão de dados via rede sem fio, banco de dados e Servidor Web.
Bolsistas PIBIC/IFPR:
  • Thiago Henrique Ribeiro (CST Análise e Desenvolvimento de Sistemas) (abr a jul)
  • Bruno Henrique Oliveira (CST Análise e Desenvolvimento de Sistemas) (ago a dez)
Alunos voluntários:
  • Matheus Santos (Licenciatura em Física)
  • Frederik Nazario Moschkowich (CST Análise e Desenvolvimento de Sistemas)
  • Matheus Marques Martinês (CST Análise e Desenvolvimento de Sistemas)
2017
Manutenção e aprimoramentos:
Alunos voluntários:
  • Pablo Souza dos Santos (Licenciatura em Física)

Produções

RIBEIRO, T. H. ; OLIVEIRA, B. H. ; SILVA, M. S. ; MOSCHKOWICH, F. N. ; MARTINES, M. M. ; SALLET, J. A. K. ; SILVA, J. M. ; BENACCHIO, A. ; BENEDUZZI, H. M. ; CANTÚ, E. . Estação hidrometeorológica automatizada com microcontrolador Arduíno. I Mostra de Inovação, Pesquisa, Ensino, Extensão e Cultura do IFPR, Foz do Iguaçu, 2016.

RIBEIRO, T. H. ; OLIVEIRA, B. H. ; SILVA, M. S. ; MARTINES, M. M. ; CANTÚ, E. . Estação hidrometeorológica automatizada com microcontrolador Arduíno. V Seminário de Extensão, Ensino, Pesquisa e Inovação do IFPR, Cascavel, 2016 (Poster SEPIN2016).

RIBEIRO, T. H. ; OLIVEIRA, B. H.; MARTINES, M. M. Estação hidrometeorológica. Projeto Integrador II, Curso Superior de Tecnologia em Análise e Desenvolvimento de Sistemas, IFPR, Foz do Iguaçu, 2016 (Documentação PI-II Estação Meteorológica).

Esposição Espaço Maker. PTI, Foz do Iguaçu, 2016.

Estudos sobre Meteorologia

Estudos sobre Hidrometeorologia
Responsável: Matheus Santos (Licenciatura em Física)

Sensores Meteorológicos Sparkfun

Conjunto de Sensores Meteorológicos Sparkfun [1] [2], contendo os seguintes elementos:

  • Sensor de Direção do Vento (Biruta)
  • Sensor de Volume de Chuva (Pluviômetro)
  • Sensor de Velocidade do Vento (Anemômetro)

Biruta

A Biruta ou sensor de direção do vento é fisicamente composto por oito chaves, ligadas a resistores variados. Quando o vento muda de direção um imã fecha um ou dois contatos, permitindo a medição de 16 resistências diferentes.

Na ligação em hardware, um resistor de 10k ohms é utilizado como divisor de tensão, produzindo uma tensão de saída que pode ser medido por um conversor analógico-digital.

No Arduíno a tensão medida nas entradas analógicas (variando de 0V a 5V) é convertida internamente em um número digital de 10 bits (variando de 0 a 1023).

Para o sensor de direção do vento os 16 valores de resistência no divisor de tensão produzem as seguintes entradas no Arduino:

Direção (Graus) Resistencia (Ohms) Tensão (Entrada=5V Resistencia=10ohms) Binário (Saída porta Analógica) Saída Leitura em Binário de 10 bits (0 - 1023)
Mínimo Máximo
0 33k 3,84 786 744 805
22,5 6,57k 1,98 405 346 432
45 8,2k 2,25 460 433 529
67,5 891 0,41 84 75 87
90 1k 0,45 92 88 109
112,5 688 0,32 65 0 74
135 2,2k 0,9 184 156 213
157,5 1,41k 0,62 127 110 115
180 3,9k 1,4 286 265 345
202,5 3,14k 1,19 243 214 264
225 16k 3,08 630 615 665
247,5 14,12k 2,93 599 530 614
270 120k 4,62 945 886 961
292,5 42,12k 4,04 827 806 885
315 64,9k 4,78 978 962 1023
337,5 21,88k 3,43 702 666 743

--José Sallet 18h52min de 18 de novembro de 2015 (BRST)--

Rosa dos ventos
Códigos utilizados para apontar a direção do vento no Brasil.

Pluviômetro

O pluviômetro é um tipo de balde de auto esvaziamento. A cada 0.2794 mm de chuva causa um fechamento de contato momentâneo que pode ser gravado com um contador digital ou acionar uma interrupção de microcontrolador (Arduíno).

O interruptor do pluviômetro é conectado com dois condutores centrais anexados em um cabo RJ11.

--Jade Mathias 16h17min de 17 de novembro de 2015 (BRST)

Pluviômetro no Arduíno
A cada 0.2794 mm de chuva uma interrupção é gerada. A rotina de interrupção, portanto, apenas deverá soma 0.2794 a uma variável que guarda a chuva acumulada em mm.
O contador de chuva acumulada em mm foi construído com uma variável circular, de 0 a 999. Isto é, uma vez chegado a 999 mm a contagem da chuva acumulada volta a zero.
Interrupções no Arduíno
No Arduíno UNO as interrupções externas são acionadas pelo comando AttachInterrupt e são acionadas pelo pino 2 (interrupção 0) e/ou pino 3 (interrupção 1).
No Arduíno as interrupções externas podem ser acionadas de diferentes modos:
  • LOW: Quando o pino está baixo;
  • CHANGE: Quando o valor do pino muda;
  • RISING: Quando o valor do pino sobe de baixo para alto;
  • FALLING: Quando o valor do pino desce de alto para baixo;
  • HIGH: Quando o pino está alto.
A cada fechamento de contados ocasionado pelos sensores uma rotina de tratamento de interrupção será acionada.
Conforme ilustrado no tópico abaixo sobre o hardware para a chave do pluviômetro, será utilizado a borda de subida do pino (RISING) para acionar a interrupção e contar a chuva acumulada.

--Evandro.cantu (discussão) 22h16min de 17 de abril de 2016 (BRT)

Anemômetro

O anemômetro mede a velocidade do vento, fechando um contato com a ajuda de um ímã. Para uma velocidade do vento de 2.4 km/h o interruptor fecha uma vez por segundo.

O interruptor anemômetro está ligado a dois condutores internos do cabo RJ11 compartilhada pelo anemômetro e cata-vento (pinos 2 e 3).

--Jade Mathias 18h28min de 18 de novembro de 2015 (BRST)

Anemômetro no Arduíno
A largura dos pulsos gerados pelo anemômetro serão medidos pelo Arduíno através da função pulseln(). O tempo da largura de pulso retornado pela função pulseln() é medido em microsegundos, portando a velocidade do vento será determinada pela expressão:
velocidadeVento = 2,4 * 106 / larguraPulso 
Conforme o hardware do anemômetro mostrado abaixo, a largura dos pulsos do anemômetro será medida durante o tempo que estiver em nível lógico baixo (LOW), entre dois fechamentos de contato.
Anemômetro
Para um vento com velocidade de 2,4 km/h o fechamento da chave ocorre uma vez por segundo (1 Hz).
A rotina de interrupção apenas implementa um contador de pulsos. No programa principal, para uma dada base de tempo a velocidade é determinada pela expressão:
Vel = ( contadorPulsos / baseTempo ) * 2,4
Exemplo:
  • Base de tempo = 10s
  • Contador de pulsos = 10
Vel = (10 / 10 ) * 2,4 = 2,4 km/h


--Evandro.cantu (discussão) 22h16min de 17 de abril de 2016 (BRT)

Hardware para chaves do pluviômetro e anemômetro

Circuito para conectar as chaves do pluviômetro e anemômetro nas entradas de Interrupção do Arduíno:

Conexão dos Sensores Meteorológicos Sparkfun ao Arduíno

Os Sensores Meteorológicos Sparkfun são conectados ao Arduíno segundo os seguintes diagramas e códigos de cores para os fios provenientes dos sensores:

Sensores de Temperatura e Humidade

Sensor de temperatura (LM35)

Funcionamento do sensor LM35
O LM35 é um circuito integrado exclusivo para medir temperatura com uma tensão de saída variando linearmente com a temperatura em graus Célsius.
Na configuração básica este sensor mede temperaturas entre 2oC e 150oC, variando a saída em função da temperatura de 0 mV + 10mV por 1oC.
Esquema de ligação com Arduíno
            _______
           |       |
           | LM 35 | 
           |_______|
             | | |
   (+5v) ----+ | +---- (Ground)
               |
          Analog Pin 
       0mV + 10mV / oC
Leitura pela entrada analógica do Arduíno
O valor de tensão (entre 0V e 5V) lido pelo Arduíno na entrada analógica é convertido um número digital com 10 bits de magnitude, ou seja, 210 (1024) valores (entre 0 e 1023).
Para obter o valor de tensão, para uso no cálculo da temperatura, multiplica-se o valor digital obtido na leitura por 5/1023.
Como a tensão medida pelo sensor varia de 0 mV + 10mV/1oC, se multiplicarmos por 100, teremos o valor em graus Celsius:
Programa Exemplo
 //Sensor de temperatura LM35
 float valorSensor;
 float temperatura;
 void setup() {
 Serial.begin(9600);
 }
 void loop() {
   valorSensor = analogRead(A0) * 5.0 / 1023.0;
   temperatura = valorSensor * 100.0;
   Serial.print("Temperatura: ");
   Serial.println(temperatura);
   delay(2000); //Tempo entre as leituras em ms
 }

O sensor de temperatura LM35 será utilizado para medir a tempetarura interna do módulo de campo da Estação Meteorolótica.

Sensor de Temperatura e Humidade DHT11

O DHT11 é um sensor de temperatura e humidade. Este sensor inclui um medidor de humidade resistivo e um sensor de temperatura tipo NTC conectado a um microcontrolador de 8 bits [3].

O DHT11 possui uma biblioteca com funções prontas para seu funcionamento [4]. Para uso, baixe a biblioteca DHT11.zip e insira no ambiente da IDE do Arduíno:

Sketch -> Import Library -> Add Library
Esquema de ligação com Arduíno
            _______
           |       |
           | DHT11 | 
           |_______|
             | | |
(Ground) ----+ | +---- (+5v)
               |
          Analog Pin 1
Programa exemplo
 //Sensor de temperatura LDHT11
 #include <dht11.h>
 dht11 sensor; //Inicializa sensor
 void setup() {
   Serial.begin(9600);
   delay(1000);
 }
 void loop() {
   sensor.read(A1);
   Serial.print("Temperatura (oC): ");
   Serial.println(sensor.temperature);
   Serial.print("Unidade (%): ");
   Serial.println(sensor.humidity);
   delay(2000); //Tempo entre as leituras em ms
 }

O sensor de temperatura e humidade DHT11 será utilizado para medir a tempetarura externa e a humidade relativa do ar no módulo de campo da Estação Meteorolótica.

Sensor de Pressão Barométrica BMP180

O Sensor de Pressão Barométrica BMP180 [5] é um sensor de pressão barométrica, o qual mede a pressão absoluta do ar ao seu redor. A pressão do ar varia com as condições do tempo e também com a altitude. Portanto, dependendo de como os dados medidos forem interpretados, pode-se tanto aferir mudanças nas condições do tempo como na altitude.

Interface I2C
O BMP180 utiliza uma interface I2C para se comunicar com o microcontrolador do Arduíno. A interface I2C é padronizada para conectar dispositivos periféricos de baixa velocidade a uma placa mãe ou sistema embarcado e usa duas linhas para comunicação: Dados Seriais (Serial Data - SDA) e Clock Serial (Serial Clock - SCL). O clock é gerado pelo mestre e a linha de dados seriais é bidirecional.
Conexões com o hardware do sensor
O sensor BMP180 possui 4 pinos para conexão com o Arduíno:
  • + (VDD): 3,3 V (Não alimentar com 5 V sob risco de danificar o compomente);
  • - (GND): Terra;
  • DA (SDA) (I2C data): Conectar ao pino A4 UNO
  • CL (SCL) (I2C clock): Conectar ao pino A5 UNO
  • IO: Não usado com Arduíno (serve para microcontroladores que operam em baixa voltagem)
Para Arduíno Leonardo ou Mega, verificar o pino de conexão no tutorial Sparkfun BMP180.

Instalação da biblioteca para o BMP180
O sensor BMP180 possui uma biblioteca e exemplos que facilitam a comunicação com o sensor e o desenvolvimento de programas. Para uso com o Arduíno, baixar a biblioteca SFE_BMP180 e instalar na IDE do Arduíno com os comandos:
Scketch -> Import Library -> Add library
Exemplos
Há dois exemplos incluídos junto com a instalação da biblioteca, que podem ser utilizados para testar o sensor BMP180 e também serem utilizados como referência para a construções de novos programas:
  1. Medição de temperatura e pressão absoluta e relativa: Este exemplo mostra a medição de temperatura e pressão barométrica absoluta e relativa, calculada a partir da altitude fornecida para o lugar da medição.
  2. Medição de altitude: Mostra como medir a altitude de um lugar, a partir da calibração do sensor para uma altitude conhecida e utilizando o barômetro para medir as variações de altitude.

Medição de tempo e altitude

O BMP180 é um sensor de pressão barométrica e pode ser usado tanto aferir mudanças nas condições do tempo como na altitude [1].

Pressão atmosférica

A pressão é medida pela força por unidade de área. No Sistema Internacional é medida por newton por metro quadrado, ou pascal (Pa).

A pressão atmosférica é dada pela força exercida pelo ar que forma a atmosfera sobre a superfície da terra. Uma coluna de ar de um centímetro quadrado, ao nível do mar, pesa aproximadamente um quilograma, ou 101325 pascals. Em uma altitude de 3810 m, a pressão atmosférica é a metade da pressão ao nível do mar.

O BMP180 mede a pressão absoluta em pascal (Pa). Entretanto, um pascal é uma unidade muito pequena, sendo normalmente a pressão dada em hectopascals (1 hPa = 100 Pa). Outras unidades utilizadas para medir a pressão atmosférica são o bar e o atm:

  • 1 mbar = 1 hPa
Pressão atmosférica ao nível do mar
1 atm
  • 1 atm = 101 325 Pa = 1013,25 hPa = 1013,25 mbar = 1,01325 bar

Efeito da temperatura

A temperatura afeta a densidade de um gaz, a densidade de um gaz afeta a massa do gaz, e a massa do gaz afeta a pressão, portanto, a pressão atmosférica é bastante influenciada pela variação da temperatura.

Observações do tempo

A pressão atmosférica em um dado ponto da terra não é constante. Há uma interação complexa entre o movimento de rotação da terra, a inclinação do eixo da terra, e muitos outros fatores relacionados ao movimento das áreas de alta e baixa pressão. Todavia, observando a variação de pressão em um dado ponto é possível fazer previsões de curto prazo sobre o tempo. Por exemplo, quedas de pressão normalmente indicam mau tempo (chuva) ou tormenta se aproximando. Subida de pressão normalmente indica que o tempo bom (seco) está chegando.

Efeito da altitude

A pressão atmosférica também varia com a altitude. A pressão medida em um dado local é a pressão absoluta. Para comparar a pressão em dois lugares com altitude diferente, deve-se descontar os efeitos da altitude, gerando o que se chama pressão relativa.

Na biblioteca do BP180 a função seaLevel(P,A) utiliza como parâmetros a pressão absoluta (P) em hPa, e a altitude corrente (A) em metros, para devolver a pressão relativa. A partir da pressão relativa é possível comparar as pressões atmosféricas em diferentes pontos da terra.

Determinando a altitude

Uma vez que a pressão atmosférica varia com a altitude, é possível utilizar o medidor de pressão atmosférica para aferir a altitude de um local.

A pressão atmosférica média ao nível do mar é 1013.25 hPa e cai a zero no vácuo do espaço.

A variação da altitude entre duas medidas de pressão (p e p0) é dada pela fórmula:

Formas de utilizar esta equação:

  1. Se utilizarmos p0 como a pressão atmosférica ao nível do mar (1013.25 hPa), teremos a altitude acima do nível do mar do local;
  2. Se utilizarmos p0 como a pressão atmosférica do um local com altitude conhecida, teremos a altitude relativa, podendo ser positiva ou negativa, dependendo se subirmos ou descermos em relação a altitude conhecida.

Na biblioteca do BP180 a função altitude(P,P0) está pronta para realizar medições de altitude.


Tradução e adaptação
--Evandro.cantu (discussão) 10h33min de 23 de agosto de 2015 (BRT)

Conexão dos Sensores DHT11 e BMP180 ao Arduíno

Sensores DHT11 e BMP180
Os sensores de Temperatura e Unidade do Ar (DHT11) e Pressão Atmosférica (BMP180) são conectados ao Arduíno através de um flat cable de 10 vias:

Os sensores são conectados da seguinte forma:

Código de cores utilizados nos fios de conexão com o Arduíno:

  • GND - Preto (pinos 2 e 8)
  • 5V - (Vermelho) (pino 4)
  • 3,3V - (Laranja) (pino 6)
  • Data - (Amarelo) (pino 3) -> A2
  • DA - (Azul) (pino 10) -> A4
  • CL - (Verde) (pino 9) -> A5

--Evandro.cantu (discussão) 10h35min de 25 de outubro de 2016 (BRST)

Código para Arduíno

Código para teste dos sensores de campo, com resultados apresentados no monitor serial da IDE do Arduíno.

/*
      Estação Meteorológica com Microcontrolador Arduino
      2015-2016 - Instituto Federal do Paraná
      Versão: V2
      Programadores: José Sallet (V1 2015)
                     Thiago Henrique Ribeiro (V2 2016)

      Orientador: Evandro Cantú

      Mudanças em 2016:

      12/04/2016 - Inclusão da função de leitura de vento por pulseIn()
      14/04/2016 - Carregar strings literais da memória flash -> Serial.println(F("String literal));
                 - Inclusão dos sensores LM35 (temperatura) e DHT11 (temperatura, umidade)
                 - Testes com anemômetro e biruta com soprador de ar

*/
//Estacao de Testes - Baseado no codigo EstacaoMeteoCompleta
//Teste de adição de sensores LM35, DHT11 e nova rotina de leitura de vento baseada em PulseIn

#include<string.h>
//incluindo biblioteca do sensor de temperatura e pressao DHT11
#include <dht11.h>
//incluindo biblioteca do sensor de pressão
#include <SFE_BMP180.h>
//biblioteca do protocolo I2C
#include <Wire.h>       // biblioteca de comunicação I2C - necessária para o sensor barométrico BMP180

#define ALTITUDE 180.0  // Altitude de Foz do Iguaçu, Parana, Brasil
#define BASETEMPO 10    // define o tempo de repeticao

SFE_BMP180 sensorPressao;     //inicializando sensor de temperatura e pressão
dht11 sensorUmidade;          //inicializando sensor DHT11

const int PINO_BIRUTA = A0;   //pino analógico A0 - Leitura da tensão da biruta
const int PINO_LM35   = A1;   //pino analógico A1 - Leitura do sensor LM35 (temperatura)
const int PINO_DHT11  = A2;   //pino analógico A2 - Leitura do sensor DHT11 (temperatura + umidade)
                              //pino analógico A3 livre
                              //pino analógico A4 usado no BMP180 (temperatura + pressão)
                              //pino analógico A5 usado no BMP180 (temperatura + pressão)

const int BUFFER_SIZE = 1000;                       //quantidade de leituras do sensor LM35 para fazer a média
                                                    //para reduzir a margem de erro
const float CONVERSAO_GRAUS_CELSIUS = 0.488758553;  //constante para calcular a temperatura do sensor LM35

//int Tensao;             //tensão de leitura da biruta - comentado para invocar em loop()
float mmChuva = 0;        //pluviômetro - Isto deveria ser gravado em EEPROM
//int contVento = 0;      //contador de pulsos de vento - substituído por pulseIn
//float velVento;         //velocidade do vento - comentado para invocar em loop

//--------------------------------------------------------------------------------------------------------------
//  ROTINA DE INTERRUPÇÃO 0 - ANEMÔMETRO (obsoleta)
//--------------------------------------------------------------------------------------------------------------

//void vento(){
//   contVento++;
//  }

//--------------------------------------------------------------------------------------------------------------
//  ROTINA DE INTERRUPÇÃO 1 - PLUVIÔMETRO
//--------------------------------------------------------------------------------------------------------------

void choveu() {
  mmChuva = mmChuva + 0.2794;

  if (mmChuva > 1000)
  {
    mmChuva = mmChuva - 1000;
  }
}

//--------------------------------------------------------------------------------------------------------------
//  ANEMÔMETRO (versão nova sem interrupção)
//--------------------------------------------------------------------------------------------------------------

float velVento(){
 //Medição de largura do pulso em microsegundos
  unsigned long larguraPulso = pulseIn(2, LOW, 2400000); //um pulso de 2400000 ms equivale a um vento de 1km/h
  float _velVento = 0;

  //calcular Velocidade de acordo com a largura do pulso; Largura de pulso mínima a ser calculada
  if (larguraPulso <= 5000) {
    byte retry = 2;
    //se houver uma leitura inválida (valores absurdos devido a erros), mais duas tentativas são feitas.
    while((retry > 0) && (larguraPulso <= 5000)){
      retry--;
      larguraPulso = pulseIn(2,LOW, 2400000);
    }
  }

  if(larguraPulso > 5000){
    _velVento = 2.4 * (1000000 / (float) larguraPulso);  
  }else{
    _velVento = 0;
  }
  
  return _velVento; 
}
//--------------------------------------------------------------------------------------------------------------
//  BIRUTA (Sparkfun)
//--------------------------------------------------------------------------------------------------------------


String biruta(int Tensao)
{
  String direcao;
  if (Tensao >= 744 && Tensao <= 805) {
    //Serial.println(F("Direcao do Vento:   Leste"));
    direcao = "L";
  }
  else if (Tensao >= 346 && Tensao <= 432) {
    //Serial.println(F("Direcao do Vento:   Leste-Norderste"));
    direcao = "LNE";
  }
  else if (Tensao >= 433 && Tensao <= 529) {
    //Serial.println(F("Direcao do Vento:   Nordeste"));
    direcao = "NE";
  }
  else if (Tensao >= 75 && Tensao <= 87) {
    //Serial.println(F("Direcao do Vento:   Norte-Nordeste"));
    direcao = "NNE";
  }
  else if (Tensao >= 88 && Tensao <= 109) {
    //Serial.println(F("Direcao do Vento:   Norte"));
    direcao = "N";
  }
  else if (Tensao >= 0 && Tensao <= 74) {
    //Serial.println(F("Direcao do Vento:   Norte-Noroeste"));
    direcao = "NNO";
  }
  else if (Tensao >= 156 && Tensao <= 213) {
    //Serial.println(F("Direcao do Vento:   Noroeste"));
    direcao = "NO";
  }
  else if (Tensao >= 110 && Tensao <= 155) {
    //Serial.println(F("Direcao do Vento:   Oeste-Noroeste"));
    direcao = "ONO";
  }
  else if (Tensao >= 265 && Tensao <= 345) {
    //Serial.println(F("Direcao do Vento:   Oeste"));
    direcao = "O";
  }
  else if (Tensao >= 214 && Tensao <= 264) {
    //Serial.println(F("Direcao do Vento:   Oeste-Sudoeste"));
    direcao = "OSO";
  }
  else if (Tensao >= 615 && Tensao <= 665) {
    //Serial.println(F("Direcao do Vento:   Sudoeste"));
    direcao = "SO";
  }
  else if (Tensao >= 530 && Tensao <= 614) {
    //Serial.println(F("Direcao do Vento:   Sul-Sudoeste"));
    direcao = "SSO";
  }
  else if (Tensao >= 886 && Tensao <= 961) {
    //Serial.println(F("Direcao do Vento:   Sul"));
    direcao = "S";
  }
  else if (Tensao >= 806 && Tensao <= 885) {
    //Serial.println(F("Direcao do Vento:   Sul-Sudeste"));
    direcao = "SSE";
  }
  else if (Tensao >= 962 && Tensao <= 1023) {
    //Serial.println(F("Direcao do Vento:   Sudeste"));
    direcao = "SE";
  }
  else if (Tensao >= 666 && Tensao <= 743) {
    //Serial.println(F("Direcao do Vento:   Leste-Sudeste"));
    direcao = "LSE";
  }
  else{
    Serial.println(F("[ERRO] Leitura na biruta fora da faixa!"));
    direcao = "ERR";
  }
    
  return direcao;
}

//--------------------------------------------------------------------------------------------------------------
//  SENSOR DE TEMPERATURA LM35
//--------------------------------------------------------------------------------------------------------------


//ler temperatura do sensor LM35 uma única vez
float temperaturaLM35() {
  return analogRead(PINO_LM35) * CONVERSAO_GRAUS_CELSIUS;
}

//ler temperatura do sensor LM35 (BUFFER_SIZE) vezes e calcular a média para obter uma medição mais precisa
//aumentar o valor de BUFFER_SIZE aumenta a precisão mas aumenta a carga do sistema
float temperaturaLM35Buffer() {
  float buffer = 0;
  for (int i = 0; i < BUFFER_SIZE ; i++) {
    buffer += analogRead(PINO_LM35);
  }
  return ((buffer) / BUFFER_SIZE) * CONVERSAO_GRAUS_CELSIUS;
}

//--------------------------------------------------------------------------------------------------------------
//  CÁLCULO DE PONTO DE ORVALHO
//  Funções de ponto de orvalho obtidas em http://playground.arduino.cc/Main/DHT11Lib
//  A fazer: Verificar e referenciar o código apropriadamente
//  O código abaixo foi copiado e usado sem alterações
//--------------------------------------------------------------------------------------------------------------

// dewPoint function NOAA
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
//
double dewPoint(double celsius, double humidity)
{
  // (1) Saturation Vapor Pressure = ESGG(T)
  double RATIO = 373.15 / (273.15 + celsius);
  double RHS = -7.90298 * (RATIO - 1);
  RHS += 5.02808 * log10(RATIO);
  RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1 / RATIO ))) - 1) ;
  RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
  RHS += log10(1013.246);

  // factor -3 is to adjust units - Vapor Pressure SVP * humidity
  double VP = pow(10, RHS - 3) * humidity;

  // (2) DEWPOINT = F(Vapor Pressure)
  double T = log(VP / 0.61078); // temp var
  return (241.88 * T) / (17.558 - T);
}

// delta max = 0.6544 wrt dewPoint()
// 6.9 x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
  double a = 17.271;
  double b = 237.7;
  double temp = (a * celsius) / (b + celsius) + log(humidity * 0.01);
  double Td = (b * temp) / (a - temp);
  return Td;
}

//    **Fim das funções de orvalho copiadas**

//--------------------------------------------------------------------------------------------------------------
//  SENSOR DE PRESSÃO E TEMPERATURA (BMP180)
//--------------------------------------------------------------------------------------------------------------


double temperaturaBMP180(SFE_BMP180 sensor) {
  double T;
  char  status = sensor.startTemperature();
  if (status != 0) {
    delay(status);
    status = sensor.getTemperature(T);
    if (status == 0) {
      Serial.println(F("[AVISO] Falha na aquisição de temperatura do sensor BMP180. Tentando novamente..."));
      return temperaturaBMP180(sensor); // recursivamente faz uma nova tentativa
    }
  } else {
    Serial.println(F("[AVISO] Falha na preparação do sensor de temperatura BMP180. Tentando novamente..."));
     return temperaturaBMP180(sensor); // recursivamente faz uma nova tentativa
  }
  return T;
}

double pressaoBMP180(double temperatura, SFE_BMP180 sensor) {
  double pressao;
  char status = sensor.startPressure(3);
  if (status != 0) {
    delay(status);
    status = sensor.getPressure(pressao, temperatura);
    if (status == 0) {
      //erro em getPressure
      Serial.println(F("[ERRO] Falha na aquisição da temperatura do sensor BMP180. Tentando novamente..."));
      return pressaoBMP180(temperatura, sensor);  //nova tentativa usando recursão
    }
  } else {
    //erro em startPressure
    Serial.println(F("[ERRO] Falha na preparação do sensor de pressão BMP180. Tentando novamente..."));
    return pressaoBMP180(temperatura, sensor); // nova tentativa usando recursão
  }

  return pressao;
}

//  cálculo da pressão relativa ao nível do mar
double pressaoNivelMar(double pressao, double altura, SFE_BMP180 sensor) {
  return sensor.sealevel(pressao, altura);
}

//  cálculo da altitude
double altitude(double pressao, double pressao_nivel_mar, SFE_BMP180 sensor) {
  return sensor.altitude(pressao, pressao_nivel_mar);
}

//--------------------------------------------------------------------------------------------------------------
//  TELEMETRIA - MEMÓRIA LIVRE NO SISTEMA
//--------------------------------------------------------------------------------------------------------------

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

//--------------------------------------------------------------------------------------------------------------
//  SETUP (Preparação)
//--------------------------------------------------------------------------------------------------------------

void setup()
{
  Serial.begin(9600); //define a frequencia
  
  attachInterrupt(1, choveu, RISING); // interrupcao do pluviometro
  
  Serial.print(F("\nInicializando sensor barometrico BMP180... "));
  // Initialize the sensor (it is important to get calibration values stored on the device).
  if (sensorPressao.begin())
    Serial.println(F("[OK]"));
  else
  {
    // Oops, something went wrong, this is usually a connection problem,
    // see the comments at the top of this sketch for the proper connections.
    Serial.println(F("[FAIL]\n\nA estação não pode ser inicializada. Verifique o sensor barométrico e reinicie o aparelho."));
    while (1); // Pause forever.
  }
}

//--------------------------------------------------------------------------------------------------------------
//  PROGRAMA PRINCIPAL
//--------------------------------------------------------------------------------------------------------------

//repeticao que imprime as informacoes do programa ao usuario
//TODO: organizar a ordem de execução levando em consideração o tempo tolerado por cada sensor
void loop()
{
  /* 
   *  Ações do programa:
   *  1.  Obter leitura do sensor de umidade (só pode ser lido a cada 2 segundos, são dois valores inteiros)
   *  2.  Obter leituras de tensão da biruta
   *  3.  Obter leituras do anemômetro
   *  4.  Obter leituras de temperatura do sensor LM35
   *  5.  Obter leituras de temperatura e pressão do sensor BMP180
  */
  unsigned long inicio = millis(); // millis() e micros() - medem o tempo corrido em milisegundos e microsegundos
  
  sensorUmidade.read(PINO_DHT11);
  double altitude_local = (double)ALTITUDE;                             //adquire a altitude do local
  float temperatura1 = (float) sensorUmidade.temperature;               //adquire temperatura do sensor DHT11
  float umidade = (float) sensorUmidade.humidity;                       //adquire umidade do sensor DHT11
  int tensaoBiruta = analogRead(PINO_BIRUTA);                           //adquire o valor da tensão na biruta
  String direcao = biruta(tensaoBiruta);                                //calcula a direção da biruta
  float velocidadeVento = velVento();                                   //adquire a velocidade do vento
  float temperatura2 = temperaturaLM35Buffer();                         //adquire temperatura do sensor LM35
  double temperatura3 = temperaturaBMP180(sensorPressao);               //adquire temperatura do sensor BMP180
  double pressaoAbsoluta = pressaoBMP180(temperatura3, sensorPressao);  //adquire pressão absolutado sensor BMP180
  double pressaoRelativa = pressaoNivelMar(pressaoAbsoluta, altitude_local, sensorPressao); //calcula pressão relativa
  double altitudeCalculada = altitude(pressaoAbsoluta, pressaoRelativa, sensorPressao);     //calcula altitude
  double pontoOrvalho = dewPoint(temperatura2, umidade);                                    //calcula ponto de orvalho
  
  unsigned long fim = millis();                                         //fim da cronometração da função
  unsigned long tempo = fim - inicio;                                   //cálculo do tempo de execução

  if(tempo < 2000){
    delay(2000 - tempo);                                                //cálculo do tempo de espera
  }                                                                     //(não pode ser menor que 2s)
  
//  exibir dados na tela ou terminal serial
  Serial.println(F("================================================================================================"));
  
  Serial.print(F("Temperatura [DHT11]:\t\t\t"));
  Serial.print(temperatura1);
  Serial.println(F(" graus Celsius"));

  Serial.print(F("Temperatura [LM35]\t\t\t"));
  Serial.print(temperatura2);
  Serial.println(F(" graus Celsius"));

  Serial.print(F("Temperatura [BMP180]\t\t\t"));
  Serial.print(temperatura3);
  Serial.println(F(" graus Celsius"));

  Serial.print(F("Velocidade do vento:\t\t\t"));
  Serial.print(velocidadeVento);
  Serial.println(F(" km/h"));

  Serial.print(F("Direcao do vento:\t\t\t"));
  Serial.print(direcao);
  Serial.println(F(""));
  
  Serial.print(F("Pressao absoluta (local):\t\t"));
  Serial.print(pressaoAbsoluta);
  Serial.println(F(" milibar"));
  
  Serial.print(F("Pressao relativa (nivel do mar):\t"));
  Serial.print(pressaoRelativa);
  Serial.println(F(" milibar"));
  
  Serial.print(F("Altitude:\t\t\t\t"));
  Serial.print(altitudeCalculada);
  Serial.println(F(" metros"));
  
  Serial.print(F("Chuva acumulada:\t\t\t"));
  Serial.print(mmChuva);
  Serial.println(F(" mm"));

  Serial.print(F("Umidade relativa do ar:\t\t\t"));
  Serial.print(umidade);
  Serial.println(F("%"));
  
  Serial.print(F("Ponto de orvalho:\t\t\t"));
  Serial.print(pontoOrvalho);
  Serial.println(F(" graus Celsius"));
  
  //exibir tempo de execução

  Serial.print(F("\nTempo de execucao total: "));
  Serial.print(tempo);
  Serial.println(F("ms\n"));

  // exibir memória livre pra determinar estabilidade
  Serial.print(F("\nMemoria Livre: "));
  Serial.print(freeRam());
  Serial.println(F(" bytes\n"));
  
 /*
  * Versão anterior do programa principal 
  * 
        velVento = (contVento / BASETEMPO) * 2.4;    
        Tensao = analogRead(A0); //variavel tensao recebe valor digital do dispositivo de direcao de vento
        Serial.print("Chuva acumalada (mm):  ");
        Serial.println(mmChuv1000a);
        Serial.print("Velocidade do Vento (km/h):  ");
        Serial.println(velVento);
 
        biruta(Tensao);
        altitudeEPressao();
 
        contVento = 0;
  Serial.println("");
        // PARA MODIFICAR O DELAY MODIFICAR A VARIAVEL "BASETEMPO"
        // NO CABECARIO DO PROGRAMA
        delay(BASETEMPO*1000); //Tempo entre as leituras em ms

  */
}

--Thiago.ribeiro (discussão) 17h53min de 27 de abril de 2016 (BRT)

Formato CSV dos dados

Os dados lidos pelos sensores da estação hidrometeorológica serão concatenados em uma string em formato CSV e transmitidos de forma serial para o servidor que armazenará os dados, utilizando os módulos Xbee.

Id da estação; direçao do vento; chuva acumulada;
velocidade do vento; temperatura; pressao atmosferica
1;N;0.5;13.3;32.8;990
1;S;0.7;17.2;30;1020
1;NO;0.4;12;19.7;980
1;NE;0.54;13.6;42.3;900

--Jade Mathias 17h59min de 9 de dezembro de 2015 (BRST)

Material técnico de referência

Materiais na Wiki

Arduíno

Tutoriais no Site Oficial do Arduíno

Bibliotecas e exemplos
Ethernet e Cartão SD:

Referências