Tamamen İşlevsel Bir Arduino Hava İstasyonunu Nasıl Yaptım?

Yayınlanan: 2022-03-11

GÜNCELLEME: Arduino hava istasyonumuz üzerindeki çalışmalar, bu makale yayınlandıktan sonra devam etti ve Open Weather Station'ın (OWS) yayınlanmasıyla sonuçlandı. Ek güncellemeler, kaynaklar, kod ve yeni öğreticiler için göz atın.

Bu ne hakkında?

Uçurtma sörfü dünyadaki en bağımlılık yapan sporlardan biridir. Tek gereken bir kiteboard, bir su kütlesi ve birkaç aksesuar. Doğayla temasa geçmenin, zihninizi boşaltmanın ve egzersiz yapmanın harika bir yolu. Ayrıca, onunla gerçekten çıldırabilirsiniz.

Sorun nedir?

Ah, önemli bir şartı unuttum: rüzgar. İşte bizim sorunumuz da burada: En sevdiğiniz uçurtma sörfü noktasında yaşamadığınız sürece rüzgar olup olmayacağını asla bilemezsiniz.

Uçurtma sörfü yaptığım gölden yaklaşık 130 kilometre (~ 80 mil) uzakta, Arjantin, Cordoba'da yaşıyorum. Bu, başa çıkabileceğim kabaca iki saatlik bir yol. Ama hava tahminlerinin yanlış olduğu gerçeğiyle baş edemiyorum. Ve yaşadığım yerde, iyi rüzgar koşulları sadece birkaç saat sürüyor. Yapmak isteyeceğiniz son şey, uçurtma sörfü yapmak için Pazartesi programınızı toplamak ve iki saatlik bir sürüşün ardından kendinizi rüzgarsız bir gölde tanrılara küfrederken bulmak.

En sevdiğim uçurtma sörfü yerimin rüzgar koşullarını gerçek zamanlı olarak bilmem gerekiyordu. Bu yüzden kendi hava istasyonumu kurmaya karar verdim.

Hava durumunu gerçek zamanlı olarak ölçmek—düşmanca bir ortamda

Amaç, gerçek zamanlı hava durumu verilerini evdeki tarayıcıya iletmekti:

Arduino meteoroloji istasyonu için genel süreç

Ayrıntılara girmeden önce, şöyle bir projede yer alan temel soruları ve uyarıları gözden geçirelim:

  • Bir hırsız için ne değerli ne de çekici olmayan bir meteoroloji istasyonunu nasıl oluşturabilirim?
  • Donanım maliyetlerini ve geliştirme süresini nasıl minimumda tutabilirim?
  • Hava durumu verilerini gerçek zamanlı olarak nasıl ölçebilir ve bunlara nasıl erişebilirim ve bunları kullanışlı bir şekilde nasıl görüntüleyebilirim?
    • Gerekli ölçümler: rüzgar ve rüzgar esintileri, rüzgar yönü, yağmur, atmosfer basıncı, sıcaklık, nem
    • İstasyonu internete bağlayın
    • Yerel hava durumu verilerini depolayın ve alın
    • Hava durumu istasyonu ve sunucu arasında iletişim kurun
  • Bakımı (neredeyse) sıfıra nasıl indirebilirim?
    • Yazılımın askıda kalmasını yönetin
    • Bağlantı kaybını yönetin
    • Enerji kaynağı kaybını yönetin

Küçük arkadaşıma merhaba de!]

dosya

Eldivenin istasyonun daha dostça görünmesini sağlamak için orada olduğunu düşünebilirsiniz; ama aslında barometrik sensörü test etmek için kullanılır (şişirilmiş eldivenin içindeki eldiven basıncı artar). Sağda, istasyonu yakındaki bir kulenin tepesinde bulunan nihai konumunda görebilirsiniz.

Ayrıca kitesurf topluluğuna yardımcı olmak için istasyonun ölçümlerinin gerçek zamanlı bir planını içeren kitesurf hakkında bir web sitesi tasarladım ve programladım. Sonunda Facebook'ta bir kitesurf grubu oluşturdum.

dosya

Bu harika! Peki nasıl yaptın?

Pekala, her noktayı sırayla ele alacağım:

"Hırsız için ne değerli ne de çekici olmayan bir meteoroloji istasyonunu nasıl oluşturabilirim?"

Bu kritik bir faktördü ve birçok yönden tasarım sürecinin geri kalanını yönlendirdi. 2000 $ hattının altındaki hazır istasyonların çoğu, bir bilgisayara USB bağlantısı gerektiriyordu. Bir hırsız istasyonun yanında bir PC olduğunu fark ederse, bilgisayarı ve istasyonu değiştirmenin maliyeti kişisel bütçemin üzerinde olacağından, bu her şeyin sonu olurdu. Bu nedenle, istasyonu sıfırdan daha düşük bir maliyetle uygulamak için birkaç donanım platformunu test etmeye karar verdim.

"Donanım maliyetlerini ve geliştirme süresini nasıl minimumda tutabilirim?"

Bu yan projenin maliyetlerini tek başıma destekliyordum ve boş zamanlarımda tüm işleri yapıyordum, bu yüzden elbette bu büyük bir endişe kaynağıydı. Popüler PIC32 ve bazı önceden monte edilmiş mikroçip Ethernet modülleriyle başladım, ancak maliyetler beklediğim kadar düşük değildi ve donanım montajı ve genişletmesi çok fazla ek yük gerektiriyordu. Ardından, Arduino'yu araştırmaya başladım: C dilini kullanarak elektronik prototipleme için açık kaynaklı bir donanım ve yazılım. Tam olarak istediğim buydu ve DealeXtreme'den modül satın alabiliyordum. Sadece 15 dolarlık harcama ve iki günlük zaman ile oynamaya başlayabildim.

Tabii ki, Arduino'nun da sınırlamaları var: benim derlenmiş yazılımım için sadece 2KByte RAM ve 32Kbyte - bu süslü diziler veya gereksiz değişkenler için fazla yer bırakmaz 1 .

“Hava durumu verilerini gerçek zamanlı olarak nasıl ölçebilir ve bunlara nasıl erişebilirim ve bunları faydalı bir şekilde nasıl görüntüleyebilirim?”

Şu anda istasyonum şunları ölçebilir: rüzgar hızı, rüzgar şiddeti, rüzgar yönü, sıcaklık, nem, yağmur ve atmosfer basıncı. Sıcaklık, nem ve basınç, hayatı çok daha kolay hale getiren birkaç kitaplık tarafından yönetilir.

Rüzgar hızını ve yağmuru ölçmek biraz dağınıktı. Sensörler, bir anahtarın (kamış anahtarı) açılıp kapanmasıyla çalıştırılır. Bu nedenle, girişi tetiklediği anda sensörü yakalamak için donanım kesintileri uygulamam gerekiyordu. Yani, bir yöntem çağırmam gerekiyordu:

 attachInterrupt(RAINGAUGE_PIN, countRainCycles, FALLING);

Bu kesme, normal kod yürütmeyi bozar ve anahtar, devreyi kapatarak veya açarak üretilen bir düşen kenarla karşılaştığında, countAnemometerCycles veya countRainCycles işlevini çağırır. Anahtarın her tetikleyicisinde birkaç değişken artırılır. (Daha sonra, birim dönüşümleri hesaba katmak için bu değişkenleri tartarsınız.)

 void countRainCycles() { rainCyclesCounter++; // This is easy! And it actually works. }

Ama o kadar hızlı değil! Bu işlem, herhangi bir donanım anahtarına özgü anahtar sıçrama etkisinin bir sonucu olarak yüzlerce yanlış tetikleyici üretir. Neyse ki, bu soruna hem donanım hem de yazılım çözümleri var.

Zıplama efekti hakkında

Sıçrama etkisi, anahtarın devrenin geri kalanıyla temas kuran 'kontaklarını' fiziksel olarak açmasının veya kapatmasının bir sonucu olarak ortaya çıkar. Kontaklar ayrılmaya (anahtarın açılması) veya birleşmeye (anahtarın kapanması) başladığında, devrede birkaç milisaniye boyunca devreyi açıp kapatacak mekanik bir elastikiyetin yanı sıra bazı küçük elektrik arkları üretilebilir. Bir ışık düğmesini çevirdiğinizde, bu etki belirgin değildir; ancak bir sinyalin düşen kenarına bir kesme eklediğinizde, bu sıçrama etkisi bir ton kesintiyi tetikler. Daha fazla burada.

Devre geri dönüşü

Hem donanımsal bir geri tepme devresi hem de yazılımda benzer bir sürüm uyguladım. Ancak bir yazılım geri dönüşünü tam olarak nasıl uygularsınız? Kolay! Beklenen ilk tetikleyici gerçekleştikten sonra, yeni kesintileri dinlemeye başlamadan önce geri dönmenin yerleşmesine yetecek kadar "bekleyin". Bu, birkaç C satırında gerçekleştirilebilir:

 void countRainCycles() { if (nextTimeRainIterrupt == 0 || nextTimeRainIterrupt < millis()) { rainCyclesCounter++; // The interrupts counter nextTimeRainIterrupt = millis() + 100; // Wait 100msecs before next trigger } }

millis() işlevi, Arduino açıldığından beri geçerli yürütme süresini milisaniye cinsinden döndürür. Derleyiciye yürütmeyi optimize etmemesini ve dolayısıyla donanım kesintileri sırasında yanlış değerlerden kaçınmasını bildirmek için bu değişkenlerin geçici olarak tanımlanması gerektiğini de belirtmekte fayda var.

Her nasılsa, biriken verileri depolamak ve bu ölçümleri periyodik olarak bir MySQL veritabanına göndermek için istasyona ihtiyacım vardı. Bu yüzden, değerleri günlüğe kaydetmek ve bir kullanıcı (sunucu) istasyona bağlandığında bunları almak için SD yuvası olan bir Ethernet modülü ekledim. Evde ADSL bağlantısıyla yapılan testler sırasında bu inanılmaz derecede iyi çalıştı - ancak bunu "sahada" 3G İnternet ile (3G modem kullanarak) test ettiğimde neredeyse saçlarımı kaybediyordum, çünkü istasyonu geri almaya çalıştığımda istasyon kendini rastgele sıfırlayacaktı. ölçümler! Önemli testlerden sonra, sonunda, tüm İnternet üzerinden sağlanan ve bağlı bir istemciye veri "sunulmasını" açıklayan örneklerin, bağlantının o kadar zayıf olabileceğini ve istemciyle olan bağlantının paket iletiminin ortasında kaybolabileceğini ve bunun sonucunda çıktı arabelleği taşar. Ama neden kopan bir bağlantı arabellek taşmasına neden olur? Diyelim ki iletim oturumu başlıyor ve istasyon çıktı arabelleğini verilerle doldurmaya başlıyor. İdeal olarak, istemci bu arabelleği doldurulduğundan daha hızlı tüketir. Ancak, bir 3G modeme bağlanırken durum böyle değildi! İstemciyle bağlantı çok zayıftı, bu nedenle arabellek tüketilenden daha hızlı doldu, bu da hem arabellek taşmasına hem de istasyonun aniden yeniden başlatılmasına neden oldu.

Sorunu çözmek için Arduino ile sağlanan Ethernet Kitaplığına şöyle bir işlev eklemem gerekiyordu:

 int EthernetClient::free() { if (_sock != MAX_SOCK_NUM) return W5100.getTXFreeSize(_sock); return 0; }

Ardından, daha fazla veriyle doldurmaya çalışmadan önce istemcinin arabellekte biraz boşluk olup olmadığını kontrol edebildim:

 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();

Bu arada, bir Arduino programlamakla ilgileniyorsanız, işte size harika bir rehber.

Bir başka ilginç görev, bir LIFO günlüğünün uygulanmasıydı. Bu neden gerekliydi? Tipik olarak, ölçümleri belirli bir dosyaya kaydettiğimde, yaklaşım basittir: dosyayı açın, yeni örnekleri sonuna ekleyin ve dosyayı kapatın. Ama diyelim ki kronolojik olarak sıralanmış en son 1000 ölçümü almak istiyorum. Bu ölçüler dosyanın sonundadır; bu yüzden dosyayı açmalı, imleci sona hareket ettirmeli, en son ölçümlerin çıktısını almalı, ardından dosya imlecini önceki ölçüme geri almalı ve nereden başlayıp nerede duracağını tespit etmek için bir örnek sınırlayıcı arayarak çıktısını almalıyım. Arduino'nun bu işlemi hızlı bir şekilde yürütmek için ne yeterli RAM'i ne de işlemci gücü var, bu yüzden başka bir yaklaşıma ihtiyacım vardı. Bunun yerine, dosyayı sunucuya ters sırayla göndermeye karar verdim ve ardından dize değişmezlerini sunucu tarafına geri döndürmeye karar verdim:

 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--; } }

Bir PHP geliştiricisi olarak herhangi bir deneyime sahipseniz, karakterleri doğru sırayla kullanarak en son örnekleri almak kolaydır:

 // $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 :)

Sunucu tarafında, her iki dakikada bir en son ölçümleri almak için bir cron işlemi kurdum ve verileri bir MySQL motoruna ekledim. Verileri görüntülemek için www.kitesurfcordoba.com.ar'ı oluşturdum ve grafikleri otomatik olarak güncellemek için jQuery kullandım (bunların kendileri harika bir açık kaynak kitaplığı olan pChart v2.0 kullanılarak oluşturulmuştur).

Hem yazılım hem de donanım mühendisliği ile ilgili işleri yürütmek için gereken bir sürü başka numara vardı, ancak yeterince uzun sürdüm - o yüzden bakımı en aza indirme hakkında konuşalım.

"Bakımı (neredeyse) sıfıra nasıl indirebilirim?"

Bu büyük bir endişe kaynağıydı çünkü istasyona ulaşmak benim için kesinlikle kolay değildi - eğer küçük bir arızayı gidermek için iki saat uzaklaşmaya istekli olsaydım, o zaman onu ilk etapta içeri sokmak zorunda kalmazdım. bundan daha önce bahsetmemiştik, ama yaşadığımız onca şeyden sonra, istasyon aslında bir “o” ve adı Dorothy).

Peki burada ne tür hatalardan bahsediyoruz? Örneğin: yazılım askıda kalabilir, ağ bağlantısını kaybedebilir, enerji kaynağı arızalanabilir (ve yapar), vb.

Esasen, istasyonun mümkün olduğu kadar kendini kurtarması gerekiyor. Bu yüzden hem yumuşak hem de sert bekçi köpekleri kullandım. Bilmeyenler için, bekçi köpeği, bir sistemin doğru çalışıp çalışmadığını kontrol eden ve değilse, onu hayata döndürmeye çalışan bir yazılım veya donanım parçasıdır. Arduino, kullanabileceğiniz gömülü bir bekçi köpeğine sahiptir. 8 saniye beklemeye ayarladım: bir arama bu süre sınırından daha uzun sürerse, yazılım bekçisi kartı sıfırlayacaktır.

 wdt_enable(WDTO_8S); // "wdt" stands for "watchdog timer"

Bu işlevi seviyorum. Ancak, kartın sıfırlandığı ve Ethernet modülünün başlamadığı zamanlar vardır. Niye ya? Pekala, bu nispeten uygun fiyatlı bir prototipleme panosu, oldukça pahalı, hatasız bir cihaz değil (bununla kesinlikle bir kalp pili yapmamalısınız). Bu dezavantajın üstesinden gelmek için, bir donanım sıfırlama girişini kartın kendisindeki bir dijital çıkışa çapraz bağlayarak Arduino'yu hacklemek zorunda kaldım. Sıfırlama döngüsünden kaçınmak için birkaç satır kod da eklenmelidir:

 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 ...

Bundan sonra, birkaç saniye sonra Dorothy'yi hayata digitalWrite(RESET_ARDUINO_PIN, LOW) çağırarak Arduino'ya ve üstündeki tüm modüllere (Ethernet modülü dahil) bir donanım sıfırlaması yapabildim.

Ek olarak, bir enerji kaybından sonra kart otomatik olarak yeniden başlatılır. İnternet bağlantısı başarısız olursa, SD kartın depolama özelliklerinden yararlanırız (veriler kartta bir haftadan fazla saklanabilir ve sunucu eksik örnekleri kurtarmak için eski verileri alabilir). Tüm bu özellikleri birleştirmek bize, izlemek için inşa edildiği zorlu koşullarda hayatta kalabilen oldukça sağlam bir hava istasyonu sağlıyor. Toplamda, bu şey bana yaklaşık 300 dolara mal oldu.

Pasta grafik

Ve sonunda

İstasyon Aralık 2012'den beri çalışıyor. Bugüne kadar başarısız olmadı (ya da arıza yaptıysa, istasyon kitesurf camiasının ve benim fark etmediğimiz kadar hızlı iyileşti). Bölgeye gitmeden önce hava istasyonunu düzenli olarak kontrol eden yaklaşık 500 uçurtma sörfçü var. Bazı zorlu teknik zorlukları çözmenin ödülünün yanı sıra, bir grup insana daha keyifli bir uçurtma sörfü deneyimi sunma fırsatım da oldu.

1 Başlangıçta bir Arduino Uno kullanıyordum. Daha sonra artan RAM ve flash bellek ihtiyacından dolayı Arduino Mega'ya geçtim.

İlgili: ESP32 Ses Örnekleme ile Çalışmak