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.
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 (
D0–D3), drie 1,8 V analoge ingangen (A0–A2), hetSCL/SDAI²C-paar en hetSCLK/CIPO/COPI/CSSPI-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¶
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
D0–D3 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 |
J5-2 |
INT |
externe interrupt-ingang op |
J5-3 |
SCL_EXT |
gedeeld met de |
J5-4 |
SDA_EXT |
gedeeld met de |
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).
P8 —
VOTP_PMIC— alleen 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 V — read_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
D1enCS.TIM1 CH3 zit op
D2enCIPO;SCLKgeeft 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 standaardmain.pyenREADME.txt; aangemaakt bij de allereerste boot.ROMFS — alleen-lezen, geheugengekoppeld bestandssysteem op
/romdat 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.pywordt uitgevoerd bij elke soft reset (koude boot,Ctrl‑Dvanuit de REPL of telkens wanneer het draaiende script terugkeert).main.pywordt alleen bij een koude boot uitgevoerd, onmiddellijk naboot.py. Volgende soft resets voerenboot.pyopnieuw uit, maar gaan rechtstreeks naar de REPL — ommain.pyopnieuw 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:
/flash— 11 MB FAT-bestandssysteem, lezen/schrijven./rom— 4 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.