Como eu fiz uma estação meteorológica Arduino totalmente funcional
Publicados: 2022-03-11ATUALIZAÇÃO: O trabalho em nossa estação meteorológica Arduino continuou após a publicação deste artigo, culminando no lançamento do Open Weather Station (OWS). Confira as atualizações adicionais, recursos, além de código e novos tutoriais.
O que é isso tudo?
O kitesurf é um dos esportes mais viciantes do mundo. Tudo o que é necessário é um kiteboard, um corpo de água e alguns acessórios. É uma ótima maneira de entrar em contato com a natureza, liberar sua mente e se exercitar. Além disso, você pode realmente enlouquecer com isso.
Então qual é o problema?
Ah, esqueci de um requisito essencial: vento. E é aí que temos o nosso problema: você nunca sabe se vai ou não ter vento a menos que você more bem perto do seu spot favorito de kitesurf.
Eu moro em Córdoba, Argentina, a aproximadamente 130 quilômetros (~80 milhas) do lago onde pratico kitesurf. Isso é aproximadamente uma viagem de duas horas, com a qual posso lidar. Mas não consigo lidar com o fato de que as previsões meteorológicas são imprecisas. E onde eu moro, boas condições de vento duram apenas algumas horas. A última coisa que você quer fazer é limpar sua agenda de segunda-feira para praticar kitesurf e se ver amaldiçoando os deuses em um lago sem vento depois de duas horas de condução.
Eu precisava saber as condições do vento do meu local de kitesurf favorito – em tempo real. Então decidi construir minha própria estação meteorológica.
Medindo o clima em tempo real - em um ambiente hostil
O objetivo era fornecer dados meteorológicos em tempo real para o navegador em casa:
Antes de entrar nos detalhes, vamos considerar as principais questões e advertências envolvidas em um projeto como este:
- Como posso criar uma estação meteorológica que não seja valiosa nem atraente para um ladrão?
- Como posso manter os custos de hardware e o tempo de desenvolvimento no mínimo?
- Como posso medir e acessar dados meteorológicos em tempo real e exibi-los de maneira útil?
- Medições necessárias: vento e rajadas de vento, direção do vento, chuva, pressão atmosférica, temperatura, umidade
- Conectar estação à Internet
- Armazene e recupere dados meteorológicos locais
- Comunique-se entre a estação meteorológica e o servidor
- Como posso reduzir a manutenção para (quase) zero?
- Gerenciar suspensão de software
- Gerenciar a perda de conectividade
- Gerenciar a perda de fornecimento de energia
Diga olá ao meu amiguinho!
Você pode pensar que a luva está lá para fazer a estação parecer mais amigável; mas na verdade é usado para testar o sensor barométrico (a pressão da luva aumenta dentro da luva inflada). À direita, você pode ver a estação em sua localização final, empoleirada no topo de uma torre próxima.
Também desenhei e programei um site sobre kitesurf, que inclui um gráfico em tempo real das medições da estação para ajudar a comunidade de kitesurf. Finalmente, criei um grupo de kitesurf no Facebook.
Fantástico! Então, como você fez isso?
Bem, vou abordar cada ponto por vez:
“Como posso criar uma estação meteorológica que não seja valiosa nem atraente para um ladrão?”
Esse foi um fator crítico e, de muitas maneiras, impulsionou o restante do processo de design. A maioria das estações pré-fabricadas abaixo da linha de US$ 2.000 exigia uma conexão USB com um computador. Se um ladrão reconhecesse que a estação tinha um PC ao lado, isso seria o fim das coisas, pois o custo para substituir o computador e a estação estaria acima do meu orçamento pessoal. Por isso, decidi testar várias plataformas de hardware para implementar a estação do zero, com um custo menor.
“Como posso manter os custos de hardware e o tempo de desenvolvimento no mínimo?”
Eu sozinho estava suportando os custos deste projeto paralelo e fazendo todo o trabalho no meu tempo livre, então é claro que isso era uma grande preocupação. Comecei com o popular PIC32 e alguns módulos Ethernet de microchip pré-montados, mas os custos não eram tão baixos quanto eu esperava e havia muita sobrecarga envolvida na montagem e extensão do hardware. Então, comecei a pesquisar o Arduino: um hardware e software de código aberto para prototipagem eletrônica usando a linguagem C. Isso era exatamente o que eu queria, e eu poderia comprar módulos no DealeXtreme. Consegui começar a brincar com apenas US$ 15 de despesas e dois dias do meu tempo.
É claro que o Arduino também tem suas limitações: apenas 2KBytes de RAM e 32Kbytes para meu software compilado - isso não deixa muito espaço para strings extravagantes ou variáveis inúteis 1 .
“Como posso medir e acessar dados meteorológicos em tempo real e exibi-los de maneira útil?”
Atualmente, minha estação pode medir: velocidade do vento, rajada de vento, direção do vento, temperatura, umidade, chuva e pressão atmosférica. Temperatura, umidade e pressão são controladas por algumas bibliotecas, o que facilitou muito a vida.
Medir a velocidade do vento e a chuva foi um pouco confuso. Os sensores operam abrindo e fechando um interruptor (interruptor reed). Assim, eu precisava implementar interrupções de hardware para capturar o sensor assim que ele acionasse a entrada. Ou seja, eu precisava chamar algum método:
attachInterrupt(RAINGAUGE_PIN, countRainCycles, FALLING);
Essa interrupção interromperia a execução normal do código e chamaria a função countAnemometerCycles ou countRainCycles assim que o switch experimentasse uma borda descendente, produzida pelo fechamento ou abertura do circuito. Algumas variáveis são incrementadas em cada trigger do switch. (Mais tarde, você pesa essas variáveis para contabilizar as conversões de unidade.)
void countRainCycles() { rainCyclesCounter++; // This is easy! And it actually works. }
Mas não tão rápido! Esse processo gera centenas de acionadores falsos como resultado do efeito de salto de switch inerente a qualquer switch de hardware. Felizmente, existem soluções de hardware e software para esse problema.
Sobre o efeito de salto
O efeito de ressalto ocorre como consequência do interruptor abrir ou fechar fisicamente seus 'contatos', que estabelecem contato com o resto do circuito. Quando os contatos começam a se separar (abrindo a chave) ou se unem (fechando a chave), alguns pequenos arcos elétricos podem ser gerados, bem como uma elasticidade mecânica no circuito que acionará o circuito ligado e desligado por alguns milissegundos. Quando você aciona um interruptor de luz, esse efeito não é aparente; mas quando você anexa uma interrupção à borda descendente de um sinal, esse efeito saltitante aciona uma tonelada de interrupções. Mais aqui.
Eu implementei um circuito de debounce de hardware e uma versão semelhante em software. Mas como exatamente você implementa um debounce de software? Fácil! Depois que o primeiro acionamento esperado ocorrer, “espere” tempo suficiente para que o salto se estabilize antes de começar a ouvir novas interrupções. Isso pode ser feito em algumas linhas de C:
void countRainCycles() { if (nextTimeRainIterrupt == 0 || nextTimeRainIterrupt < millis()) { rainCyclesCounter++; // The interrupts counter nextTimeRainIterrupt = millis() + 100; // Wait 100msecs before next trigger } }
A função millis() retorna o tempo de execução atual em milissegundos desde que o Arduino foi ligado. Vale ressaltar também que essas variáveis devem ser definidas como voláteis para instruir o compilador a não otimizar a execução e assim evitar valores imprecisos durante as interrupções de hardware.

De alguma forma, eu precisava que a estação armazenasse os dados acumulados e enviasse periodicamente essas medições para um banco de dados MySQL. Então eu adicionei um módulo Ethernet com um slot SD para registrar os valores e recuperá-los sempre que um usuário (o servidor) se conectar à estação. Durante o teste em casa com conectividade ADSL isso funcionou incrivelmente bem - mas eu quase perdi meu cabelo quando testei isso "no campo" com Internet 3G (usando um modem 3G), pois a estação se reiniciava aleatoriamente quando eu tentava recuperar o Medidas! Após testes significativos, eu finalmente descobri que os exemplos fornecidos em toda a Internet que descrevem “servir” dados para um cliente conectado não consideram que a conexão pode ser tão ruim que a conexão com o cliente pode ser perdida na transmissão do pacote intermediário, causando a buffer de saída iria estourar. Mas por que uma conexão perdida causaria um estouro de buffer? Bem, digamos que a sessão de transmissão comece e a estação comece a preencher o buffer de saída com dados. Idealmente, o cliente consome esse buffer mais rápido do que é preenchido. No entanto, ao conectar com um modem 3G, esse não era o caso! A conexão com o cliente era muito ruim, então o buffer encheu mais rápido do que foi consumido, o que causou um estouro de buffer e uma reinicialização repentina da estação.
Para resolver o problema, precisei adicionar uma função à Biblioteca Ethernet fornecida com o Arduino que era algo assim:
int EthernetClient::free() { if (_sock != MAX_SOCK_NUM) return W5100.getTXFreeSize(_sock); return 0; }
Então, consegui verificar se o cliente tinha algum espaço no buffer antes de tentar preenchê-lo com mais dados:
while (file.available() > 0) { if (client.free() > 0) { // This was key to solving the issue c = file.read(); client.print((char)c); } else { // No free buffer? Ok, I'll wait a couple of millis... delay(50); } } file.close();
A propósito, se você estiver interessado em programar um Arduino, aqui está um ótimo guia.
Outra tarefa interessante foi a implementação de um log LIFO. Por que isso era necessário? Bem, normalmente, quando salvo medições em um determinado arquivo, a abordagem é simples: abra o arquivo, anexe as novas amostras ao final e feche o arquivo. Mas digamos que eu queira buscar as últimas 1.000 medições, ordenadas cronologicamente. Essas medidas estão no final do arquivo; então eu deveria abrir o arquivo, mover o cursor para o final, produzir as medições mais recentes, então levar o cursor do arquivo de volta para a medição anterior e produzir isso, buscando um delimitador de amostra para detectar onde começar e parar. O Arduino não tem RAM suficiente nem poder de processador para executar esse processo rapidamente, então eu precisava de outra abordagem. Em vez disso, decidi enviar o arquivo na ordem inversa para o servidor e, em seguida, reverter os literais de string de volta no lado do servidor:
unsigned long filePosition = file.size(); file.seek(filePosition); while (filePosition >= 0) { if (client.free() > 0){ file.seek(filePosition); c = file.peek(); if (c != -1) { client.print((char)c); } if (filePosition <= 0) { break; } filePosition--; } }
Com qualquer experiência como desenvolvedor PHP, é fácil obter as amostras mais recentes com os caracteres na ordem correta:
// $output has the reversed string measures, each sample is delimited by ; $rows = split(";", trim($output)); array_walk_recursive($rows, 'reverseString'); if (strlen($rows[0]) == 0) { array_shift($rows); // Remove the first line if empty } function reverseString(&$row, $key) { $row = trim(strrev($row)); } // $rows is now the array of the latest samples :)
No lado do servidor, configurei um processo cron para buscar as medições mais recentes a cada dois minutos e inserir os dados em um mecanismo MySQL. Para exibir os dados, criei www.kitesurfcordoba.com.ar e usei jQuery para atualizar automaticamente os gráficos (que são gerados usando pChart v2.0, uma ótima biblioteca de código aberto).
Havia um monte de outros truques necessários para fazer as coisas funcionarem, relacionadas à engenharia de software e hardware, mas eu me arrastei o suficiente - então vamos falar sobre minimizar a manutenção.
“Como posso reduzir a manutenção para (quase) zero?”
Esta foi uma grande preocupação porque certamente não é fácil para mim chegar à estação - se eu estivesse disposto a dirigir duas horas apenas para consertar um pequeno defeito, então eu não teria que fazê-la em primeiro lugar (eu não mencionei isso antes, mas depois de tudo que passamos, a estação é na verdade uma “ela”, e o nome dela é Dorothy).
Então, de que tipos de erros estamos falando aqui? Bem, por exemplo: o software pode travar, a rede pode perder conectividade, o fornecimento de energia pode falhar (e acontece), etc.
Essencialmente, a estação precisa realizar o máximo de auto-recuperação possível. É por isso que eu utilizei cães de guarda macios e rígidos. Para quem não conhece, um watchdog é um software ou hardware que verifica se um sistema está funcionando corretamente e, se não estiver, tenta trazê-lo de volta à vida. O Arduino tem um watchdog embutido que você pode usar. Eu configurei para esperar 8 segundos: se uma chamada demorar mais que esse limite de tempo, o watchdog do software irá resetar a placa.
wdt_enable(WDTO_8S); // "wdt" stands for "watchdog timer"
Eu amo essa função. No entanto, há momentos em que a placa é reinicializada e o módulo Ethernet não. Por quê? Bem, esta é uma placa de prototipagem relativamente acessível, não um dispositivo altamente caro e à prova de falhas (você certamente não deve construir um marcapasso com ela). Para superar essa desvantagem, tive que hackear o Arduino conectando uma entrada de reinicialização de hardware a uma saída digital na própria placa. Para evitar um loop de reset, algumas linhas de código também devem ser adicionadas:
void setup() { digitalWrite(RESET_ARDUINO_PIN, HIGH); // Set it to HIGH immediately on boot pinMode(RESET_ARDUINO_PIN, OUTPUT); // We declare it an output ONLY AFTER it's HIGH digitalWrite(RESET_ARDUINO_PIN, HIGH); // Default to HIGH, set to LOW to HARD RESET ...
Depois disso, consegui redefinir o hardware do Arduino e de todos os módulos sobre ele (incluindo o módulo Ethernet) simplesmente chamando digitalWrite(RESET_ARDUINO_PIN, LOW)
, o que trouxe Dorothy de volta à vida após alguns segundos.
Além disso, a placa reinicializa automaticamente após uma perda de energia. E se a conectividade com a Internet falhar, exploramos os recursos de armazenamento do cartão SD (os dados podem ser armazenados no cartão por mais de uma semana e o servidor pode obter dados antigos para recuperar quaisquer amostras ausentes). A combinação de todos esses recursos nos dá uma estação meteorológica altamente robusta que pode sobreviver às condições hostis para a qual foi construída para monitorar. No total, essa coisa me custou apenas cerca de US $ 300.
E no final
A estação está funcionando desde dezembro de 2012. Até o momento, não falhou (ou se falhou, a estação se recuperou rápido o suficiente para que a comunidade de kitesurf e eu não notássemos). Existem cerca de 500 kitesurfistas que verificam a estação meteorológica regularmente antes de viajar para o local. Então, além da recompensa por resolver alguns desafios técnicos difíceis, também tive a oportunidade de proporcionar a um grupo de pessoas uma experiência de kitesurf mais agradável.
1 Inicialmente, eu estava usando um Arduino Uno. Mais tarde, mudei para um Arduino Mega devido à necessidade de aumento de RAM e memória flash.
Relacionado: Trabalhando com Amostragem de Áudio ESP32