حل مشكلة الWiFi للوحة Arduino Giga R1 WiFi

مؤخرًا مع بداية شهر 3 أطلقت شركة Arduino لوحة Arduino Giga R1 حيث أنها تأتي بإمكانيات عالية وتتضمن معها وحدة WiFi مما يجعلها مناسبة لتطبيقات إنترنت الأشياء، ولكن واجهتني إشكالية تحول بيني وبين تفعيل ميزة الWiFi، سنتحدث عنها لاحقًا.

بشكل مختصر لوحة Arduino Giga R1 WiFi، عبارة عن لوحة تطوير مبنية على متحكم دقيق يدعى STM32H747XIH6 ويمتاز هذا المتحكم بسرعة عالية بالإضافة لكونه مبني على معمارية Arm Cortex M7 فيجعله مناسبٌا لمختلف تطبيقات الهندسية المعقدة.

مميزات لوحة Arduino Giga R1 WiFi

  • مبني على المتحكم STM32H747XIH6
    • يحتوى على تعليمات معالجة الإشارات الرقمية
    • يتوفر على وحدة MPU
  • وحدة اتصال الخاصة بالوايفاي والبلوتوث Murata 1DX
  • الذاكرة
    • STM32H747XI
      • 2 ميجا بايت من ذاكرة الفلاش.
      • 1 ميجا بايت من ذاكرة الوصول العشوائي (RAM).
    • AT25SF128A-MHB-T ذاكرة فلاش خارجية
      • 16 ميجا بايت ذاكرة فلاش من نوع NOR.
      • بواجهة تخاطب QUAD SPI.
    • AS4C4M16SA
      • 8 ميجابايت من ذاكرة وصول عشوائي من نوع ديناميكي.
  • وحدات الإدخال و الإخراج
    • 76 مدخل ومخرج رقمي.
    • 12 مدخل تماثلي.
    • 12 منفذ بعرض نبضي متغير.
    • 2 مخارج تماثلية.
    • دعم لبروتوكول USB.
    • جهد التخاطب المنطقي 3.3 فولت.
  • واجهات التخاطب (Communication Protocols)
    • 4x UART
    • 3x I2C
    • 2x SPI
    • Can bus يتطلب وجود مستقبل ومرسل خارجي.
  • USB
    • USB HOST
    • USB Peripheral Type-C
  • منافذ جاهزة للاستخدام بشكل مباشر
    • منفذ الكاميرا.
    • منفذ الشاشة.
    • منفذ صوتيات.
  • التغذية
    • جهد عمل الدائرة 3.3 فولت
    • الجهد المسموح لتغذية اللوحة من 6 إلى 24 فولت.

هذه مميزات اللوحة بشكل مختصر، والآن سنتجه للإشكالية التي واجهتني خلال عملي واختبارها.

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

فكان البرنامج يقف عند هذه النقطة دون تقدم مع وجود إضاءة تحذيرية من اللوحة تبلغ عن وجود خطأ.

No filesystem containing the WiFi firmware was found.
Usually that means that the WiFi firmware has not been installed yet or was overwritten with another firmware.

Formatting the filsystem to install the firmware and certificates...

Error Format Flash: -3101
Flashing /wlan/4343WA1.BIN file
Flashed 0%

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

Available partition schemes:

Partition scheme 1
Partition 1: WiFi firmware and certificates 1MB
Partition 2: OTA and user data 13MB

Partition scheme 2
Partition 1: WiFi firmware and certificates 1MB
Partition 2: OTA 5MB
Partition 3: User data 8MB

Do you want to use partition scheme 1? Y/[n]
If No, partition scheme 2 will be used.

WARNING! Running the sketch all the content of the QSPI flash will be erased.
Do you want to proceed? Y/[n]
Error formatting WiFi partition

فهنا تيقنت جيدًا ربما يكون هناك خلل على صعيد البرمجي أو العتاد، فقررت أن اعمل على بحث عن أصل الإشكالية و وصلت لنتيجة أنه هناك خلل مع ذاكرة الفلاش الخارجية حيث أنه لا تستطيع قراءة البيانات على وضع (Fast Quad Mode I/O) (مستقبلًا سأكتب مقالة مفصلة عن ماهية الQSPI) بشكلها الصحيح، مما دفعني لتطوير مكتبة تحل الإشكالية لحين اصلاحها من طرف شركة الArduino.

حيث أنه تعمل المكتبة على تحميل الملف التشغيلي لأول مرة ومن ثم استخدامها كبديل عن المكتبة الافتراضية.

رابط المكتبة: https://github.com/ahmedalkabir/GigaWiFiSolver

نقوم بتحميل المكتبة من الرابط المرفق مسبقًا، واتباع الخطوات الآتية:

ننقل مجلد المكتبة إلى مسار التالي Document/

نقوم برفع البرنامج كما موضح في الصور.

ومن ثم سيقوم البرنامج بتحميل البرنامج التشغيلي لوحدة الWiFi على ذاكرة الفلاش الخارجية.

بعد الانتهاء من البرنامج لنقوم باختبارالبرنامج WiFi المرفق مع المكتبة.

وكما يبدو واضحًا، وحدة الWiFi تعمل بشكل جيد بدون أي مشكلة، يجدر الملاحظة أنه لكي تعمل وحدة الWiFi بشكل ممتاز يجدر إضافة مكتبة GigaWiFiSolver في بداية السطر حيث ستعمل كبديل عن المكتبة الإفتراضية التي تأتي مع الحزمة.

وهكذا قمت بحل الإشكالية التي واجهتني و قريبًا ستكون هناك سلسلة مقالات حول لوحة الArduino Giga R1 والمشاريع التي سأقوم بها باستخدام هذه اللوحة.

برمجة المتحكمات الدقيقة بلغة الPython

ماذا لو أردت بناء تطبيق إنترنت الأشياء أو أحد التطبيقات التي ترتكز حول المتحكمات الدقيقة ولكن لا تملك دراية كبيرة بلغات الرئيسية لهذا المجال مثل الC و الC++ و الAssembly و غيرها من اللغات، وربما قد تملك دراية بسيطة عن أحد لغات البرمجة مثل الPython، حسنًا مع هذه اللغة أصبح من الممكن القيام بأحد هذه التطبيقات بإستخدام منصة MicroPython وهي نسخة مصغرة عن لغة الPython لكي يتم إستخدامها داخل المتحكمات الدقيقة مثل متحكمات STM32 و ESP8266 و ESP32 وغيرها التي تملك القدرة على إستضافة هذه المنصة نظرًا لإمكانياتها الكبيرة، في هذه المقالة سنتطرق إلى عملية تنصيب الMicroPython على المتحكمات ESP8266 و ESP32 نظرًا لتكلفتهم الرخيصة ووفرتهم (إن كنت من ليبيا يمكننا الحصول عليهم من شركة الأساس لتكنولوجيا في الزاوية أو محل القدرة الرقمية في طرابلس).

حسنًا أيها القارئ ربما أنت على دراية بلغة البرمجة Python أو ربما لا ولكن سأقوم بشرح وجيز وبسيط عن هذه اللغة كتمهيد لموضوعنا حول الMicroPython.

كسائر باقي لغات البرمجة و بإختلافاتها، تعتبر لغة الPython أحد لغات البرمجية عالية المستوى وذو أغراض عامة بمعنى أنها لا تقتصر على نطاق (domain) معين في حل المُعضلات؛ بمعنى أدق يمكن إستخدامه على نطاق واسع سواء لبرمجة تطبيقات الويب أو برمجة تطبيقات السطح المكتب أو كتابة أدوات أتمتة لمدراء النظم و غيرها من التطبيقات، ولا يقف الأمر عند هذا الحد وبل أصبح من الممكن أن يتم برمجة المتحكمات الدقيقة بإستخدام لغة الPython!! (نعم يمكن هذا عن طريق إستخدام بيئة MicroPython وسنتطرق إليها قريبًا في هذه المقالة)؛ بجانب هذا تعتبر لغة الPython لغة مُفسرة (Interpreted) وهذا على عكس لغات التي تنتهج عملية الCompilation والتي يقصد بها عملية تحويل الكود البرمجي إلى لغة الألة بحيث يستطيع جهاز الحاسب فهم هذه التعليمات وأما للغات المُفسرة يتم الإعتماد على عملية تنفيذ العمليات البرمجية سطرًا وراء سطر دون الحاجة إلى عملية الCompilation، هذا مجرد موجز بسيط و سأفترض على القارئ على دراية بسيطة بأحد اللغات البرمجة لكي يفهم المقالة بشكل جيد.

ماهو الMicroPython ؟

يمكننا إعتبارها كنسخة مصغرة عن لغة الPython ومخصصة خصيصًا لعالم النظم المتضمنة أو لنقل لعالم المتحكمات الدقيقة (Micro-controller)، بمعنى أدق هو إعادة توظيف للغة البرمجة الPython ولجعلها متاحة لعالم المتحكمات الدقيقة كالتي توجد داخل أجهزتنا المنزلية مثل الغسالة أو المبرد أو وغيرها، وطبعًا لطبيعة هذه الأجهزة والأنظمة حيث أنها تأتي بموارد قليلة سواء من ناحية ذاكرة الوصول العشوائي (RAM) أو ذاكرة الFlash حيث يرتكز فيها التعليمات الرئيسية ويمكن تشبيها بالقرص الصلب الذي يتواجد داخل جهازك الحاسب؛ فأنها لا تأتي بكامل مميزات اللغة سواء من ناحية المكتبيات القياسية أو كمميزات اللغة، ولكن هذا لا يعنى إفتقاد لكل المكتبيات التي تأتي مع لغة الPython حيث تمت إعادة كتابة بعض المكتبيات لكي تتوافق مع طبيعة هذه البيئة و تعمل بشكل جيد، بجانب هذا تحتوي أيضًا على Virtual Machine حيث ترتكز وظيفتها على تنفيذ تعليمات bytecode ولكن يمكن أيضًا ترجمة بعض التعليمات إلى native عن طريق إستخدام decorator native لكي يكون الكود أسرع ولكن الحجم يزيد نسبيًا عن bytecode، على العموم لن أتطرق في هذا الموضوع حاليًا لكن الملخص يمكن إعتبار الMicropython عن نظام تشغيل مصغر يمكن برمجته بإستخدام لغة الPython.

ربما تعلم عن الArduino أو لا تعلم (مستقبلًا سيكون هناك تدوينات حول هذه البيئة) لكن ببساطة هي عبارة عن منظومة متكاملة (ecosystem – لم أجد ترجمة مناسبة لكن ستفى بالغرض حتى الان) منظومة متكاملة تتكون من لوحات تطوير تعتمد على المتحكمات الدقيقة سواء كان متحكمات Atmega أو Arm و تملك واجهة برمجية خاص بها و فلسفة خاصة بها، والغرض الأساسي من تطوير هذه اللوحات أو من الArduino بصفة عامة كان لتسهيل عملية التعامل مع المتحكمات الدقيقة بصورة بسيطة جدًا و الأمر ينطبق هنا على الMicroPython ولكن بنكهة لغة الPython.

وطالما هي عبارة عن نسخة مصغرة من لغة الPython ولنقل الإصدار 3، (أن كنت لا تزال تستخدم الإصدار 2، الرجاء غادر المدونة وراجع نفسك ) فهي تحتوي على غالب المميزات أن لم تكن كل المميزات مثل :

  • أسلوب برمجة الكائنات-التوجه الخاص بلغة الPython (لكن بدون metaclasses).
  • تتوفر على مختلف الأنواع من البيانات ( مثل unicode strings, integers, and floating-point numbers) وأيضًا تراكيب البيانات (data structures) (مثل lists, sets, and dictionaries).
  • ويجدر الذكر بالطبيعة المتغيرة للObjects التي تتميز بها اللغة.
  • الدوال ككائنات من الدرجة الأولى (أن لم تفهم الأمر، ببساطة يمكننا إعتبار الدوال كمتغير عادي ويمكننا إسنادها وتمريرها مثل أي متغير عادي )
  • معالجة الإستثناءات (Exception handling)
  • ومميزات أخرى مثل يمكن إستخدام الكلمات المفتاحية async و await و الدوال المولدة (gererator functions) التي تعتمد على الكلمة المفتاحية yield و ناهيك عن توفر الميزة التي أفضلها في لغة البايثون list comprehensions، والعديد من الكثير لايسعنا ذكرها.

ولطبيعة إختلاف خصائص الأجهزة واللوحات التي تعمل على MicroPython سيكون هناك إختلاف في الوحدات التي تأتي مع MicroPython، على سبيل المثال في اللوحات التي تعتمد على ESP8266 أو ESP32 ستتوفر على مزايا تقنية الWifi والوحدات التي تعتمد على الإنترنت مثل urequest أو ujson (يجعلها مناسبة بشكل ممتاز لتطبيقات إنترنت الإشياء – IOT)، بينما غيرها مثل PyBoard أو MicroBit لا تأتي بمثل هذه الإمكانيات.

لماذا لغة الPython ؟

ربما يطرح أحد هذا السؤال أو لا يطرح، لكن لنسأل أنفسنا لما لغة الPython، بسبب سهولتها وبساطتها في تصميم وتطوير النماذج الأولية للمشاريع النظم المتضمنة ومشاريع إنترنت الأشياء في وقت قصير وهذا يجعلها بديل أفضل عن لغة الC التقليدية أو واجهة الArduino رغم أنه أيضًا أتت لكي تقوم بتسهيل عملية تطوير النماذج، فلغة البايثون أو لنقل الMicroPython هو بديل جيد لخوض تجربة حول المتحكمات الدقيقة واللوحات التطوير وتطوير نماذج تفاعلية أو مشاريع إنترنت الإشياء – IOT حيث أن أسلفت في ذكر مميزاتها سابقًا و على سياق أخر تمتلك مجتمع كبير ومما يعنى عدد كبير من المكتبيات التي تساعد على تطوير المشاريع في وقت وجيز.

ولغة الPython سهلة التعلم ومن الممكن للفرد أن يبدأ البرمجة عن طريقها أو يتعلم البرمجة و النظم المتضمنة على كل حد سواء وهذا نظرًا لي ماتوفره MicroPython من سهولة التعامل معاها حيث تأتي محملة بREPL إختصار إلى Read Evaluate Print Loop وهي بيئة تفاعلية كالتي تأتي بها لغة Python، فمنها يمكننا إختبار وتجربة الأوامر بسطر من أومر مباشرة دون الحاجة إلى كتابة ورفع الكود كما هو متعارف عليه عند أستخدام لوحات الأردوينو، كل ماعليك فعله ربط لوحة محملة بالMicroPython بجهازك الحاسب و إختبار الكود، ومن هذا السياق نفهم أنه الكود يتم تحويله إلى bytecode و أيضًا تتيح MicroPython على القدرة تحويل الكود إلى الmachine code إلى جانب توفرها على Inline Assembler بمعنى مبسط توفر بيئة MicroPython على قدرة للوصول لتعليمات المتحكم كما لو كانت لغة منخفضة المستوى وهذا يجعلها من الممكن تطوير تطبيقات بكفاءة عالية.

ولبدأ العمل على الMicroPython كل مايتطلبه منك هو لغة الPython لا غير وفي أن ذاته يمكنك تعلم الإلكترونيات عن طريق بناء مشاريع بإستخدام هذه المنصة.

أول مشروع بالMicroPython

لبدء بإستخدام الMicroPython تحتاج إلى أحد اللوحات الموضحة في الصور الأتية ويمكن الحصول عليها من داخل ليبيا أو شراءها من الخارج.

  • لوحة NodeMCU المبنية على متحكم ESP8266
NodeMCU V3
  • أو لوحة NodeMCU المبنية على متحكم ESP32
NodeMCU ESP32

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

الخطوة الأخرى والمهمة وهي أن تتأكد من وجود بايثون على جهازك الحاسب وتأكد بأن تملك أحدث إصدار من لغة، ولحد ساعة إصدار 3.8 هو أحدث إصدار ويمكن تحميله من هذا الرابط https://www.python.org/downloads/

ولإستخدام بيئة الMicroPython سنبتعد عن أي تعقيد ممكن فهذه المقالة وسنستخدم برنامج uPyCraft وهو مشابه لوظيفة Arduino IDE من ناحية المفهوم و الوظيفة ومنه يمكننا التعامل ورفع برامج المكتوبة بالPython لأحد اللوحات سواء NodeMCU أو غيرها. يمكنك تحميله من هذا الرابط هنا

واجهة البرنامج

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

كيف يمكن التفريق النسخ، أغلب NodeMCU المبنية على ESP32 تأتي محملة بشريحة cp210x والتي مبنية على ESP8266 تختلف ويمكن تميزها من الصورتين.

ماوظيفة كل من CH340 و CP210X ببساطة هما عبارة عن USB to Serial يعملون كحلقة أو جسر تواصل بين ESP8266 أو ESP32 وجهازك الحاسب حيث كل من المتحكمين لا يأتين بدعم مضمن للUSB في الوقت الحالي واحد من إحد منتجات Espressif وهو ESP32-S2 يأتي بدعم لUSB OTG، على العموم هذا ليس موضوعنا حاليًا لكن مجرد معلومات للفائدة.

كل من المتحكمين لا يأتين بدعم MicroPython مسبقًا وعلى أثر هذا سنقوم بتحميل الFirmware من موقع الرسمي لكل من نسختين ESP8266 و ESP32، سأقوم بتوفير الروابط مباشرة لتسهيل العملية.

لنقم بتوصيل لوحة الNodeMCU ولنتأكد من وجود أحد المنافذ أو تعريف هذه اللوحات على جهازنا عن طريق الذهاب إلى Computer Management ثم إلى Device Manager.

من الصورة نرى ان اللوحة تم التعرف عليها من قبل جهازنا الحاسب وجاهزة للإستخدام، الان لنبدا بحرق الفيرموير على اللوحة عن طريق الخطوات الأتية

لنقم بإختيار اللوحة و الملف والمنفذ ومن ثم نضغط على OK، وستظهر لنا النافذة التالية

عليك الإنتظار حتى تتم العملية، ولنقم الان بربط الuPyCraft بالمتحكم وقبل هذا عليك التأكد من الخيارات الأتية كما هي موضحة في الصور.

في حالتي سأختار esp8266

والان لنقم بالإتصال باللوحة، عند نجاح الاتصال سيظهر لك ثلاث مؤشرات وهي خاص بالREPL والتي من خلالها يمكننا كتابة التعليمات باللغة الPython.

سأقوم بكتابة أول جملة شهيرة وهي طباعة كلمتين Hello, World

بينقو، الأمر يعمل جيدًا كما هو موضح.

من خلال الREPL يمكننا القيام الكثير بالعديد من الأمور سواء من عمليات حسابية مختلفة أو إستدعاء مكتبيات و غيرها الكثير من الأمور، حسنًا سأقوم بكتابة مشروع بسيط وهو مشروع blink وهو عبارة عن إضاءة LED وإطفاءه كل ثانية ورفعه على اللوحة.

قبل البدء في المشروع علينا نفهم كيف يعمل الMicroPython داخل المتحكم، عند تغذية المتحكم أول مايقوم به الMicroPython تجهيز الruntime ومن ثم يبدأ البحث عن أول ملفين وهما boot.py و main.py، يبدا بتنفيذ boot ثم ينتقل إلى main وفي حال عدم وجوده يتجاوزه ولا يقوم بتنفيذ أي شئ.

كما ترى من مجلد device على يسار البرنامج وهو يعكس المحتويات التي توجد داخل المتحكم وحاليًا يتوفر على boot.py ويحبذ تركه كما هو الان.

الان لنقم بإنشاء ملف جديد ولنقم بتسميته main.py من خلال البرنامج، ومن ثم نقم بكتابة الكود الاتي

from machine import Pin
import time

# D8 = GPIO15
p2 = Pin(15, Pin.OUT)

if __name__ == "__main__":
  
  while True:
    # led is high
    p2.on()
    # delay for 1 second
    time.sleep_ms(1000)
    # led is low
    p2.off()
    # delay for 1 second
    time.sleep_ms(1000)

كما هو ملاحظ الكود يبدو بسيط وواضحًا ربما للبعض والبعض لا، سأقوم بشرحه على كل حدة لهذا الكود فقط كتوضيح.

قمت بتضمين كلاس Pin من الوحدة machine وهذه مسؤولة عن عمليات المنخفضة المستوى لمنافذ المتحكم أو اللوحة حيث سنقوم بتحكم بإضاءة الLED من ناحية تشغيلها أو إطفاءها، وأما بالنسبة إلى time فهي تحتوي على بعض الدوال المهمة ومن ضمنها الدوال التأخير حيث سنقوم بتأخير أو بعمل block لمشروع لفترة من زمن (يستحسن عدم إستخدامها كثيرًا وإستخدام الtimers التي تأتي متضمنة مع الmicropython).

from machine import Pin
import time

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

# D8 = GPIO15
p2 = Pin(15, Pin.OUT)

سيدخل الكود إلى حلقة مالانهائية حيث ستقوم بعملية تشغيل وإطفاء الLED بإستمرار دون توقف، هذا مجرد مثال بسيط وتوضيحي لألية عملية برمجة اللوحات التي تستخدم الMicroPython.

if __name__ == "__main__":
  
  while True:
    # led is high
    p2.on()
    # delay for 1 second
    time.sleep_ms(1000)
    # led is low
    p2.off()
    # delay for 1 second
    time.sleep_ms(1000)

بعد ما قمنا بإنشاء ملف main.py و كتابة الكود، لنقم بتحميل الكود على اللوحة وتنفيذه عن طريق الخطوات الأتية

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