Arduino Nicla Vision

Arduino Nicla Vision to płytka do wizji maszynowej o wymiarach 22,86 × 22,86 mm, zbudowana wokół układu STMicroelectronics STM32H747AII6 — dwurdzeniowego SoC łączącego rdzeń Cortex‑M7 taktowany 400 MHz z rdzeniem Cortex‑M4 taktowanym 200 MHz. Oprogramowanie układowe OpenMV działa w całości na rdzeniu M7. Płytka łączy mikrokontroler z 2 MP kolorowym sensorem CMOS GC2145, 6‑osiową jednostką IMU LSM6DSOX, mikrofonem MEMS MP34DT06, dalmierzem time‑of‑flight VL53L1CB, modułem Wi‑Fi + Bluetooth LE 5.1 oraz ładowarką akumulatora / wskaźnikiem poziomu naładowania.

Arduino Nicla Vision

Pełną kartę katalogową, zdjęcia i wymiary znajdziesz na stronie produktu Arduino Nicla Vision.

Najważniejsze cechy

  • STMicroelectronics STM32H747AII6 — dwurdzeniowy Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). Oprogramowanie układowe OpenMV działa wyłącznie na rdzeniu M7.

  • 2 MB wewnętrznej pamięci flash oraz 16 MB zewnętrznej pamięci flash QSPI (używanej na aplikację + ROMFS).

  • 1 MB wewnętrznej pamięci SRAM.

  • Sprzętowy enkoder/dekoder JPEG.

  • GC2145 — 2 MP kolorowy sensor CMOS.

  • Wbudowana jednostka IMU (akcelerometr + żyroskop LSM6DSOX), mikrofon MEMS (MP34DT06JTR) oraz dalmierz time‑of‑flight VL53L1CB (do ~4 m).

  • Wi‑Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 dzięki modułowi Murata 1DX (CYW4343W) — łączy się z dołączoną anteną poprzez wbudowane złącze U.FL.

  • USB High‑Speed (480 Mb/s) przez Micro USB za pośrednictwem zewnętrznego układu ULPI PHY (USB3320C).

  • 13 użytkowych pinów I/O na krawędziowych listwach Arduino — cztery cyfrowe LPIO (D0D3), trzy wejścia analogowe 1,8 V (A0A2), para I²C SCL/SDA oraz czwórka SPI SCLK/CIPO/COPI/CS.

  • Obsługa akumulatora — złącze Li‑Po z tyłu, ładowarka typu BQ oraz wskaźnik poziomu naładowania MAX17262 na wewnętrznej magistrali PMIC.

  • 5‑pinowe złącze ESLOV z tyłu do beztynowej rozbudowy I²C.

Ostrzeżenie

Użytkowe piny cyfrowe domyślnie pracują na 3,3 V, ale są poprowadzone przez programowo konfigurowalne konwertery poziomów logicznych (VDDIO_EXT), które można przestawić na 1,8 V. Piny analogowe (A0–A2) działają wyłącznie na 1,8 V — omijają konwertery poziomów i łączą się bezpośrednio z mikrokontrolerem. Podanie 3,3 V na A0–A2 uszkodzi układ SoC.

Rozkład pinów

Rozkład pinów Arduino Nicla Vision

Opis pinów

Trzynaście użytkowych pinów jest wyprowadzonych na krawędziowych listwach Arduino (J1 i J2). Dodatkowe sygnały debugowania, odzyskiwania i PMIC są poprowadzone do pól testowych z tyłu płytki.

Nazwa pinu

Napięcie odniesienia

Funkcja

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 kanał 4 (J1‑8)

A1

1,8 V

ADC2 kanał 2 (J1‑7)

A2

1,8 V

ADC3 kanał 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

podciągnij do GND (lub naciśnij wbudowany przycisk), aby zresetować płytkę

LED_RED

3,3 V

czerwony kanał diody RGB (aktywny stanem niskim)

LED_GREEN

3,3 V

zielony kanał diody RGB (aktywny stanem niskim)

LED_BLUE

3,3 V

niebieski kanał diody RGB (aktywny stanem niskim)

Informacja

D0D3 oraz SCLK/CIPO/COPI/CS znajdują się za dwukierunkowym konwerterem poziomów TXB0108 — ten układ obsługuje wyłącznie sterowanie GPIO typu push‑pull, więc ruch po magistrali typu open‑drain (np. programowo emulowane 1‑Wire lub I²C na tych pinach) nie zadziała.

SCL/SDA znajdują się za osobnym konwerterem NTS0304, który obsługuje zarówno sterowanie push‑pull, jak i open‑drain, dlatego działa tam I²C 1.

Oba konwertery są odniesione do VDDIO_EXT (domyślnie 3,3 V z wbudowanego PMIC), a ich obciążalność prądowa jest ograniczona w porównaniu z bezpośrednim GPIO — są przeznaczone do przesyłania sygnałów, a nie do zasilania obciążeń.

Piny zasilania

Piny listwy krawędziowej:

  • VIN (J2‑9) — główna szyna systemowa 3,6 – 5 V. PMIC pobiera tu swoje zasilanie.

  • VDDIO_EXT (J2‑7) — wyjście szyny konwerterów poziomów, 1,8 V lub 3,3 V (domyślnie 3,3 V). Użyj go do zasilania zewnętrznych urządzeń peryferyjnych 1,8 V lub 3,3 V podłączonych do pinów LPIO/SPI/I²C, aby pracowały na tym samym poziomie logicznym co listwy.

  • VBAT (J3‑2) — wejście akumulatora Li‑Po. Wbudowany PMIC ładuje ogniwo z VIN i raportuje stan naładowania poprzez wskaźnik poziomu naładowania.

  • NTC (J3‑1) — opcjonalne wejście termistora Li‑Po.

  • GND (J2‑6) — masa wspólna.

  • NC (J2‑8) — bez połączenia.

Pola testowe z tyłu płytki:

  • +3V3 — główna szyna 3,3 V.

  • D_P / D_N — para danych USB High‑Speed (za układem PHY).

USB i złącze ESLOV zasilają VIN poprzez parę idealnych diod LM66100 (po jednej na źródło), więc każde z zasilań może samodzielnie zasilać płytkę, a oba nigdy wzajemnie się nie wstecznie zasilają. Jeśli sterujesz VIN zewnętrznie na J2‑9, ma to pierwszeństwo — diody po prostu przestają przewodzić z USB / ESLOV, gdy zewnętrzna szyna wzrośnie wyżej.

Płytkę można zatem zasilać dowolną z tych dróg:

  • Micro USB — 5 V na VIN poprzez idealną diodę po stronie USB.

  • Złącze ESLOV — do 5 V na pinie VESLOV złącza J5, poprowadzone do VIN poprzez idealną diodę po stronie ESLOV (zobacz Złącze ESLOV).

  • Pin VIN (J2‑9) — podaj bezpośrednio stabilizowane zasilanie 3,6 – 5 V.

  • Akumulator Li‑Po — podłącz do złącza akumulatora J4 z tyłu lub do pól VBAT/GND/NTC na J3 / J2‑6. Nie podłączaj dwóch akumulatorów jednocześnie.

Złącze ESLOV

J5 z tyłu płytki to 5‑pinowe beztynowe złącze Molex ESLOV:

Pin

Nazwa

Funkcja

J5‑1

VESLOV

wejście zasilania (≤ 5 V) — dołączone do VIN poprzez idealną diodę LM66100

J5‑2

INT

wejście przerwania zewnętrznego na PD9

J5‑3

SCL_EXT

współdzielone z polem SCL na J2 — ta sama magistrala I²C 1 co listwa użytkownika

J5‑4

SDA_EXT

współdzielone z polem SDA na J2 — ta sama magistrala I²C 1 co listwa użytkownika

J5‑5

GND

masa wspólna

SCL_EXT/SDA_EXT ESLOV oraz SCL/SDA na J2 to te same piny — jedna magistrala I²C 1 wyprowadzona na dwa złącza.

Wskazówka

Użyj estymatora czasu pracy na baterii, aby oszacować, jak długo Nicla Vision będzie działać na baterii przy danym cyklu pracy aktywny / głęboki uśpienie.

Piny odzyskiwania i debugowania

  • RESET — zarówno chwilowy przycisk na górze płytki, jak i pole (J3‑4 / pole testowe P5) połączone z linią NRST układu SoC. Podciągnij do GND, aby zresetować.

Nicla Vision używa standardowego dla Arduino podwójnego naciśnięcia resetu, aby wejść do bootloadera Arduino — naciśnij szybko dwukrotnie przycisk resetu, a płytka zgłosi się jako urządzenie DFU. OpenMV IDE wykorzystuje ten tryb do ponownego wgrania oprogramowania układowego.

Sygnały SWD układu STM32 są wyprowadzone z tyłu płytki poprzez rząd pól testowych pomiędzy dwiema listwami J2. Wlutuj w nie listwę 2,54 mm (100 mil), aby podłączyć adapter ST‑LINK lub J‑Link:

  • P1 / P2 — wewnętrzna magistrala I²C PMIC na PF0 (SDA) i PF1 (SCL). To machine.I2C(2) na Nicla Vision i obsługuje ruch PMIC, wskaźnika poziomu naładowania oraz ToF.

  • P3 — TMS / SWDIO (PA13)

  • P4 — TCK / SWCLK (PA14)

  • P5 — NRST

  • P6 — TDO / SWO (PB3)

  • P7 — szyna +1V8 (zasilanie I/O układu SoC — również właściwe odniesienie dla adaptera debugowania).

  • P8VOTP_PMICwyłącznie do programowania fabrycznego. Musi pozostać niepodłączony.

Wszystkie sygnały debugowania są odniesione do 1,8 V — pierścień I/O układu STM32H747 na tej płytce zasilany jest z szyny +1V8. Przed podłączeniem ustaw swój adapter debugowania na logikę 1,8 V.

Wbudowane urządzenia peryferyjne

Diody LED

Nicla Vision ma jedną użytkową diodę RGB, sterowalną programowo poprzez machine.LED

from machine import LED

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

Osobna dioda DL2 CHARGE z boku płytki jest podłączona bezpośrednio do wyjścia CHGB układu PMIC — świeci podczas ładowania akumulatora Li‑Po z USB / ESLOV / VIN i nie jest sterowalna przez użytkownika.

Sensor kamery

Sensor GC2145 jest obsługiwany poprzez moduł csi — sensory kamery

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()

Gdy zażądasz małego rozmiaru ramki, sterownik GC2145 wycina proporcjonalnie małe okno odczytu z sensora — domyślnie współczynnik skalowania w dół odczytu względem wyjścia jest ograniczony do 3x, aby utrzymać wysoką liczbę klatek. csi.IOCTL_SET_FOV_WIDE podnosi ten limit do 5x, co oznacza, że przy strumieniowaniu małych rozdzielczości sterownik pobiera dane z szerszego obszaru sensora. Efektem jest zauważalnie szersze pole widzenia przy małych rozmiarach ramki, kosztem pewnej przepustowości:

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

Rdzeń M4

Rdzeń Cortex‑M4 jest udostępniony poprzez openamp do komunikacji międzyprocesorowej. Oprogramowanie układowe OpenMV działa wyłącznie na rdzeniu M7; rdzeń M4 nie ma własnego środowiska uruchomieniowego MicroPython, więc jego użycie oznacza zbudowanie osobnego obrazu oprogramowania układowego w C i wczytanie go z systemu plików poprzez openamp.RemoteProc. Gotowe przykładowe oprogramowanie układowe implementujące wirtualny punkt końcowy UART jest dostępne w repozytorium openamp_vuart — postępuj zgodnie z jego plikiem README, aby zbudować 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)

W praktyce tę obsługę najlepiej traktować jako demonstrację interfejsu openamp, a nie jako działającą platformę dwurdzeniową — rdzenia M4 nie można zresetować niezależnie od M7, więc zatrzymanie M4 wymusza pełny restart systemu.

Mikrofon

Wbudowany mikrofon PDM MP34DT06JTR jest przechwytywany poprzez audio — Moduł Audio za pośrednictwem peryferium DFSDM układu STM32. Każdy bufor przychodzi jako 16‑bitowy ze znakiem PCM bytearray, gotowy do podania do ulab/numpy w celu przetwarzania DSP — na przykład prosty detektor głośności:

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

Wbudowany akcelerometr + żyroskop LSM6DSOX jest udostępniony poprzez imu — sensor 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 jest podłączona do dedykowanej wewnętrznej magistrali SPI (SPI5), więc nie rywalizuje z użytkową magistralą SPI4 wyprowadzoną na listwach.

Dalmierz time‑of‑flight

Wbudowany dalmierz time‑of‑flight ST VL53L1CB znajduje się na wewnętrznej magistrali I²C PMIC (I²C 2). Użyj zamrożonego sterownika vl53l1x — sterownik czujnika odległości ToF VL53L1X, aby uzyskać odczyty odległości do ~4 m:

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)

Wskaźnik poziomu naładowania akumulatora

Wskaźnik poziomu naładowania Maxim MAX17262 ModelGauge m5 śledzi napięcie, prąd, temperaturę i stan naładowania akumulatora Li‑Po. Znajduje się na I²C 2 pod adresem 0x36.

MAX17262 ma wewnętrzny pomiar prądu, więc rejestr prądu odczytuje się bezpośrednio w mikroamperach, bez stosowania zewnętrznego współczynnika Rsense. Odczyt wskaźnika poziomu naładowania jest nieszkodliwy — żaden sterownik nie jest dostarczany, ale rejestry udokumentowane w karcie katalogowej MAX17262 można odczytać bezpośrednio:

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 jest liczbą ze znakiem w kodzie uzupełnień do dwóch: dodatnia podczas ładowania, ujemna podczas rozładowywania. TTE ma sens tylko wtedy, gdy prąd jest ujemny; TTF tylko wtedy, gdy prąd jest dodatni.

Układ zarządzania zasilaniem (PMIC)

Układ PMIC NXP MC34PF1550A0EP obsługuje każdy stabilizator na Nicla Vision — główną szynę +3V3, szynę rdzenia / I/O SoC +1V8, VDDIO_EXT do konwerterów poziomów oraz ładowarkę Li‑Po. Znajduje się na I²C 2 pod adresem 0x08.

Ostrzeżenie

Odczyt rejestrów PMIC jest bezpieczny; zapis do nich jest niebezpieczny. Błędna konfiguracja stabilizatora buck lub ustawienia ładowarki może trwale uszkodzić płytkę, akumulator lub oba. Traktuj PMIC jako tylko do odczytu, chyba że dokładnie wiesz, co robisz.

Najbardziej przydatną informacją, którą podaje PMIC, a której nie może podać wskaźnik poziomu naładowania, jest maszyna stanów ładowarki — czy płytka aktualnie działa na USB / ESLOV / VIN, na jakim etapie cyklu ładowania jest akumulator Li‑Po oraz czy ładowarka znajduje się w stanie błędu termicznego lub watchdoga. Rejestry ładowarki znajdują się z przesunięciem 0x80 w głównej przestrzeni adresowej I²C układu PF1550 (zobacz §22.2 karty katalogowej PF1550), więc na przykład CHG_INT_OK pod adresem ładowarki 0x04 odczytuje się z rejestru 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)

Inne rejestry tylko do odczytu warte zajrzenia w karcie katalogowej (wszystkie z przesunięciem ładowarki 0x80): 0x80 CHG_INT (zatrzaśnięte przerwania ładowarki — flagi błędów), 0x86 VBUS_SNS (wielobitowy stan VBUS, w tym OVLO / UVLO / DPM) oraz 0x88 BATT_SNS (obecność akumulatora i stan przeciążenia prądowego).

Wi‑Fi

Wbudowany Murata 1DX (CYW4343W) jest udostępniony poprzez network — konfiguracja sieci jako interfejs stacji. Przed uruchomieniem radia podłącz dołączoną antenę do wbudowanego złącza 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

Ten sam moduł Murata 1DX udostępnia również Bluetooth LE 5.1. Użyj aioble — Asynchroniczne BLE do BLE przyjaznego dla asyncio — na przykład rozgłaszaj jako urządzenie peryferyjne i czekaj na połączenie ze stacją centralną:

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())

Opis magistral

GPIO

Użyj machine.Pin, aby odczytać lub sterować dowolnym z opisanych na sitodruku pinów. Wyjścia to 3,3 V CMOS (domyślnie VDDIO_EXT), a konwertery poziomów ograniczają obciążalność prądową pojedynczego pinu do kilku miliamperów — są przeznaczone do przesyłania sygnałów, a nie do zasilania obciążeń.

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())

Każdy pin wejściowy może również wyzwolić przerwanie przy zmianach na krawędzi:

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

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

UART

Magistrala

TX

RX

UART4

SDA

SCL

from machine import UART

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

Informacja

UART4 współdzieli swoje piny z I²C 1 — te same pola SDA/SCL obsługują obie magistrale. Na tych pinach wybierz UART albo I²C, nie obie naraz.

Sitodruk D1/D2 zawiera również opisy UART_TX/UART_RX, ale w tym oprogramowaniu układowym te piny są poprowadzone do LPUART1, a nie do machine.UART. Samo machine.UART(1) jest zarezerwowane dla wbudowanego kontrolera Bluetooth i nie jest dostępne na listwach.

I²C

Magistrala

SCL

SDA

I2C1

SCL

SDA

from machine import I2C

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

Pola SCL/SDA na J2 oraz piny SCL_EXT/SDA_EXT złącza ESLOV trafiają na tę samą magistralę I²C 1 — zobacz Złącze ESLOV powyżej dla rozkładu pinów ESLOV.

Tego samego sprzętu można użyć również w trybie docelowym (slave) poprzez machine.I2CTarget, aby udostępnić obszar pamięci innemu kontrolerowi I²C:

from machine import I2CTarget

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

SPI

Magistrala

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 udostępnia trzy kanały 12‑bitowego ADC na A0, A1 i A2. Wszystkie trzy są odniesione do 1,8 Vread_u16 zwraca 0–65535 w zakresie 0–1,8 V na pinie:

from machine import ADC
import time

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

Ostrzeżenie

Wejścia ADC Nicla Vision są odniesione do 1,8 V (i nie mają konwertera poziomów przed układem SoC). Podanie sygnału 3,3 V nasyci przetwornik i może uszkodzić pin — wyższe napięcia podziel zewnętrznie w dół.

PWM

Pin

Licznik czasu / kanał

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

Steruj dowolnym z nich poprzez machine.PWM

from machine import Pin, PWM

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

Informacja

Kilka pinów współdzieli kanały TIM1:

  • TIM1 CH2 jest na D1 oraz CS.

  • TIM1 CH3 jest na D2 oraz CIPO; SCLK wyprowadza odwrócone dopełnienie (TIM1 CH3N) tego samego kanału.

  • TIM1 CH4 jest wyłącznie na COPI.

Wybierz jednego odbiorcę na kanał licznika czasu. Piny czwórki SPI (SCLK/CIPO/COPI/CS) nie mogą być również sterowane PWM, gdy używa ich machine.SPI(4).

Programowo emulowane magistrale

machine.SoftI2C i machine.SoftSPI działają na dowolnym GPIO, jeśli potrzebujesz dodatkowej magistrali.

Sensor termiczny (zewnętrzny)

Oprogramowanie układowe zawiera sterownik fir — sterownik sensora termicznego (fir == far infrared, daleka podczerwień) do zewnętrznie podłączonych kamer termowizyjnych:

  • MLX90621 — matryca IR 16 × 4

  • MLX90640 — matryca IR 32 × 24

  • MLX90641 — matryca IR 16 × 12

  • AMG8833 — matryca IR 8 × 8

Podłącz moduł do magistrali I²C płytki i odczytuj ramki za pomocą 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())

Sterownik fir komunikuje się z sensorem wyłącznie po I²C 1 — podłącz moduł do opisanych na sitodruku pól SCL / SDA.

Pomiar czasu

time

Moduł time obejmuje blokujące opóźnienia, monotoniczne tyknięcia oraz pomiar upływającego czasu:

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)

Wirtualne liczniki czasu

machine.Timer planuje okresowe lub jednorazowe wywołania zwrotne bez zajmowania sprzętowego slotu licznika czasu. Przekaż -1 jako id, aby użyć wirtualnego (programowego) licznika czasu:

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"))

Wartości okresu podawane są w milisekundach. Wywołaj deinit(), aby zatrzymać i zwolnić slot.

Zegar czasu rzeczywistego

machine.RTC utrzymuje czas zegarowy pomiędzy resetami:

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 resetuje płytkę, jeśli aplikacja się zawiesi. Po uruchomieniu nie można go zatrzymać ani ponownie skonfigurować — karm go okresowo wewnątrz głównej pętli:

from machine import WDT

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

Informacje o rozruchu i działaniu

Aktualizacja oprogramowania układowego (DFU)

Nicla Vision używa standardowego dla Arduino podwójnego naciśnięcia resetu, aby wejść do bootloadera Arduino. Naciśnij szybko dwukrotnie przycisk resetu — płytka ponownie zgłosi się przez USB jako urządzenie DFU, a OpenMV IDE może wgrać nowy obraz oprogramowania układowego.

Działający skrypt może na żądanie ponownie wejść do bootloadera, wywołując machine.bootloader()

import machine

machine.bootloader()

System plików i kolejność rozruchu

Oprogramowanie układowe Nicla Vision montuje przy rozruchu do dwóch systemów plików:

  • Wewnętrzna pamięć flash — zawsze montowana pod /flash. Domyślnie zawiera main.py i README.txt; tworzona przy pierwszym rozruchu.

  • ROMFS — tylko do odczytu, mapowany w pamięci system plików pod /rom montowany automatycznie przez MicroPython przy starcie.

Po zamontowaniu katalog roboczy jest ustawiany na /flash. Interpreter uruchamia następnie skrypty z tego katalogu:

  • boot.py jest wykonywany przy każdym miękkim resecie (zimny rozruch, Ctrl‑D z REPL lub za każdym razem, gdy działający skrypt zakończy działanie).

  • main.py jest wykonywany tylko przy zimnym rozruchu, bezpośrednio po boot.py. Kolejne miękkie resety ponownie uruchamiają boot.py, ale przechodzą prosto do REPL — aby ponownie uruchomić main.py, musisz w pełni zresetować płytkę.

Domyślny main.py dostarczany na świeżo wgranej płytce po prostu miga niebieskim kanałem użytkowej diody RGB jako sygnał życia (dwa krótkie błyski, krótka przerwa), dzięki czemu możesz stwierdzić, że oprogramowanie układowe wystartowało poprawnie bez podłączonego hosta.

sys.path jest rozszerzane o oba systemy plików oraz ich podkatalogi lib/, więc importowalne moduły mogą znajdować się w /flash/lib lub /rom/lib.

Po podłączeniu przez USB /flash zgłasza się również jako dysk pamięci masowej USB na hoście, pozwalając bezpośrednio edytować boot.py, main.py i wszelkie inne pliki. Wysuń dysk przed zresetowaniem kamery, aby host opróżnił buforowane zapisy.

Informacja

Ponieważ system operacyjny traktuje dysk jako pasywne urządzenie blokowe, pliki utworzone lub zmodyfikowane przez kod działający na kamerze nie pojawią się, dopóki host ponownie nie zamontuje dysku. Jeśli system operacyjny i kamera zapisują ten sam system plików w tym samym czasie, system operacyjny wygra i nadpisze zmiany wprowadzone przez kamerę. Do danych zapisywanych przez skrypt używaj karty SD i ponownie zamontuj dysk przed odczytaniem tych plików z hosta.

Informacja

Czerwony kanał użytkowej diody RGB może na chwilę zaświecić, gdy host odczytuje z dysku pamięci masowej USB lub na niego zapisuje — to sterowany oprogramowaniem układowym wskaźnik aktywności, a nie usterka.

Rozmiary pamięci

Nicla Vision jest dostarczana z:

  • /flash — system plików FAT 11 MB, do odczytu/zapisu.

  • /rom — mapowany w pamięci ROMFS 4 MB tylko do odczytu, używany do dostarczania skryptów i modeli ML, które korzystają z bezkopiowego dostępu mmap.

Wskaźnik twardej awarii (hard fault)

Jeśli użytkowa dioda RGB szybko przechodzi przez wszystkie kolory — na tyle szybko, że zwykle wygląda jak migocząca biała dioda LED zamiast wyraźnych barw — oprogramowanie układowe napotkało nieodwracalną twardą awarię (hard fault). Aby odzyskać działanie, wgraj ponownie oprogramowanie układowe; jeśli to nie pomoże, płytka może być fizycznie uszkodzona.

Biblioteki programowe

Pełną listę modułów — w tym które z nich są unikalne dla wersji Nicla Vision — znajdziesz w indeksie bibliotek.