للطلاب والخريجين الأدلة التقنية

أفكار مشاريع تخرج في هندسة الحاسب Embedded Systems

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

أفكار مشاريع تخرج في هندسة الحاسب Embedded Systems

في آخر محاضرة من مادة مقدمة مشروع التخرج يقول لكم المشرف جملة واحدة: «الأسبوع القادم أريد من كل فريق ثلاث أفكار مكتوبة، لكل فكرة صفحة: المشكلة، والعتاد Hardware الذي ستستخدمونه، وكيف ستقيسون النجاح». فتجلسون أربعة في المكتبة، ويقترح أحدكم نظام حضور ببصمة الإصبع، ويقترح الثاني بيتاً ذكياً تفتح أنواره من الجوال، ويقترح الثالث روبوتاً يتبع الخط، ثم يقول الرابع ما يعرفه الجميع: هذه الأفكار نفسها قدمها الفريق الذي قبلنا والذي قبله. وطالب هندسة الحاسب Computer Engineering عنده مشكلة إضافية لا يعرفها زميله في علوم الحاسب، فالفكرة عنده ليست كوداً فقط، وإنما لوحة ستشتريها وحساسات قد تصل بعد أسابيع وقياسات يجب أن تأخذها بيدك، وإذا اخترت فكرة لا تناسب ميزانية الفريق أو وقته فسوف تكتشف ذلك في منتصف الفصل الثاني، أي بعد أن يفوت وقت التغيير.

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

وسوف نناقش في هذا المقال ما يلي:

  • ما الذي يجعل مشروع هندسة الحاسب مختلفاً عن مشروع برمجي، ولماذا تحسب حساب العتاد من اليوم الأول.
  • الفرق بين مشروع التصميم Capstone في البكالوريوس والسؤال البحثي Research Question في الماجستير.
  • طبقات النظام المدمج من الحساس Sensor إلى لوحة العرض Dashboard، وأين تقع كل فكرة.
  • ثماني أفكار للبكالوريوس: عداد الطاقة الذكي، والري، وجودة الهواء، وعد الحشود دون تصوير، وشبكة CAN، ومعالج RISC-V على FPGA، واللوحات العربية منخفضة الطاقة، والمساهمة في Zephyr.
  • ست أفكار للماجستير: الجدولة في أنظمة الزمن الحقيقي RTOS، والمسرعات العتادية، والتعلم الآلي الصغير TinyML لكشف الأعطال، وحصاد الطاقة، وتحمل الأخطاء العتادية، ودقة المحاكيات.
  • الأفكار المستهلكة التي مل منها المشرفون، وكيف تحول واحدة منها إلى مشروع حقيقي.
  • جدول مقارنة لكل الأفكار.
  • تجربة عملية Lab: برنامج ثابت Firmware لعداد طاقة على معالج Cortex-M3 داخل المحاكي QEMU، ببيانات استهلاك حقيقية، وخطأ حقيقي ظهر في التشغيل الأول، وماذا يحدث إذا استخدمنا الأعداد العشرية بدل الصحيحة.
  • من المحاكاة إلى اللوحة الحقيقية، وأخطاء شائعة، وقائمة تحقق Checklist.

لماذا يختلف مشروع هندسة الحاسب Computer Engineering عن مشروع برمجي؟

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

والفرق الثاني هو القياس Measurement. فمنهج CE2016 يطلب من خريج هندسة الحاسب أن يستخدم أدوات المختبر والحاسب في التحليل والتصميم، ولجنة المناقشة في قسم هندسة الحاسب لا تسألك «هل يعمل النظام؟» فقط، وإنما تسألك «كم يستهلك من الطاقة؟ وما زمن الاستجابة Latency؟ وما نسبة الخطأ مقارنة بجهاز مرجعي؟». والمشروع الذي يعمل أمام اللجنة دون أرقام يبقى نموذجاً للعرض Demo، أما المشروع الذي يأتي ومعه جدول قياسات بظروف مختلفة فهو مشروع هندسي. ولاحظ أن القياس لا يحتاج أجهزة غالية دائماً، فمقياس متعدد Multimeter جيد ومحلل منطقي Logic Analyzer رخيص مع برنامج مفتوح المصدر مثل sigrok يكفيان أغلب مشاريع البكالوريوس.

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

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

البكالوريوس أم الماجستير: مشروع التصميم Capstone أم السؤال البحثي Research Question؟

قبل أن تقرأ الأفكار يجب أن تعرف أي نوع من المشاريع يطلب منك، لأن نفس الموضوع يمكن أن يكون مشروع بكالوريوس جيداً ورسالة ماجستير ضعيفة، والعكس. فمشروع البكالوريوس في أغلب الأقسام عمل فريق من ثلاثة إلى خمسة طلاب على مدى فصلين، الأول للتحليل والتصميم والنموذج الأولي Prototype، والثاني للبناء الكامل والاختبار والتقرير والمناقشة، والمطلوب فيه أن تبني نظاماً يحل مشكلة حقيقية ضمن قيود واضحة، ثم تقيس هل حلها فعلاً. وهذا ما يسميه منهج CE2016 ومعايير ABET تجربة تصميم كبرى Major Design Experience، أي أن اللجنة تقيم قرارات التصميم والمقايضات Trade-offs بين الكلفة والطاقة والدقة أكثر مما تقيم الجدة العلمية.

أما رسالة الماجستير فعمل فرد واحد غالباً، والسؤال فيها ليس «هل نستطيع بناءه؟»، وإنما «ما الذي لا نعرفه بعد، وكيف سأقيسه؟». لذلك تبدأ من سؤال بحثي محدد، ثم مراجعة الأعمال السابقة Related Work لتعرف ما قام به غيرك، ثم مساهمة جديدة Novelty ولو كانت صغيرة، ثم تقييم قابل للقياس والتكرار بمعايير معروفة Benchmarks، وقد شرحنا في كيف تجد الفجوة البحثية في الأدبيات طريقة الوصول إلى هذا السؤال. ولاحظ أن العتاد في الماجستير وسيلة وليس هدفاً، فاللوحة التي تبني عليها هي المختبر الذي تجيب فيه عن السؤال، ولذلك تجد أن أفكار الماجستير في هذا المقال أقرب إلى المعمارية والجدولة والطاقة منها إلى المنتجات.

الصورة التالية تبين الفرق بين الشكلين على نفس الموضوع، وهو عداد الطاقة الذي سوف نجربه في نهاية المقال:

لوحة من عمودين: عمود البكالوريوس فيه فريق من ثلاثة إلى خمسة طلاب وفصلان دراسيان ومراحل التحليل والنموذج الأولي والبناء والقياس والمناقشة لعداد طاقة ذكي على ESP32، وعمود الماجستير فيه باحث واحد وسؤال بحثي عن دقة الأعداد الصحيحة مقابل العشرية على متحكمات مختلفة ومراجعة الأعمال السابقة والمساهمة والتقييم بمعايير قياس
نفس الموضوع في المستويين: البكالوريوس يبني ويقيس، والماجستير يسأل ويقيس ما لم يقسه أحد

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

أين يقع مشروعك في طبقات النظام المدمج Embedded Stack؟

أغلب مشاريع هندسة الحاسب، مهما اختلفت مواضيعها، تمر بنفس الطبقات: حساس يقيس شيئاً من العالم الحقيقي مثل التيار أو الرطوبة أو الحركة، ثم متحكم دقيق Microcontroller يقرأ الحساس ويعالج القراءة ببرنامج ثابت Firmware، ثم وسيلة اتصال مثل Wi-Fi أو LoRaWAN أو ناقل CAN Bus، ثم بوابة Gateway تجمع القراءات، وغالباً تكون حاسباً صغيراً مثل Raspberry Pi، ثم خادم يخزنها ولوحة عرض يراها المستخدم. وفي بعض المشاريع تنزل إلى طبقة أعمق من المتحكم نفسه، فتصمم المعالج أو جزءاً منه على شريحة FPGA، وهي شريحة منطق قابلة لإعادة البرمجة تصف دوائرها بلغة وصف العتاد HDL مثل Verilog، وقد شرحنا أساس هذه الدوائر في البوابات المنطقية Logic Gates.

رسم لطبقات النظام المدمج من الأسفل إلى الأعلى: الحساسات مثل محول التيار ورطوبة التربة وحساس الغبار، ثم المتحكم الدقيق ESP32 أو Cortex-M مع البرنامج الثابت، ثم الاتصال Wi-Fi وLoRaWAN وCAN، ثم البوابة Raspberry Pi، ثم الخادم ولوحة العرض، وفي الأسفل طبقة FPGA للمعالج والمسرع، وعلى كل طبقة أرقام أفكار المقال التي تتركز فيها
الطبقات التي تمر بها أغلب مشاريع هندسة الحاسب، وأين يتركز ثقل كل فكرة

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

وأشهر لوحتين ستراهما في هذه الطبقات هما ESP32 من Espressif، وهي متحكم دقيق فيه Wi-Fi وBluetooth بسعر منخفض ويبرمج بأداة ESP-IDF الرسمية أو ببيئة Arduino، وRaspberry Pi، وهو حاسب كامل يعمل عليه Linux ويصلح بوابة أو حاسباً للرؤية الحاسوبية، والفرق بينهما جوهري: ESP32 يبدأ في أجزاء من الثانية ويعمل بالبطارية شهوراً إذا نام معظم الوقت، أما Raspberry Pi فيحتاج نظام تشغيل ومصدر طاقة ثابتاً، ولذلك لا تضع Raspberry Pi في مكان يكفيه متحكم دقيق.

لوحة تطوير ESP32 سوداء عليها وحدة ESP-WROOM-32 المعدنية في طرفها وهوائي مطبوع ومنفذ USB ودبابيس على الجانبين
لوحة تطوير ESP32 بوحدة ESP-WROOM-32، وهي أكثر لوحة تراها في مشاريع إنترنت الأشياء IoT لأنها تجمع المتحكم والاتصال اللاسلكي في قطعة واحدة. الصورة: Ubahnverleih، رخصة CC0، المصدر: Wikimedia Commons (تم تحويلها إلى WebP).
لوحة Raspberry Pi 4 Model B خضراء من الأعلى عليها المعالج تحت غطاء معدني ومنافذ USB وEthernet ومنفذا HDMI صغيران وصف دبابيس GPIO على الحافة
Raspberry Pi 4 Model B، حاسب صغير يعمل عليه Linux، ويناسب دور البوابة التي تجمع قراءات المتحكمات وترسلها إلى الخادم. الصورة: Laserlicht، رخصة CC BY-SA 4.0، المصدر: Wikimedia Commons (تم تحويلها إلى WebP).

كيف تقرأ بطاقة الفكرة Idea Card؟

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

  • المشكلة Problem: ما الذي لا يعمل اليوم، ولمن، بكلام يفهمه شخص خارج القسم.
  • المستفيد User: من سيستخدم النظام فعلاً، لأن «المجتمع» ليس مستخدماً، أما «مشرف صيانة مبنى جامعي» فمستخدم.
  • النطاق Scope: ما الذي يستطيع فريق من ثلاثة إلى خمسة طلاب أن ينجزه في فصلين، وما الذي يجب أن يبقى خارج المشروع.
  • الأدوات Stack: العتاد والبرمجيات المقترحة، مع بديل أرخص إذا وجد.
  • البيانات Data: مصادر حقيقية مفتوحة تبدأ بها قبل أن يصل العتاد، وقد فتحنا كل رابط منها قبل النشر.
  • التقييم Evaluation: كيف تثبت للجنة أن النظام يحل المشكلة، بأرقام وظروف تجربة.
  • الصعوبة Difficulty: من متوسط إلى عال جداً، بحسب العتاد والمعرفة المطلوبة.
  • الخطر Risk: الشيء الذي إذا حدث توقف المشروع، وكيف تتجنبه من البداية.
  • التميز Stand Out: الإضافة التي تجعل لجنة المناقشة تتذكر مشروعك بعد أن ترى عشرين مشروعاً.

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

أفكار مشاريع البكالوريوس Bachelor Projects

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

1. عداد طاقة ذكي Smart Energy Meter يقيس ويفسر الاستهلاك

Project title: Smart Energy Meter with Consumption Analysis

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

  • المستفيد User: مشرف صيانة مبنى في الجامعة أو مدرسة أو مسجد، وصاحب البيت الذي يريد أن يفهم فاتورته، وهي مشكلة يهتم بها المركز السعودي لكفاءة الطاقة على مستوى المملكة.
  • النطاق Scope: دائرة واحدة أو لوحة واحدة، وقياس أحادي الطور Single Phase فقط، وتقرير يومي وأسبوعي، ولا يدخل في النطاق التحكم في الأجهزة أو فصلها.
  • الأدوات Stack: ESP32 مع محول تيار Current Transformer من النوع الذي يلتف حول السلك، ومحول جهد صغير منفصل عن الكهرباء AC-AC Adapter، ومكتبة EmonLib مرجعاً للحساب، وMQTT إلى Mosquitto على Raspberry Pi.
  • البيانات Data: مجموعة Individual Household Electric Power Consumption في UCI، وفيها أكثر من مليوني قراءة بالدقيقة لبيت واحد على مدى أربع سنوات تقريباً، وسوف نستخدمها في التجربة العملية.
  • التقييم Evaluation: نسبة الخطأ في الطاقة مقارنة بعداد تجاري معروف الدقة على عدة أجهزة: سخان مقاوم، ومكيف فيه محرك، وشاحن جوال، والسبب أن معامل القدرة يختلف بينها، وجدول بالخطأ عند كل جهاز.
  • الصعوبة Difficulty: متوسطة إلى عالية.
  • الخطر Risk: كهرباء المنزل خطرة، فلا تقم بفتح أي موصل أو توصيل الحساس مباشرة بالخط، واستخدم محول التيار الملتف ومحول الجهد المنفصل كما يشرح دليل OpenEnergyMonitor، واطلب من المختبر أو كهربائي مختص أن يركب العداد.
  • التميز Stand Out: برنامج ثابت يحسب بالأعداد الصحيحة Fixed-Point بدل العشرية، مع جدول يثبت أن الدقة لم تتأثر، وكشف تلقائي للقراءات المفقودة، وهذا بالضبط ما سنجربه في المختبر.

2. نظام ري بالتنقيط Drip Irrigation يقرر بالرطوبة والطقس

Project title: Smart Drip Irrigation Using Soil Moisture and Weather Data

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

  • المستفيد User: مشرف حديقة الجامعة أو مدرسة، ومزارع صغير عنده بيت محمي.
  • النطاق Scope: ثلاث إلى خمس عقد Nodes للحساسات، وصمام واحد أو اثنان، وقاعدة قرار واضحة، ولا يدخل في النطاق التسميد أو التحكم في مضخة كبيرة.
  • الأدوات Stack: ESP32 أو متحكم منخفض الطاقة مع وحدة LoRa، وشبكة LoRaWAN عبر The Things Network أو بوابة خاصة، وحساسات رطوبة سعوية Capacitive، وصمام كهربائي يعمل على 12 فولت.
  • البيانات Data: واجهة NASA POWER للإشعاع الشمسي والحرارة لأي إحداثيات، وOpen-Meteo للتوقعات بالساعة.
  • التقييم Evaluation: تجربة مقارنة على أحواض متطابقة لعدة أسابيع، حوض بالمؤقت وحوض بالنظام، وقياس كمية الماء بعداد مياه صغير، وحالة النبات بمقياس بسيط متفق عليه مع المشرف.
  • الصعوبة Difficulty: متوسطة.
  • الخطر Risk: الحساسات المقاومة الرخيصة تتآكل في التربة، فتعطيك قراءات تنحرف ببطء ولا تنتبه لها، لذلك استخدم الحساسات السعوية، وابدأ التجربة مبكراً لأن النبات لا ينمو بسرعة الفصل الدراسي.
  • التميز Stand Out: منحنى معايرة Calibration Curve لكل حساس مقابل وزن عينة تربة جافة ورطبة، وحساب الماء الموفر بالأرقام.

3. محطة جودة الهواء Air Quality بحساسات منخفضة التكلفة

Project title: Low-Cost Air Quality Monitoring Station

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

  • المستفيد User: إدارة مدرسة أو حرم جامعي، ومرضى الربو وأهاليهم.
  • النطاق Scope: ثلاث محطات في مواقع مختلفة، ولوحة عرض، ومعايرة مقابل مرجع، ولا يدخل في النطاق قياس الغازات مثل الأوزون، لأن حساساتها الرخيصة أصعب في المعايرة.
  • الأدوات Stack: ESP32 مع حساس جسيمات بالليزر من الأنواع المنتشرة، وحساس حرارة ورطوبة، وصندوق يحمي من الشمس ويسمح بمرور الهواء، وخادم بقاعدة بيانات زمنية.
  • البيانات Data: منصة OpenAQ تجمع قراءات محطات الرصد حول العالم، وتسمح لك بمقارنة قراءات محطتك بأقرب محطة مرجعية عبر واجهتها البرمجية.
  • التقييم Evaluation: معامل الارتباط ومتوسط الخطأ بين محطتك والمحطة المرجعية على عدة أسابيع، مع فصل الأيام الرطبة عن الجافة.
  • الصعوبة Difficulty: متوسطة.
  • الخطر Risk: حساسات الجسيمات الرخيصة تبالغ في القراءة عندما ترتفع الرطوبة، لأن قطرات الماء تحسب كجسيمات، فإذا لم تنتبه لهذا فسوف تقدم للجنة أرقاماً تبدو خطيرة وهي ليست كذلك.
  • التميز Stand Out: وضع محطتك بجانب محطة مرجعية Co-location لأيام، ثم بناء نموذج تصحيح بسيط بالرطوبة، وعرض الأرقام قبل التصحيح وبعده.

4. عد الحشود دون تصوير Privacy-Preserving People Counting

Project title: Privacy-Preserving People Counting Without Cameras

في الفعاليات الكبرى ومواسم العمرة والحج تحتاج إدارة المكان أن تعرف كم شخصاً دخل البوابة أو الممر في كل دقيقة، حتى تقرر متى تغلق مدخلاً أو تفتح آخر، وقد شرحنا هذه الأنظمة على مستوى المنصة في أنظمة الحشود الكبرى. والحل المعتاد كاميرا وتحليل فيديو، ولكن الكاميرا تجمع وجوه الناس، وهذه بيانات شخصية لها أحكامها في نظام حماية البيانات الشخصية الذي تشرف عليه سدايا. والفكرة عداد يعمل بحساس لا يرى الوجوه، مثل مصفوفة حرارية صغيرة Thermal Array من 8 في 8 نقاط، أو رادار بموجات المليمتر mmWave، أو حساس مسافة بزمن الطيران Time of Flight، ويحسب الدخول والخروج واتجاه الحركة.

  • المستفيد User: فريق تشغيل قاعة أو ملعب أو ممر في فعالية، والجهة المنظمة التي تريد تقريراً بالكثافة.
  • النطاق Scope: ممر واحد بعرض محدد، وعقدتان على الأقل، ولوحة عرض بالعدد لحظياً، ولا يدخل في النطاق تتبع الأفراد أو التعرف عليهم بأي شكل.
  • الأدوات Stack: ESP32 أو Raspberry Pi Pico مع حساس حراري أو رادار، ومعالجة على العقدة نفسها، وإرسال العدد فقط دون البيانات الخام.
  • البيانات Data: تسجيلاتك أنت في تجربة مضبوطة، لأن البيانات الحرارية الخام لهذا النوع من الحساسات قليلة في المصادر المفتوحة، ولذلك اكتب في المقترح طريقة جمعها وموافقة المشاركين.
  • التقييم Evaluation: نسبة الخطأ في العدد مقابل عد يدوي في تجربة ممر بعدد معروف من المشاركين، بثلاث كثافات: فرد فرد، ومجموعات صغيرة، وتدفق متواصل.
  • الصعوبة Difficulty: عالية.
  • الخطر Risk: الدقة تنهار عندما يمشي شخصان متلاصقين أو عندما يكثر الزحام، فحدد في النطاق أعلى كثافة تدعمها، ولا تعد اللجنة بما لا تستطيع قياسه.
  • التميز Stand Out: تصميم الخصوصية من البداية Privacy by Design، أي أن البيانات الخام لا تغادر العقدة أصلاً، مع فصل في التقرير يشرح لماذا هذا الاختيار أنسب من الكاميرا لهذه المهمة.

5. شبكة CAN Bus Network لمركبة أو خط إنتاج صغير

Project title: CAN Bus Network for a Vehicle or Small Production Line

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

  • المستفيد User: فريق صيانة خط إنتاج في مصنع، أو مختبر السيارات في الكلية، أو فريق سباق طلابي.
  • النطاق Scope: ثلاث عقد، وقاموس رسائل مكتوب بصيغة DBC، وتسجيل الرسائل وتحليلها، ولا يدخل في النطاق الاتصال بسيارة حقيقية أثناء السير.
  • الأدوات Stack: ESP32، لأن فيه وحدة TWAI متوافقة مع إطار ISO 11898-1، مع شريحة مرسل ومستقبل CAN Transceiver لكل عقدة، وعلى الحاسب Linux مع SocketCAN وcan-utils.
  • البيانات Data: مستودع opendbc فيه ملفات DBC مفتوحة لرسائل سيارات حقيقية، وتستطيع أن تبدأ قبل وصول العتاد بواجهة CAN افتراضية اسمها vcan على Linux، أو بمحاكاة CAN في QEMU.
  • التقييم Evaluation: نسبة انشغال الناقل Bus Utilization، وزمن وصول الرسالة ذات الأولوية العالية عندما يزدحم الناقل، وسلوك الشبكة عند قطع سلك أو إزالة مقاومة الإنهاء Termination.
  • الصعوبة Difficulty: متوسطة إلى عالية.
  • الخطر Risk: أغلب مشاكل CAN في المختبر تأتي من التوصيل، مثل نسيان مقاومة 120 أوم في طرفي الناقل، فخصص أسبوعاً كاملاً للتوصيل والقياس بالمحلل المنطقي قبل كتابة أي منطق.
  • التميز Stand Out: حقن الأخطاء Fault Injection عمداً وقياس كيف يتعامل المتحكم معها، مثل إعادة الإرسال والانتقال إلى حالة الإيقاف Bus Off.

6. معالج RISC-V Soft Core على FPGA مع ملحق من تصميمك

Project title: RISC-V Soft Core on FPGA with a Custom Peripheral

درست في مادة المعمارية كيف يجلب المعالج التعليمة ويفكها وينفذها، ولكنك غالباً رأيت ذلك على ورق أو في محاكي تعليمي. والفكرة أن تشغل معالجاً مفتوح المصدر بمعمارية RISC-V على شريحة FPGA حقيقية، ثم تضيف إليه ملحقاً Peripheral من تصميمك، مثل وحدة PWM أو مؤقت أو وحدة حساب صغيرة، وتكتب له برنامجاً بلغة C يستخدمه.

  • المستفيد User: مختبر المعمارية في القسم، لأن ما تبنيه يصلح تجربة لطلاب المادة في الفصول القادمة.
  • النطاق Scope: معالج جاهز من مشروع مفتوح، وملحق واحد كامل باختباراته، وبرنامج تجريبي، وقياسات أداء، ولا يدخل في النطاق تصميم معالج من الصفر، فهذا مشروع لوحده.
  • الأدوات Stack: لوحة FPGA رخيصة مثل Tang Nano 9K التي فيها 8640 وحدة منطق LUT4 ويذكر صانعها أنها تكفي لمعالج RISC-V مثل PicoRV، ومعالج PicoRV32 أو NEORV32، وأدوات مفتوحة مثل Yosys وnextpnr، والمحاكاة بـ Verilator والاختبار بـ cocotb.
  • البيانات Data: لا يحتاج المشروع بيانات، وإنما معايير أداء Benchmarks معروفة مثل CoreMark وEmbench.
  • التقييم Evaluation: نتيجة CoreMark لكل ميغاهيرتز، وعدد وحدات المنطق والذاكرة المستخدمة، وأعلى تردد يمر فيه التصميم بفحص التوقيت Timing، ومقارنة أداء مهمة بالملحق وبدونه.
  • الصعوبة Difficulty: عالية.
  • الخطر Risk: أدوات FPGA قد تأخذ أياماً لتعمل على جهازك أول مرة، والتصميم قد لا يمر بفحص التوقيت، لذلك شغل مثالاً جاهزاً على اللوحة في الأسبوع الأول قبل أي تعديل.
  • التميز Stand Out: تعليمة مخصصة Custom Instruction تضيفها للمعالج، مع قياس التسريع الذي تعطيه في مهمة حقيقية، وهذا يفتح لك باب الماجستير في المسرعات.
لوحة Tang Nano 9K صغيرة طويلة عليها شريحة FPGA من Gowin في الوسط ومنفذ HDMI ومنفذ USB-C وأزرار ودبابيس على الحافتين
لوحة Tang Nano 9K وعليها شريحة FPGA بـ 8640 وحدة LUT4، وهي من اللوحات الرخيصة التي تكفي لتشغيل معالج RISC-V صغير بأدوات مفتوحة المصدر. الصورة: Popolon، رخصة CC0، المصدر: Wikimedia Commons (تم تحويلها إلى WebP).

7. لوحة إعلانات عربية بالحبر الإلكتروني E-Paper Arabic Signage

Project title: Arabic E-Paper Digital Signage

لوحات مواعيد القاعات وأسماء المكاتب في أغلب الجامعات ورق يطبع ويعلق، أو شاشة كبيرة تعمل طوال اليوم لتعرض نصاً لا يتغير إلا مرتين في اليوم. والفكرة لوحة بالحبر الإلكتروني E-Paper تعمل بالبطارية، تعرض نصاً عربياً بأشكال الحروف الصحيحة Arabic Shaping، أي أن الحرف يأخذ شكله الصحيح في أول الكلمة ووسطها وآخرها، وتتحدث مع خادم صغير تأخذ منه الجدول الجديد. وهذه مشكلة عربية حقيقية، فمكتبة الواجهات الرسومية المدمجة المشهورة LVGL تدعم أشكال الحروف العربية عند تفعيل الخيار LV_USE_ARABIC_PERSIAN_CHARS، ولكن توثيقها يذكر حدوداً، منها أن حقول إدخال النص لا تدعم هذه المعالجة، وأن النص الثابت المعرف بـ const لا يعالج.

  • المستفيد User: إدارة المرافق في الجامعة، والمساجد التي تعرض مواعيد الدروس، والمستشفيات لأرقام الغرف والعيادات.
  • النطاق Scope: لوحتان أو ثلاث، وخادم بواجهة بسيطة لتحديث النص، واختبار عرض عربي شامل، ولا يدخل في النطاق الصور أو الفيديو.
  • الأدوات Stack: ESP32 مع شاشة E-Paper، وLVGL أو مكتبة رسم بسيطة مع خط عربي مضمن، ونوم عميق Deep Sleep بين التحديثات.
  • البيانات Data: مجموعة اختبار عربية تبنيها أنت من كلمات فيها كل أشكال الحروف واللام ألف والأرقام والنص المختلط مع الإنجليزية، وهي جزء من مساهمة المشروع.
  • التقييم Evaluation: عمر البطارية المتوقع من قياس التيار في كل حالة، النوم والاستيقاظ والتحديث، ونسبة الكلمات التي تعرض صحيحة من مجموعة الاختبار، وزمن وصول التحديث.
  • الصعوبة Difficulty: متوسطة.
  • الخطر Risk: الخط العربي الكامل قد يكون أكبر من ذاكرة المتحكم، فاحسب حجم الخط في الأسبوع الأول، واختر الحروف والأحجام التي تحتاجها فقط.
  • التميز Stand Out: مساهمة في LVGL نفسها، مثل إصلاح أو اختبار لحالة عربية لا تعمل، وهذا يجمع هذه الفكرة مع الفكرة التالية.

8. مساهمة مفتوحة المصدر في Zephyr RTOS Contribution

Project title: Open Source Contribution to Zephyr RTOS

هذه فكرة لا يتوقعها كثير من المشرفين، ولكنها من أقوى ما يمكن أن تقدمه، لأن نتيجتها كود يراجعه مهندسون من شركات كثيرة ويدخل في مشروع يستخدمه عدد كبير من المطورين. وZephyr نظام تشغيل للزمن الحقيقي Real-Time Operating System مفتوح المصدر تحت مظلة Linux Foundation، ويدعم عدداً كبيراً من اللوحات. والفكرة أن يأخذ الفريق مساحة محددة في المشروع، مثل مشغل Driver لحساس غير مدعوم، أو أمثلة واختبارات ناقصة، ويقوم بالعمل حتى يقبل في المستودع الرئيسي.

  • المستفيد User: مجتمع المشروع، وكل من يستخدم هذا الحساس أو هذه اللوحة بعدكم.
  • النطاق Scope: مشغل واحد أو اثنان مع أمثلة واختبارات، أو مجموعة إصلاحات في موضوع واحد، ووثيقة تشرح التصميم ونقاشات المراجعة.
  • الأدوات Stack: Zephyr وأداة west، والاختبار بـ Twister على لوحة المحاكاة qemu_cortex_m3 وعلى لوحة حقيقية، وGit الذي شرحناه في إدارة النسخ وGit.
  • البيانات Data: قائمة المشاكل المفتوحة في المستودع، وفيها وسم Good first issue للمبتدئين، وإرشادات المساهمة الرسمية.
  • التقييم Evaluation: طلبات الدمج Pull Requests المقبولة، وعدد جولات المراجعة، والاختبارات التي أضفتموها ونتيجتها على المحاكي واللوحة.
  • الصعوبة Difficulty: عالية.
  • الخطر Risk: المراجعة في المشاريع الكبيرة قد تأخذ أسابيع، ولا تستطيع أن تجبر أحداً على قبول الكود قبل موعد المناقشة، لذلك ابدأ بمساهمة صغيرة في الشهر الأول، واتفق مع المشرف على أن التقييم يشمل العمل المقدم والمراجعة حتى لو لم يدمج كله.
  • التميز Stand Out: رابط طلب الدمج في سيرتك الذاتية، فلا يوجد دليل على قدرتك أوضح من كود مقبول في مشروع بهذا الحجم، واقرأ قبل أن تبدأ عن تراخيص البرمجيات مفتوحة المصدر، لأن كل مساهمة تدخل تحت رخصة المشروع.

أفكار رسائل الماجستير Master Theses

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

1. الجدولة في أنظمة الزمن الحقيقي RTOS Scheduling بين التحليل والقياس

Project title: Real-Time Scheduling in RTOS: Analysis Versus Measurement

نظرية الجدولة في الزمن الحقيقي تعطيك معادلات تقول إن مجموعة مهام بأزمنة تنفيذ وفترات معينة سوف تلتزم بحدودها الزمنية Deadlines، ولكن هذه المعادلات تفترض أنك تعرف أسوأ زمن تنفيذ Worst-Case Execution Time لكل مهمة، وأن المقاطعات Interrupts ووقت تبديل المهام معروفة. وعلى متحكم حقيقي فيه ذاكرة مخبئية Cache وناقل مشترك ومقاطعات من الشبكة، تبتعد الأرقام المقاسة عن الأرقام المحسوبة، وقد شرحنا أساس الجدولة في أنظمة التشغيل العامة في العمليات وجدولة المعالج في Linux.

  • السؤال البحثي Research Question: إلى أي حد يتنبأ تحليل زمن الاستجابة Response Time Analysis بالأزمنة المقاسة فعلاً لمهام Zephyr أو FreeRTOS على متحكم Cortex-M حقيقي، وما مقدار الهامش الذي يجب إضافته عندما تعمل مقاطعات الشبكة؟
  • الأعمال السابقة Related Work: أدبيات تحليل زمن الاستجابة وتحليل أسوأ زمن تنفيذ، وتوثيق جدولة المهام في FreeRTOS ومجدول Zephyr.
  • المساهمة Novelty: مجموعة قياسات قابلة للتكرار على لوحات محددة، ونموذج للهامش بحسب نوع المقاطعة، وأداة صغيرة تقارن التحليل بالقياس تلقائياً.
  • الأدوات Stack: لوحتان بمعالجين مختلفين، ومحلل منطقي لقياس الأزمنة من الخارج عبر دبابيس GPIO، وRenode أو QEMU للتجارب القابلة للتكرار.
  • التقييم Evaluation: نسبة الحدود الزمنية المفقودة Deadline Miss Ratio، والتذبذب Jitter، والفرق بين الزمن المحسوب والمقاس لكل مهمة، تحت عدة مستويات من نشاط المقاطعات.
  • الصعوبة Difficulty: عالية.
  • الخطر Risk: القياس من داخل البرنامج نفسه يغير الزمن الذي تقيسه، لذلك قس من الخارج بالمحلل المنطقي وتأكد من دقة أداة القياس قبل أي نتيجة.
  • التميز Stand Out: نشر الكود والبيانات بحيث يعيد غيرك التجربة على لوحته، كما شرحنا في البحث القابل لإعادة الإنتاج.

2. مسرع عتادي Hardware Accelerator على FPGA مقابل المعالج

Project title: FPGA Hardware Accelerator Versus CPU Execution

عندما تكون عند جهاز طرفي مهمة حسابية تتكرر آلاف المرات في الثانية، مثل ضرب مصفوفات صغيرة بأعداد صحيحة من ثمانية بتات أو مرشح إشارة رقمي FIR، يكون السؤال: هل تنفذها على المعالج، أم تبني لها دائرة خاصة على FPGA؟ والإجابة ليست واضحة كما تبدو، لأن المسرع يحتاج نقل بيانات إليه ومنه، ووحدات منطق، وطاقة، وجهد تصميم أكبر بكثير.

  • السؤال البحثي Research Question: عند أي حجم للمهمة يصبح المسرع على FPGA صغيرة أفضل من معالج RISC-V مع تعليمات مخصصة، بمقياس الطاقة لكل عملية والزمن ووحدات المنطق؟
  • الأعمال السابقة Related Work: أدوات تحويل النماذج إلى عتاد مثل hls4ml وFINN، ومسرعات بحثية مفتوحة مثل Gemmini، ومعالجات مفتوحة مثل CVA6.
  • المساهمة Novelty: منحنى قرار بين الخيارين لفئة محددة من المهام على عتاد رخيص، وهذا ما ينقص أغلب الأدبيات التي تقيس على شرائح كبيرة غالية.
  • الأدوات Stack: لوحة FPGA متوسطة، وأدوات تصنيع عالي المستوى High-Level Synthesis أو Verilog مباشرة، ومعالج NEORV32 للمقارنة، وجهاز قياس تيار.
  • التقييم Evaluation: الزمن لكل عملية، والطاقة لكل عملية، ووحدات المنطق والذاكرة الداخلية المستخدمة، وأعلى تردد، لعدة أحجام من المهمة.
  • الصعوبة Difficulty: عالية جداً.
  • الخطر Risk: قياس الطاقة على لوحة FPGA تطويرية صعب لأن اللوحة فيها مكونات كثيرة غير الشريحة، فحدد طريقة القياس في المقترح وناقشها مع المشرف قبل البدء.
  • التميز Stand Out: نشر التصميم بترخيص مفتوح للعتاد مثل CERN OHL ليستطيع غيرك أن يبني عليه.

3. كشف أعطال المضخات بالتعلم الآلي الصغير TinyML Fault Detection

Project title: Pump Fault Detection with TinyML

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

  • السؤال البحثي Research Question: كيف تتغير دقة كشف الشذوذ Anomaly Detection عندما تقلص النموذج ليناسب ذاكرة متحكم بعشرات الكيلوبايتات، وما أفضل توزيع للذاكرة بين النافذة الزمنية للإشارة والنموذج نفسه؟
  • الأعمال السابقة Related Work: معيار MLPerf Tiny وفيه مهمة كشف الشذوذ، ومكتبة TensorFlow Lite Micro.
  • المساهمة Novelty: منحنى الدقة مقابل الذاكرة والطاقة على متحكمات محددة، مع بيانات اهتزاز تجمعها من مضخة حقيقية في مختبر القسم.
  • الأدوات Stack: متحكم Cortex-M4F أو ESP32-S3، وحساس تسارع، وTensorFlow Lite Micro، وأداة قياس تيار.
  • التقييم Evaluation: مساحة تحت المنحنى AUC لكشف الشذوذ، والذاكرة المستخدمة، والزمن لكل قرار، والطاقة لكل قرار.
  • الصعوبة Difficulty: عالية.
  • الخطر Risk: أن تتحول الرسالة إلى مقارنة نماذج على الحاسب، وهذا موضوع علم البيانات وليس هندسة الحاسب، لذلك اجعل كل نتيجة مقاسة على المتحكم نفسه.
  • التميز Stand Out: تجربة في الموقع على مضخة تعمل فعلاً لأسابيع، وليس على بيانات معمل فقط.

4. عقدة حساسات بحصاد الطاقة Energy Harvesting Sensor Node

Project title: Energy Harvesting Wireless Sensor Node

في المملكة شمس كثيرة، ومع ذلك تموت عقد الحساسات في المزارع والطرق لأن بطارياتها نفدت قبل موعد الصيانة. والعقدة التي تعمل بلوح شمسي صغير ومكثف كبير Supercapacitor تحتاج أن تقرر كل مرة: هل أقيس الآن وأرسل، أم أنام وأوفر الطاقة لليلة؟ وهذا قرار جدولة يعتمد على الطاقة المتوقعة، وليس على الزمن فقط.

  • السؤال البحثي Research Question: هل سياسة نوم تكيفية Adaptive Duty Cycling تعتمد على توقع الإشعاع الشمسي تزيد عدد القراءات المفيدة في الأسبوع دون أن تنطفئ العقدة، مقارنة بالسياسة الثابتة؟
  • الأعمال السابقة Related Work: أدبيات الحوسبة المتقطعة Intermittent Computing وإدارة الطاقة في شبكات الحساسات اللاسلكية.
  • المساهمة Novelty: سياسة تستخدم بيانات الإشعاع التاريخية للموقع من NASA POWER مع قياسات العقدة نفسها، وتقييمها في ظروف صيف وشتاء محلية.
  • الأدوات Stack: متحكم منخفض الطاقة جداً، ولوح شمسي صغير، ودائرة حصاد طاقة جاهزة، ومكثف كبير، وLoRa للإرسال.
  • التقييم Evaluation: عدد القراءات المرسلة في الأسبوع، وعدد مرات الانطفاء، والطاقة لكل رسالة، ومحاكاة لسنة كاملة ببيانات الإشعاع.
  • الصعوبة Difficulty: عالية.
  • الخطر Risk: التجربة الميدانية تحتاج أشهراً، فابدأ بالمحاكاة ببيانات الإشعاع، ثم تجربة قصيرة تتحقق بها من نموذج المحاكاة.
  • التميز Stand Out: أداة محاكاة مفتوحة يستطيع غيرك أن يضع فيها إحداثيات موقعه ومواصفات لوحه ليعرف هل تكفيه الطاقة.

5. تحمل الأخطاء العتادية Fault Tolerance في معالج على FPGA

Project title: Hardware Fault Tolerance in an FPGA Soft Processor

في الفضاء وفي البيئات ذات الإشعاع، وحتى على الأرض بنسبة صغيرة، يمكن أن ينقلب بت في الذاكرة أو في مسجل داخل المعالج دون أي خطأ في الكود، وهذا ما يسمى خطأ عابر Soft Error. والحلول المعروفة مثل تكرار الوحدة ثلاث مرات والتصويت بينها Triple Modular Redundancy أو تصحيح الأخطاء في الذاكرة ECC لها كلفة في المساحة والطاقة، والسؤال: أين تضعها لتحصل على أكبر حماية بأقل كلفة؟ وقد شرحنا تصحيح الأخطاء في الذاكرة في كيف تعمل الذاكرة RAM.

  • السؤال البحثي Research Question: ما هي مسجلات ووحدات معالج RISC-V صغير التي إذا حميتها وحدها حصلت على أغلب الحماية، بالقياس بحقن الأخطاء؟
  • الأعمال السابقة Related Work: أدبيات حقن الأخطاء في المعالجات، والمعالجات مفتوحة المصدر التي فيها خيارات للتحقق مثل NEORV32.
  • المساهمة Novelty: خريطة حساسية لوحدات معالج محدد، وتصميم حماية انتقائية مع قياس كلفتها.
  • الأدوات Stack: معالج مفتوح المصدر، وVerilator لحقن الأخطاء في المحاكاة بأعداد كبيرة، ولوحة FPGA للتأكد من النتائج.
  • التقييم Evaluation: نسبة الأخطاء المحقونة التي أدت إلى نتيجة خاطئة صامتة أو توقف، قبل الحماية وبعدها، وزيادة المساحة والطاقة.
  • الصعوبة Difficulty: عالية جداً.
  • الخطر Risk: عدد التجارب المطلوب كبير جداً، فاحسب زمن المحاكاة في الشهر الأول، وقلص البرنامج المختبر أو المعالج إذا لزم الأمر.
  • التميز Stand Out: تطبيق النتيجة على حالة استخدام حقيقية مثل حاسب قمر صناعي صغير CubeSat، مع شرح لماذا اخترت هذا المعالج.

6. دقة المحاكيات Emulator Fidelity في اختبار البرامج الثابتة

Project title: Emulator Fidelity in Firmware Testing

هذه الفكرة خرجت مباشرة من التجربة العملية في هذا المقال. فالفرق تختبر برامجها الثابتة على محاكيات مثل QEMU وRenode وWokwi لأنها رخيصة وسريعة وتعمل في خطوط التكامل المستمر CI، ولكن المحاكي يختلف عن الشريحة في أشياء كثيرة: التوقيت، وحالة الذاكرة عند التشغيل، وسلوك الملحقات عند الخطأ. وسوف ترى في المختبر خطأ لا يظهر في QEMU أبداً لأنه يبدأ الذاكرة بأصفار، بينما الشريحة الحقيقية لا تعدك بذلك.

  • السؤال البحثي Research Question: ما أنواع أخطاء البرامج الثابتة التي يكشفها كل محاك والتي لا يكشفها إلا العتاد الحقيقي، وكم منها يمكن كشفه إذا أضفنا للمحاكي سلوكاً أقرب للواقع؟
  • الأعمال السابقة Related Work: أدبيات إعادة استضافة البرامج الثابتة Firmware Rehosting واختبارها، وتوثيق المحاكيات نفسها.
  • المساهمة Novelty: مجموعة أخطاء معروفة مزروعة في برامج حقيقية، ونتيجة كل محاك عليها، وتعديل صغير في محاك مفتوح المصدر يكشف فئة منها.
  • الأدوات Stack: QEMU وRenode، ولوحتان حقيقيتان على الأقل، وبرامج ثابتة مفتوحة المصدر من Zephyr أو غيره.
  • التقييم Evaluation: نسبة الأخطاء المكتشفة في كل بيئة، والزمن اللازم لكل تشغيل، وكلفة التعديل المقترح.
  • الصعوبة Difficulty: عالية.
  • الخطر Risk: الأخطاء المزروعة يدوياً قد لا تمثل الأخطاء الحقيقية، فخذ جزءاً منها من سجلات الأخطاء المغلقة في مشاريع مفتوحة المصدر.
  • التميز Stand Out: إرسال التعديل إلى المحاكي نفسه كمساهمة، فتجمع البحث والمساهمة المفتوحة في رسالة واحدة.

الأفكار المستهلكة Overused Ideas: لماذا مل منها المشرفون وكيف تنقذ واحدة منها؟

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

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

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

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

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

جدول مقارنة الأفكار Comparison Table

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

الفكرةالمستوىالصعوبةتوفر البياناتالمهارات التي تتعلمها
عداد طاقة ذكي Smart Energy Meter
Smart Energy Meter with Consumption Analysis
بكالوريوسمتوسطة إلى عاليةعالية: UCI ومنصات مفتوحةقياس الإشارات، الحساب بالأعداد الصحيحة، MQTT، السلامة الكهربائية
ري بالتنقيط Drip Irrigation
Smart Drip Irrigation Using Soil Moisture and Weather Data
بكالوريوسمتوسطةعالية للطقس، وتجمع الرطوبة بنفسكLoRaWAN، المعايرة، تصميم التجارب الميدانية
جودة الهواء Air Quality
Low-Cost Air Quality Monitoring Station
بكالوريوسمتوسطةعالية: OpenAQالحساسات منخفضة التكلفة، التصحيح والمعايرة، قواعد البيانات الزمنية
عد الحشود دون تصوير People Counting
Privacy-Preserving People Counting Without Cameras
بكالوريوسعاليةمنخفضة: تجمعها بنفسكالحساسات الحرارية والرادار، المعالجة على العقدة، الخصوصية
شبكة CAN Bus Network
CAN Bus Network for a Vehicle or Small Production Line
بكالوريوسمتوسطة إلى عاليةمتوسطة: opendbc وvcanالبروتوكولات الصناعية، التوصيل والقياس، حقن الأخطاء
معالج RISC-V Soft Core على FPGA
RISC-V Soft Core on FPGA with a Custom Peripheral
بكالوريوسعاليةلا تحتاج: معايير أداءVerilog، أدوات FPGA المفتوحة، التحقق، المعمارية
لوحة عربية E-Paper Arabic Signage
Arabic E-Paper Digital Signage
بكالوريوسمتوسطةتبنيها: مجموعة اختبار عربيةالطاقة المنخفضة، الخطوط والعرض العربي، LVGL
مساهمة في Zephyr RTOS Contribution
Open Source Contribution to Zephyr RTOS
بكالوريوسعاليةعالية: المستودع ومشاكلهالمشغلات Drivers، المراجعة، الاختبار الآلي، العمل المفتوح
جدولة الزمن الحقيقي RTOS Scheduling
Real-Time Scheduling in RTOS: Analysis Versus Measurement
ماجستيرعاليةتقيسها بنفسكنظرية الزمن الحقيقي، القياس الدقيق، قابلية التكرار
مسرع عتادي Hardware Accelerator
FPGA Hardware Accelerator Versus CPU Execution
ماجستيرعالية جداًلا تحتاج: معايير أداءالتصنيع عالي المستوى، قياس الطاقة، المقايضات العتادية
كشف الأعطال TinyML Fault Detection
Pump Fault Detection with TinyML
ماجستيرعاليةمتوسطة: MLPerf Tiny وقياساتكالنماذج المصغرة، الذاكرة المحدودة، الطاقة لكل قرار
عقدة بحصاد الطاقة Energy Harvesting Sensor Node
Energy Harvesting Wireless Sensor Node
ماجستيرعاليةعالية للإشعاع: NASA POWERإدارة الطاقة، المحاكاة، التجارب الطويلة
تحمل الأخطاء Fault Tolerance
Hardware Fault Tolerance in an FPGA Soft Processor
ماجستيرعالية جداًلا تحتاج: حقن أخطاءالتحقق العتادي، المحاكاة الكبيرة، التصميم الآمن
دقة المحاكيات Emulator Fidelity
Emulator Fidelity in Firmware Testing
ماجستيرعاليةمتوسطة: مشاريع مفتوحةالمحاكيات، البرامج الثابتة، منهجية التقييم

وإذا كنت لا تعرف من أين تبدأ، فاختر ثلاث أفكار مختلفة في طبيعتها: واحدة قريبة من منتج ولها مستخدم واضح مثل العداد أو الري، وواحدة أعمق في العتاد مثل CAN أو RISC-V، وواحدة مفتوحة المصدر مثل Zephyr، لأن المشرف يختار عادة بين أفكار مختلفة أسهل من الاختيار بين ثلاث نسخ من نفس الفكرة.

تجربة عملية Lab: برنامج عداد الطاقة Firmware على Cortex-M3 في QEMU

أخذنا الفكرة الأولى، عداد الطاقة الذكي، وأردنا أن نجيب عن سؤال الجدوى الذي سيسأله المشرف قبل أن يوافق: هل يستطيع متحكم صغير بلا وحدة أعداد عشرية Floating Point Unit أن يعالج قراءات يوم كامل ويخرج بنفس الأرقام التي يحسبها الحاسب، وكم يحتاج من الذاكرة والتعليمات؟ ولا توجد عندنا لوحة في هذه التجربة، لذلك شغلنا البرنامج الثابت على المحاكي QEMU الذي يحاكي لوحة التقييم Stellaris LM3S6965EVB، وعليها معالج Arm Cortex-M3 بتردد 50 ميغاهيرتز وذاكرة فلاش 256 كيلوبايت وذاكرة SRAM بـ 64 كيلوبايت بحسب صفحة الشريحة عند TI. وهذه هي الطريقة التي ننصحك بها في الأسبوع الأول، أي قبل أن تصل اللوحة: البرنامج الثابت نفسه، ببيانات حقيقية، على محاك مجاني.

💡
صفحة TI تصف شريحة LM3S6965 بأنها غير موصى بها للتصاميم الجديدة Not Recommended for New Designs، ولذلك استخدمناها هنا لأنها مدعومة في QEMU وفي Zephyr باسم qemu_cortex_m3 فقط، أي أنها بيئة اختبار وليست اختياراً للمنتج. وفي مشروعك الحقيقي سوف تنقل نفس الكود إلى ESP32 أو متحكم حديث، وتبقى الأرقام التي تقيسها هنا عن الكود نفسه وليس عن الشريحة.

والصورة التالية تبين مسار التجربة كاملاً، من ملف البيانات إلى المخرج:

مسار التجربة من اليمين إلى اليسار: ملف UCI المضغوط بحجم 20 ميغابايت، ثم السكربت fetch_day.py الذي يستخرج يوماً واحداً من 1440 قراءة إلى ملف day.h، ثم المترجم arm-none-eabi-gcc الذي يبني ملف ELF، ثم QEMU بلوحة lm3s6965evb وعليها Cortex-M3 والمخرج عبر UART، ثم المقارنة مع reference.py على الحاسب، وفي الأسفل سجل التعليمات المنفذة لعدها
يوم من القراءات الحقيقية يدخل البرنامج الثابت كمصفوفة في الفلاش، والمخرج يقارن بحساب Python على الحاسب

البيانات Dataset: يوم كامل من قراءات بيت حقيقي

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

# Takes one day of minute readings from the UCI "Individual household electric power consumption" dataset
# and writes it as a C header for the firmware (day.h) plus a small CSV sample for the reader.
#   python3 fetch_day.py <zip or txt> 17/12/2006 day.h day.csv
# The zip (20 MB) stays outside lab/; download it from
#   https://archive.ics.uci.edu/static/public/235/individual+household+electric+power+consumption.zip
import io, sys, zipfile

src, day, out_h, out_csv = sys.argv[1:5]
if src.endswith('.zip'):
    z = zipfile.ZipFile(src)
    f = io.TextIOWrapper(z.open('household_power_consumption.txt'), encoding='ascii')
else:
    f = open(src, encoding='ascii')

rows = []
for line in f:
    if line.startswith(day + ';'):
        d, t, gap = line.split(';')[:3]
        rows.append((t, gap))
    elif rows:
        break  # the file is sorted by time, so the day is over

watts = []
for t, gap in rows:
    # Global_active_power is in kW with 3 decimals; '?' marks a minute the meter did not record
    watts.append(0xFFFF if gap == '?' else round(float(gap) * 1000))

missing = sum(1 for w in watts if w == 0xFFFF)
with open(out_h, 'w') as h:
    h.write(f'/* {day}: {len(watts)} minute readings of Global_active_power in W, 0xFFFF = missing ({missing}) */\n')
    h.write(f'#define DAY_NAME "{day}"\n#define N_MIN {len(watts)}\n')
    h.write('static const unsigned short day_w[N_MIN] = {\n')
    for i in range(0, len(watts), 12):
        h.write('  ' + ', '.join(str(w) for w in watts[i:i + 12]) + ',\n')
    h.write('};\n')
with open(out_csv, 'w') as c:
    c.write('time,watts\n')
    for (t, _), w in zip(rows, watts):
        c.write(f'{t},{"" if w == 0xFFFF else w}\n')
print(f'{day}: {len(watts)} minutes, {missing} missing, max {max(w for w in watts if w != 0xFFFF)} W -> {out_h}')

ولاحظ في السكربت أن القراءة المفقودة في الملف الأصلي مكتوبة بعلامة استفهام، فحولناها إلى القيمة 0xFFFF، وهي أكبر قيمة في عدد صحيح من 16 بت، والسبب أننا نريد أن نحفظ كل قراءة في بايتين فقط، فأعلى قراءة في المجموعة كلها نحو 11 كيلوواط، أي 11 ألف واط تقريباً، وهي أصغر من 65535. وبهذا الشكل يأخذ اليوم كله 2880 بايتاً في الفلاش. وشغلنا السكربت على يومين: 17 ديسمبر 2006 لأنه يوم كامل، و21 ديسمبر 2006 لأن فيه قراءات مفقودة، والمخرج كما يلي:

17/12/2006: 1440 minutes, 0 missing, max 7064 W -> day.h
21/12/2006: 1440 minutes, 2 missing, max 5854 W -> day-gap.h

البرنامج الثابت Firmware في الملف meter.c

البرنامج مكتوب بلغة C دون مكتبة C القياسية، أي دون printf، والسبب أن هذا يجعل كل بايت في الملف الناتج من كودنا أو من مكتبة المترجم libgcc فقط، فيكون قياس الحجم صادقاً. وإذا كانت C جديدة عليك فابدأ من لغة C لمن يبرمج بلغة أخرى، ولفهم الفرق بين المكدس Stack والذاكرة الثابتة فاقرأ الذاكرة للمبرمجين. والكود كاملاً كما يلي:

/* Feasibility spike for a smart energy meter: one day of real minute readings (UCI household power dataset)
 * processed by bare-metal firmware on an emulated Cortex-M3 (TI Stellaris LM3S6965, QEMU machine lm3s6965evb).
 * Fixed-point (integers only) by default; build with -DUSE_FLOAT to do the same with double. */
#include DAY_HEADER

#define UART0_DR (*(volatile unsigned int *)0x4000C000u)   /* UART0 data register of the LM3S6965 */
#define PEAK_LIMIT_W 3000u                                  /* "heavy use" threshold for one minute */
#define MISSING 0xFFFFu

static void putc_(char c) { UART0_DR = (unsigned int)c; }
static void puts_(const char *s) { while (*s) putc_(*s++); }
static void putu(unsigned int v) {                          /* no printf: newlib is not linked */
    char b[11]; int i = 0;
    do { b[i++] = (char)('0' + v % 10u); v /= 10u; } while (v);
    while (i) putc_(b[--i]);
}
static void put3(unsigned int milli) {                      /* prints 12345 as 12.345 */
    putu(milli / 1000u); putc_('.');
    unsigned int f = milli % 1000u;
    putc_((char)('0' + f / 100u)); putc_((char)('0' + f / 10u % 10u)); putc_((char)('0' + f % 10u));
}

static unsigned int hour_wmin[24];                          /* watt-minutes per hour, in RAM (.bss) */

static void semihost_exit(void) {                           /* tells QEMU to stop: SYS_EXIT, ApplicationExit */
    register unsigned int r0 __asm__("r0") = 0x18u;
    register unsigned int r1 __asm__("r1") = 0x20026u;
    __asm__ volatile("bkpt 0xAB" : : "r"(r0), "r"(r1) : "memory");
}

extern unsigned int _sbss, _ebss;
void reset_handler(void) {
    /* a real chip does not promise zeroed SRAM after reset; QEMU does, which hides this line's absence */
    for (unsigned int *p = &_sbss; p < &_ebss; p++) *p = 0;
    unsigned int peak = 0, peak_min = 0, heavy = 0, missing = 0;
#ifdef USE_FLOAT
    double kwh = 0.0, last = 0.0;
#else
    unsigned int wmin = 0, last = 0;                        /* watt-minutes: 1440 * 11122 fits in 32 bits */
#endif
    for (unsigned int m = 0; m < N_MIN; m++) {
        unsigned int w = day_w[m];
#ifdef CHECK_MISSING
        if (w == MISSING) { missing++; w = (unsigned int)last; }  /* hold the last valid reading */
#endif
#ifdef USE_FLOAT
        double kw = (double)w / 1000.0;
        kwh += kw / 60.0;
        last = (double)w;
#else
        wmin += w;
        last = w;
#endif
        hour_wmin[m / 60u] += w;
        if (w > peak) { peak = w; peak_min = m; }
        if (w > PEAK_LIMIT_W) heavy++;
    }
    puts_("day ");          puts_(DAY_NAME); puts_("  minutes "); putu(N_MIN); puts_("  missing "); putu(missing); putc_('\n');
#ifdef USE_FLOAT
    puts_("energy kWh  ");  put3((unsigned int)(kwh * 1000.0 + 0.5)); puts_("  (double)\n");
#else
    puts_("energy kWh  ");  put3((wmin + 30u) / 60u); puts_("  (fixed)\n");
#endif
    puts_("peak W      ");  putu(peak); puts_(" at minute "); putu(peak_min);
    puts_(" ("); putu(peak_min / 60u); putc_(':'); putu(peak_min % 60u / 10u); putu(peak_min % 10u); puts_(")\n");
    puts_("minutes > ");    putu(PEAK_LIMIT_W); puts_(" W  "); putu(heavy); putc_('\n');
    puts_("busiest hour ");
    unsigned int bh = 0;
    for (unsigned int h = 1; h < 24; h++) if (hour_wmin[h] > hour_wmin[bh]) bh = h;
    putu(bh); puts_(":00  kWh "); put3((hour_wmin[bh] + 30u) / 60u); putc_('\n');
    semihost_exit();
    for (;;) {}
}

extern unsigned int _stack_top;
__attribute__((section(".vectors"), used))
static const void *vectors[2] = { &_stack_top, (void *)reset_handler };

في الكود أعلاه لاحظ التالي:

  • جدول المتجهات Vector Table في آخر الملف فيه قيمتان فقط: عنوان قمة المكدس، وعنوان دالة البداية reset_handler، وهذا كل ما يحتاجه معالج Cortex-M ليبدأ، فهو يقرأ هاتين القيمتين من أول الفلاش عند التشغيل.
  • الكتابة إلى العنوان 0x4000C000 هي الكتابة إلى سجل البيانات في وحدة الاتصال التسلسلي UART0، وQEMU يحول كل حرف يكتب فيه إلى الطرفية، وعلى اللوحة الحقيقية يخرج الحرف من دبوس الإرسال.
  • الطاقة محسوبة بوحدة واط دقيقة Watt-Minute في عدد صحيح من 32 بت، ثم تقسم على 60 في النهاية فقط، والسبب أن القسمة على 60 في كل دقيقة تضيع الكسور وتتراكم، أما الجمع ثم القسمة مرة واحدة فلا يضيع إلا أقل من نصف واط ساعة.
  • الخيار CHECK_MISSING يفعل فحص القراءة المفقودة، والخيار USE_FLOAT يحول الحساب إلى double، وسوف نستخدم الاثنين بعد قليل.
  • الدالة semihost_exit تستخدم ما يسمى Semihosting، أي تعليمة bkpt برقم خاص يفهمها QEMU كطلب لإنهاء المحاكاة، وعلى اللوحة الحقيقية لا تستخدمها إلا مع أداة تصحيح Debugger موصولة.

وملف الربط Linker Script يحدد مكان كل جزء في ذاكرة الشريحة:

/* LM3S6965: 256 KB flash at 0x0, 64 KB SRAM at 0x20000000 */
MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
         SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K }
SECTIONS {
  .text : { KEEP(*(.vectors)) *(.text*) *(.rodata*) } > FLASH
  .bss (NOLOAD) : { _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } > SRAM
  _stack_top = ORIGIN(SRAM) + LENGTH(SRAM);
}

وسكربت البناء والتشغيل يترجم البرنامج بخيارات المعالج Cortex-M3، ثم يطبع حجم كل قسم بالأداة arm-none-eabi-size، ثم يشغله على QEMU:

#!/bin/sh
# build.sh <name> <day header> [extra flags]   ->  <name>.elf, then runs it on QEMU's lm3s6965evb
set -e
name=$1; hdr=$2; shift 2
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -ffreestanding -nostdlib -T link.ld \
  -DDAY_HEADER="\"$hdr\"" "$@" -o "$name.elf" meter.c -lgcc
arm-none-eabi-size "$name.elf"
qemu-system-arm -M lm3s6965evb -nographic -semihosting -kernel "$name.elf"

وشغلنا كل ذلك داخل Container من debian:trixie-slim، ثبتنا فيه الحزم gcc-arm-none-eabi وqemu-system-arm وpython3، وكانت النسخ arm-none-eabi-gcc 14.2.1 وQEMU 10.0.13، وكل الأوامر مجمعة في السكربت run_all.sh في مجلد التجربة.

المشكلة الحقيقية الأولى: قراءة مفقودة تصبح 65 كيلوواط Missing Readings

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

   text	   data	    bss	    dec	    hex	filename
   3590	      0	     96	   3686	    e66	v1-gap.elf
day 21/12/2006  minutes 1440  missing 0
energy kWh  30.795  (fixed)
peak W      65535 at minute 683 (11:23)
minutes > 3000 W  86
busiest hour 11:00  kWh 2.701

والأرقام تبدو معقولة من الوهلة الأولى، ولكن انظر إلى السطر الثالث: أعلى قراءة 65535 واط عند الساعة 11:23، أي أن البيت استهلك أكثر من 65 كيلوواط في دقيقة واحدة، وهذا مستحيل في بيت. والسبب أن البرنامج عامل علامة القراءة المفقودة 0xFFFF كأنها قراءة حقيقية، فدخلت في مجموع الطاقة وفي الساعة الأكثر استهلاكاً وفي عدد دقائق الاستهلاك العالي. ولكي نعرف حجم الخطأ شغلنا الحساب المرجعي على الحاسب بلغة Python بالأعداد العشرية، وبنفس سياسة القراءة المفقودة التي سنضيفها، أي أن نكرر آخر قراءة صحيحة:

# Host-side reference for the firmware: the same day computed in Python floats from the CSV sample.
#   python3 reference.py day-2006-12-17.csv
import csv, sys
rows = list(csv.DictReader(open(sys.argv[1])))
w, last, missing = [], 0, 0
for r in rows:
    if r['watts'] == '':
        missing += 1; w.append(last)          # same policy as the firmware: hold the last valid reading
    else:
        last = int(r['watts']); w.append(last)
kwh = sum(x / 1000 for x in w) / 60
peak = max(w); pm = w.index(peak)
hours = [sum(w[h * 60:(h + 1) * 60]) / 60000 for h in range(24)]
bh = max(range(24), key=lambda h: hours[h])
print(f'day {sys.argv[1]}  minutes {len(w)}  missing {missing}')
print(f'energy kWh  {kwh:.6f}')
print(f'peak W      {peak} at minute {pm} ({pm // 60}:{pm % 60:02d})')
print(f'minutes > 3000 W  {sum(1 for x in w if x > 3000)}')
print(f'busiest hour {bh}:00  kWh {hours[bh]:.6f}')
day day-2006-12-17.csv  minutes 1440  missing 0
energy kWh  56.507667
peak W      7064 at minute 543 (9:03)
minutes > 3000 W  423
busiest hour 18:00  kWh 3.697100
day day-2006-12-21.csv  minutes 1440  missing 2
energy kWh  28.618533
peak W      5854 at minute 1199 (19:59)
minutes > 3000 W  84
busiest hour 9:00  kWh 2.575800

في المقارنة لاحظ التالي:

  • الطاقة الصحيحة لليوم 28.619 كيلوواط ساعة، والبرنامج الأول قال 30.795، أي خطأ بأكثر من 2 كيلوواط ساعة، ونحو 7.6% من استهلاك اليوم، بسبب قراءتين فقط من 1440.
  • الساعة الأكثر استهلاكاً الصحيحة هي التاسعة صباحاً، والبرنامج الأول قال الحادية عشرة، لأن القراءة الكاذبة وقعت فيها.
  • عدد الدقائق فوق 3000 واط 84 وليس 86، لأن القراءتين المفقودتين حسبتا فوق الحد.

وهذه بالضبط المشكلة التي سوف تواجهها في العداد الحقيقي، فالحساس ينقطع، والاتصال يضيع، والمحول التماثلي الرقمي ADC يعطي قيمة قصوى عندما ينفصل السلك، وإذا لم يكن في البرنامج الثابت سياسة واضحة للقراءة المفقودة فسوف ترسل للمستخدم فاتورة خاطئة وتنبيه ذروة كاذباً. والإصلاح سطر واحد يفعله الخيار CHECK_MISSING: نعد القراءة المفقودة، ونضع مكانها آخر قراءة صحيحة.

⚠️
تكرار آخر قراءة صحيحة سياسة واحدة من عدة سياسات، وتناسب انقطاعاً قصيراً لدقيقة أو اثنتين. أما إذا انقطع الحساس ساعة كاملة فتكرار آخر قراءة يخترع استهلاكاً لم يحدث، والأصح أن يعلم البرنامج تلك الساعة بأنها ناقصة ويعرضها للمستخدم كذلك. اكتب السياسة التي اخترتها في تقرير المشروع، لأن اللجنة سوف تسأل عنها.

بعد الإصلاح: البرنامج بالأعداد الصحيحة Fixed-Point مقابل المرجع

شغلنا النسخة المصلحة على اليومين، والمخرج كما يلي:

   text	   data	    bss	    dec	    hex	filename
   3606	      0	     96	   3702	    e76	fixed.elf
day 17/12/2006  minutes 1440  missing 0
energy kWh  56.508  (fixed)
peak W      7064 at minute 543 (9:03)
minutes > 3000 W  423
busiest hour 18:00  kWh 3.697
   text	   data	    bss	    dec	    hex	filename
   3606	      0	     96	   3702	    e76	fixed-gap.elf
day 21/12/2006  minutes 1440  missing 2
energy kWh  28.619  (fixed)
peak W      5854 at minute 1199 (19:59)
minutes > 3000 W  84
busiest hour 9:00  kWh 2.576

والآن الأرقام مطابقة للمرجع في الحالتين: 56.508 مقابل 56.507667 في اليوم الكامل، و28.619 مقابل 28.618533 في يوم القراءات المفقودة، والفرق في الخانة الرابعة فقط لأن البرنامج يقرب إلى ثلاث خانات عند الطباعة، وأعلى قراءة وساعتها، وعدد الدقائق فوق الحد، والساعة الأكثر استهلاكاً، كلها متطابقة. وانظر إلى سطر الحجم: البرنامج كاملاً 3606 بايت في قسم text، منها 2880 بايتاً لبيانات اليوم نفسه، أي أن الكود الفعلي أقل من 730 بايتاً، وقسم bss الذي فيه مجاميع الساعات 96 بايتاً فقط، وهذا يعني أن هذا الجزء من العداد لا يأخذ إلا جزءاً صغيراً جداً من ذاكرة أي متحكم حديث، ويبقى أغلب الفلاش والذاكرة لمكتبات الشبكة والتشفير والتحديث عن بعد.

ماذا يحدث إذا استخدمنا double بدل الأعداد الصحيحة؟

أغلب الطلاب يكتبون هذا الحساب بـ float أو double لأنه أسهل في القراءة، والسؤال المهم في متحكم مثل Cortex-M3: كم يكلف ذلك؟ فهذا المعالج لا يحتوي وحدة أعداد عشرية، والمترجم يحول كل عملية عشرية إلى استدعاء لدالة برمجية في libgcc. لذلك بنينا نفس البرنامج بالخيار USE_FLOAT، ثم عددنا التعليمات التي نفذها المعالج فعلاً بتشغيل QEMU في وضع يترجم كل تعليمة وحدها ويسجل تنفيذها، بالسكربت التالي:

#!/bin/sh
# count.sh <elf>: counts the guest instructions QEMU executes, one translation block per instruction,
# by logging every executed block. QEMU is not cycle-accurate: this is an instruction count, not a cycle count.
qemu-system-arm -M lm3s6965evb -nographic -semihosting -accel tcg,one-insn-per-tb=on \
  -d exec,nochain -D /tmp/exec.log -kernel "$1" > /dev/null
echo "$1: $(grep -c '^Trace' /tmp/exec.log) instructions executed"
rm -f /tmp/exec.log
   text	   data	    bss	    dec	    hex	filename
   6304	      0	     96	   6400	   1900	float.elf
day 17/12/2006  minutes 1440  missing 0
energy kWh  56.508  (double)
peak W      7064 at minute 543 (9:03)
minutes > 3000 W  423
busiest hour 18:00  kWh 3.697
fixed.elf: 30249 instructions executed
float.elf: 1826356 instructions executed

في النتيجة لاحظ التالي:

  • الأرقام المطبوعة نفسها لم تتغير، فلا توجد أي فائدة في الدقة من double في هذه المهمة، لأن القراءات أصلاً أعداد صحيحة بالواط.
  • حجم text ارتفع من 3606 إلى 6304 بايت، أي أن الكود الفعلي دون البيانات ارتفع من 726 بايتاً إلى 3424 بايتاً، وهذه الزيادة كلها دوال القسمة والجمع والتحويل العشرية من libgcc.
  • عدد التعليمات المنفذة ارتفع من 30249 إلى 1826356، أي أكثر من 60 ضعفاً، لأن كل قسمة على 1000 وعلى 60 بالأعداد العشرية أصبحت عشرات التعليمات بدل تعليمة جمع واحدة.
رسم مقارنة من ثلاث لوحات: الأولى حجم الكود دون البيانات 726 بايتاً بالأعداد الصحيحة مقابل 3424 بايتاً بـ double، والثانية التعليمات المنفذة 30249 مقابل 1826356 أي أكثر من 60 ضعفاً، والثالثة الطاقة لليوم الذي فيه قراءات مفقودة 30.795 كيلوواط ساعة قبل الإصلاح و28.619 بعده مطابقة للمرجع، مع أعلى قراءة 65535 واط قبل الإصلاح و5854 بعده
نفس النتيجة بأقل من خمس الكود وأقل من جزء من ستين من التعليمات، وقراءتان مفقودتان كانتا تكفيان لإفساد فاتورة اليوم

وقد يتساءل البعض: وهل يهم هذا الفرق إذا كان المعالج ينفذ ملايين التعليمات في الثانية؟ والإجابة أنه لا يهم في الزمن هنا، فحتى مليونا تعليمة تنتهي في جزء صغير من الثانية على 50 ميغاهيرتز، ولكنه يهم في الطاقة، لأن العداد الذي يعمل بالبطارية أو يريد أن ينام أطول وقت ممكن يدفع ثمن كل تعليمة من بطاريته، ويهم أكثر في العداد الحقيقي الذي يحسب القدرة من آلاف العينات في الثانية وليس من قراءة واحدة في الدقيقة. ولاحظ أن QEMU لا يحاكي التوقيت بدقة الدورة Cycle-Accurate، ولذلك قسنا عدد التعليمات ولم نقس الزمن، وهذا الفرق يجب أن تكتبه في تقريرك كما هو.

ما الذي يخفيه المحاكي Emulator Limits؟

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

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

سلم من أربع مراحل: اختبار المنطق على الحاسب بلغة Python أو C، ثم المحاكي مثل QEMU وRenode وWokwi للبرنامج الثابت كاملاً، ثم لوحة التطوير مع الحساس الحقيقي، ثم النموذج النهائي على لوحة مطبوعة PCB في الصندوق، وتحت كل مرحلة ما تكشفه وما لا تكشفه: المحاكي يكشف أخطاء الحساب والبيانات ولا يكشف التوقيت والطاقة والذاكرة غير المصفرة، واللوحة تكشف التوصيل والضوضاء، والنموذج النهائي يكشف الحرارة والتغليف
كل مرحلة تكشف أخطاء لا تكشفها التي قبلها، فلا تقفز إلى اللوحة قبل أن ينجح المنطق، ولا تكتف بالمحاكي

من المحاكاة إلى اللوحة Hardware Bring-up: خطة الفصلين

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

وفي طلب القطع ثلاث قواعد توفر عليك أسابيع. الأولى: اطلب من كل قطعة حرجة اثنتين، لأن الحساس الذي يحترق في أسبوع المناقشة بسبب توصيل خاطئ لا ينتظرك حتى يصل البديل. والثانية: اختر قطعاً لها توثيق ومجتمع، أي أن لها مشغلاً في ESP-IDF أو Zephyr أو مكتبة معروفة، والسبب أن الحساس الغامض الرخيص يأخذ من وقتك أكثر من فرق سعره. والثالثة: لا تصمم لوحة مطبوعة PCB في الفصل الأول، فلوحة التطوير وأسلاك التوصيل تكفي حتى يستقر التصميم، ثم صمم اللوحة إذا كان الوقت يسمح، بأداة مفتوحة مثل KiCad.

وإذا تأخرت القطع، فلا تتوقف، فالمحاكي Wokwi يحاكي ESP32 مع حساسات وشاشات شائعة في المتصفح، وRenode يحاكي لوحات كاملة ويستخدم في خطوط التكامل المستمر، وQEMU كما رأيت يكفي لاختبار المنطق. وتذكر أن تكتب في التقرير بوضوح أي نتيجة جاءت من المحاكي وأي نتيجة جاءت من العتاد، لأن خلط الاثنين أسرع طريقة لتفقد ثقة اللجنة.

أخطاء شائعة Common Mistakes في مشاريع هندسة الحاسب

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

قائمة تحقق Checklist قبل اجتماع المشرف

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

الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

  • مشروع هندسة الحاسب يختلف عن المشروع البرمجي في ثلاثة أشياء: العتاد له زمن وكلفة، واللجنة تسأل عن القياس، والسلامة جزء من التصميم.
  • البكالوريوس تجربة تصميم لفريق في فصلين تبني وتقيس، والماجستير سؤال بحثي لفرد بمساهمة جديدة وتقييم قابل للتكرار.
  • ثماني أفكار للبكالوريوس: عداد الطاقة، والري، وجودة الهواء، وعد الحشود دون تصوير، وشبكة CAN، ومعالج RISC-V على FPGA، واللوحة العربية بالحبر الإلكتروني، والمساهمة في Zephyr.
  • ست أفكار للماجستير: الجدولة في أنظمة الزمن الحقيقي، والمسرعات العتادية، وTinyML لكشف الأعطال، وحصاد الطاقة، وتحمل الأخطاء العتادية، ودقة المحاكيات.
  • الفكرة المستهلكة تنقذ إذا وجدت فيها قراراً هندسياً وجعلته مركز المشروع، وإلا فاتركها.
  • في التجربة العملية عالج برنامج ثابت على Cortex-M3 في QEMU يوماً حقيقياً من 1440 قراءة بأقل من 730 بايتاً من الكود ونحو 30 ألف تعليمة، وطابق المرجع، وكشفت التجربة أن قراءتين مفقودتين ترفعان طاقة اليوم 7.6%، وأن double يضاعف التعليمات أكثر من 60 مرة دون أي فائدة في الدقة.
  • المحاكي لاختبار المنطق في الأسبوع الأول، واللوحة لكل رقم أداء أو طاقة في التقرير.

وإذا لم تقرأ بعد دليل التخصص نفسه فابدأ من دليل هندسة الحاسب ومنهج CE2016، وإذا كنت ما زلت تقارن بين التخصصات فاقرأ أي تخصص تقني تختار؟. وأقرب المقالات إلى هذا الموضوع على الموقع:

دليلهندسة الحاسب Computer Engineering: منهج CE2016 ومواد الجامعةلماذا يدرس طالب هندسة الحاسب الدوائر والإشارات والمعمارية بحسب منهج CE2016، وأين تقصر خطط الجامعات السعودية، وكيف تكمل الباقي بيدك.دليلكيف يعمل المعالج CPU من الداخل ولماذا يهمك ذلكنتابع تعليمة واحدة داخل نواة المعالج، ونرى لماذا يصبح نفس الكود أبطأ بعشر مرات عندما تغير ترتيب المرور على البيانات.دليلكيف تعمل الذاكرة RAM من الداخل، ولماذا تحتاج التحديث Refreshنفتح وحدة الذاكرة من الشريحة إلى الخلية، لتفهم ما تعنيه الأرقام المكتوبة عليها عندما تشتري جهازاً أو تختار سيرفراً.دليلالبوابات المنطقية Logic Gates: من الترانزستور إلى الجامعنبني من بوابة NAND واحدة دائرة تجمع رقمين وأخرى تحفظ الناتج، ونرى في محاكي Python لماذا للمعالج سرعة قصوى ولماذا يحتاج إلى ساعة.دليللغة C لمن يبرمج بلغة أخرى: المترجم GCC والأدواتنبني مكتبة صغيرة تحسب ضريبة الفاتورة بالهللات بأحدث GCC، ونمر على ما يختلف في C عما تعرفه، ومراحل الترجمة، والتحذيرات، وCMake، وأدوات التنسيق والفحص والاختبار والتصحيح.دليلأنظمة الحشود الكبرى: كيف تصمد في مواسم الحج والعمرةكيف تصمم نظام حجز وتصاريح يتحمل ملايين الطلبات في مواعيد معروفة مسبقاً، وماذا تطفئ عندما يتجاوز الضغط خطتك.دليلتجميع طائرة مسيرة رباعية: من القطع إلى أول إقلاعكيف تختار قطع طائرة رباعية وتحسب دفعها وزمن طيرانها من جداول المحركات، ثم توصلها وتضبطها بأمان قبل أول إقلاع.دليلكيف تجد الفجوة البحثية Research Gap في الأدبيات العلمية؟أين تبحث عن الأبحاث المنشورة، وكيف ترسم خريطة موضوعك بالأرقام عبر OpenAlex وSemantic Scholar، ثم تتحقق من الفجوة قبل أن تبني عليها.

سجل التحديثات

  • نوفمبر 2026: كتابة المقال، وتشغيل تجربة عداد الطاقة على arm-none-eabi-gcc 14.2.1 وQEMU 10.0.13 بلوحة lm3s6965evb داخل Container من debian:trixie-slim، ببيانات يومي 17 و21 ديسمبر 2006 من مجموعة UCI لاستهلاك الكهرباء المنزلي، والتحقق من روابط مصادر البيانات والأدوات.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.