Arduino Nicla Vision

إن Arduino Nicla Vision هي لوحة رؤية آلية بأبعاد 22.86 × 22.86 ملم مبنية حول الشريحة STMicroelectronics STM32H747AII6 — وهي نظام على شريحة (SoC) ثنائي النواة يجمع بين Cortex‑M7 بتردد 400 MHz وCortex‑M4 بتردد 200 MHz. يعمل برنامج OpenMV الثابت بالكامل على نواة M7. تقرن اللوحة المتحكم الدقيق مع مستشعر CMOS الملوّن GC2145 بدقة 2 ميغابكسل، ووحدة قياس بالقصور الذاتي LSM6DSOX سداسية المحاور، وميكروفون MEMS من طراز MP34DT06، ومستشعر مدى زمن‑الطيران VL53L1CB، وWi‑Fi + Bluetooth LE 5.1، وشاحن بطارية / مقياس شحن.

Arduino Nicla Vision

للاطلاع على ورقة البيانات الكاملة والصور والأبعاد، راجع صفحة منتج Arduino Nicla Vision.

أبرز الميزات

  • STMicroelectronics STM32H747AII6 ثنائي النواة Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). يعمل برنامج OpenMV الثابت على نواة M7 فقط.

  • 2 ميغابايت من ذاكرة الفلاش الداخلية بالإضافة إلى 16 ميغابايت من ذاكرة فلاش QSPI الخارجية (تُستخدم للتطبيق + ROMFS).

  • 1 ميغابايت من ذاكرة SRAM الداخلية.

  • مشفّر/مفكّك تشفير JPEG عتادي.

  • مستشعر CMOS الملوّن GC2145 بدقة 2 ميغابكسل.

  • وحدة قياس بالقصور الذاتي مدمجة (مقياس تسارع + جيروسكوب LSM6DSOX)، وميكروفون MEMS (MP34DT06JTR)، ومستشعر مدى زمن‑الطيران VL53L1CB (حتى ~4 أمتار).

  • Wi‑Fi b/g/n (2.4 GHz) + Bluetooth LE 5.1 عبر وحدة Murata 1DX (CYW4343W) — تتصل بالهوائي المرفق عبر موصّل U.FL على اللوحة.

  • USB عالي السرعة (480 Mb/s) عبر Micro USB من خلال طبقة فيزيائية ULPI خارجية (USB3320C).

  • 13 دبوس إدخال/إخراج للمستخدم على ترويسات حافة Arduino — أربعة منافذ LPIO رقمية (D0D3)، وثلاثة مداخل تماثلية بجهد 1.8 فولت (A0A2)، وزوج I²C المكوّن من SCL/SDA، ورباعية SPI المكوّنة من SCLK/CIPO/COPI/CS.

  • دعم البطارية — موصّل Li‑Po في الخلف، وشاحن من طراز BQ، ومقياس شحن MAX17262 عبر ناقل PMIC الداخلي.

  • موصّل ESLOV بخمسة دبابيس في الخلف للتوسعة عبر I²C دون لحام.

تحذير

إن دبابيس المستخدم الرقمية تعمل بجهد 3.3 فولت افتراضياً لكنها موجّهة عبر مبدّلات مستوى قابلة للبرمجة برمجياً (VDDIO_EXT) يمكن إعادة ضبطها إلى 1.8 فولت. أما الدبابيس التماثلية (A0–A2) فتعمل بجهد 1.8 فولت فقط — فهي تتجاوز مبدّلات المستوى وتتصل مباشرة بالمتحكم الدقيق. وسيؤدي تطبيق 3.3 فولت على A0–A2 إلى إتلاف الـ SoC.

مخطط الدبابيس

Arduino Nicla Vision Pinout

مرجع الدبابيس

ثلاثة عشر دبوساً للمستخدم مكشوفة على ترويسات حافة Arduino (J1 وJ2). وُجّهت إشارات تنقيح الأخطاء والاستعادة وPMIC الإضافية إلى نقاط اختبار في خلف اللوحة.

اسم الدبوس

المرجع

الوظيفة

D0

3.3 فولت

GPIO / LPIO0 (J1‑1)

D1

3.3 فولت

LPUART1 TX / TIM1 CH2 / LPIO1 (J2‑3)

D2

3.3 فولت

LPUART1 RX / TIM1 CH3 / LPIO2 (J2‑4)

D3

3.3 فولت

GPIO / LPIO3 (J2‑5)

A0

1.8 فولت

ADC1 channel 4 (J1‑8)

A1

1.8 فولت

ADC2 channel 2 (J1‑7)

A2

1.8 فولت

ADC3 channel 5 (J1‑2)

SCL

3.3 فولت

I2C1 SCL / UART4 RX / TIM4 CH3 (J2‑2)

SDA

3.3 فولت

I2C1 SDA / UART4 TX / TIM4 CH4 (J2‑1)

SCLK

3.3 فولت

SPI4 SCK / TIM1 CH3N (J1‑6)

CIPO

3.3 فولت

SPI4 MISO / TIM1 CH3 (J1‑5)

COPI

3.3 فولت

SPI4 MOSI / TIM1 CH4 (J1‑4)

CS

3.3 فولت

SPI4 NSS / TIM1 CH2 (J1‑3)

RESET

3.3 فولت

اسحبه إلى GND (أو اضغط المفتاح الموجود على اللوحة) لإعادة ضبط اللوحة

LED_RED

3.3 فولت

القناة الحمراء من LED RGB (فعّالة عند المستوى المنخفض)

LED_GREEN

3.3 فولت

القناة الخضراء من LED RGB (فعّالة عند المستوى المنخفض)

LED_BLUE

3.3 فولت

القناة الزرقاء من LED RGB (فعّالة عند المستوى المنخفض)

ملاحظة

تقع D0D3 وSCLK/CIPO/COPI/CS خلف مبدّل المستوى ثنائي الاتجاه TXB0108 — وهذه القطعة لا تدعم إلا قيادة GPIO من نوع الدفع‑السحب، لذا فإن حركة الناقل من نوع المصرف‑المفتوح (مثل 1‑Wire أو I²C المنفّذة برمجياً على تلك الدبابيس) لن تعمل.

تقع SCL/SDA خلف مبدّل منفصل من طراز NTS0304 يدعم قيادة الدفع‑السحب والمصرف‑المفتوح على حد سواء، وهذا هو سبب عمل I²C 1 هناك.

كلا المبدّلين مرجعهما VDDIO_EXT (3.3 فولت افتراضياً من PMIC الموجود على اللوحة)، وقوة قيادتهما محدودة مقارنة بـ GPIO مباشر — فقد صُمّما لأحمال مستوى الإشارة وليس لأحمال الطاقة.

دبابيس الطاقة

دبابيس ترويسة الحافة:

  • VIN (J2‑9) — قضيب النظام الرئيسي بجهد 3.6 – 5 فولت. تأخذ PMIC مدخلها من هنا.

  • VDDIO_EXT (J2‑7) — خرج قضيب مبدّل المستوى، 1.8 فولت أو 3.3 فولت (3.3 فولت افتراضياً). استخدمه لتشغيل الطرفيات الخارجية بجهد 1.8 فولت أو 3.3 فولت المتصلة بدبابيس LPIO/SPI/I²C كي تتحدث بنفس مستوى المنطق الخاص بالترويسات.

  • VBAT (J3‑2) — مدخل بطارية Li‑Po. تشحن PMIC الموجودة على اللوحة الخلية من VIN وتبلّغ عن حالة الشحن عبر مقياس الشحن.

  • NTC (J3‑1) — مدخل اختياري لمقاومة حرارية لبطارية Li‑Po.

  • GND (J2‑6) — الأرضي المشترك.

  • NC (J2‑8) — لا اتصال.

نقاط الاختبار في خلف اللوحة:

  • +3V3 — قضيب 3.3 فولت الرئيسي.

  • D_P / D_N — زوج بيانات USB عالي السرعة (بعد الطبقة الفيزيائية).

يغذّي كل من USB وموصّل ESLOV قضيب VIN عبر زوج من الثنائيات المثالية LM66100 (واحد لكل مصدر)، لذا يمكن لأي من المصدرين تشغيل اللوحة بمفرده دون أن يدفع الواحد التيار عكسياً نحو الآخر. وإذا قدت VIN خارجياً على J2‑9، فإن لذلك الأولوية — إذ تتوقف الثنائيات ببساطة عن التوصيل من USB / ESLOV بمجرد ارتفاع القضيب الخارجي أعلى منهما.

وبالتالي يمكن تشغيل اللوحة عبر أي من هذه المسارات:

  • Micro USB — 5 فولت إلى VIN عبر الثنائي المثالي في جانب USB.

  • موصّل ESLOV — حتى 5 فولت على دبوس VESLOV في J5، موجّهة إلى VIN عبر الثنائي المثالي في جانب ESLOV (راجع موصّل ESLOV).

  • دبوس VIN (J2‑9) — قُد مصدراً منظَّماً بجهد 3.6 – 5 فولت مباشرة.

  • بطارية Li‑Po — وصّلها بموصّل البطارية J4 في الخلف أو بنقاط VBAT/GND/NTC على J3 / J2‑6. لا توصّل بطاريتين في آنٍ واحد.

موصّل ESLOV

إن J5 في خلف اللوحة هو موصّل ESLOV من Molex بخمسة دبابيس وبلا لحام:

الدبوس

الاسم

الوظيفة

J5‑1

VESLOV

مدخل طاقة (≤ 5 فولت) — مُدمج في VIN عبر ثنائي مثالي LM66100

J5‑2

INT

مدخل مقاطعة خارجية على PD9

J5‑3

SCL_EXT

مشترك مع نقطة SCL في J2 — نفس ناقل I²C 1 الخاص بترويسة المستخدم

J5‑4

SDA_EXT

مشترك مع نقطة SDA في J2 — نفس ناقل I²C 1 الخاص بترويسة المستخدم

J5‑5

GND

الأرضي المشترك

إن SCL_EXT/SDA_EXT الخاصة بـ ESLOV وSCL/SDA الخاصة بـ J2 هي نفس الدبابيس — ناقل I²C 1 واحد مكشوف على موصّلين.

نصيحة

استخدم مقدّر عمر البطارية لنمذجة المدة التي ستعمل خلالها Nicla Vision على البطارية لدورة عمل معيّنة من النشاط / النوم العميق.

دبابيس الاستعادة وتنقيح الأخطاء

  • RESET — مفتاح لحظي في أعلى اللوحة ونقطة (J3‑4 / نقطة الاختبار P5) معاً، مرتبطان بخط NRST الخاص بالـ SoC. اسحبه إلى GND لإعادة الضبط.

تستخدم Nicla Vision إعادة الضبط بالنقر المزدوج القياسية من Arduino للدخول إلى محمّل إقلاع Arduino — اضغط زر إعادة الضبط مرتين بسرعة فتظهر اللوحة كجهاز DFU. ويستخدم OpenMV IDE هذا الوضع لإعادة كتابة البرنامج الثابت.

تُكشف إشارات SWD الخاصة بـ STM32 في خلف اللوحة من خلال صف من نقاط الاختبار بين ترويستي J2. الحم ترويسة بمسافة 2.54 ملم (100‑mil) فيها لتوصيل مهايئ ST‑LINK أو J‑Link:

  • P1 / P2 — ناقل PMIC I²C الداخلي على PF0 (SDA) وPF1 (SCL). وهذا هو machine.I2C(2) على Nicla Vision ويحمل حركة PMIC ومقياس الشحن ومستشعر زمن‑الطيران.

  • P3 — TMS / SWDIO (PA13)

  • P4 — TCK / SWCLK (PA14)

  • P5 — NRST

  • P6 — TDO / SWO (PB3)

  • P7 — قضيب +1V8 (مصدر إدخال/إخراج الـ SoC — وهو أيضاً المرجع الصحيح لمهايئ تنقيح الأخطاء).

  • P8VOTP_PMICللبرمجة المصنعية فقط. يجب تركه غير موصّل.

جميع إشارات تنقيح الأخطاء مرجعها 1.8 فولت — إذ تعمل حلقة الإدخال/الإخراج لـ STM32H747 على هذه اللوحة من قضيب +1V8. اضبط مهايئ تنقيح الأخطاء على منطق 1.8 فولت قبل التوصيل.

الطرفيات الموجودة على اللوحة

مصابيح LED

تحتوي Nicla Vision على مصباح LED RGB واحد للمستخدم، يمكن التحكم به برمجياً عبر machine.LED

from machine import LED

LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()

هناك مصباح DL2 CHARGE منفصل على جانب اللوحة موصّل مباشرة بخرج CHGB الخاص بـ PMIC — يضيء أثناء شحن بطارية Li‑Po من USB / ESLOV / VIN ولا يمكن التحكم به من قبل المستخدم.

مستشعر الكاميرا

يُقاد GC2145 عبر وحدة csi --- مستشعرات الكاميرا

import csi

cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.QVGA)
cam.snapshot(time=2000)       # let auto‑exposure settle

while True:
    img = cam.snapshot()

عندما تطلب حجم إطار صغيراً، يقتطع مشغّل GC2145 نافذة قراءة صغيرة متناسبة من المستشعر — وافتراضياً تُقيَّد نسبة التصغير من القراءة إلى الخرج عند 3 أضعاف للحفاظ على ارتفاع معدل الإطارات. ويرفع csi.IOCTL_SET_FOV_WIDE ذلك الحد إلى 5 أضعاف، ما يعني أن المشغّل يسحب من منطقة أوسع من المستشعر عند بث الدقات الصغيرة. والنتيجة مجال رؤية أوسع بشكل ملحوظ عند أحجام الإطارات الصغيرة، على حساب بعض الإنتاجية:

cam.ioctl(csi.IOCTL_SET_FOV_WIDE, True)
cam.ioctl(csi.IOCTL_GET_FOV_WIDE)  # returns the current setting

نواة M4

تُكشف نواة Cortex‑M4 من خلال openamp للاتصال بين المعالجات. يعمل برنامج OpenMV الثابت على M7 فقط؛ ولا يملك M4 بيئة تشغيل MicroPython خاصة به، لذا فإن استخدامه يعني بناء صورة برنامج ثابت منفصلة بلغة C وتحميلها من نظام الملفات عبر openamp.RemoteProc. ويتوفر برنامج ثابت تجريبي مبني مسبقاً ينفّذ نقطة نهاية UART افتراضية في مستودع openamp_vuart — اتّبع ملف README الخاص به لبناء vuart.elf

import openamp
import time

def ept_recv_callback(src_addr, data):
    print("Received:", data.decode())

ept = openamp.Endpoint("vuart-channel", callback=ept_recv_callback)

rproc = openamp.RemoteProc("vuart.elf")
rproc.start()

count = 0
while True:
    if ept.is_ready():
        ept.send("Hello World %d!" % count, timeout=1000)
        count += 1
    time.sleep_ms(1000)

من الناحية العملية، من الأفضل التعامل مع هذا الدعم كعرض توضيحي لواجهة openamp وليس كمنصة ثنائية النواة عاملة — إذ لا يمكن إعادة ضبط M4 بشكل مستقل عن M7، لذا فإن إيقاف M4 يفرض إعادة تشغيل كاملة للنظام.

الميكروفون

يُلتقط ميكروفون PDM من طراز MP34DT06JTR الموجود على اللوحة عبر audio --- وحدة الصوت فوق طرفية DFSDM الخاصة بـ STM32. ويصل كل مخزن مؤقت على هيئة bytearray بصيغة PCM ذات 16 بت معلّمة، جاهز للتغذية في ulab/numpy لمعالجة الإشارات الرقمية — على سبيل المثال، كاشف بسيط لمستوى الصوت:

import audio
from ulab import numpy as np

def loudness(pcmbuf):
    samples = np.array(np.frombuffer(pcmbuf, dtype=np.int16), dtype=np.float)
    rms = np.sqrt(np.mean(samples ** 2))
    if rms > 10000:
        print("Loud!", int(rms))

audio.init(channels=1, frequency=16000, gain_db=24)
audio.start_streaming(loudness)

while True:
    pass

وحدة القياس بالقصور الذاتي

يُكشف مقياس التسارع + الجيروسكوب LSM6DSOX الموجود على اللوحة عبر imu --- مستشعر imu

import imu
import time

while True:
    print(imu.acceleration_mg())   # (x, y, z) in milli‑g
    print(imu.angular_rate_mdps()) # (x, y, z) in milli‑deg/s
    time.sleep_ms(100)

وحدة القياس بالقصور الذاتي موصّلة بناقل SPI داخلي مخصص (SPI5) كي لا تتنازع مع SPI4 الخاص بالمستخدم المكشوف على الترويسات.

مستشعر مدى زمن‑الطيران

يقع مستشعر مدى زمن‑الطيران VL53L1CB من ST الموجود على اللوحة على ناقل PMIC I²C الداخلي (I²C 2). استخدم مشغّل vl53l1x --- مشغّل مستشعر المسافة VL53L1X بتقنية ToF المجمّد للحصول على قراءات المسافة حتى ~4 أمتار:

import time
from machine import I2C
import vl53l1x

bus = I2C(2)               # internal bus (PMIC / fuel gauge / ToF)
tof = vl53l1x.VL53L1X(bus)

while True:
    print("Distance:", tof.read(), "mm")
    time.sleep_ms(100)

مقياس شحن البطارية

يتتبع مقياس الشحن MAX17262 ModelGauge m5 من Maxim جهد بطارية Li‑Po وتيارها ودرجة حرارتها وحالة شحنها. ويقع على I²C 2 عند العنوان 0x36.

يمتلك MAX17262 استشعار تيار داخلي، لذا يقرأ سجل التيار مباشرة بالميكرو أمبير دون عامل Rsense خارجي يُطبَّق. وقراءة مقياس الشحن غير مؤذية — لا يُشحن أي مشغّل معه، لكن يمكن قراءة السجلات الموثّقة في ورقة بيانات MAX17262 مباشرة:

import time
import struct
from machine import I2C

FUEL_GAUGE = 0x36   # MAX17262

def read_reg(bus, addr, reg):
    return struct.unpack("<H", bus.readfrom_mem(addr, reg, 2))[0]

def read_signed(bus, addr, reg):
    v = read_reg(bus, addr, reg)
    return v - 0x10000 if v & 0x8000 else v

bus = I2C(2)

while True:
    # 0x05 RepCap — remaining capacity, raw × 0.5 mAh
    rep_cap   = read_reg(bus, FUEL_GAUGE, 0x05) * 0.5
    # 0x06 RepSOC — state of charge, raw / 256 %
    soc       = read_reg(bus, FUEL_GAUGE, 0x06) / 256
    # 0x08 Temp — die temperature, signed, raw / 256 °C
    temp      = read_signed(bus, FUEL_GAUGE, 0x08) / 256
    # 0x09 VCell — battery voltage, raw × 78.125 µV
    vcell     = read_reg(bus, FUEL_GAUGE, 0x09) * 78.125 / 1_000_000
    # 0x0A Current — signed, raw × 156.25 µA
    current   = read_signed(bus, FUEL_GAUGE, 0x0A) * 156.25 / 1000
    # 0x0B AvgCurrent — averaged current
    avg_curr  = read_signed(bus, FUEL_GAUGE, 0x0B) * 156.25 / 1000
    # 0x10 FullCapRep — learned full capacity, raw × 0.5 mAh
    full_cap  = read_reg(bus, FUEL_GAUGE, 0x10) * 0.5
    # 0x11 TTE — time-to-empty (valid while discharging), raw × 5.625 s
    tte_s     = read_reg(bus, FUEL_GAUGE, 0x11) * 5.625
    # 0x20 TTF — time-to-full   (valid while charging),  raw × 5.625 s
    ttf_s     = read_reg(bus, FUEL_GAUGE, 0x20) * 5.625
    # 0x17 Cycles — charge-cycle counter, 1% per LSB
    cycles    = read_reg(bus, FUEL_GAUGE, 0x17) / 100

    print("V:        %.3f V" % vcell)
    print("Capacity: %.1f / %.1f mAh (%.1f %%)" % (rep_cap, full_cap, soc))
    print("Temp:     %.1f C" % temp)
    print("Current:  %.1f mA  (avg %.1f mA)" % (current, avg_curr))
    print("TTE:      %.0f s   TTF: %.0f s" % (tte_s, ttf_s))
    print("Cycles:   %.2f" % cycles)
    print()
    time.sleep_ms(1000)

Current بصيغة المتمم الثنائي المعلّمة: موجب أثناء الشحن، سالب أثناء التفريغ. أما TTE فلا معنى له إلا عندما يكون التيار سالباً؛ وTTF إلا عندما يكون التيار موجباً.

دارة إدارة الطاقة

تتولى PMIC من طراز MC34PF1550A0EP من NXP كل منظّم على Nicla Vision — قضيب +3V3 الرئيسي، وقضيب نواة / إدخال‑إخراج الـ SoC +1V8، وVDDIO_EXT لمبدّلات المستوى، وشاحن Li‑Po. وتقع على I²C 2 عند العنوان 0x08.

تحذير

قراءة سجلات PMIC أمر سليم؛ لكن الكتابة إليها خطيرة. فقد يؤدي سوء ضبط منظّم خفض أو إعداد شاحن إلى إتلاف اللوحة أو البطارية أو كليهما بشكل دائم. تعامل مع PMIC كأنها للقراءة فقط ما لم تكن تعرف تماماً ما تفعله.

أكثر ما تخبرك به PMIC نفعاً مما لا يستطيع مقياس الشحن إخبارك به هو آلة حالات الشاحن — أي ما إذا كانت اللوحة تعمل حالياً على USB / ESLOV / VIN، وفي أي مرحلة من دورة الشحن توجد بطارية Li‑Po، وما إذا كان الشاحن في حالة عطل حراري أو عطل مراقب. تقع سجلات الشاحن عند إزاحة قدرها 0x80 في مساحة عناوين I²C الرئيسية لـ PF1550 (راجع §22.2 من ورقة بيانات PF1550)، لذا فإن CHG_INT_OK مثلاً عند عنوان الشاحن 0x04 يُقرأ من سجل PMIC 0x84

import time
from machine import I2C

PMIC = 0x08

# Charger state machine (low nibble of CHG_SNS, register 0x87)
CHG_STATES = {
    0x0: "precharge",
    0x1: "fast charge (constant current)",
    0x2: "fast charge (constant voltage)",
    0x3: "end of charge",
    0x4: "done",
    0x6: "timer fault",
    0x7: "thermistor suspend",
    0x8: "off — input invalid or charger disabled",
    0x9: "battery overvoltage",
    0xA: "thermal shutdown",
    0xC: "linear mode (not charging)",
}

bus = I2C(2)

while True:
    # 0x84 CHG_INT_OK — single-bit indicators
    ok = bus.readfrom_mem(PMIC, 0x84, 1)[0]
    vbus_ok = bool(ok & (1 << 5))   # bit 5 — VBUS valid (USB/ESLOV/VIN)
    bat_ok  = bool(ok & (1 << 2))   # bit 2 — battery OK
    chg_ok  = bool(ok & (1 << 3))   # bit 3 — charger actively charging
    thm_ok  = bool(ok & (1 << 7))   # bit 7 — thermistor in normal range

    # 0x87 CHG_SNS — charger state + thermal regulation flag
    chg_sns = bus.readfrom_mem(PMIC, 0x87, 1)[0]
    state   = CHG_STATES.get(chg_sns & 0x0F, "reserved")
    treg    = bool(chg_sns & (1 << 7))   # thermal regulation active

    print("VBUS valid:         ", vbus_ok)
    print("battery OK:         ", bat_ok)
    print("charger active:     ", chg_ok)
    print("thermistor normal:  ", thm_ok)
    print("thermal reg active: ", treg)
    print("state:              ", state)
    print()
    time.sleep_ms(1000)

سجلات أخرى للقراءة فقط تستحق النظر إليها في ورقة البيانات (جميعها عند إزاحة الشاحن 0x80): 0x80 CHG_INT (مقاطعات الشاحن المُمسكة — رايات الأعطال)، و0x86 VBUS_SNS (حالة VBUS متعددة البتات بما في ذلك OVLO / UVLO / DPM)، و0x88 BATT_SNS (وجود البطارية وحالة فرط التيار).

Wi‑Fi

يُكشف Murata 1DX (CYW4343W) الموجود على اللوحة عبر network --- تهيئة الشبكة كواجهة محطة. وصّل الهوائي المرفق بـ موصّل U.FL على اللوحة قبل تشغيل الراديو:

import network, time

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("ssid", "password")
while not wlan.isconnected():
    time.sleep(1)
print("Wi‑Fi IP:", wlan.ipconfig("addr4")[0])

Bluetooth

يكشف نفس Murata 1DX أيضاً Bluetooth LE 5.1. استخدم aioble --- BLE غير المتزامن لـ BLE الملائم لـ asyncio — على سبيل المثال، الإعلان كطرفية وانتظار اتصال جهاز مركزي:

import asyncio
import aioble

async def run():
    while True:
        conn = await aioble.advertise(250_000, name="Nicla-Vision")
        print("Connected:", conn.device)
        await conn.disconnected()

asyncio.run(run())

مرجع الناقل

GPIO

استخدم machine.Pin لقراءة أي من الدبابيس المطبوعة على اللوحة أو قيادتها. المخرجات بصيغة 3.3 فولت CMOS (الافتراضي VDDIO_EXT) وتحدّ مبدّلات المستوى من قوة القيادة لكل دبوس إلى بضعة ميلي أمبير — فقد صُمّمت لأحمال مستوى الإشارة وليس لأحمال الطاقة.

from machine import Pin

out = Pin("D0", Pin.OUT)
out.on()
out.off()
out.value(1)

inp = Pin("D1", Pin.IN, Pin.PULL_UP)
print(inp.value())

يمكن لأي دبوس إدخال أيضاً أن يطلق مقاطعة عند انتقالات الحافة:

def handler(pin):
    print("triggered:", pin)

Pin("D1", Pin.IN, Pin.PULL_UP).irq(
    handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)

UART

الناقل

TX

RX

UART4

SDA

SCL

from machine import UART

uart = UART(4, baudrate=115200)
uart.write("hello")
uart.read(5)

ملاحظة

يتشارك UART4 دبابيسه مع I²C 1 — إذ تحمل نفس نقطتي SDA/SCL كلا الناقلين. اختر UART أو I²C، لا كليهما، على تلك الدبابيس.

تقرأ الطباعة على اللوحة لـ D1/D2 أيضاً UART_TX/UART_RX، لكن في هذا البرنامج الثابت توجّه تلك الدبابيس إلى LPUART1، وليس إلى machine.UART. أما machine.UART(1) نفسه فمحجوز لمتحكم Bluetooth على الشريحة وغير قابل للوصول على الترويسات.

I²C

الناقل

SCL

SDA

I2C1

SCL

SDA

from machine import I2C

i2c = I2C(1, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")

تقع نقطتا SCL/SDA على J2 ودبابيس SCL_EXT/SDA_EXT الخاصة بموصّل ESLOV على نفس ناقل I²C 1 — راجع موصّل ESLOV أعلاه للاطلاع على مخطط دبابيس ESLOV.

يمكن أيضاً استخدام نفس العتاد في وضع الهدف (التابع) عبر machine.I2CTarget لكشف منطقة ذاكرة لمتحكم I²C آخر:

from machine import I2CTarget

buf = bytearray(32)
target = I2CTarget(1, addr=0x42, mem=buf)

SPI

الناقل

MOSI

MISO

SCK

CS

SPI4

COPI

CIPO

SCLK

CS

from machine import SPI
from machine import Pin

spi = SPI(4, baudrate=10_000_000)
cs = Pin("CS", Pin.OUT, value=1)   # CS is not driven by the SPI peripheral

cs.value(0)
spi.write(b"hello")
cs.value(1)

ADC

تكشف Nicla Vision ثلاث قنوات ADC بدقة 12 بت على A0 وA1 وA2. وجميعها مرجعها 1.8 فولت — يُرجع read_u16 القيم 0–65535 عبر المدى 0–1.8 فولت عند الدبوس:

from machine import ADC
import time

adc = ADC("A0")
while True:
    voltage = adc.read_u16() * 1.8 / 65535
    print(voltage)
    time.sleep_ms(100)

تحذير

إن مداخل ADC الخاصة بـ Nicla Vision مرجعها 1.8 فولت (وليس أمامها مبدّل مستوى قبل الـ SoC). وسيؤدي تطبيق إشارة 3.3 فولت إلى إشباع المحوّل وقد يتلف الدبوس — قسّم الجهود الأعلى خارجياً.

PWM

الدبوس

المؤقت / القناة

D1

TIM1 CH2

D2

TIM1 CH3

SCL

TIM4 CH3, TIM16 CH1

SDA

TIM4 CH4, TIM17 CH1

SCLK

TIM1 CH3N

CIPO

TIM1 CH3

COPI

TIM1 CH4

CS

TIM1 CH2

قُد أياً منها عبر machine.PWM

from machine import Pin, PWM

pwm = PWM(Pin("D1"), freq=1_000, duty_u16=32768)

ملاحظة

تتشارك عدة دبابيس قنوات TIM1:

  • TIM1 CH2 موجودة على D1 و CS.

  • TIM1 CH3 موجودة على D2 و CIPO؛ ويُخرج SCLK المتمم المعكوس (TIM1 CH3N) لنفس القناة.

  • TIM1 CH4 موجودة على COPI وحده.

اختر مستهلكاً واحداً لكل قناة مؤقت. كما لا يمكن قيادة دبابيس رباعية SPI (SCLK/CIPO/COPI/CS) بـ PWM أثناء استخدام machine.SPI(4) لها.

النواقل المنفّذة برمجياً (bit‑banged)

يعمل machine.SoftI2C وmachine.SoftSPI على أي GPIO إذا كنت بحاجة إلى ناقل إضافي.

المستشعر الحراري (خارج اللوحة)

يتضمن البرنامج الثابت مشغّل fir --- مشغّل المستشعر الحراري (fir == far infrared) لأجهزة التصوير الحراري الموصّلة خارجياً:

  • 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 1 — وصّل الوحدة بنقطتي SCL / SDA المطبوعتين على اللوحة.

التوقيت

time

تغطي وحدة time التأخيرات الحاجبة، والنبضات الرتيبة، وقياس الوقت المنقضي:

import time

time.sleep(1)              # seconds
time.sleep_ms(500)
time.sleep_us(10)

start = time.ticks_ms()
# ...do work...
elapsed = time.ticks_diff(time.ticks_ms(), start)

المؤقتات الافتراضية

يجدول machine.Timer دوال رد النداء الدورية أو الفردية دون استهلاك فتحة مؤقت عتادي. مرّر -1 كمعرّف لاستخدام مؤقت افتراضي (برمجي):

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() لإيقاف الفتحة وتحريرها.

ساعة الوقت الحقيقي

تحافظ machine.RTC على وقت الساعة الجدارية عبر عمليات إعادة الضبط:

from machine import RTC

rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))   # Y, M, D, weekday, h, m, s, subsec
print(rtc.datetime())

المراقب (Watchdog)

يعيد machine.WDT ضبط اللوحة إذا تعلّق التطبيق. وبمجرد بدئه لا يمكن إيقافه أو إعادة ضبطه — قم بتغذيته دورياً داخل حلقتك الرئيسية:

from machine import WDT

wdt = WDT(timeout=5_000)   # 5 second window
while True:
    # ...do work...
    wdt.feed()

معلومات الإقلاع ووقت التشغيل

تحديث البرنامج الثابت (DFU)

تستخدم Nicla Vision إعادة الضبط بالنقر المزدوج القياسية من Arduino للدخول إلى محمّل إقلاع Arduino. اضغط زر إعادة الضبط مرتين بسرعة — فتظهر اللوحة من جديد عبر USB كجهاز DFU ويمكن لـ OpenMV IDE كتابة صورة برنامج ثابت جديدة.

يمكن لبرنامج نصي قيد التشغيل أن يعيد الدخول إلى محمّل الإقلاع عند الطلب باستدعاء machine.bootloader()

import machine

machine.bootloader()

نظام الملفات وترتيب الإقلاع

يركّب برنامج Nicla Vision الثابت ما يصل إلى نظامي ملفات عند الإقلاع:

  • ذاكرة الفلاش الداخلية — مركّبة دائماً عند /flash. تحتوي على main.py وREADME.txt افتراضياً؛ وتُنشأ عند أول إقلاع على الإطلاق.

  • ROMFS — نظام ملفات للقراءة فقط ومخطّط في الذاكرة عند /rom تركّبه MicroPython تلقائياً عند بدء التشغيل.

بعد التركيب، يُضبط دليل العمل على /flash. ثم يشغّل المفسّر البرامج النصية من ذلك الدليل:

  • يُنفَّذ boot.py عند كل إعادة ضبط ناعمة (إقلاع بارد، أو Ctrl‑D من REPL، أو عند عودة البرنامج النصي قيد التشغيل).

  • يُنفَّذ main.py عند الإقلاع البارد فقط، مباشرة بعد boot.py. وتعيد عمليات إعادة الضبط الناعمة اللاحقة تشغيل boot.py لكنها تنتقل مباشرة إلى REPL — ولإعادة تشغيل main.py عليك إعادة ضبط اللوحة بالكامل.

إن main.py الافتراضي المشحون على لوحة حُدّثت حديثاً يومض فقط القناة الزرقاء من LED RGB الخاص بالمستخدم كنبضة قلب (نبضتان قصيرتان، مع فجوة قصيرة)، حتى يمكنك معرفة أن البرنامج الثابت أقلع بشكل نظيف دون أي مضيف متصل.

يُمدَّد sys.path ليشمل كلا نظامي الملفات ودليليهما الفرعيين lib/، بحيث يمكن للوحدات القابلة للاستيراد أن تقيم في /flash/lib أو /rom/lib.

عند الاتصال عبر USB، يظهر /flash أيضاً كقرص تخزين كتلي USB على المضيف، ما يتيح لك تحرير boot.py وmain.py وأي ملفات أخرى مباشرة. أخرج القرص قبل إعادة ضبط الكاميرا كي يفرّغ المضيف عمليات كتابته المخزّنة.

ملاحظة

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

ملاحظة

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

أحجام التخزين

تُشحن Nicla Vision مع:

  • /flash — نظام ملفات FAT بسعة 11 ميغابايت، للقراءة/الكتابة.

  • /rom — نظام ملفات ROMFS مخطّط في الذاكرة وللقراءة فقط بسعة 4 ميغابايت، يُستخدم لشحن البرامج النصية ونماذج تعلّم الآلة التي تستفيد من وصول mmap دون نسخ.

مؤشر العطل الجسيم (Hard‑fault)

إذا كان LED RGB الخاص بالمستخدم يدور بسرعة عبر جميع الألوان — بسرعة كافية بحيث يميل إلى أن يبدو كـ مصباح LED أبيض وامض بدلاً من ألوان مميزة — فهذا يعني أن البرنامج الثابت اصطدم بعطل جسيم غير قابل للاستعادة. أعد كتابة البرنامج الثابت للاستعادة؛ وإذا لم تساعد إعادة الكتابة، فقد تكون اللوحة متضررة فيزيائياً.

مكتبات البرمجيات

راجع فهرس المكتبات للاطلاع على القائمة الكاملة للوحدات — بما في ذلك أي منها فريد لإصدار Nicla Vision.