Arduino Nicla Vision

ה‑Arduino Nicla Vision הוא לוח ראייה ממוחשבת בגודל 22.86 × 22.86 מ“מ הבנוי סביב ה‑STMicroelectronics STM32H747AII6 — SoC דו‑ליבתי המשלב Cortex‑M7 ב‑400 MHz עם Cortex‑M4 ב‑200 MHz. קושחת OpenMV רצה כולה על ליבת ה‑M7. הלוח משלב את ה‑MCU עם חיישן CMOS צבעוני GC2145 של 2 MP, IMU בעל 6 צירים LSM6DSOX, מיקרופון MEMS מסוג MP34DT06, מד טווח מסוג time‑of‑flight VL53L1CB, Wi‑Fi + Bluetooth LE 5.1, ומטען סוללה / מד דלק.

Arduino Nicla Vision

ל‑datasheet המלא, תמונות, ומידות ראו את דף המוצר של Arduino Nicla Vision.

עיקרי המאפיינים

  • STMicroelectronics STM32H747AII6 דו‑ליבתי Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). קושחת OpenMV רצה על ליבת ה‑M7 בלבד.

  • 2 MB זיכרון פלאש (flash) פנימי בתוספת 16 MB זיכרון פלאש (flash) חיצוני מסוג QSPI (משמש לאפליקציה + ROMFS).

  • 1 MB SRAM פנימי.

  • מקודד/מפענח JPEG חומרתי.

  • חיישן CMOS צבעוני GC2145 של 2 MP.

  • IMU מובנה (מד תאוצה + ג’ירוסקופ LSM6DSOX), מיקרופון MEMS (MP34DT06JTR), ומד טווח VL53L1CB מסוג time‑of‑flight (עד ~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 PHY חיצוני (USB3320C).

  • 13 פיני I/O למשתמש על מחברי הקצה של Arduino — ארבעה LPIO דיגיטליים (D0D3), שלושה כניסות אנלוגיות של 1.8 V (A0A2), הזוג SCL/SDA של I²C, ורביעיית ה‑SPI SCLK/CIPO/COPI/CS.

  • תמיכה בסוללה — מחבר Li‑Po בגב, מטען בסגנון BQ, ומד דלק MAX17262 על אפיק ה‑PMIC הפנימי.

  • מחבר ESLOV בעל 5 פינים בגב להרחבת I²C ללא הלחמה.

אזהרה

הפינים הדיגיטליים של המשתמש הם 3.3 V כברירת מחדל אך מנותבים דרך ממירי מתח הניתנים לתכנות בתוכנה (VDDIO_EXT) שניתן להגדיר מחדש ל‑1.8 V. הפינים האנלוגיים (A0–A2) הם 1.8 V בלבד — הם עוקפים את ממירי המתח ומתחברים ישירות אל ה‑MCU. הזרמת 3.3 V אל A0–A2 תפגע ב‑SoC.

מפת פינים

Arduino Nicla Vision Pinout

מדריך פינים

שלושה‑עשר פיני משתמש חשופים על מחברי הקצה של Arduino (J1 ו‑J2). אותות נוספים של debug, שחזור, ו‑PMIC מנותבים אל test pads בגב הלוח.

שם פין

מדריך

פונקציה

D0

3.3 V

GPIO / LPIO0 (J1‑1)

D1

3.3 V

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

D2

3.3 V

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

D3

3.3 V

GPIO / LPIO3 (J2‑5)

A0

1.8 V

ADC1 channel 4 (J1‑8)

A1

1.8 V

ADC2 channel 2 (J1‑7)

A2

1.8 V

ADC3 channel 5 (J1‑2)

SCL

3.3 V

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

SDA

3.3 V

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

SCLK

3.3 V

SPI4 SCK / TIM1 CH3N (J1‑6)

CIPO

3.3 V

SPI4 MISO / TIM1 CH3 (J1‑5)

COPI

3.3 V

SPI4 MOSI / TIM1 CH4 (J1‑4)

CS

3.3 V

SPI4 NSS / TIM1 CH2 (J1‑3)

RESET

3.3 V

משכו ל‑GND (או לחצו על המתג שעל הלוח) כדי לאתחל את הלוח

LED_RED

3.3 V

ערוץ אדום של RGB LED (פעיל בנמוך)

LED_GREEN

3.3 V

ערוץ ירוק של RGB LED (פעיל בנמוך)

LED_BLUE

3.3 V

ערוץ כחול של RGB LED (פעיל בנמוך)

הערה

D0D3 ו‑SCLK/CIPO/COPI/CS יושבים מאחורי ממיר המתח הדו‑כיווני TXB0108 — רכיב זה תומך רק בהנעת GPIO מסוג push‑pull, כך שתעבורת אפיק מסוג open‑drain (למשל 1‑Wire או I²C מבוססי bit‑bang על אותם פינים) לא תעבוד.

SCL/SDA יושבים מאחורי ממיר נפרד NTS0304 התומך בהנעה מסוג push‑pull וגם open‑drain, ולכן I²C 1 עובד שם.

שני הממירים מיוחסים אל VDDIO_EXT (3.3 V כברירת מחדל מה‑PMIC שעל הלוח), וחוזק ההנעה שלהם מוגבל בהשוואה ל‑GPIO ישיר — הם תוכננו לעומסי אות ולא לעומסי הספק.

פיני הספק

פיני מחבר הקצה:

  • VIN (J2‑9) — מסילת המערכת הראשית 3.6 – 5 V. ה‑PMIC מקבל כאן את הכניסה שלו.

  • VDDIO_EXT (J2‑7) — יציאה של מסילת ממיר המתח, 1.8 V או 3.3 V (3.3 V כברירת מחדל). השתמשו בה כדי להזין התקנים היקפיים חיצוניים של 1.8 V או 3.3 V המחוברים לפיני LPIO/SPI/I²C כך שידברו באותה רמת לוגיקה כמו המחברים.

  • VBAT (J3‑2) — כניסת סוללת Li‑Po. ה‑PMIC שעל הלוח טוען את התא מ‑VIN ומדווח על מצב הטעינה דרך מד הדלק.

  • NTC (J3‑1) — כניסת תרמיסטור Li‑Po אופציונלית.

  • GND (J2‑6) — הארקה משותפת.

  • NC (J2‑8) — ללא חיבור.

Test pads בגב הלוח:

  • +3V3 — מסילת 3.3 V ראשית.

  • D_P / D_N — זוג נתוני USB מהיר (אחרי ה‑PHY).

ה‑USB ומחבר ה‑ESLOV מזינים שניהם את VIN דרך זוג דיודות אידיאליות LM66100 (אחת לכל מקור), כך שכל מקור הספק יכול להפעיל את הלוח בעצמו ושניהם לעולם אינם מניעים זה את זה לאחור. אם אתם מניעים את VIN חיצונית ב‑J2‑9, היא מקבלת עדיפות — הדיודות פשוט מפסיקות להוליך מ‑USB / ESLOV ברגע שהמסילה החיצונית עולה גבוה יותר.

ניתן אפוא להפעיל את הלוח דרך כל אחד מהמסלולים הבאים:

  • Micro USB — 5 V אל VIN דרך הדיודה האידיאלית שבצד ה‑USB.

  • מחבר ESLOV — עד 5 V על פין ה‑VESLOV של J5, מנותב אל VIN דרך הדיודה האידיאלית שבצד ה‑ESLOV (ראו מחבר ESLOV).

  • פין VIN (J2‑9) — הניעו ספק מיוצב של 3.6 – 5 V ישירות.

  • סוללת Li‑Po — חברו למחבר הסוללה J4 בגב או לרפידות VBAT/GND/NTC על J3 / J2‑6. אל תחברו שתי סוללות בו‑זמנית.

מחבר ESLOV

J5 בגב הלוח הוא מחבר ESLOV של Molex בעל 5 פינים ללא הלחמה:

פין

שם

פונקציה

J5‑1

VESLOV

כניסת הספק (≤ 5 V) — מצורף עם OR אל 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 יפעל על סוללה עבור מחזור עבודה נתון של פעילות / שינה עמוקה.

פיני שחזור ו‑debug

  • RESET — גם מתג רגעי בחלק העליון של הלוח וגם רפידה (J3‑4 / test pad P5) הקשורה לקו ה‑NRST של ה‑SoC. משכו ל‑GND כדי לאתחל.

ה‑Nicla Vision משתמש ב‑double‑tap reset הסטנדרטי של Arduino כדי להיכנס ל‑bootloader של Arduino — לחצו במהירות פעמיים על כפתור ה‑reset והלוח יזוהה כהתקן DFU. OpenMV IDE משתמש במצב זה כדי לרענן את הקושחה.

אותות ה‑SWD של ה‑STM32 חשופים בגב הלוח דרך שורה של test pads בין שני מחברי ה‑J2. הלחימו מחבר 2.54 מ“מ (100‑mil) אליהם כדי לחבר מתאם ST‑LINK או J‑Link:

  • P1 / P2 — אפיק I²C של ה‑PMIC הפנימי על PF0 (SDA) ו‑PF1 (SCL). זהו machine.I2C(2) ב‑Nicla Vision ונושא את תעבורת ה‑PMIC, מד הדלק, וה‑ToF.

  • P3 — TMS / SWDIO (PA13)

  • P4 — TCK / SWCLK (PA14)

  • P5 — NRST

  • P6 — TDO / SWO (PB3)

  • P7 — מסילת +1V8 (מקור ה‑I/O של ה‑SoC — וגם הייחוס הנכון עבור מתאם ה‑debug).

  • P8VOTP_PMICתכנות במפעל בלבד. חייב להישאר לא מחובר.

כל אותות ה‑debug מיוחסים ל‑1.8 V — טבעת ה‑I/O של ה‑STM32H747 בלוח זה פועלת ממסילת ה‑+1V8. הגדירו את מתאם ה‑debug שלכם ללוגיקת 1.8 V לפני החיבור.

התקנים היקפיים מובנים

LEDs

ל‑Nicla Vision יש RGB LED יחיד למשתמש, הניתן לשליטה בתוכנה דרך 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()

כשאתם מבקשים framesize קטן, מנהל ההתקן של ה‑GC2145 חותך חלון קריאה קטן באופן יחסי מהחיישן — כברירת מחדל יחס ההקטנה מהקריאה אל הפלט מוגבל ל‑3x כדי לשמור על קצב פריימים גבוה. csi.IOCTL_SET_FOV_WIDE מעלה את התקרה הזו ל‑5x, מה שאומר שמנהל ההתקן מושך מאזור רחב יותר של החיישן כשמזרימים רזולוציות קטנות. התוצאה היא שדה ראייה רחב יותר באופן ניכר ברזולוציות קטנות, במחיר מסוים של תפוקה:

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. כל חוצץ (buffer) מגיע כ‑PCM bytearray בעל סימן של 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

IMU

מד התאוצה + הג’ירוסקופ 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)

ה‑IMU מחווט לאפיק SPI פנימי ייעודי (SPI5) כך שאינו מתחרה עם ה‑SPI4 של המשתמש המוצא אל המחברים.

מד טווח time‑of‑flight

מד הטווח VL53L1CB מסוג time‑of‑flight של ST שעל הלוח יושב על אפיק ה‑I²C של ה‑PMIC הפנימי (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)

מד דלק לסוללה

מד הדלק ModelGauge m5 MAX17262 של Maxim עוקב אחר המתח, הזרם, הטמפרטורה, ומצב הטעינה של סוללת ה‑Li‑Po. הוא יושב על I²C 2 בכתובת 0x36.

ל‑MAX17262 יש חיישת זרם פנימית, כך שאוגר הזרם נקרא ישירות במיקרו‑אמפר ללא גורם Rsense חיצוני ליישום. קריאת מד הדלק בלתי מזיקה — אין מנהל התקן מסופק, אך את האוגרים המתועדים ב‑datasheet של 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 הוא בעל סימן בשיטת two’s-complement: חיובי בעת טעינה, שלילי בעת פריקה. TTE משמעותי רק כשהזרם שלילי; TTF רק כשהזרם חיובי.

רכיב ניהול הספק (PMIC)

ה‑PMIC MC34PF1550A0EP של NXP מטפל בכל מייצב ב‑Nicla Vision — מסילת ה‑+3V3 הראשית, מסילת ליבת / I/O של ה‑SoC +1V8, VDDIO_EXT אל ממירי המתח, ומטען ה‑Li‑Po. הוא יושב על I²C 2 בכתובת 0x08.

אזהרה

קריאת אוגרי PMIC היא בסדר; כתיבה אליהם מסוכנת. הגדרה שגויה של מייצב buck או הגדרת מטען עלולה לפגוע באופן קבוע בלוח, בסוללה, או בשניהם. התייחסו אל ה‑PMIC כאל קריאה בלבד אלא אם אתם יודעים בדיוק מה אתם עושים.

הדבר השימושי ביותר שה‑PMIC מספר לכם ושמד הדלק אינו יכול הוא מכונת המצבים של המטען — האם הלוח פועל כעת מ‑USB / ESLOV / VIN, באיזה שלב של מחזור הטעינה נמצאת ה‑Li‑Po, והאם המטען נמצא בתקלה תרמית או בתקלת watchdog. אוגרי המטען נמצאים בהיסט של 0x80 במרחב כתובות ה‑I²C הראשי של ה‑PF1550 (ראו §22.2 של datasheet של 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)

אוגרי קריאה‑בלבד נוספים ששווה לעיין בהם ב‑datasheet (כולם בהיסט מטען 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 — לדוגמה, פרסום כהתקן היקפי והמתנה ל‑central שיתחבר:

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 V 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.

ניתן להשתמש באותה חומרה גם במצב target (slave) דרך 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 Vread_u16 מחזיר 0–65535 על פני 0–1.8 V בפין:

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 V (ואין להן ממיר מתח לפני ה‑SoC). הזרמת אות של 3.3 V תרווה את הממיר ועלולה לפגוע בפין — חלקו מתחים גבוהים יותר חיצונית.

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‑bang בתוכנה

machine.SoftI2C ו‑machine.SoftSPI עובדים על כל GPIO אם אתם זקוקים לאפיק נוסף.

חיישן תרמי (חיצוני ללוח)

הקושחה כוללת את מנהל ההתקן fir — מנהל התקן לחיישן תרמי (fir == far infrared) עבור מצלמות הדמיה תרמיות מחווטות חיצונית:

  • MLX90621 — מערך IR של 16 × 4

  • MLX90640 — מערך IR של 32 × 24

  • MLX90641 — מערך IR של 16 × 12

  • AMG8833 — מערך IR של 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 מתזמן פונקציות callback מחזוריות או חד‑פעמיות מבלי לצרוך משבצת טיימר חומרתי. העבירו -1 כ‑id כדי להשתמש בטיימר וירטואלי (תוכנה):

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 משתמש ב‑double‑tap reset הסטנדרטי של Arduino כדי להיכנס ל‑bootloader של Arduino. לחצו במהירות פעמיים על כפתור ה‑reset — הלוח מזוהה מחדש על גבי USB כהתקן DFU ו‑OpenMV IDE יכול לצרוב קושחה חדשה.

סקריפט פעיל יכול להיכנס מחדש ל‑bootloader לפי דרישה על ידי קריאה לmachine.bootloader()

import machine

machine.bootloader()

מערכת קבצים וסדר אתחול

קושחת ה‑Nicla Vision מעלה עד שתי מערכות קבצים באתחול:

  • זיכרון פלאש (flash) פנימי — תמיד מועלה ב‑/flash. מכיל main.py ו‑README.txt כברירת מחדל; נוצר באתחול הראשון ממש.

  • ROMFS — מערכת קבצים לקריאה בלבד, ממופת זיכרון ב‑/rom המועלית אוטומטית על ידי MicroPython בעת ההפעלה.

לאחר ההעלאה, ספריית העבודה מוגדרת ל‑/flash. המפרש מריץ אז סקריפטים מספרייה זו:

  • boot.py מורץ בכל אתחול רך (cold boot, Ctrl‑D מה‑REPL, או בכל פעם שהסקריפט הרץ חוזר).

  • main.py מורץ רק ב‑cold boot, מיד לאחר boot.py. אתחולים רכים עוקבים מריצים מחדש את boot.py אך צונחים ישירות אל ה‑REPL — כדי להריץ מחדש את main.py עליכם לאתחל את הלוח לחלוטין.

ברירת המחדל של main.py המסופקת על לוח שזה עתה נצרב פשוט מהבהבת את הערוץ הכחול של ה‑RGB LED של המשתמש כפעימת לב (שני פעימות קצרות, רווח קצר), כך שתוכלו לדעת שהקושחה אותחלה בנקיון ללא host מחובר.

sys.path מורחב כדי לכלול את שתי מערכות הקבצים ואת תת‑הספריות lib/ שלהן, כך שמודולים הניתנים לייבוא יכולים לשבת ב‑/flash/lib או ב‑/rom/lib.

כשמחובר על גבי USB, /flash מזוהה גם ככונן אחסון המוני USB ב‑host, ומאפשר לכם לערוך את boot.py, main.py, וכל קובץ אחר ישירות. הוציאו את הכונן לפני אתחול המצלמה כדי שה‑host ירוקן את הכתיבות שבמטמון שלו.

הערה

מכיוון שמערכת ההפעלה מתייחסת אל הכונן כאל התקן בלוקים פסיבי, קבצים שנוצרו או שונו על ידי קוד הרץ על המצלמה לא יופיעו עד שה‑host יעלה מחדש את הכונן. אם גם מערכת ההפעלה וגם המצלמה כותבות לאותה מערכת קבצים בו‑זמנית, מערכת ההפעלה תנצח ותדרוס שינויים שביצעה המצלמה. השתמשו בכרטיס ה‑SD עבור כל נתון שהסקריפט כותב חזרה, והעלו מחדש לפני קריאת קבצים אלו מה‑host.

הערה

הערוץ האדום של ה‑RGB LED של המשתמש עשוי להידלק לרגע קצר בעוד ה‑host קורא או כותב אל כונן האחסון ההמוני USB — זהו מחוון פעילות מבוסס קושחה, ולא תקלה.

גדלי אחסון

ה‑Nicla Vision מגיע עם:

  • /flash — מערכת קבצים FAT של 11 MB, קריאה/כתיבה.

  • /rom — ROMFS ממופת זיכרון לקריאה בלבד של 4 MB, משמש לשליחת סקריפטים ומודלי ML שמרוויחים מגישת mmap ללא העתקה.

מחוון hard‑fault

אם ה‑RGB LED של המשתמש עובר במהירות בין כל הצבעים — מהר מספיק שזה נוטה להיראות כמו נורית לבנה מנצנצת ולא כגוונים נפרדים — הקושחה נתקלה ב‑hard fault שאי אפשר להתאושש ממנו. צרבו מחדש את הקושחה כדי להתאושש; אם הצריבה מחדש אינה עוזרת, ייתכן שהלוח ניזוק פיזית.

ספריות תוכנה

ראו את אינדקס הספרייה לרשימה המלאה של המודולים — כולל אלו הייחודיים לבניית ה‑Nicla Vision.