Bagaimana Saya Membuat Stasiun Cuaca Arduino yang Berfungsi Penuh
Diterbitkan: 2022-03-11PEMBARUAN: Pekerjaan di stasiun cuaca Arduino kami berlanjut setelah artikel ini diterbitkan, yang berpuncak pada rilis Stasiun Cuaca Terbuka (OWS). Lihat untuk pembaruan tambahan, sumber daya, bersama dengan kode dan tutorial baru.
Apa ini semua tentang?
Kitesurfing adalah salah satu olahraga paling adiktif di dunia. Yang dibutuhkan hanyalah kiteboard, badan air, dan beberapa aksesori. Ini adalah cara yang bagus untuk berhubungan dengan alam, membebaskan pikiran Anda, dan berolahraga. Plus, Anda benar-benar bisa menjadi gila dengannya.
Jadi apa masalahnya?
Oh, saya lupa satu persyaratan penting: angin. Dan di situlah kita memiliki masalah: Anda tidak pernah tahu apakah akan ada angin atau tidak kecuali Anda tinggal tepat di dekat tempat selancar layang favorit Anda.
Saya tinggal di Cordoba, Argentina, sekitar 130 kilometer (~80 mil) dari danau tempat saya bermain layang-layang. Itu kira-kira dua jam perjalanan, yang bisa saya tangani. Tapi saya tidak bisa menerima kenyataan bahwa ramalan cuaca tidak akurat. Dan di tempat saya tinggal, kondisi angin yang baik hanya berlangsung beberapa jam. Hal terakhir yang ingin Anda lakukan adalah menjernihkan jadwal Senin Anda untuk pergi selancar layang dan menemukan diri Anda mengutuk para dewa di danau tak berangin setelah dua jam mengemudi.
Saya perlu mengetahui kondisi angin di tempat selancar layang favorit saya—secara real time. Jadi saya memutuskan untuk membangun stasiun cuaca saya sendiri.
Mengukur cuaca secara real time—di lingkungan yang tidak bersahabat
Tujuannya adalah untuk mengirimkan data cuaca real-time ke browser di rumah:
Sebelum saya membahas secara spesifik, mari luangkan waktu sejenak untuk mempertimbangkan pertanyaan kunci dan peringatan yang terlibat dalam proyek seperti ini:
- Bagaimana cara membuat stasiun cuaca yang tidak berharga dan tidak menarik bagi pencuri?
- Bagaimana saya bisa menjaga biaya perangkat keras dan waktu pengembangan seminimal mungkin?
- Bagaimana saya bisa mengukur dan mengakses data cuaca secara real time dan menampilkannya dengan cara yang berguna?
- Pengukuran yang diperlukan: angin dan hembusan angin, arah angin, hujan, tekanan atmosfer, suhu, kelembaban
- Hubungkan stasiun ke Internet
- Simpan dan ambil data cuaca lokal
- Berkomunikasi antara stasiun cuaca dan server
- Bagaimana saya bisa mengurangi pemeliharaan menjadi (hampir) nol?
- Kelola penggantungan perangkat lunak
- Kelola hilangnya konektivitas
- Kelola hilangnya pasokan energi
Sampaikan salamku pada teman kecilku!
Anda mungkin berpikir bahwa sarung tangan itu ada untuk membuat stasiun tampak lebih ramah; tapi itu sebenarnya digunakan untuk menguji sensor barometrik (tekanan sarung tangan meningkat di dalam sarung tangan yang mengembang). Di sebelah kanan, Anda dapat melihat stasiun di lokasi terakhirnya, bertengger di atas menara terdekat.
Saya juga merancang dan memprogram situs web tentang kitesurfing, yang mencakup plot pengukuran stasiun secara real-time untuk membantu komunitas kitesurfing. Akhirnya, saya membuat grup kitesurfing di Facebook.
Itu luar biasa! Jadi bagaimana Anda melakukannya?
Baiklah, saya akan membahas setiap poin secara bergantian:
"Bagaimana saya bisa membuat stasiun cuaca yang tidak berharga dan tidak menarik bagi pencuri?"
Ini adalah faktor kritis dan, dalam banyak hal, mendorong sisa proses desain. Kebanyakan stasiun premade di bawah garis $2000 memerlukan koneksi USB ke komputer. Jika pencuri mengetahui bahwa stasiun memiliki PC di sebelahnya, itu akan menjadi akhir segalanya, karena biaya untuk mengganti komputer dan stasiun akan berada di atas anggaran pribadi saya. Oleh karena itu, saya memutuskan untuk menguji beberapa platform perangkat keras untuk mengimplementasikan stasiun dari awal, dengan biaya lebih rendah.
“Bagaimana saya bisa menjaga biaya perangkat keras dan waktu pengembangan seminimal mungkin?”
Saya sendiri yang menanggung biaya proyek sampingan ini dan mengerjakan semua pekerjaan di waktu senggang, jadi tentu saja ini menjadi perhatian besar. Saya mulai dengan PIC32 yang populer dan beberapa modul Ethernet microchip pra-rakitan, tetapi biayanya tidak serendah yang saya harapkan dan terlalu banyak overhead yang terlibat dalam perakitan dan ekstensi perangkat keras. Kemudian, saya mulai melihat ke Arduino: perangkat keras dan perangkat lunak open source untuk prototipe elektronik menggunakan bahasa C. Inilah yang saya inginkan, dan saya dapat membeli modul di DealeXtreme. Saya dapat mulai bermain-main hanya dengan pengeluaran $15 dan waktu dua hari.
Tentu saja, Arduino juga memiliki keterbatasan: hanya 2KBytes RAM dan 32Kbytes untuk perangkat lunak saya yang dikompilasi—itu tidak meninggalkan banyak ruang untuk string mewah atau variabel yang tidak berguna 1 .
“Bagaimana saya bisa mengukur dan mengakses data cuaca secara real time dan menampilkannya dengan cara yang bermanfaat?”
Saat ini, stasiun saya dapat mengukur: kecepatan angin, hembusan angin, arah angin, suhu, kelembapan, hujan, dan tekanan atmosfer. Suhu, kelembaban, dan tekanan ditangani oleh beberapa perpustakaan, yang membuat hidup jauh lebih mudah.
Mengukur kecepatan angin dan hujan sedikit berantakan. Sensor dioperasikan dengan cara membuka dan menutup saklar (reed switch). Jadi, saya perlu menerapkan interupsi perangkat keras untuk menangkap sensor segera setelah memicu input. Artinya, saya perlu memanggil beberapa metode:
attachInterrupt(RAINGAUGE_PIN, countRainCycles, FALLING);
Interupsi ini akan merusak eksekusi kode normal dan memanggil fungsi countAnemometerCycles atau countRainCycles segera setelah sakelar mengalami tepi jatuh, yang dihasilkan dengan menutup atau membuka sirkuit. Beberapa variabel bertambah pada setiap pemicu sakelar. (Kemudian, Anda menimbang variabel ini untuk memperhitungkan konversi unit.)
void countRainCycles() { rainCyclesCounter++; // This is easy! And it actually works. }
Tapi tidak secepat itu! Proses ini menghasilkan ratusan pemicu palsu sebagai akibat dari efek pantulan sakelar yang melekat pada sakelar perangkat keras apa pun. Untungnya, ada solusi perangkat keras dan perangkat lunak untuk masalah ini.
Tentang efek memantul
Efek memantul terjadi sebagai konsekuensi dari sakelar yang secara fisik membuka atau menutup 'kontaknya', yang membuat kontak dengan rangkaian lainnya. Ketika kontak mulai terpisah (membuka sakelar) atau menyatu (menutup sakelar), beberapa busur listrik kecil dapat dihasilkan, serta elastisitas mekanis di sirkuit yang akan memicu sirkuit hidup dan mati selama beberapa milidetik. Saat Anda menekan tombol lampu, efek ini tidak terlihat; tetapi ketika Anda memasang interupsi ke tepi sinyal yang jatuh, efek pantulan ini memicu banyak interupsi. Lebih banyak di sini.
Saya menerapkan sirkuit debounce perangkat keras dan versi serupa dalam perangkat lunak. Tetapi bagaimana tepatnya Anda menerapkan debounce perangkat lunak? Mudah! Setelah pemicu pertama yang diharapkan terjadi, "tunggu" waktu yang cukup untuk bouncing untuk diselesaikan sebelum Anda mulai mendengarkan interupsi baru. Ini dapat dicapai dalam beberapa baris C:
void countRainCycles() { if (nextTimeRainIterrupt == 0 || nextTimeRainIterrupt < millis()) { rainCyclesCounter++; // The interrupts counter nextTimeRainIterrupt = millis() + 100; // Wait 100msecs before next trigger } }
Fungsi milis() mengembalikan waktu eksekusi saat ini dalam milidetik sejak Arduino dihidupkan. Perlu juga dicatat bahwa variabel-variabel ini harus didefinisikan sebagai volatil untuk menginstruksikan kompiler agar tidak mengoptimalkan eksekusi dan oleh karena itu menghindari nilai yang tidak akurat selama interupsi perangkat keras.

Entah bagaimana, saya membutuhkan stasiun untuk menyimpan data yang terakumulasi dan secara berkala mengirim pengukuran ini ke database MySQL. Jadi saya menambahkan modul Ethernet dengan slot SD untuk mencatat nilai dan mengambilnya setiap kali pengguna (server) terhubung ke stasiun. Selama pengujian di rumah dengan konektivitas ADSL, ini bekerja dengan sangat baik—tetapi saya hampir kehilangan rambut saya ketika saya menguji ini "di lapangan" dengan Internet 3G (menggunakan modem 3G), karena stasiun akan mereset sendiri secara acak ketika saya mencoba untuk mengambil pengukuran! Setelah pengujian yang signifikan, saya akhirnya menemukan bahwa contoh yang disediakan di seluruh Internet yang menggambarkan "menyajikan" data ke klien yang terhubung tidak menganggap bahwa koneksi mungkin sangat buruk sehingga koneksi ke klien dapat hilang di tengah transmisi paket, menyebabkan buffer keluaran akan meluap. Tetapi mengapa koneksi yang terputus menyebabkan buffer overflow? Nah, katakanlah bahwa sesi transmisi dimulai dan stasiun mulai mengisi buffer output dengan data. Idealnya, klien kemudian mengkonsumsi buffer ini lebih cepat daripada terisi. Namun, saat terhubung dengan modem 3G, ini tidak terjadi! Sambungan ke klien terlalu buruk, sehingga buffer terisi lebih cepat daripada yang dikonsumsi, yang menyebabkan buffer overflow dan stasiun reboot tiba-tiba.
Untuk mengatasi masalah ini, saya perlu menambahkan fungsi ke Perpustakaan Ethernet yang disediakan dengan Arduino yang berjalan seperti ini:
int EthernetClient::free() { if (_sock != MAX_SOCK_NUM) return W5100.getTXFreeSize(_sock); return 0; }
Kemudian, saya dapat memeriksa apakah klien memiliki ruang di buffer sebelum mencoba mengisinya dengan lebih banyak data:
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();
Omong-omong, jika Anda tertarik untuk memprogram Arduino, inilah panduan yang bagus.
Tugas menarik lainnya adalah implementasi log LIFO. Mengapa ini perlu? Biasanya, ketika saya menyimpan pengukuran ke file tertentu, pendekatannya sederhana: buka file, tambahkan sampel baru ke akhir, dan tutup file. Tapi katakan saya ingin mengambil 1000 pengukuran terbaru, diurutkan secara kronologis. Pengukuran tersebut ada di akhir file; jadi saya harus membuka file, memindahkan kursor ke akhir, menampilkan pengukuran terbaru, lalu mengembalikan kursor file ke pengukuran dan output sebelumnya dengan mencari pembatas sampel untuk mendeteksi di mana harus memulai dan berhenti. Arduino tidak memiliki cukup RAM atau daya prosesor untuk menjalankan proses ini dengan cepat, jadi saya membutuhkan pendekatan lain. Sebagai gantinya, saya memutuskan untuk menampilkan file dalam urutan terbalik ke server, dan kemudian mengembalikan literal string kembali ke sisi server:
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--; } }
Dengan pengalaman apa pun sebagai pengembang PHP, mudah untuk mendapatkan sampel terbaru dengan karakter dalam urutan yang benar:
// $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 :)
Di sisi server, saya kemudian menyiapkan proses cron untuk mengambil pengukuran terbaru setiap dua menit dan memasukkan data ke mesin MySQL. Untuk menampilkan data, saya membuat www.kitesurfcordoba.com.ar dan menggunakan jQuery untuk memperbarui grafik secara otomatis (yang dibuat sendiri menggunakan pChart v2.0, perpustakaan sumber terbuka yang hebat).
Ada banyak trik lain yang diperlukan untuk membuat semuanya berfungsi, terkait dengan rekayasa perangkat lunak dan perangkat keras, tetapi saya sudah cukup lama berlarut-larut—jadi mari kita bicara tentang meminimalkan pemeliharaan.
“Bagaimana saya bisa mengurangi perawatan hingga (hampir) nol?”
Hal ini menjadi perhatian utama karena tentu saja tidak mudah bagi saya untuk mencapai stasiun—jika saya bersedia berkendara selama dua jam hanya untuk memperbaiki kerusakan kecil, maka saya tidak perlu membawanya masuk (saya tidak menyebutkan ini sebelumnya, tetapi setelah semua yang kita lalui, stasiun itu sebenarnya adalah "dia", dan namanya adalah Dorothy).
Jadi jenis kesalahan apa yang kita bicarakan di sini? Yah, misalnya: perangkat lunak mungkin hang, jaringan mungkin kehilangan konektivitas, pasokan energi mungkin gagal (dan memang demikian), dll.
Pada dasarnya, stasiun perlu melakukan pemulihan diri sebanyak mungkin. Itu sebabnya saya menggunakan kedua pengawas lembut dan keras. Bagi mereka yang tidak terbiasa, pengawas adalah perangkat lunak atau perangkat keras yang memeriksa apakah suatu sistem beroperasi dengan benar dan, jika tidak, mencoba menghidupkannya kembali. Arduino memiliki pengawas tertanam yang dapat Anda gunakan. Saya mengaturnya untuk menunggu selama 8 detik: jika panggilan membutuhkan waktu lebih lama dari batas waktu itu, pengawas perangkat lunak akan mengatur ulang papan.
wdt_enable(WDTO_8S); // "wdt" stands for "watchdog timer"
Saya suka fungsi ini. Namun, ada kalanya papan direset dan modul Ethernet tidak. Mengapa? Nah, ini adalah papan prototipe yang relatif terjangkau, bukan perangkat anti-gagal yang sangat mahal (Anda tentu tidak boleh membuat alat pacu jantung dengannya). Untuk mengatasi kelemahan ini, saya harus meretas Arduino dengan menghubungkan input perangkat keras-reset ke output digital di papan itu sendiri. Untuk menghindari pengulangan reset, beberapa baris kode juga harus ditambahkan:
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 ...
Setelah itu, saya dapat melakukan reset perangkat keras ke Arduino dan semua modul di atasnya (termasuk modul Ethernet) hanya dengan memanggil digitalWrite(RESET_ARDUINO_PIN, LOW)
, yang menghidupkan kembali Dorothy setelah beberapa detik.
Selain itu, board melakukan boot ulang otomatis setelah kehilangan energi. Dan jika konektivitas Internet gagal, kami memanfaatkan kemampuan penyimpanan kartu SD (data dapat disimpan di kartu selama lebih dari seminggu, dan server dapat menarik data lama untuk memulihkan sampel yang hilang). Menggabungkan semua fitur ini memberi kami stasiun cuaca yang sangat kuat yang dapat bertahan dalam kondisi tidak bersahabat yang dibangun untuk dipantau. Secara total, barang ini berharga sekitar $300.
Dan pada akhirnya
Stasiun ini telah bekerja sejak Desember 2012. Sampai saat ini, tidak ada yang gagal (atau jika ya, stasiun pulih cukup cepat sehingga komunitas kitesurfing dan saya tidak menyadarinya). Ada sekitar 500 peselancar layang yang memeriksa stasiun cuaca secara teratur sebelum melakukan perjalanan ke tempat tersebut. Jadi selain hadiah dari memecahkan beberapa tantangan teknis yang sulit, saya juga memiliki kesempatan untuk memberikan pengalaman kitesurfing yang lebih menyenangkan kepada banyak orang.
1 Awalnya, saya menggunakan Arduino Uno. Kemudian, saya beralih ke Arduino Mega karena kebutuhan untuk peningkatan RAM dan memori flash.
Terkait: Bekerja dengan Pengambilan Sampel Audio ESP32