يعرفُ برنامجُ Flutter بأنَّهُ مجموعةُ أدواتٍ مفتوحةُ المصدرِ لتطويرِ البرامجِ ذاتُ واجهةِ المستخدمِ التي تسهّلُ البدءَ في إنشاءِ تطبيقاتِ الأجهزةِ المحمولةِ العاملةِ بنظامي iOS وأندرويد، والأردوينو منصةً لتطويرِ برمجياتِ المتحكماتِ التي تسمحُ بإنشاءِ تطبيقاتٍ مدمجةٍ لمجموعةٍ متنوعةٍ من المتحكماتِ الصغريةِ، وباستخدامِ هاتين الأداتين معاً يسهلُ إنشاء أجهزةٍ يمكنُ التحكمُ بها باستخدامِ تطبيقاتِ الأجهزةِ المحمولةِ.كتمرين، سنستخدمُ بعض العناصرِ الالكترونيةِ الرخيصةِ والأردوينو وFlutter لصنعِ الجهاز والتطبيق اللازمين للتحكمِ بالأجهزةِ التي يتم التحكمُ فيها عن بُعد بالأشعة تحت الحمراء مثل أجهزةِ التلفزيون ومكيفاتِ الهواءِ والمدافئ وأجهزةِ الستيريو.
المعداتُ اللازمةُ لإكمال المشروعِ هي: لوحُ تطوير NodeMCU esp8266، وليد يصدرُ أشعةً تحت حمراء، وجهازُ استقبالٍ يعملُ بالأشعةِ تحتَ الحمراء بتردد 38 كيلو هرتز، وترانزستور 2n3904 PNP.
تكوين بيئة التطوير المتكاملة للأردوينو (Arduino IDE)
نحتاجُ في البداية إلى برمجةِ وحدةِ NodeMCU.
تشغيل خادم بروتوكول التحكم في الإرسال (TCP) على اللوحة esp8266
كخطوةٍ أولى، نشغلُ خادمَ TCP ونختبرُ ما إذا كان يعمل.
- نقوم بإنشاء كائن WiFiServer باسم wifiServer.
- نعرف مؤشراً محرفياً ثابتاً ليحمل اسم الشبكة اللاسلكية (SSID) وكلمة المرور.
- نكتب التعليمات التالية في تابع ()setup:
- إنشاء الاتصالِ التسلسلي بسرعة 115200 بت في الثانية.
- الانتظار لمدةِ ثانيةٍ للتأكد من اكتمالِ تهيئة الاتصال التسلسلي.
- البدء بتهيئة اتصال شبكة WiFi.
- الانتظار حتى يتم الاتصال بالشبكة.
- تشغيلُ الخادم.
ثم ننتقل إلى التابع ()loop.
وظيفته التعامل مع عميل متصل بالخادم ولديه بيانات متاحة للقراءة.
- يمكنك تنفيذ الحلقة طالما أن العميل مُتصل.
- بما أنَّ بيانات العميل متوفرة، يمكنك قراءة البيانات وطباعتها على المنفذ التسلسلي.
الآن نقوم بتجميع ورفعِ الكود إلى ذاكرةِ لوحةِ NodeMCU.
بعد رفعِ البرنامج، نفتحُ شاشةَ المنفذ التسلسلي (بالضغط على Ctrl + Shift + M في الحواسيب العاملة على نظام ويندوز) إذا لم يظهر لدينا الموجود في الشكل التالي على الشاشة، فنحاول فصل كابل USB وتوصيله مرةً أخرى ثمَّ نفتح شاشة المنفذ بسرعة.
الآن، بعد أن أصبحَ لدينا خادم TCP بسيط نَشِط، نختبرهُ باستخدام برنامج PuTTY، حيث نقوم بتكوين اتصالٍ باستخدامِ عنوان IP، في الشاشة التسلسلية والمنفذ 80 ونوع الاتصال (Raw).
كل ما يتم كتابته في موجِّه الأوامر يجب أن يُكرَر تلقائياً على شاشة المنفذ التسلسلي.
إذاً بتوفر أجهزةٍ تعملُ بشكلٍ جيدٍ في الشّق الأول من المشروع يمكننا الانتقال إلى الشّق الذي سنستخدمُ فيه أدواتُ Flutter.
إنشاء واجهة بسيطة في Flutter
بدايةً نُغلِقُ برنامج PuTTY، لأنَّ الخادم الذي يعملُ على NodeMCU يمكنه فقط التعامل مع اتصالٍ واحدٍ فقط. الخطوة التالية هي أن نقوم بفتح برنامج Android Studio ونُنشِئ مشروع Flutter جديداً باستخدام الخيارات الافتراضية.
في الدرجةِ MyHomePageState نحذفُ عناصرَ أدواتِ الواجهةِ النصيَّة من المتن.
ونحذف الزر العائم، ولكن قبل القيام بذلك ننتبه للطريقة التي يتصرف بها عند الضغط عليه (onPressed) ودالة incrementCounter المخصصة له.
الآن على متنِ الدرجةِ MyHomePageState نقوم بإضافة زر من النوع RasiedButton، سنلاحظ أن الزر يحتوي على عنصر واجهة نصيّ بنيوي مُضمناً فيه. إنَّ العديد من أدوات واجهة المستخدم في Flutter مصنوعة من أدوات واجهة بدائيّة متعدِّدة.
في هذه المرحلة سنتمكن من تشغيل التطبيق.
اللون الرَّمادي للزر يشير إلى أنه غير فعّال لأنّنا لم نقم بتحديد وظيفته عندما ضغطنا عليه حيث سنقوم بذلك فيما بعد.
إنّنا جاهزون الآن للانتقال إلى مرحلةِ إرسال الأمر عبر TCP إلى NodeMCU عند الضغط على الزر.
الخطوة التالية هي تضمين مكتبتين من الـ Flutter هما foundation.dart و dart.io.
ونعيد كتابة التابع الرئيسي كما هو موضح في الشكل التالي
في الكود الموجود في الصورة السابقة، يجب أن يكون عنوان الـ IP الموجود في دالة Socket.connect هو نفسه العنوان المنسوخ سابقاً من شاشة المنفذ التسلسلي عندما كنا نختبر خادم الاتصال.
نضيف كائناً ودالة بناء من النوع Socket إلى الدرجة MyApp كما هو موضح في الصورة التالية.
إلى الأسفل قليلاً من عبارة return من أداة Build، نضيف بارامتر channel ونسند إليه القيمة socket في عنصر MyHomePage.
في الدرجة MyHomePage نضيف حقل channel من نوع Socket.
في الدرجة MyHomePageState نضيف التابع togglePower_، ويمكننا حذف المتغير counter_ وتابع ()incrementCounter_ منها.
نتجاوز التابع ()dispose في الدرجة MyHomePageState ونغلق القناة عندما يكون كائن الحالة مغلقاً.
لنعُدْ الآن ونعين القيمة “OnPressed” لدالة togglePower عند الضغط على الزر ،وسيتم إرسال القيمة “POWER\n” إلى وحدة NodeMCU عند الضغط على زر الطاقة.
نقوم بتشغيل التطبيق ، وفي حال عدم وجود أية أخطاء سنكون مستعدين لاختبار التطبيق مع لوح NodeMCU.
اختبار اتصال الأندرويد وخادم NodeMCU TCP
أولاً، نعيد توصيل لوح NodeMCU ببرنامج الأندرويد الذي قمنا بإنشاءه مسبقاً والذي تم رفعه إليه.
نفتح شاشة المنفذ التسلسلي، ثم نشغل تطبيق flutter الذي كنا نعمل عليه ونضغط زر التشغيل، سنرى النص “POWER\n” يظهر تلقائياً على شاشة المنفذ التسلسلي كما في الشكل.
تدريب جهاز التحكم عن بعد
بعد التحقق من التواصل بين تطبيق الجوال ولوح NodeMCU، يمكننا الانتقال تواً للعمل على الاتصال بين لوح NodeMCU والأجهزة باستخدام بروتوكولات التحكم عن بعد بالأشعة تحت الحمراء.
لحسن الحظ، فإن مكتبة IRremoteESP8266 توفر علينا الكثير من الجهد والمشقة، وهي متوفرة على هذا الرابط هنا.
بمجرد تثبيت المكتبة، ننتقل إلى File > Examples>IRremoteESP8266>IRrecvDumpV2 ونفتح هذا الرسم التخطيطي.
قبل البدء بفعل أي شيء آخر، نحتاج إلى توصيل مستقبل الأشعة تحت الحمراء إلى لوح NodeMCU، ثم سنحتاج إلى تحديد الطرف الخاص بمستقبل الأشعة تحت الحمراء؛ تم توضيح طرف التوصيل الخاص في الشكل التالي، وهو شكل نموذجي لهذه المستقبلات.
نقوم بتوصيل الطرف Serial بالطرف رقم 14 للوح NodeMCU D5، والطرف الموجب إلى الطرف 3.3 فولت والأرضي بالطرف GND.
يُمكِنُنا مخطط IRrecvDumpV2 من التقاط أوامر الأشعة تحت الحمراء المرسلة بواسطة جهاز التحكم عن بُعد أو تلكَ التي تتحكم بأجهزتنا المستهدفة. نبدأ بتحميل مخطط IRrecvDumpV2 على NodeMCU ونفتح شاشة المنفذ التسلسلي، ثمَّ نقوم بعد ذلك بتوجيه جهاز التحكم عن بعد إلى مستقبل الأشعة تحت الحمراء ونضغط على زر التشغيل عدة مرات؛ الخرج الناتج في الشكل التالي بواسطة جهاز تحكم عن بعد من شركة Haier AC.
نحدّد عدة أسطر من النّص مع التأكد من التقاط البيانات الخام و ننسخها إلى الحافظة بالضغط على Ctrl + C على نظام ويندوز، ثم نفتح أي محرّر نصوص ونلصقها بداخله. تم تنسيق البيانات بحيث تبقى ضمن إطار الشاشة.
نفتح مجدداً مخطط الأردوينو و الذي أنشأناه سابقًا لاختبار اتصالات TCP، ومن ثمَّ نضيف ثابتاً لتحديد الطرف الذي سنستخدمه لنقل أوامر التحكم عن بُعد.
const uint16_t kIrLed = 4
و سوف نستخدم هذا الثابت عند تنفيذ الأمر IRsend.
IRsend irsend(kIrLed)
نقوم بلصق البيانات الخام التي نسخناها سابقاً، مع ضرورة الانتباه بشكل خاص لعدد عناصر المصفوفة وهو 71 كما في الشكل 29.
نسمي المصفوفة HaierAC_power ونتأكد من أن نوع المصفوفة هو uint16_t (عدد صحيح بدون إشارة بطول 16 بت).
uint16_t HaierAC_power[71] ={8928, 4556, …
نجري تغييراً واحداً فقط إلى السطر الأول في التابع ()setup و قبل تعليمه Serial.begin(115200) وهو: ()irsend.begin
قمنا سابقاً في تابع الحلقة بنسخ الدخل وطباعته على شاشة المنفذ التسلسلي.
نحتاج إلى تعديل وظيفة الحلقة بحيث تقوم بتجميع الحروف المستلمة حتى تصل إلى حرف فصل (في حالتنا هو محرف السطر الجديد)، ثم تتحقق من كون الكلمة الناتجة أمراً نحتاج إلى تنفيذه.
نقوم بتحميل الكود الأخير إلى لوح NodeMCU ثم نفتح تطبيق flutter، وعندها يجب أن نكون قد حصلنا على تطبيق صالح للاستعمال للتحكم عن بعد.
الكود البرمجي: للتحميل من هنا
فيديو التطبيق العملي للمشروع
المصدر: هنا
ترجمة: إيليا سليمان، مراجعة: لؤي ديب، تدقيق لغوي: بولا ابراهيم، تصميم: علي العلي، تحرير: محمد نور البوشي.