كيف صنعت محطة طقس اردوينو وظيفية بالكامل

نشرت: 2022-03-11

تحديث: استمر العمل في محطة الطقس الخاصة بنا في Arduino بعد نشر هذه المقالة ، وبلغت ذروتها في إصدار Open Weather Station (OWS). تحقق من ذلك للحصول على تحديثات إضافية وموارد بالإضافة إلى التعليمات البرمجية والبرامج التعليمية الجديدة.

حول ماذا يدور كل هذا؟

Kitesurfing هي واحدة من أكثر الرياضات إدمانًا في العالم. كل ما يتطلبه الأمر هو لوح شراعي ، وجسم مائي ، وعدد قليل من الملحقات. إنها طريقة رائعة للتواصل مع الطبيعة وتحرير عقلك وممارسة الرياضة. بالإضافة إلى ذلك ، يمكنك حقًا أن تصاب بالجنون.

إذا ما هي المشكلة؟

أوه ، لقد نسيت مطلبًا أساسيًا واحدًا: الريح. وهذا هو المكان الذي نواجه فيه مشكلتنا: فأنت لا تعرف أبدًا ما إذا كانت هناك رياح أم لا إلا إذا كنت تعيش بالقرب من مكانك المفضل لركوب الأمواج الشراعي.

أعيش في قرطبة ، الأرجنتين ، على بعد حوالي 130 كيلومترًا (حوالي 80 ميلاً) من البحيرة حيث أركب الطائرات الشراعية. هذا ما يقرب من ساعتين بالسيارة ، والتي يمكنني التعامل معها. لكن لا يمكنني التعامل مع حقيقة أن تنبؤات الطقس غير دقيقة. وحيث أعيش ، تستمر ظروف الرياح الجيدة بضع ساعات فقط. آخر شيء تريد القيام به هو مسح جدول يوم الإثنين للذهاب للتزلج الشراعي وتجد نفسك تلعن الآلهة في بحيرة بلا ريح بعد ساعتين من القيادة.

كنت بحاجة إلى معرفة ظروف الرياح في بقعة التزلج الشراعي المفضلة لدي - في الوقت الفعلي. لذلك قررت بناء محطة الطقس الخاصة بي.

قياس الطقس في الوقت الحقيقي - في بيئة معادية

كان الهدف هو تقديم بيانات الطقس في الوقت الفعلي إلى المتصفح في المنزل:

العملية الشاملة لمحطة الطقس اردوينو

قبل الدخول في التفاصيل ، دعنا نتوقف لحظة للنظر في الأسئلة الرئيسية والمحاذير التي ينطوي عليها مشروع مثل هذا:

  • كيف يمكنني إنشاء محطة أرصاد جوية ليست ذات قيمة أو جذابة للسارق؟
  • كيف يمكنني تقليل تكاليف الأجهزة ووقت التطوير إلى الحد الأدنى؟
  • كيف يمكنني قياس بيانات الطقس والوصول إليها في الوقت الفعلي وعرضها بطريقة مفيدة؟
    • القياسات المطلوبة: الرياح والرياح ، اتجاه الرياح ، المطر ، الضغط الجوي ، درجة الحرارة ، الرطوبة
    • ربط المحطة بالإنترنت
    • تخزين واسترداد بيانات الطقس المحلية
    • التواصل بين محطة الطقس والخادم
  • كيف يمكنني تقليل الصيانة إلى (تقريبًا) الصفر؟
    • إدارة تعليق البرامج
    • إدارة فقدان الاتصال
    • إدارة فقدان إمدادات الطاقة

قل مرحبا لصديقي الصغير!

ملف

قد تعتقد أن القفاز موجود لجعل المحطة تبدو أكثر ودية ؛ لكنها تستخدم في الواقع لاختبار المستشعر البارومتري (يزداد ضغط القفاز داخل القفاز المنفوخ). على اليمين ، يمكنك أن ترى المحطة في موقعها النهائي ، تطفو فوق برج قريب.

لقد قمت أيضًا بتصميم وبرمجة موقع ويب حول رياضة ركوب الأمواج شراعيًا ، والذي يتضمن مخططًا في الوقت الفعلي لقياسات المحطة لمساعدة مجتمع ركوب الأمواج شراعيًا. أخيرًا ، أنشأت مجموعة للتزلج الشراعي على Facebook.

ملف

هذا رائع! فكيف يمكنك أن تفعل ذلك؟

حسنًا ، سأتناول كل نقطة على حدة:

"كيف يمكنني إنشاء محطة أرصاد جوية ليست ذات قيمة أو جذابة للسارق؟"

كان هذا عاملاً حاسمًا ، ومن نواح كثيرة ، قاد بقية عملية التصميم. تتطلب معظم المحطات الجاهزة التي تقل عن خط 2000 دولار اتصال USB بجهاز كمبيوتر. إذا أدرك اللص أن المحطة بها جهاز كمبيوتر بجوارها ، فستكون هذه نهاية الأشياء ، لأن تكلفة استبدال الكمبيوتر والمحطة ستكون أعلى من ميزانيتي الشخصية. لذلك قررت أن أجرب عدة منصات للأجهزة لتنفيذ المحطة من الصفر وبتكلفة أقل.

"كيف يمكنني تقليل تكاليف الأجهزة ووقت التطوير إلى الحد الأدنى؟"

كنت وحدي أدعم تكاليف هذا المشروع الجانبي وأقوم بكل العمل في أوقات فراغي ، لذلك كان هذا بالطبع مصدر قلق كبير. لقد بدأت مع PIC32 الشهير وبعض وحدات microchip Ethernet المجمعة مسبقًا ، لكن التكاليف لم تكن منخفضة كما كنت أتوقع وكان هناك الكثير من النفقات العامة المتضمنة في تجميع الأجهزة وامتدادها. بعد ذلك ، بدأت في البحث عن Arduino: جهاز مفتوح المصدر وبرامج للنماذج الأولية للإلكترونيات باستخدام لغة C. كان هذا بالضبط ما أردت ، ويمكنني شراء وحدات على DealeXtreme. تمكنت من بدء اللعب بمبلغ 15 دولارًا فقط من النفقات ويومين من وقتي.

بالطبع ، فإن Arduino أيضًا له حدوده: 2 كيلو بايت فقط من ذاكرة الوصول العشوائي و 32 كيلو بايت لبرامجي المترجمة - وهذا لا يترك مساحة كبيرة للسلاسل الفاخرة أو المتغيرات غير المفيدة 1 .

"كيف يمكنني قياس بيانات الطقس والوصول إليها في الوقت الفعلي وعرضها بطريقة مفيدة؟"

حاليًا ، يمكن لمحطتي قياس: سرعة الرياح وعاصفة الرياح واتجاه الرياح ودرجة الحرارة والرطوبة والمطر والضغط الجوي. يتم التعامل مع درجة الحرارة والرطوبة والضغط من قبل مكتبتين ، مما يجعل الحياة أسهل كثيرًا.

كان قياس سرعة الرياح والأمطار فوضويًا بعض الشيء. تعمل المستشعرات عن طريق فتح وإغلاق مفتاح (مفتاح القصب). وبالتالي ، كنت بحاجة إلى تنفيذ مقاطعات الأجهزة من أجل التقاط المستشعر بمجرد تشغيل الإدخال. وهذا يعني أنني كنت بحاجة إلى استدعاء طريقة ما:

 attachInterrupt(RAINGAUGE_PIN, countRainCycles, FALLING);

قد تؤدي هذه المقاطعة إلى كسر تنفيذ الكود العادي واستدعاء وظيفة countAnemometerCycles أو countRainCycles بمجرد أن يواجه المحول حافة هبوط ، ينتج عن إغلاق أو فتح الدائرة. يتم زيادة عدد قليل من المتغيرات على كل مشغل للمفتاح. (لاحقًا ، تقوم بموازنة هذه المتغيرات لحساب تحويلات الوحدات.)

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

لكن ليس بهذه السرعة! تولد هذه العملية المئات من المشغلات الخاطئة كنتيجة لتأثير ارتداد المفتاح المتأصل في أي مفتاح تبديل للأجهزة. لحسن الحظ ، هناك حلول للأجهزة والبرامج لهذه المشكلة.

حول تأثير كذاب

يحدث تأثير الارتداد نتيجة لفتح أو إغلاق `` جهات الاتصال '' فعليًا ، مما يؤدي إلى الاتصال ببقية الدائرة. عندما تبدأ جهات الاتصال في الانفصال (فتح المفتاح) أو التوحيد (إغلاق المفتاح) ، يمكن إنشاء بعض الأقواس الكهربائية الصغيرة ، بالإضافة إلى مرونة ميكانيكية في الدائرة تؤدي إلى تشغيل الدائرة وإيقافها لبضعة أجزاء من الثانية. عندما تقلب مفتاح الضوء ، لا يكون هذا التأثير واضحًا ؛ ولكن عندما تقوم بإرفاق مقاطعة بالحافة المتساقطة للإشارة ، فإن هذا التأثير المرتد يؤدي إلى عدد كبير من المقاطعات. المزيد هنا.

حلبة debounce

لقد قمت بتنفيذ كل من دائرة debounce للأجهزة وإصدار مشابه في البرنامج. ولكن كيف بالضبط تقوم بتنفيذ برنامج debounce؟ سهل! بعد حدوث أول محفز متوقع ، "انتظر" وقتًا كافيًا حتى يستقر الارتداد قبل أن تبدأ في الاستماع لمقاطعات جديدة. يمكن تحقيق ذلك في سطرين من C:

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

تُرجع الدالة millis () وقت التنفيذ الحالي بالمللي ثانية منذ تشغيل Arduino. تجدر الإشارة أيضًا إلى أنه يجب تعريف هذه المتغيرات على أنها متقلبة لإرشاد المترجم إلى عدم تحسين التنفيذ وبالتالي تجنب القيم غير الدقيقة أثناء مقاطعة الأجهزة.

بطريقة ما ، كنت بحاجة إلى المحطة لتخزين البيانات المتراكمة وإرسال هذه القياسات بشكل دوري إلى قاعدة بيانات MySQL. لذلك أضفت وحدة Ethernet بفتحة SD لتسجيل القيم واستردادها كلما اتصل مستخدم (الخادم) بالمحطة. أثناء الاختبار في المنزل باستخدام اتصال ADSL ، نجح هذا الأمر بشكل مذهل - لكنني كدت أفقد شعري عندما اختبرت هذا "في الميدان" مع إنترنت 3G (باستخدام مودم 3G) ، حيث أن المحطة ستعيد ضبط نفسها بشكل عشوائي عندما حاولت استرداد قياسات! بعد إجراء اختبارات مهمة ، وجدت أخيرًا أن الأمثلة المقدمة عبر الإنترنت والتي تصف بيانات "الخدمة" إلى عميل متصل لا تعتبر أن الاتصال قد يكون ضعيفًا لدرجة أن الاتصال بالعميل يمكن أن يفقد إرسال الحزمة المتوسطة ، مما يتسبب في سوف يتجاوز المخزن المؤقت الإخراج. ولكن لماذا يتسبب انقطاع الاتصال في تجاوز سعة المخزن المؤقت؟ حسنًا ، لنفترض أن جلسة الإرسال تبدأ وتبدأ المحطة في ملء المخزن المؤقت للإخراج بالبيانات. من الناحية المثالية ، يستهلك العميل بعد ذلك هذا المخزن المؤقت أسرع مما يتم ملؤه. ومع ذلك ، عند الاتصال بمودم 3G ، لم يكن هذا هو الحال! كان الاتصال بالعميل ضعيفًا للغاية ، لذلك امتلأ المخزن المؤقت بشكل أسرع مما تم استهلاكه ، مما تسبب في حدوث تجاوز في المخزن المؤقت وإعادة تشغيل المحطة بشكل مفاجئ.

لمعالجة المشكلة ، كنت بحاجة إلى إضافة وظيفة إلى مكتبة Ethernet المزودة بـ Arduino والتي تعمل على النحو التالي:

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

بعد ذلك ، تمكنت من التحقق مما إذا كان لدى العميل بعض المساحة في المخزن المؤقت قبل محاولة ملئه بمزيد من البيانات:

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

بالمناسبة ، إذا كنت مهتمًا ببرمجة Arduino ، فإليك دليل رائع.

كانت المهمة الأخرى المثيرة للاهتمام هي تنفيذ سجل LIFO. لماذا كان هذا ضروريا؟ حسنًا ، عادةً ، عندما أقوم بحفظ القياسات في ملف معين ، يكون الأسلوب بسيطًا: افتح الملف ، وألحق العينات الجديدة في النهاية ، وأغلق الملف. لكن لنفترض أنني أريد إحضار أحدث 1000 قياس ، مرتبة ترتيبًا زمنيًا. هذه القياسات موجودة في نهاية الملف ؛ لذلك يجب أن أفتح الملف ، وأنقل المؤشر إلى النهاية ، وأخرج أحدث القياسات ، ثم أعود بمؤشر الملف إلى القياس السابق وإخراج ذلك من خلال البحث عن محدد عينة لاكتشاف مكان البدء والتوقف. لا يمتلك Arduino ذاكرة وصول عشوائي كافية ولا قوة معالج لتنفيذ هذه العملية بسرعة ، لذلك كنت بحاجة إلى طريقة أخرى. بدلاً من ذلك ، قررت إخراج الملف بترتيب عكسي إلى الخادم ، ثم إعادة القيم الحرفية للسلسلة مرة أخرى على جانب الخادم:

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

مع أي خبرة كمطور PHP ، من السهل الحصول على أحدث العينات مع الأحرف بالترتيب الصحيح:

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

على جانب الخادم ، أقوم بعد ذلك بإعداد عملية cron لجلب أحدث القياسات كل دقيقتين وإدخال البيانات في محرك MySQL. لعرض البيانات ، قمت بإنشاء www.kitesurfcordoba.com.ar واستخدمت jQuery لتحديث الرسوم البيانية تلقائيًا (والتي تم إنشاؤها باستخدام pChart v2.0 ، وهي مكتبة رائعة مفتوحة المصدر).

كانت هناك مجموعة من الحيل الأخرى الضرورية لتشغيل الأشياء ، والمتعلقة بكل من هندسة البرمجيات والأجهزة ، لكنني استغرقت وقتًا طويلاً بما فيه الكفاية - لذا دعنا نتحدث عن تقليل الصيانة.

"كيف يمكنني تقليل الصيانة إلى (تقريبًا) الصفر؟"

كان هذا مصدر قلق كبير لأنه بالتأكيد ليس من السهل بالنسبة لي الوصول إلى المحطة - إذا كنت على استعداد للقيادة لمدة ساعتين فقط لإصلاح عطل بسيط ، فلن أضطر إلى جعلها في المقام الأول (أنا لم أذكر هذا من قبل ، ولكن بعد كل ما مررنا به ، فإن المحطة هي في الواقع "هي" ، واسمها دوروثي).

إذن ما أنواع الأخطاء التي نتحدث عنها هنا؟ حسنًا ، على سبيل المثال: قد يتعطل البرنامج ، وقد تفقد الشبكة الاتصال ، وقد يفشل مصدر الطاقة (وهو كذلك) ، وما إلى ذلك.

بشكل أساسي ، تحتاج المحطة إلى إجراء أكبر قدر ممكن من التعافي الذاتي. هذا هو السبب في أنني استخدمت كل من الحراسة اللينة والصلبة. بالنسبة لأولئك غير المألوفين ، فإن المراقبة هي جزء من البرامج أو الأجهزة التي تتحقق مما إذا كان النظام يعمل بشكل صحيح ، وإذا لم يكن الأمر كذلك ، فإنه يحاول إعادة الحياة إليه. يحتوي Arduino على جهاز مراقبة مدمج يمكنك استخدامه. لقد قمت بتعيينه على الانتظار لمدة 8 ثوانٍ: إذا استغرقت المكالمة وقتًا أطول من هذا الحد الزمني ، فسيقوم برنامج المراقبة بإعادة ضبط اللوحة.

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

أنا أحب هذه الوظيفة. ومع ذلك ، هناك أوقات يتم فيها إعادة تعيين اللوحة ولا يتم تشغيل وحدة Ethernet. لماذا ا؟ حسنًا ، هذه لوحة نماذج أولية ميسورة التكلفة نسبيًا ، وليست جهازًا باهظ الثمن ومقاوم للفشل (لا يجب عليك بالتأكيد بناء جهاز تنظيم ضربات القلب به). للتغلب على هذا العيب ، اضطررت إلى اختراق Arduino عن طريق توصيل مدخلات إعادة تعيين الأجهزة إلى إخراج رقمي على اللوحة نفسها. لتجنب حدوث حلقة إعادة تعيين ، يجب إضافة سطرين من التعليمات البرمجية أيضًا:

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

بعد ذلك ، تمكنت من إصدار إعادة تعيين للأجهزة إلى Arduino وجميع الوحدات الموجودة فوقه (بما في ذلك وحدة Ethernet) ببساطة عن طريق الاتصال digitalWrite(RESET_ARDUINO_PIN, LOW) ، مما أعاد دوروثي إلى الحياة بعد بضع ثوانٍ.

بالإضافة إلى ذلك ، يتم إعادة تشغيل اللوحة تلقائيًا بعد فقد الطاقة. وفي حالة فشل الاتصال بالإنترنت ، فإننا نستغل إمكانيات تخزين بطاقة SD (يمكن تخزين البيانات على البطاقة لأكثر من أسبوع ، ويمكن للخادم سحب البيانات القديمة لاستعادة أي عينات مفقودة). يمنحنا الجمع بين كل هذه الميزات محطة أرصاد جوية قوية للغاية يمكنها تحمل الظروف المعادية التي تم تصميمها لمراقبتها. في المجموع ، كلفني هذا الشيء حوالي 300 دولار فقط.

رسم بياني دائري

و في النهاية

تعمل المحطة منذ ديسمبر 2012. حتى الآن ، لم تفشل (أو إذا حدث ذلك ، فقد تعافت المحطة بسرعة كافية بحيث لم ألاحظ مجتمع التزلج الشراعي وأنا). هناك ما يقرب من 500 متزلج شراعي يقومون بفحص محطة الطقس بانتظام قبل السفر إلى الموقع. لذا بصرف النظر عن مكافأة حل بعض التحديات التقنية الصعبة ، فقد أتيحت لي أيضًا الفرصة لتزويد مجموعة من الأشخاص بتجربة ركوب الأمواج شراعيًا أكثر متعة.

1 في البداية ، كنت أستخدم Arduino Uno. في وقت لاحق ، قمت بالتبديل إلى Arduino Mega بسبب الحاجة إلى زيادة ذاكرة الوصول العشوائي وذاكرة فلاش.

ذات صلة: العمل مع عينات الصوت ESP32