3.1. المتحكمات الدقيقة

تعمل OpenMV Cam على متحكم دقيق (MCU): شريحة واحدة تجمع بين وحدة معالجة مركزية CPU وذاكرة عمل (RAM) ووحدة تخزين البرامج (ذاكرة فلاش) ومجموعة من الطرفيات -- وهي كتل أجهزة للتفاعل مع العالم الخارجي.

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

تغلّف MicroPython تلك السجلات في صفوف داخل وحدة machine. تُرجع machine.Pin(...) كائناً يتحكم في دبوس إدخال/إخراج للأغراض العامة (GPIO) -- وهو سلك يمكن للشريحة إبقاؤه مرتفعاً (حوالي 3.3 فولت) أو منخفضاً (حوالي 0 فولت)، أو قراءته على أنه إحدى هاتين الحالتين عندما يدفعه شيء خارجي. تكشف machine.ADC(...) المحوّل التماثلي إلى الرقمي، الذي يقيس الجهد على دبوس ويبلّغ عنه كرقم. تشغّل machine.UART(...) مستقبِلاً/مرسِلاً غير متزامن عالمياً (UART) -- وهي طرفية ترسل وتستقبل البايتات بتاً واحداً في كل مرة عبر زوج من الأسلاك، TX (الإرسال) وRX (الاستقبال). تغطي صفوف أخرى بقية الطرفيات. يقرأ البرنامج النصي كائنات Python ويكتبها؛ وتترجم MicroPython كل وصول إلى قراءات وكتابات السجلات المقابلة، وتلك تحرّك بتات على أسلاك فعلية.

A single chip outline containing labelled blocks -- CPU, RAM, flash, and a row of peripheral blocks (GPIO, ADC, Timer/PWM, UART/SPI/I2C, CAN) connected by an internal bus, with arrows from each peripheral exiting the chip toward physical pin labels.

تجمع وحدة MCU بين وحدة المعالجة المركزية والذاكرة والطرفيات في شريحة واحدة. تُكشف كل طرفية لـ Python عبر صف في وحدة machine.

3.1.1. الحلقة الرئيسية

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

# setup, runs once
from machine import Pin
led = Pin("P0", Pin.OUT)

# main loop, runs forever
while True:
    led.value(1)
    # ... do work ...
    led.value(0)
    # ... do other work ...

هذا الشكل -- الإعداد مرة واحدة ثم التكرار إلى الأبد -- هو نمط الحلقة الرئيسية. وكل ما يلي يتعلق بما يدخل بداخلها.

3.1.2. التحكم في الزمن الحقيقي

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

برنامج المتحكم الدقيق هو العكس. افتراضياً لا يوجد نظام تشغيل، ولا مجدوِل، ولا خيط آخر. الحلقة الرئيسية المعروضة للتو هي الحلقة الوحيدة. تطلق الطرفيات مقاطعات أو تكشف رايات حالة؛ والحلقة تستطلعها أو تعالج المقاطعات مباشرة. إذا توقفت الحلقة في time.sleep_ms(1000)، فلن يفعل الجهاز شيئاً خلال تلك الثانية؛ فلا يوجد خيط آخر يملأ الفجوة.

تنتج عن ذلك نتيجتان تنطبقان في كل مكان:

  • الزمن حقيقي. قراءة دبوس مرتين في حلقة محكمة تستغرق ميكروثوانٍ؛ والنوم لعشرة مللي ثانية يعني عشرة مللي ثانية لا يحدث خلالها أي شيء آخر. ونمط التوقيت غير الحاجب هو الاستجابة لذلك.

  • الأجهزة حقيقية. ضبط machine.Pin.value على 1 يضع حوالي 3.3 فولت على سلك فعلي؛ وضبطه على 0 يضع حوالي 0 فولت هناك. تشاهد أجزاء أخرى من الدائرة ذلك الجهد فوراً -- بما في ذلك أي مكونات قد يتلفها الدبوس إذا دُفع بشكل خاطئ.