OpenMV Pure Thermal¶
إن OpenMV Pure Thermal هي لوحة تصوير حراري متكاملة النظام مبنية حول المعالج STMicroelectronics STM32H743 (Cortex‑M7 بتردد 480 MHz) مع 64 MB من ذاكرة SDRAM خارجية، و32 MB من ذاكرة فلاش QSPI، ومُرمِّز JPEG عتادي، وشاشة لمس سعوية IPS مقاس 4.3" بدقة 800×480، ومخرج HDMI، ومقبس حراري FLIR® Lepton®، وكاميرا ضوء مرئي OV5640 بدقة 5 ميجابكسل. كما تتضمن Wi‑Fi، ومقبس microSD، ومقياس مدى بالليزر، وجرس صفّارة، ومُضيء أبيض عالي الطاقة.
للاطلاع على ورقة البيانات الكاملة والصور والأبعاد، راجع صفحة منتج OpenMV Pure Thermal.
أبرز المواصفات¶
STMicroelectronics STM32H743XI بنواة Cortex‑M7 بتردد 480 MHz.
مُرمِّز/فاك ترميز JPEG عتادي.
64 MB من ذاكرة SDRAM خارجية (~400 MB/s) بالإضافة إلى 1 MB من ذاكرة SRAM داخلية.
2 MB من ذاكرة فلاش داخلية + 32 MB من ذاكرة فلاش QSPI خارجية (قراءة ~50 MB/s).
مستشعر ضوء مرئي OV5640 بدقة 5 ميجابكسل بمصراع متدحرج.
مقبس FLIR® Lepton® — يقبل أي وحدة Lepton طراز 1/2/2.5/3/3.5، إشعاعية أو غير إشعاعية، مع قياس درجة الحرارة لكل بكسل بالدرجات المئوية.
شاشة لمس سعوية IPS مقاس 4.3" بدقة 800×480 (لون 24‑بت بتردد 60 Hz) مع دعم إيماءات يصل إلى 5 نقاط.
مخرج HDMI عبر مُسلسِل DVI من نوع TFP410 — حتى دقة 1280×720 بتردد 60 Hz.
Wi‑Fi عبر WINC1500؛ مع دعم MJPEG عبر RTSP جاهزاً للاستخدام.
USB‑C بسرعة كاملة (12 Mb/s، محدود التيار عند 900 mA) — يظهر للمضيف كـ VCP + جهاز تخزين USB، ويتولى الشحن أيضاً.
مقبس microSD — بطاقات SD حتى 2 GB، وSDHC حتى 32 GB، وSDXC حتى 2 TB.
مقياس مدى بالليزر VL53L1CX (حتى ~4 أمتار).
جرس صفّارة مع التحكم بالصوت/التردد برمجياً.
مُضيء LED أبيض عالي الطاقة بالإضافة إلى مؤشر LED RGB للمستخدم.
موصّل بطارية LiPo مع شحن عبر USB بتيار 500 mA.
10 دبابيس إدخال/إخراج، تتحمل 5 فولت بمخرج 3.3 فولت، 25 mA لكل دبوس (120 mA إجمالاً)، قابلة للمقاطعة. لا يتحمل الدبوس P6 جهد 5 فولت عند استخدامه في وضع ADC أو DAC.
موصّل ARM SWD ذو 10 دبابيس لتصحيح الأخطاء عبر ST‑LINK / J‑Link.
موصّل Qwiic للطرفيات على ناقل I²C.
ملاحظة
تحتوي اللوحة على فتحة عند حافتها السفلية اليسرى لتركيب صامولة حامل ثلاثي القوائم بمقاس ¼"–20 اختيارية. وهي غير مركّبة من المصنع — قم بلحام واحدة في الفتحة إذا أردت تثبيت اللوحة على حامل كاميرا ثلاثي قياسي.
مخطط الدبابيس¶
مرجع الدبابيس¶
اسم الدبوس |
الوظيفة |
|---|---|
P0 |
UART1 RX / SPI2 MOSI |
P1 |
UART1 TX / SPI2 MISO |
P2 |
SPI2 SCK / FDCAN2 TX |
P3 |
SPI2 NSS (CS) / FDCAN2 RX |
P4 |
I2C2 SCL / UART3 TX / TIM2 CH3 |
P5 |
I2C2 SDA / UART3 RX / TIM2 CH4 |
P6 |
ADC / DAC / TIM2 CH1 |
P7 |
I2C4 SCL / TIM4 CH1 |
P8 |
I2C4 SDA / TIM4 CH2 |
P9 |
إدخال/إخراج رقمي |
RESET |
اوصله بـ GND لإعادة ضبط اللوحة |
SYN |
وسادة مزامنة الإطارات — غير موصولة |
VIN |
وسادة VIN للدرع — غير موصولة |
BOOT0 |
اوصله بـ 3.3 فولت عند التشغيل لدخول وضع DFU / محمّل إقلاع ROM |
BUZZER |
جرس الصفّارة البيزو على اللوحة (مدفوع عبر TIM2/PWM) |
LED_RED |
القناة الحمراء لمؤشر LED RGB للحالة (فعّال عند المنخفض) |
LED_GREEN |
القناة الخضراء لمؤشر LED RGB للحالة (فعّال عند المنخفض) |
LED_BLUE |
القناة الزرقاء لمؤشر LED RGB للحالة (فعّال عند المنخفض) |
LED_WHITE |
مُضيء LED أبيض عالي الطاقة |
ملاحظة
وسادتا SYN وVIN على الدرع/الترويسة ليس لهما أي اتصال كهربائي على Pure Thermal — فهما موجودتان لأغراض التوافق مع الترويسة فقط. شغّل اللوحة بدلاً من ذلك عبر USB‑C أو موصّل بطارية LiPo على اللوحة (راجع دبابيس الطاقة أدناه). لاحظ أيضاً أن وسادة VIN مطبوعة بالحرير VBAT على اللوحة (خطأ في الوسم) — الموضع هو دبوس VIN القياسي في ترويسة OpenMV وهو غير موصول في كلتا الحالتين.
دبابيس الطاقة¶
3.3V — خط طاقة 3.3 فولت منظَّم. يتوفر حتى 250 mA للدروع.
GND — الأرضي المشترك.
تُغذَّى Pure Thermal بالطاقة عبر USB‑C أو موصّل بطارية LiPo على اللوحة. منفذ USB‑C محدود التيار عند 900 mA إجمالاً ويتولى أيضاً شحن LiPo بتيار 500 mA، لذا فإن توصيل بطارية إلى جانب USB مدعوم.
يبدّل زر الطاقة على اللوحة خطوط طاقة النظام بين التشغيل والإيقاف ويعمل سواء كانت اللوحة مُغذّاة من USB أو من LiPo. اضغط مع الاستمرار على الزر لبضع ثوانٍ لتغيير الحالة — يُتجاهل النقر السريع لمنع الإيقاف العرضي.
يتبع اختيار المصدر قاعدتين بسيطتين:
لا تُغذّي البطارية اللوحة إلا عندما يكون جهدها أعلى من 3 فولت. وأدنى من تلك العتبة تفصل دائرة PMIC على اللوحة البطارية لحمايتها من التفريغ المفرط.
عند وجود USB، فإن USB يُغذّي اللوحة وتُشحن أي بطارية LiPo موصولة في الخلفية.
كما يتميز موصّل LiPo بـ حماية من عكس الجهد، لذا فإن توصيل البطارية بشكل معكوس لن يضر باللوحة.
ملاحظة
كما توجّه اللوحة إشارتي جهد البطارية واستشعار تيار البطارية إلى قنوات ADC في المتحكم الدقيق، لكن لم يُضَف بعد دعم البرنامج الثابت لأي منهما.
دبابيس الاسترداد وتصحيح الأخطاء¶
RESET — اوصله بـ GND لإعادة ضبط اللوحة. تحتوي Pure Thermal أيضاً على زر RESET مخصص على اللوحة يقوم بالشيء نفسه.
BOOT0 — اوصله بـ 3.3 فولت أثناء تشغيل اللوحة لدخول محمّل إقلاع ROM في STM32 (وضع DFU). يستخدم OpenMV IDE هذا الوضع لإعادة تحميل محمّل الإقلاع على اللوحة. يوجد زر BOOT0 مخصص على اللوحة يقوم بالشيء نفسه — اضغط مع الاستمرار عليه أثناء توصيل الطاقة.
تعرض اللوحة ترويسة تصحيح أخطاء SWD (RST / SWCLK / SWDIO / SWO) بجوار ترويسة GPIO، متوافقة مع مهايئات ST‑LINK وSEGGER J‑Link. كما رُكّب موصّل منفصل ARM SWD ذو 10 دبابيس — يحمل إشارات SWD نفسها (دون JTAG كامل) لكن بالشكل القياسي ذي العشرة دبابيس بمقاس 0.05".
ملاحظة
دبوس تتبع SWO مشترك مع ساعة SPI الخاصة بـ FLIR® Lepton® على اللوحة. لا يمكن استخدام SWO في الوقت نفسه مع Lepton — اختر أحدهما.
رُكّب على اللوحة موصّل ثالث باسم PURE Modules Debug. وهو يُخرج حفنة من الإشارات الموجهة لتصحيح الأخطاء (SWCLK، وSWDIO، وRST، وSPI2_MISO، وSPI2_MOSI، وVBUS، و3.3 فولت، وGND، ودبوسي GPIO) لتوصيل وحدات مرافقة. ويُدفع دبوسا GPIO على هذا الموصّل عبر ناقل I²C مُحاكى ببرمجة البتات بدلاً من طرفية عتادية.
تشير موصّلات تصحيح الأخطاء الثلاثة جميعها (ترويسة SWD المضمّنة، وموصّل ARM SWD ذو 10 دبابيس، وموصّل PURE Modules Debug) إلى 3.3 فولت — تأكد من ضبط مهايئ تصحيح الأخطاء لديك على منطق 3.3 فولت قبل التوصيل.
الطرفيات المدمجة على اللوحة¶
مؤشرات LED¶
تحتوي Pure Thermal على ثلاثة مؤشرات LED على اللوحة:
مؤشر LED RGB للمستخدم — قابل للتحكم برمجياً، ومعروض كـ
LED_REDوLED_GREENوLED_BLUEfrom machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
المُضيء الأبيض — مدفوع عبر
LED_WHITE. سُلِّكLED_WHITEليكون فعّالاً عند المرتفع في العتاد بينما يعامل البرنامج الثابت كل مؤشر LED آخر على اللوحة على أنه فعّال عند المنخفض، لذا استخدمlow()/high()بدلاً منon()/off()(التي ستعكس المنطق):from machine import LED light = LED("LED_WHITE") light.low() # turn the white LED ON light.high() # turn the white LED OFF
مؤشر LED للشحن — مدفوع مباشرة بعتاد إدارة الطاقة على اللوحة، دون أي تحكم برمجي. ويعمل سواء كانت خطوط طاقة النظام قيد التشغيل أو الإيقاف (أي مع زر الطاقة في أي من الوضعين).
اللون
المعنى
أزرق
قيد الشحن — راجع قائمة الأخطاء: قد لا ينطفئ عند اكتمال الشحن
أخضر
اكتمل الشحن — راجع قائمة الأخطاء: قد لا يُفعَّل بشكل موثوق
أحمر
بطارية منخفضة (≤ 3.2 فولت، فقط عند عدم الشحن الفعّال)
جرس الصفّارة¶
جرس الصفّارة البيزو على اللوحة مُسلَّك إلى قناة مؤقت — ادفعه باستخدام machine.PWM لإصدار نغمات مع التحكم برمجياً في التردد (طبقة الصوت) ودورة التشغيل (مستوى الصوت):
import time
from machine import Pin, PWM
beep = PWM(Pin("BUZZER"), freq=2_000, duty_u16=32768) # ~50% duty
time.sleep_ms(500) # sound for 0.5 s
beep.deinit()
مستشعر الكاميرا¶
إن OV5640 هو CSI الأساسي على Pure Thermal — مرّر cid=csi.OV5640 لمخاطبته صراحةً:
import csi
cam = csi.CSI(cid=csi.OV5640)
cam.reset(hard=True)
cam.pixformat(csi.RGB565)
cam.framesize(csi.WVGA)
cam.snapshot(time=2000) # let auto‑exposure settle
while True:
img = cam.snapshot()
يحتوي OV5640 على ضاغط JPEG على اللوحة. اضبط csi.CSI.pixformat على csi.JPEG فيقوم المستشعر بتسليم إطارات مضغوطة مباشرة إلى الكاميرا عبر ناقل الكاميرا، مما يجعل الالتقاطات عالية الدقة عملية: تُبثّ جميع csi.HD (1280×720) وcsi.FHD (1920×1080) ودقة 5 ميجابكسل الكاملة csi.WQXGA2 (2592×1944) بصيغة JPEG. اضبط الضغط عبر csi.CSI.quality (0-100، الأعلى = إطارات أكبر وتفاصيل أكثر):
cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)
يحتوي OV5640 على عدسة تركيز تلقائي مُحرَّكة بمشغّل ملف صوتي. شغّل تمريرة تركيز تلقائي واحدة عبر csi.CSI.ioctl مع csi.IOCTL_TRIGGER_AUTO_FOCUS — يكنس المستشعر محرك التركيز مرة واحدة ويثبّت على أي شيء أمامه:
cam.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)
أعد إصدار ioctl في أي وقت يتغير فيه المشهد — التركيز التلقائي ذو لقطة واحدة، وليس مستمراً.
ملاحظة
مخرج STROBE الخاص بـ OV5640 (يُستخدم للفلاش المتزامن / إضاءة الأشعة تحت الحمراء) مُسلَّك إلى المتحكم الدقيق على Pure Thermal، لكن لم يُضَف بعد دعم البرنامج الثابت له.
مستشعر الكاميرا الحرارية¶
يظهر مقبس FLIR® Lepton® كـ CSI ثانٍ على واجهة csi --- مستشعرات الكاميرا نفسها. مرّر cid=csi.LEPTON لمخاطبته، وتخطَّ إعادة ضبط العتاد:
import csi
lepton = csi.CSI(cid=csi.LEPTON)
lepton.reset(hard=False)
lepton.pixformat(csi.GRAYSCALE)
lepton.framesize(csi.QVGA)
while True:
img = lepton.snapshot()
ملاحظة
مخرج VSYNC الخاص بـ Lepton (نبضة واحدة لكل إطار حراري) مُسلَّك إلى المتحكم الدقيق على Pure Thermal، لكن لم يُضَف بعد دعم البرنامج الثابت له.
يمكن تشغيل كلا CSI جنباً إلى جنب. يسحب المثال أدناه إطاراً ملوناً من OV5640 وإطاراً حرارياً من Lepton، ثم يطبق Lepton فوق الإطار الملون باستخدام لوحة ألوان Ironbow وقناع ألفا يتلاشى ليصبح شفافاً عند الكثافات المنخفضة:
import csi
import image
import math
alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
alpha_pal[i] = int(math.pow((i / 255), 2) * 255)
csi0 = csi.CSI()
csi0.reset(hard=True)
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.WVGA)
csi1 = csi.CSI(cid=csi.LEPTON)
csi1.reset(hard=False)
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize(csi.QVGA)
img1 = image.Image(csi1.width(), csi1.height(), csi1.pixformat())
while True:
img0 = csi0.snapshot()
csi1.snapshot(blocking=False, image=img1)
img0.draw_image(
img1, 0, 0,
color_palette=image.PALETTE_IRONBOW,
alpha_palette=alpha_pal,
hint=image.BILINEAR,
)
تعلّم الآلة¶
تشغّل ml --- التعلم الآلي نماذج TFLite المُكمَّمة على نواة Cortex‑M7 باستخدام نوى CMSIS‑NN — وهي سريعة بما يكفي للكواشف المدمجة عند بضعة إطارات في الثانية. تُحمَّل النماذج الموجودة على نظام الملفات للقراءة فقط /rom مباشرة من الفلاش دون نسخها إلى RAM. إليك كاشف وجوه BlazeFace بدقة 128×128 يطبق الوجه المكتشف ونقاطه الست المميزة على كل إطار من كاميرا الضوء المرئي:
import csi
import time
import ml
from ml.postprocessing.mediapipe import BlazeFace
# Initialize the sensor.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi0.window((400, 400))
# Load built-in face detection model
model = ml.Model("/rom/blazeface_front_128.tflite", postprocess=BlazeFace(threshold=0.4))
print(model)
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
# faces is a list of ((x, y, w, h), score, keypoints) tuples
for r, score, keypoints in model.predict([img]):
ml.utils.draw_predictions(img, [r], ("face",), ((0, 0, 255),), format=None)
# keypoints is a ndarray of shape (6, 2)
# 0 - right eye (x, y)
# 1 - left eye (x, y)
# 2 - nose (x, y)
# 3 - mouth (x, y)
# 4 - right ear (x, y)
# 5 - left ear (x, y)
ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))
print(clock.fps(), "fps")
مقياس المدى بالليزر¶
مقياس المدى بزمن الرحلة من نوع ST VL53L1CX على اللوحة مُسلَّك إلى ناقل I²C رقم 2. استخدم المُشغّل المجمَّد vl53l1x --- مشغّل مستشعر المسافة VL53L1X بتقنية ToF للحصول على قراءات المسافة حتى ~4 أمتار:
import time
from machine import I2C
import vl53l1x
bus = I2C(2)
tof = vl53l1x.VL53L1X(bus)
while True:
print("Distance:", tof.read(), "mm")
time.sleep_ms(100)
مخرج LCD¶
شاشة LCD مقاس 4.3" على اللوحة بدقة 800 × 480 (WVGA) ومدفوعة عبر واجهة عرض RGB في وحدة display --- مشغّل العرض — مرّر framesize=display.FWVGA لمطابقة دقتها الأصلية:
import display
lcd = display.RGBDisplay(framesize=display.FWVGA, refresh=60)
lcd.backlight(True) # turn the LCD backlight on
lcd.write(img)
الإضاءة الخلفية مُسلَّكة إلى GPIO، لذا تقبل backlight() القيمة True / False (أو أي قيمة بين 0–100، حيث 0 يعني إيقاف وأي قيمة غير صفرية تعني تشغيل):
lcd.backlight(False) # turn the backlight off
lcd.backlight(True) # back on
شاشة اللمس¶
متحكم اللمس السعوي هو FT5X06؛ تُعرض مواضع اللمس المتعدد وأحداث الإيماءات عبر ft5x06 --- مشغّل شاشة اللمس. سجّل دالة رد نداء للتفاعل مع اللمسات واقرأ النقاط النشطة بداخلها:
import ft5x06
touch = ft5x06.FT5X06()
def on_touch(n):
for i in range(n):
x = touch.get_point_x(i)
y = touch.get_point_y(i)
print("touch", i, "at", x, y)
gesture = touch.get_gesture()
if gesture != ft5x06.GESTURE_NONE:
print("gesture:", gesture)
touch.touch_callback(on_touch)
مخرج HDMI¶
يوزّع البرنامج الثابت أيضاً مخزن إطارات LCD إلى مُسلسِل HDMI من نوع tfp410 --- وحدة تحكم DVI/HDMI على اللوحة، بحيث تعكس شاشة خارجية ما يظهر على LCD. أنشئ نسخة من tfp410.TFP410 لتفعيل مخرج HDMI:
import tfp410
hdmi = tfp410.TFP410()
إذا كنت تريد مخرج HDMI فقط ولا يهمك شاشة LCD على اللوحة، أطفئ الإضاءة الخلفية وارفع دقة مخزن الإطارات فوق WVGA. يدعم TFP410 حتى دقة 1280×720 بتردد 60 Hz، فعلى سبيل المثال:
lcd = display.RGBDisplay(framesize=display.HD, refresh=60)
lcd.backlight(False) # the on‑board LCD can't render HD
hdmi = tfp410.TFP410()
اللوحة الموجودة على اللوحة الإلكترونية ثابتة عند دقة 800×480، لذا فإن أي دقة أعلى من WVGA لها معنى فقط على شاشة HDMI الخارجية.
لمعرفة متى تم توصيل شاشة HDMI أو فصلها، سجّل دالة رد نداء للتوصيل السريع على TFP410. تُطلَق دالة رد النداء بقيمة True عند التوصيل وFalse عند الفصل:
def on_hotplug(connected):
print("HDMI", "connected" if connected else "disconnected")
hdmi.hotplug_callback(on_hotplug)
يمكنك أيضاً استطلاع حالة الاتصال في أي وقت باستخدام isconnected() (فقط عند عدم تسجيل دالة رد نداء).
يحمل منفذ HDMI أيضاً قناتي DDC (بيانات العرض) وCEC (التحكم بالإلكترونيات الاستهلاكية)، المعروضتين عبر صنف class DisplayData -- بيانات العرض. استخدمه لقراءة كتلة EDID الخاصة بالشاشة الموصولة (لتتمكن من التكيف مع دقتها الأصلية / معدل تحديثها) أو لإرسال/استقبال إطارات CEC للتحكم بأجهزة HDMI أخرى على السلك نفسه:
from display import DisplayData
dd = DisplayData(cec=True, ddc=True)
edid = dd.display_id() # EDID bytes from the monitor
print(len(edid), "byte EDID")
# Send a CEC "image view on" command (opcode 0x04) from address 1 to address 0
dd.send_frame(0, 1, b"\x04")
# ...or wait for an incoming CEC frame addressed to us (logical address 1)
src, data = dd.receive_frame(1, timeout=5_000)
print("CEC from", src, ":", data)
Wi‑Fi¶
يعمل Wi‑Fi عبر وحدة Microchip WINC1500، المعروضة عبر واجهة class WINC -- مشغّل درع WiFi
import network, time
wlan = network.WINC()
wlan.connect("ssid", "password")
while not wlan.isconnected():
time.sleep(1)
print("Wi‑Fi IP:", wlan.ipconfig("addr4")[0])
ملاحظة
بسبب نقص في القطع، شُحنت بعض وحدات Pure Thermal دون تركيب وحدة WINC1500. إذا أطلقت network.WINC خطأً أو لم تتصل مطلقاً، تحقق من اللوحة بحثاً عن وحدة Wi‑Fi مفقودة — تعمل بقية الكاميرا بالطريقة نفسها تماماً بدونها.
بطاقة microSD¶
عند إدخال بطاقة، تُركَّب تلقائياً عند /sdcard وتكون قابلة للاستخدام عبر نظام الملفات العادي:
import os
for entry in os.listdir("/sdcard"):
print(entry)
مرجع النواقل¶
GPIO¶
استخدم machine.Pin لقراءة أو دفع أي من الدبابيس المطبوعة بالحرير. المخارج بمنطق CMOS بجهد 3.3 فولت، تتحمل 5 فولت على جانب الإدخال، ويمكنها سحب/مصدرة حتى 25 mA لكل دبوس (120 mA إجمالاً عبر الترويسة بأكملها).
from machine import Pin
out = Pin("P0", Pin.OUT)
out.on()
out.off()
out.value(1)
inp = Pin("P1", Pin.IN, Pin.PULL_UP)
print(inp.value())
يمكن لأي دبوس إدخال أيضاً إطلاق مقاطعة عند انتقالات الحافة:
def handler(pin):
print("triggered:", pin)
Pin("P1", Pin.IN, Pin.PULL_UP).irq(
handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)
UART¶
الناقل |
TX |
RX |
|---|---|---|
UART1 |
P1 |
P0 |
UART3 |
P4 |
P5 |
from machine import UART
uart = UART(3, baudrate=115200)
uart.write("hello")
uart.read(5)
I²C¶
الناقل |
SCL |
SDA |
|---|---|---|
I2C2 |
P4 |
P5 |
I2C4 |
P7 |
P8 |
from machine import I2C
i2c = I2C(2, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")
يمكن أيضاً استخدام العتاد نفسه في وضع الهدف (التابع) عبر machine.I2CTarget لعرض منطقة ذاكرة لمتحكم I²C آخر:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(2, addr=0x42, mem=buf)
يُخرج موصّل Qwiic على اللوحة أحد ناقلي I²C هذين للوحدات الجاهزة للتوصيل والتشغيل. خط Qwiic مُحوَّل المستوى إلى 5 فولت عبر ترانزستورات مفتوحة المصرف، لذا فإن الناقل محدود بـ الوضع القياسي (100 kHz) والوضع السريع (400 kHz) فقط — لا تحاول تشغيل الوضع السريع‑بلس أو معدلات أعلى عبر ترويسة Qwiic.
يُخرج موصّل Qwiic جهد 5 فولت لتغذية الوحدات الموصولة؛ ولا يمكن استخدامه لتغذية Pure Thermal نفسها — شغّل اللوحة بدلاً من ذلك عبر USB‑C أو موصّل بطارية LiPo.
SPI¶
الناقل |
MOSI |
MISO |
SCK |
CS |
|---|---|---|---|---|
SPI2 |
P0 |
P1 |
P2 |
P3 |
from machine import SPI
from machine import Pin
spi = SPI(2, baudrate=10_000_000)
cs = Pin("P3", Pin.OUT, value=1) # CS is not driven by the SPI peripheral
cs.value(0)
spi.write(b"hello")
cs.value(1)
CAN (FDCAN)¶
الناقل |
TX |
RX |
|---|---|---|
FDCAN2 |
P2 |
P3 |
from machine import CAN
can = CAN(2, 500_000)
can.set_filters(None)
can.send(0x123, b"\xDE\xAD\xBE\xEF")
print(can.recv())
ADC وDAC¶
إن P6 هو دبوس المستخدم التناظري الوحيد. يمكن استخدامه إما كمدخل ADC بدقة 12‑بت أو كمخرج DAC.
ADC — المقياس الكامل عند 3.3 فولت على الدبوس:
from machine import ADC import time adc = ADC("P6") while True: voltage = adc.read_u16() * 3.3 / 65535 print(voltage) time.sleep_ms(100)
DAC — عبر
pyb.DAC. تغطي القيمة ذات 8‑بت النطاق من 0 إلى 3.3 فولت:from pyb import DAC dac = DAC("P6") voltage = 1.65 dac.write(int(voltage / 3.3 * 255))
في وضع ADC أو DAC، فإن P6 يتحمل 3.3 فولت فقط — لا تُغذّه بـ 5 فولت.
PWM¶
الدبوس |
المؤقت / القناة |
|---|---|
P4 |
TIM2 CH3 |
P5 |
TIM2 CH4 |
P6 |
TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
ملاحظة
TIM1 محجوز من قبل البرنامج الثابت لتوليد ساعة بكسل مستشعر الكاميرا، لذا فإن قنوات TIM1 الموجودة فعلياً على P0/P1/P2 لا يمكن استخدامها لـ PWM الخاص بالمستخدم دون تعطيل الكاميرا.
TIM4 مشترك مع pyb.Servo — إنشاء نسخة من servo يعيد ضبط المؤقت بأكمله للعمل عند 50 Hz، لذا لا تخلط بين machine.PWM على P7/P8 وpyb.Servo في البرنامج النصي نفسه.
ادفع أياً منها عبر machine.PWM
from machine import Pin, PWM
pwm = PWM(Pin("P7"), freq=1_000, duty_u16=32768)
النواقل المُحاكاة برمجياً ببرمجة البتات¶
تعمل machine.SoftI2C وmachine.SoftSPI على أي GPIO إذا احتجت إلى ناقل إضافي.
المستشعر الحراري (خارج اللوحة)¶
بالإضافة إلى FLIR Lepton على اللوحة، يتضمن البرنامج الثابت أيضاً مُشغّل fir --- مشغّل المستشعر الحراري (fir == far infrared) لأجهزة التصوير الحراري عبر I²C الموصولة خارجياً:
MLX90621 — مصفوفة أشعة تحت حمراء 16 × 4
MLX90640 — مصفوفة أشعة تحت حمراء 32 × 24
MLX90641 — مصفوفة أشعة تحت حمراء 16 × 12
AMG8833 — مصفوفة أشعة تحت حمراء 8 × 8
وصّل الوحدة إلى ناقل I²C في اللوحة واقرأ الإطارات باستخدام fir.init() + fir.snapshot()
import time
import image
import fir
fir.init() # auto‑detects the sensor
clock = time.clock()
while True:
clock.tick()
try:
img = fir.snapshot(x_scale=5, y_scale=5,
color_palette=image.PALETTE_IRONBOW,
hint=image.BICUBIC,
copy_to_fb=True)
except OSError:
continue
print(clock.fps())
لا يتواصل مُشغّل fir مع المستشعر إلا عبر I²C 2 — وصّل الوحدة إلى P4 (SCL) وP5 (SDA).
التوقيت¶
time¶
import time
time.sleep(1)
time.sleep_ms(500)
time.sleep_us(10)
start = time.ticks_ms()
elapsed = time.ticks_diff(time.ticks_ms(), start)
المؤقتات الافتراضية¶
from machine import Timer
one_shot = Timer(-1)
one_shot.init(period=5_000, mode=Timer.ONE_SHOT,
callback=lambda t: print("once"))
periodic = Timer(-1)
periodic.init(period=2_000, mode=Timer.PERIODIC,
callback=lambda t: print("tick"))
قيم الفترة بالمللي ثانية. استدعِ deinit() لإيقاف الخانة وتحريرها.
ساعة الوقت الحقيقي¶
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))
print(rtc.datetime())
إذا كانت بطارية LiPo موصولة، تحافظ RTC على الوقت حتى أثناء إيقاف خطوط طاقة النظام (مُطفأة عبر زر الطاقة على اللوحة). أما مع توصيل USB فقط، فإن الضغط على زر الطاقة يقطع الطاقة عن RTC أيضاً — لذا لن يبقى وقت الساعة الحائطية بعد دورة طاقة دون بطارية موصولة.
كلب الحراسة (Watchdog)¶
from machine import WDT
wdt = WDT(timeout=5_000)
while True:
# ...do work...
wdt.feed()
معلومات الإقلاع ووقت التشغيل¶
نافذة محمّل إقلاع USB¶
عند كل تشغيل، تشغّل الكاميرا محمّل إقلاع قصير (بضع ثوانٍ) يسمح لـ OpenMV IDE بتحديث البرنامج الثابت دون اضطرار المستخدم للدخول إلى وضع DFU. بعد انقضاء النافذة، يسلّم محمّل الإقلاع المهمة إلى boot.py ثم main.py.
يمكن لبرنامج نصي قيد التشغيل إعادة الدخول إلى محمّل الإقلاع عند الطلب باستدعاء machine.bootloader().
نظام الملفات وترتيب الإقلاع¶
يركّب البرنامج الثابت لـ Pure Thermal ما يصل إلى ثلاثة أنظمة ملفات عند الإقلاع:
الفلاش الداخلي — مُركَّب دائماً عند
/flash. يحتوي علىmain.pyوREADME.txtافتراضياً؛ يُنشأ عند أول إقلاع على الإطلاق.بطاقة microSD — إذا أُدخلت بطاقة، تُركَّب عند
/sdcard.ROMFS — نظام ملفات للقراءة فقط ومُسقَط في الذاكرة عند
/romيُستخدم لشحن أصول البيانات الكبيرة (مثل نماذج الذكاء الاصطناعي) التي تستفيد من الوصول دون نسخ. يُركَّب تلقائياً بواسطة MicroPython عند بدء التشغيل، قبل تشغيل أي كود Python للمستخدم.
بعد التركيب، يُضبط دليل العمل على /sdcard عند وجود البطاقة، وإلا فعلى /flash. ثم يشغّل المفسّر البرامج النصية من ذلك الدليل:
يُنفَّذ
boot.pyعند كل إعادة ضبط ناعمة.يُنفَّذ
main.pyفقط عند الإقلاع البارد، مباشرة بعدboot.py.
إن وضع boot.py أو main.py على بطاقة SD يتجاوز النسخة الموجودة في الفلاش دون المساس بها.
عند الاتصال عبر USB، يظهر نظام ملفات الإقلاع (/sdcard إن وُجدت بطاقة، وإلا فـ /flash) أيضاً كقرص تخزين USB على المضيف. أخرج القرص قبل إعادة ضبط الكاميرا حتى يفرغ المضيف عمليات الكتابة المخزّنة لديه.
ملاحظة
لن تظهر الملفات التي يُنشئها أو يعدّلها الكود الذي يعمل على OpenMV Cam على المضيف حتى تُعاد عملية تركيب القرص. استخدم بطاقة SD لأي بيانات يكتبها البرنامج النصي، وأعد تركيبها قبل قراءة تلك الملفات من المضيف.
أحجام التخزين¶
تُشحن Pure Thermal مع:
/flash— نظام ملفات FAT بحجم 24 MB، للقراءة/الكتابة./rom— نظام ملفات ROMFS مُسقَط في الذاكرة وللقراءة فقط بحجم 8 MB، يُستخدم لشحن البرامج النصية ونماذج تعلّم الآلة التي تستفيد من الوصول عبر mmap دون نسخ./sdcard— الحجم الكامل لأي بطاقة microSD مُدخلة (عند وجودها)، للقراءة/الكتابة.
مؤشر الخطأ الفادح¶
إذا كان مؤشر LED RGB للمستخدم يتنقل بسرعة عبر جميع الألوان — بسرعة كافية بحيث يبدو وكأنه مؤشر LED أبيض متلألئ بدلاً من ألوان متميزة — فهذا يعني أن البرنامج الثابت قد اصطدم بخطأ فادح غير قابل للاسترداد. أعد تحميل البرنامج الثابت للاسترداد.
قائمة أخطاء العتاد¶
تُوثَّق حفنة من المراوغات على مستوى اللوحة في قائمة أخطاء عتاد Pure Thermal. أبرز العناصر التي ينبغي الانتباه إليها:
تداخل موصّل البطارية — تجلس مكوّنات على لوحة الدارة المطبوعة مباشرة أسفل موصّل بطارية LiPo، ويمكن للإسفين البارز على قابس كابل البطارية أن يعلق بها عند إزالة الكابل، مما يقتلع أحياناً قطعاً من اللوحة. اقطع الإسفين عن قابس الكابل بقصّافة مسطّحة قبل أول استخدام.
تتوقف RTC أثناء إيقاف تشغيل اللوحة — سعة الحمل على بلورة 32 kHz (Y2) عالية جداً. تتيح إزالة C96 وC97 (الزوج المحيط بالبلورة بجوار STM32) استمرار عمل RTC على طاقة الاحتياط. تُشحن معظم اللوحات مع إزالة هذين المكثفين مسبقاً؛ إذا فقدت RTC الوقت عند فصل الطاقة، فتحقق من هذين الموضعين. راجع مشكلتي GitHub #1536 و#1600 للاطلاع على النقاش الكامل.
يبقى مؤشر LED للشحن أزرق — قد ينهي الشاحن دورة شحنه في أي نقطة بين 4.15 فولت و4.19 فولت دون قلب المؤشر من الأزرق (قيد الشحن) إلى الأخضر (مشحون). تبقى البطارية مشحونة بالكامل في هذه الحالة؛ فثق بقياس الجهد، لا بمؤشر LED.
يضع الطبع بالحرير وسماً خاطئاً لـ VIN على أنه VBAT — الوسادة في موضع VIN القياسي لترويسة OpenMV مطبوعة بالحرير
VBATعلى Pure Thermal. الوسم خاطئ، لكنه لا يهم عملياً لأن الوسادة ليس لها أي اتصال كهربائي في كلتا الحالتين.
مكتبات البرامج¶
راجع فهرس المكتبات للاطلاع على القائمة الكاملة للوحدات — بما في ذلك تلك الفريدة لبنية Pure Thermal.