Arduino Nicla Vision

De Arduino Nicla Vision is een machine-vision-bord van 22,86 × 22,86 mm dat is opgebouwd rond de STMicroelectronics STM32H747AII6 — een dual-core SoC die een Cortex-M7 op 400 MHz combineert met een Cortex-M4 op 200 MHz. De OpenMV-firmware draait volledig op de M7-kern. Het bord combineert de MCU met de GC2145 2 MP-kleuren-CMOS-sensor, een LSM6DSOX 6-assige IMU, een MP34DT06 MEMS-microfoon, een VL53L1CB time-of-flight-afstandsmeter, Wi-Fi + Bluetooth LE 5.1 en een batterijlader / fuel gauge.

Arduino Nicla Vision

Voor de volledige datasheet, foto’s en afmetingen, zie de productpagina van de Arduino Nicla Vision.

Hoogtepunten

  • STMicroelectronics STM32H747AII6 dual Cortex-M7 (400 MHz) + Cortex-M4 (200 MHz). De OpenMV-firmware draait alleen op de M7-kern.

  • 2 MB intern flashgeheugen plus 16 MB extern QSPI-flashgeheugen (gebruikt voor de applicatie + ROMFS).

  • 1 MB interne SRAM.

  • Hardware JPEG-encoder/-decoder.

  • GC2145 2 MP-kleuren-CMOS-sensor.

  • Ingebouwde IMU (LSM6DSOX-versnellingsmeter + gyroscoop), MEMS-microfoon (MP34DT06JTR) en VL53L1CB time-of-flight-afstandsmeter (tot ~4 m).

  • Wi-Fi b/g/n (2,4 GHz) + Bluetooth LE 5.1 via de Murata 1DX (CYW4343W) module — verbindt met de meegeleverde antenne via een ingebouwde U.FL-connector.

  • High-speed USB (480 Mb/s) via Micro USB door een externe ULPI PHY (USB3320C).

  • 13 I/O-pinnen voor de gebruiker op de Arduino-randheaders — vier digitale LPIO’s (D0D3), drie 1,8 V analoge ingangen (A0A2), het SCL/SDA I²C-paar en het SCLK/CIPO/COPI/CS SPI-kwartet.

  • Batterijondersteuning — Li-Po-connector aan de achterkant, een lader in BQ-stijl en MAX17262 fuel gauge via de interne PMIC-bus.

  • 5-pins ESLOV-connector aan de achterkant voor soldeervrije I²C-uitbreiding.

Waarschuwing

De digitale pinnen voor de gebruiker zijn standaard 3,3 V, maar lopen via softwarematig programmeerbare level shifters (VDDIO_EXT) die kunnen worden geherconfigureerd naar 1,8 V. De analoge pinnen (A0–A2) zijn uitsluitend 1,8 V — ze omzeilen de level shifters en zijn rechtstreeks verbonden met de MCU. Het aansturen van 3,3 V op A0–A2 beschadigt de SoC.

Pinout

Pinout van de Arduino Nicla Vision

Pinreferentie

Dertien pinnen voor de gebruiker zijn beschikbaar op de Arduino-randheaders (J1 en J2). Aanvullende debug-, herstel- en PMIC-signalen lopen naar testpads aan de achterkant van het bord.

Pinnaam

Referentie

Functie

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 kanaal 4 (J1-8)

A1

1,8 V

ADC2 kanaal 2 (J1-7)

A2

1,8 V

ADC3 kanaal 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

trek naar GND (of druk op de ingebouwde schakelaar) om het bord te resetten

LED_RED

3,3 V

rode kanaal van de RGB-LED (actief laag)

LED_GREEN

3,3 V

groene kanaal van de RGB-LED (actief laag)

LED_BLUE

3,3 V

blauwe kanaal van de RGB-LED (actief laag)

Notitie

D0D3 en SCLK/CIPO/COPI/CS zitten achter de TXB0108 bidirectionele level shifter — dat onderdeel ondersteunt alleen push-pull GPIO-aansturing, dus open-drain-busverkeer (bijv. een bit-banged 1-Wire of I²C op die pinnen) werkt niet.

SCL/SDA zitten achter een afzonderlijke NTS0304-shifter die zowel push-pull als open-drain-aansturing ondersteunt, en daarom werkt I²C 1 daar.

Beide shifters zijn gerefereerd aan VDDIO_EXT (standaard 3,3 V vanaf de ingebouwde PMIC), en hun aanstuursterkte is beperkt vergeleken met een directe GPIO — ze zijn ontworpen voor signaalniveaus in plaats van vermogensbelastingen.

Voedingspinnen

Pinnen op de randheader:

  • VIN (J2-9) — hoofdsysteemrail van 3,6 – 5 V. De PMIC neemt zijn ingang hier af.

  • VDDIO_EXT (J2-7) — uitgang van de level-shifter-rail, 1,8 V of 3,3 V (standaard 3,3 V). Gebruik dit om externe 1,8 V- of 3,3 V-randapparaten te voeden die zijn aangesloten op de LPIO-/SPI-/I²C-pinnen, zodat ze hetzelfde logische niveau hanteren als de headers.

  • VBAT (J3-2) — Li-Po-batterij-ingang. De ingebouwde PMIC laadt de cel vanaf VIN op en rapporteert de laadtoestand via de fuel gauge.

  • NTC (J3-1) — optionele Li-Po-thermistoringang.

  • GND (J2-6) — gemeenschappelijke massa.

  • NC (J2-8) — niet aangesloten.

Testpads aan de achterkant van het bord:

  • +3V3 — hoofdrail van 3,3 V.

  • D_P / D_N — USB high-speed datapaar (na PHY).

USB en de ESLOV-connector voeden beide VIN via een paar LM66100 ideale diodes (één per bron), zodat elke voeding het bord op zichzelf kan voeden en de twee elkaar nooit terugvoeden. Als je VIN extern aanstuurt op J2-9, krijgt die voorrang — de diodes stoppen simpelweg met geleiden vanaf USB / ESLOV zodra de externe rail hoger stijgt.

Het bord kan daarom via elk van deze paden worden gevoed:

  • Micro USB — 5 V naar VIN via de ideale diode aan de USB-zijde.

  • ESLOV-connector — tot 5 V op de VESLOV-pin van J5, geleid naar VIN via de ideale diode aan de ESLOV-zijde (zie ESLOV-connector).

  • VIN-pin (J2-9) — stuur rechtstreeks een gestabiliseerde voeding van 3,6 – 5 V aan.

  • Li-Po-batterij — sluit aan op de J4-batterijconnector aan de achterkant of op de VBAT-/GND-/NTC-pads op J3 / J2-6. Sluit nooit twee batterijen tegelijk aan.

ESLOV-connector

J5 aan de achterkant van het bord is een 5-pins Molex soldeervrije ESLOV-connector:

Pin

Naam

Functie

J5-1

VESLOV

voedingsingang (≤ 5 V) — via een LM66100 ideale diode OR’d naar VIN

J5-2

INT

externe interrupt-ingang op PD9

J5-3

SCL_EXT

gedeeld met de SCL-pad van J2 — dezelfde I²C 1-bus als de gebruikersheader

J5-4

SDA_EXT

gedeeld met de SDA-pad van J2 — dezelfde I²C 1-bus als de gebruikersheader

J5-5

GND

gemeenschappelijke massa

De SCL_EXT/SDA_EXT van ESLOV en de SCL/SDA van J2 zijn dezelfde pinnen — één I²C 1-bus die op twee connectoren beschikbaar is.

Tip

Gebruik de batterijlevensduurschatter om te modelleren hoe lang de Nicla Vision op een batterij zal werken bij een bepaalde actieve / deep-sleep-arbeidscyclus.

Herstel- en debugpinnen

  • RESET — zowel een momentschakelaar bovenop het bord als een pad (J3-4 / testpad P5) verbonden met de NRST-lijn van de SoC. Trek naar GND om te resetten.

De Nicla Vision gebruikt Arduino’s standaard double-tap reset om Arduino’s bootloader te openen — druk snel twee keer op de resetknop en het bord wordt als DFU-apparaat geënumereerd. OpenMV IDE gebruikt deze modus om de firmware opnieuw te flashen.

De STM32 SWD-signalen zijn beschikbaar aan de achterkant van het bord via een rij testpads tussen de twee J2-headers. Soldeer er een 2,54 mm (100-mil) header in om een ST-LINK- of J-Link-adapter aan te sluiten:

  • P1 / P2 — interne PMIC I²C-bus op PF0 (SDA) en PF1 (SCL). Dit is machine.I2C(2) op de Nicla Vision en draagt het PMIC-, fuel-gauge- en ToF-verkeer.

  • P3 — TMS / SWDIO (PA13)

  • P4 — TCK / SWCLK (PA14)

  • P5 — NRST

  • P6 — TDO / SWO (PB3)

  • P7 — +1V8-rail (de I/O-voeding van de SoC — ook de juiste referentie voor de debug-adapter).

  • P8VOTP_PMICalleen voor fabrieksprogrammering. Moet niet aangesloten worden.

Alle debug-signalen zijn gerefereerd aan 1,8 V — de I/O-ring van de STM32H747 op dit bord werkt vanaf de +1V8-rail. Stel je debug-adapter in op 1,8 V-logica voordat je verbinding maakt.

Ingebouwde randapparaten

LED’s

De Nicla Vision heeft één RGB-LED voor de gebruiker, softwarematig bestuurbaar via machine.LED

from machine import LED

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

Een afzonderlijke DL2 CHARGE-LED aan de zijkant van het bord is rechtstreeks bedraad met de CHGB-uitgang van de PMIC — deze brandt terwijl een Li-Po-batterij wordt opgeladen vanaf USB / ESLOV / VIN en is niet door de gebruiker bestuurbaar.

Camerasensor

De GC2145 wordt aangestuurd via de module csi — camerasensoren

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

Wanneer je een kleine framesize aanvraagt, snijdt de GC2145-driver een proportioneel klein uitleesvenster uit de sensor — standaard is de downscale-verhouding van uitlezing naar uitvoer begrensd op 3x om de framesnelheid hoog te houden. csi.IOCTL_SET_FOV_WIDE verhoogt die limiet naar 5x, wat betekent dat de driver bij het streamen van kleine resoluties uit een breder gebied van de sensor put. Het resultaat is een merkbaar breder gezichtsveld bij kleine framesizes, ten koste van wat doorvoer:

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

M4-kern

De Cortex-M4-kern is beschikbaar via openamp voor inter-processorcommunicatie. De OpenMV-firmware draait alleen op de M7; de M4 heeft geen eigen MicroPython-runtime, dus het gebruik ervan betekent dat je een aparte C-firmware-image moet bouwen en die via openamp.RemoteProc vanaf het bestandssysteem moet laden. Vooraf gebouwde voorbeeldfirmware die een virtueel UART-eindpunt implementeert, is beschikbaar in de repository openamp_vuart — volg de README om vuart.elf te bouwen:

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)

In de praktijk kan deze ondersteuning het best worden beschouwd als een demonstratie van de openamp-interface in plaats van een werkend dual-core-platform — de M4 kan niet onafhankelijk van de M7 worden gereset, dus het stoppen van de M4 forceert een volledige systeemherstart.

Microfoon

De ingebouwde MP34DT06JTR PDM-microfoon wordt vastgelegd via audio — Audio Module over de DFSDM-randapparaat van de STM32. Elke buffer komt aan als een signed-16-bit PCM bytearray, klaar om in te voeren in ulab/numpy voor DSP — bijvoorbeeld een eenvoudige luidheidsdetector:

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

De ingebouwde LSM6DSOX-versnellingsmeter + gyroscoop is beschikbaar via imu — imu-sensor

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)

De IMU is bedraad met een toegewijde interne SPI-bus (SPI5), zodat hij niet concurreert met de SPI4 voor de gebruiker die op de headers is uitgebracht.

Time-of-flight-afstandsmeter

De ingebouwde ST VL53L1CB time-of-flight-afstandsmeter zit op de interne PMIC I²C-bus (I²C 2). Gebruik de bevroren vl53l1x — VL53L1X ToF-afstandssensordriver-driver om afstandsmetingen tot ~4 m te krijgen:

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)

Batterij-fuel-gauge

De Maxim MAX17262 ModelGauge m5 fuel gauge volgt de spanning, stroom, temperatuur en laadtoestand van de Li-Po-batterij. Hij zit op I²C 2 op adres 0x36.

De MAX17262 heeft interne stroommeting, dus het stroomregister leest rechtstreeks in microampère uit zonder dat er een externe Rsense-factor moet worden toegepast. Het uitlezen van de fuel gauge is onschadelijk — er wordt geen driver meegeleverd, maar de registers die in de MAX17262-datasheet worden gedocumenteerd, kunnen rechtstreeks worden uitgelezen:

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 is signed twee’s-complement: positief tijdens het opladen, negatief tijdens het ontladen. TTE is alleen zinvol wanneer de stroom negatief is; TTF alleen wanneer de stroom positief is.

Power-management-IC

De NXP MC34PF1550A0EP PMIC beheert elke regelaar op de Nicla Vision — de +3V3-hoofdrail, de +1V8 SoC-kern-/I/O-rail, VDDIO_EXT naar de level shifters en de Li-Po-lader. Hij zit op I²C 2 op adres 0x08.

Waarschuwing

PMIC-registers uitlezen is prima; ernaar schrijven is gevaarlijk. Het verkeerd configureren van een buck-regelaar of laderinstelling kan het bord, de batterij of beide permanent beschadigen. Behandel de PMIC als alleen-lezen, tenzij je precies weet wat je doet.

Het nuttigste dat de PMIC je vertelt en de fuel gauge niet, is de toestandsmachine van de lader — of het bord momenteel op USB / ESLOV / VIN draait, in welke fase van de laadcyclus de Li-Po zich bevindt en of de lader zich in een thermische of watchdog-fout bevindt. De laderregisters bevinden zich op een offset van 0x80 in de hoofd-I²C-adresruimte van de PF1550 (zie §22.2 van de PF1550-datasheet), dus bijvoorbeeld CHG_INT_OK op laderadres 0x04 wordt uitgelezen vanaf PMIC-register 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)

Andere alleen-lezen-registers die het bekijken in de datasheet waard zijn (allemaal op lader-offset 0x80): 0x80 CHG_INT (vergrendelde lader-interrupts — foutvlaggen), 0x86 VBUS_SNS (de multi-bit VBUS-toestand inclusief OVLO / UVLO / DPM) en 0x88 BATT_SNS (batterijaanwezigheid en overstroomtoestand).

Wi-Fi

De ingebouwde Murata 1DX (CYW4343W) is beschikbaar via network — netwerkconfiguratie als station-interface. Sluit de meegeleverde antenne aan op de ingebouwde U.FL-connector voordat je de radio inschakelt:

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

Dezelfde Murata 1DX biedt ook Bluetooth LE 5.1. Gebruik aioble — Async BLE voor asyncio-vriendelijke BLE — adverteer bijvoorbeeld als randapparaat en wacht tot een central verbinding maakt:

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

Busreferentie

GPIO

Gebruik machine.Pin om een van de op de zeefdruk aangegeven pinnen uit te lezen of aan te sturen. Uitgangen zijn 3,3 V CMOS (standaard VDDIO_EXT) en de level shifters beperken de aanstuursterkte per pin tot een paar milliampère — ze zijn ontworpen voor signaalniveaus in plaats van vermogensbelastingen.

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

Elke ingangspin kan ook een interrupt afvuren bij randovergangen:

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

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

UART

Bus

TX

RX

UART4

SDA

SCL

from machine import UART

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

Notitie

UART4 deelt zijn pinnen met I²C 1 — dezelfde SDA/SCL-pads dragen beide bussen. Kies UART of I²C, niet beide, op die pinnen.

De zeefdruk D1/D2 leest ook UART_TX/UART_RX, maar in deze firmware lopen die pinnen naar LPUART1, niet naar machine.UART. machine.UART(1) zelf is gereserveerd voor de on-chip Bluetooth-controller en is niet toegankelijk op de headers.

I²C

Bus

SCL

SDA

I2C1

SCL

SDA

from machine import I2C

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

De SCL/SDA-pads op J2 en de SCL_EXT/SDA_EXT-pinnen van de ESLOV-connector komen uit op dezelfde I²C 1-bus — zie ESLOV-connector hierboven voor de ESLOV-pinout.

Dezelfde hardware kan ook in target- (slave-)modus worden gebruikt via machine.I2CTarget om een geheugengebied bloot te stellen aan een andere I²C-controller:

from machine import I2CTarget

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

SPI

Bus

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

De Nicla Vision biedt drie 12-bits ADC-kanalen op A0, A1 en A2. Alle drie zijn gerefereerd aan 1,8 Vread_u16 geeft 0–65535 terug over 0–1,8 V op de pin:

from machine import ADC
import time

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

Waarschuwing

De ADC-ingangen van de Nicla Vision zijn gerefereerd aan 1,8 V (en hebben geen level shifter vóór de SoC). Het aansturen van een 3,3 V-signaal verzadigt de converter en kan de pin beschadigen — deel hogere spanningen extern naar beneden.

PWM

Pin

Timer / kanaal

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

Stuur elke ervan aan via machine.PWM

from machine import Pin, PWM

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

Notitie

Meerdere pinnen delen TIM1-kanalen:

  • TIM1 CH2 zit op D1 en CS.

  • TIM1 CH3 zit op D2 en CIPO; SCLK geeft het geïnverteerde complement (TIM1 CH3N) van hetzelfde kanaal uit.

  • TIM1 CH4 zit alleen op COPI.

Kies één verbruiker per timerkanaal. De SPI-kwartetpinnen (SCLK/CIPO/COPI/CS) kunnen ook niet via PWM worden aangestuurd terwijl machine.SPI(4) ze gebruikt.

Softwarematig bit-banged bussen

machine.SoftI2C en machine.SoftSPI werken op elke GPIO als je een extra bus nodig hebt.

Thermische sensor (extern)

De firmware bevat de fir — thermische sensor-driver (fir == far infrared)-driver voor extern bedrade thermische beeldsensoren:

  • MLX90621 — 16 × 4 IR-array

  • MLX90640 — 32 × 24 IR-array

  • MLX90641 — 16 × 12 IR-array

  • AMG8833 — 8 × 8 IR-array

Bedraad de module met de I²C-bus van het bord en lees frames uit met 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())

De fir-driver communiceert alleen met de sensor over I²C 1 — bedraad de module met de op de zeefdruk aangegeven SCL- / SDA-pads.

Timing

time

De module time behandelt blokkerende vertragingen, monotone ticks en het meten van verstreken tijd:

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)

Virtuele timers

machine.Timer plant periodieke of eenmalige callbacks zonder een hardware-timerslot te verbruiken. Geef -1 door als de id om een virtuele (software-)timer te gebruiken:

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

Periodewaarden zijn in milliseconden. Roep deinit() aan om te stoppen en het slot vrij te geven.

Realtimeklok

machine.RTC houdt de kloktijd bij over resets heen:

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 reset het bord als de applicatie vastloopt. Eenmaal gestart kan hij niet worden gestopt of geherconfigureerd — voed hem periodiek binnen je hoofdlus:

from machine import WDT

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

Boot- en runtime-informatie

Firmware-update (DFU)

De Nicla Vision gebruikt Arduino’s standaard double-tap reset om Arduino’s bootloader te openen. Druk snel twee keer op de resetknop — het bord wordt opnieuw geënumereerd via USB als een DFU-apparaat en OpenMV IDE kan een nieuwe firmware-image flashen.

Een draaiend script kan op verzoek de bootloader opnieuw openen door machine.bootloader() aan te roepen:

import machine

machine.bootloader()

Bestandssysteem en bootvolgorde

De Nicla Vision-firmware koppelt bij het opstarten maximaal twee bestandssystemen:

  • Intern flashgeheugen — altijd gekoppeld op /flash. Bevat standaard main.py en README.txt; aangemaakt bij de allereerste boot.

  • ROMFS — alleen-lezen, geheugengekoppeld bestandssysteem op /rom dat bij het opstarten automatisch door MicroPython wordt gekoppeld.

Na het koppelen wordt de werkdirectory ingesteld op /flash. De interpreter draait vervolgens scripts vanuit die directory:

  • boot.py wordt uitgevoerd bij elke soft reset (koude boot, Ctrl‑D vanuit de REPL of telkens wanneer het draaiende script terugkeert).

  • main.py wordt alleen bij een koude boot uitgevoerd, onmiddellijk na boot.py. Volgende soft resets voeren boot.py opnieuw uit, maar gaan rechtstreeks naar de REPL — om main.py opnieuw uit te voeren moet je het bord volledig resetten.

De standaard main.py die op een vers geflasht bord wordt meegeleverd, laat eenvoudigweg het blauwe kanaal van de RGB-LED voor de gebruiker knipperen als hartslag (twee korte pulsen, korte pauze), zodat je kunt zien dat de firmware schoon is opgestart zonder dat er een host is aangesloten.

sys.path wordt uitgebreid met beide bestandssystemen en hun lib/-submappen, zodat importeerbare modules in /flash/lib of /rom/lib kunnen staan.

Wanneer verbonden via USB, wordt /flash op de host ook geënumereerd als een USB-massaopslagstation, zodat je boot.py, main.py en alle andere bestanden rechtstreeks kunt bewerken. Werp het station uit voordat je de camera reset, zodat de host zijn gecachete schrijfacties wegschrijft.

Notitie

Omdat het besturingssysteem het station als een passief blokapparaat behandelt, verschijnen bestanden die zijn aangemaakt of gewijzigd door code die op de camera draait pas wanneer de host het station opnieuw koppelt. Als zowel het besturingssysteem als de camera tegelijkertijd naar hetzelfde bestandssysteem schrijven, wint het besturingssysteem en overschrijft het de wijzigingen die door de camera zijn aangebracht. Gebruik de SD-kaart voor alle data die het script terugschrijft, en koppel opnieuw voordat je die bestanden vanaf de host leest.

Notitie

Het rode kanaal van de RGB-LED voor de gebruiker kan kort oplichten terwijl de host leest van of schrijft naar het USB-massaopslagstation — dit is een door de firmware aangestuurde activiteitsindicator, geen fout.

Opslaggroottes

De Nicla Vision wordt geleverd met:

  • /flash11 MB FAT-bestandssysteem, lezen/schrijven.

  • /rom4 MB alleen-lezen geheugengekoppeld ROMFS, gebruikt om scripts en ML-modellen te leveren die baat hebben bij zero-copy mmap-toegang.

Hard-fault-indicator

Als de RGB-LED voor de gebruiker snel door alle kleuren cyclet — snel genoeg dat het eerder op een flikkerende witte LED lijkt dan op afzonderlijke tinten — heeft de firmware een onherstelbare hard fault opgelopen. Flash de firmware opnieuw om te herstellen; als opnieuw flashen niet helpt, is het bord mogelijk fysiek beschadigd.

Softwarebibliotheken

Zie de bibliotheekindex voor de volledige lijst met modules — inclusief welke uniek zijn voor de Nicla Vision-build.