Arduino Nicla Vision¶
Arduino Nicla Vision은 STMicroelectronics STM32H747AII6를 중심으로 구성된 22.86 × 22.86 mm 크기의 머신 비전 보드입니다. STM32H747AII6은 400 MHz Cortex‑M7과 200 MHz Cortex‑M4를 결합한 듀얼 코어 SoC이며, OpenMV 펌웨어는 전적으로 M7 코어에서 실행됩니다. 이 보드는 MCU와 함께 GC2145 2 MP 색상 CMOS 센서, LSM6DSOX 6축 IMU, MP34DT06 MEMS 마이크, VL53L1CB 비행 시간(time‑of‑flight) 거리 측정 센서, Wi‑Fi + Bluetooth LE 5.1, 그리고 배터리 충전기 / 연료 게이지를 갖추고 있습니다.
전체 데이터시트, 사진, 치수는 Arduino Nicla Vision 제품 페이지 를 참조하십시오.
주요 특징¶
STMicroelectronics STM32H747AII6 듀얼 코어 Cortex‑M7 (400 MHz) + Cortex‑M4 (200 MHz). OpenMV 펌웨어는 M7 코어에서만 실행됩니다.
2 MB 내부 플래시 및 16 MB 외부 QSPI 플래시 (애플리케이션 + ROMFS에 사용).
1 MB 내부 SRAM.
하드웨어 JPEG 인코더/디코더.
GC2145 2 MP 색상 CMOS 센서.
온보드 IMU (LSM6DSOX 가속도계 + 자이로스코프), MEMS 마이크 (MP34DT06JTR), VL53L1CB 비행 시간 거리 측정 센서 (최대 약 4 m).
Murata 1DX (CYW4343W) 모듈을 통한 Wi‑Fi b/g/n (2.4 GHz) + Bluetooth LE 5.1 — 온보드 U.FL 커넥터를 통해 동봉된 안테나에 연결됩니다.
외부 ULPI PHY (USB3320C)를 통해 Micro USB로 제공되는 고속 USB (480 Mb/s).
Arduino 엣지 헤더의 13개 사용자 I/O 핀 — 4개의 디지털 LPIO (
D0–D3), 3개의 1.8 V 아날로그 입력 (A0–A2),SCL/SDAI²C 쌍, 그리고SCLK/CIPO/COPI/CSSPI 4종.배터리 지원 — 뒷면의 Li‑Po 커넥터, BQ 스타일 충전기, 그리고 내부 PMIC 버스를 통한 MAX17262 연료 게이지.
납땜이 필요 없는 I²C 확장을 위한 뒷면의 5핀 ESLOV 커넥터.
경고
사용자 디지털 핀은 기본적으로 3.3 V이지만, 소프트웨어로 프로그래밍 가능한 레벨 시프터(VDDIO_EXT)를 통해 라우팅되며 1.8 V로 재구성할 수 있습니다. 아날로그 핀(A0–A2)은 1.8 V 전용입니다 — 레벨 시프터를 우회하여 MCU에 직접 연결됩니다. A0–A2에 3.3 V를 가하면 SoC가 손상됩니다.
핀아웃¶
핀 레퍼런스¶
13개의 사용자 핀이 Arduino 엣지 헤더(J1 및 J2)에 노출되어 있습니다. 추가적인 디버그, 복구, PMIC 신호는 보드 뒷면의 테스트 패드로 라우팅됩니다.
핀 이름 |
레퍼런스 |
기능 |
|---|---|---|
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 채널 4 (J1‑8) |
A1 |
1.8 V |
ADC2 채널 2 (J1‑7) |
A2 |
1.8 V |
ADC3 채널 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 파랑 채널 (액티브 로우) |
참고
D0–D3 및 SCLK/CIPO/COPI/CS는 TXB0108 양방향 레벨 시프터 뒤에 위치합니다 — 이 부품은 푸시‑풀 GPIO 구동만 지원하므로, 해당 핀에서의 오픈 드레인 버스 통신(예: 비트뱅잉 방식의 1‑Wire 또는 I²C)은 동작하지 않습니다.
SCL/SDA는 푸시‑풀과 오픈 드레인 구동을 모두 지원하는 별도의 NTS0304 시프터 뒤에 위치하며, 이 때문에 I²C 1이 동작합니다.
두 시프터 모두 VDDIO_EXT(기본값은 온보드 PMIC에서 공급되는 3.3 V)를 기준으로 동작하며, 직접 연결된 GPIO에 비해 구동 능력이 제한됩니다. 이들은 전력 부하가 아닌 신호 레벨 용도로 설계되었습니다.
전원 핀¶
엣지 헤더 핀:
VIN (J2‑9) — 메인 3.6 – 5 V 시스템 레일. PMIC가 여기서 입력을 받습니다.
VDDIO_EXT (J2‑7) — 레벨 시프터 레일의 출력, 1.8 V 또는 3.3 V (기본 3.3 V). LPIO/SPI/I²C 핀에 연결된 외부 1.8 V 또는 3.3 V 주변장치가 헤더와 동일한 논리 레벨로 통신하도록 전원을 공급할 때 사용합니다.
VBAT (J3‑2) — Li‑Po 배터리 입력. 온보드 PMIC가 VIN으로부터 셀을 충전하고 연료 게이지를 통해 충전 상태를 보고합니다.
NTC (J3‑1) — 선택적 Li‑Po 서미스터 입력.
GND (J2‑6) — 공통 접지.
NC (J2‑8) — 연결 없음.
보드 뒷면의 테스트 패드:
+3V3 — 메인 3.3 V 레일.
D_P / D_N — USB 고속 데이터 쌍 (PHY 이후).
USB와 ESLOV 커넥터는 모두 한 쌍의 LM66100 이상적 다이오드(소스당 하나씩)를 통해 VIN에 전원을 공급하므로, 두 공급원 중 어느 하나로도 보드에 단독으로 전원을 공급할 수 있으며 서로 역방향으로 전류를 흘리지 않습니다. J2‑9에서 VIN을 외부로 구동하면 그것이 우선합니다 — 외부 레일이 더 높이 상승하면 다이오드는 USB / ESLOV로부터의 도통을 단순히 중단합니다.
따라서 보드는 다음 경로 중 어느 것으로도 전원을 공급받을 수 있습니다:
Micro USB — USB 측 이상적 다이오드를 통해 VIN에 5 V 공급.
ESLOV 커넥터 — J5의
VESLOV핀에 최대 5 V, ESLOV 측 이상적 다이오드를 통해 VIN으로 라우팅 (ESLOV 커넥터 참조).VIN 핀 (J2‑9) — 조정된 3.6 – 5 V 공급원을 직접 구동.
Li‑Po 배터리 — 뒷면의 J4 배터리 커넥터 또는 J3 / J2‑6의 VBAT/GND/NTC 패드에 연결. 두 개의 배터리를 동시에 연결하지 마십시오.
ESLOV 커넥터¶
보드 뒷면의 J5는 납땜이 필요 없는 5핀 Molex ESLOV 커넥터입니다:
핀 |
이름 |
기능 |
|---|---|---|
J5‑1 |
VESLOV |
전원 입력 (≤ 5 V) — LM66100 이상적 다이오드를 통해 |
J5‑2 |
INT |
|
J5‑3 |
SCL_EXT |
J2의 |
J5‑4 |
SDA_EXT |
J2의 |
J5‑5 |
GND |
공통 접지 |
ESLOV의 SCL_EXT/SDA_EXT와 J2의 SCL/SDA는 동일한 핀입니다 — 두 커넥터에 노출된 하나의 I²C 1 버스입니다.
팁
주어진 활성 / 딥 슬립 듀티 사이클에서 Nicla Vision이 배터리로 얼마나 오래 동작할지 모델링하려면 배터리 수명 추정기 를 사용하십시오.
복구 및 디버그 핀¶
RESET — 보드 상단의 모멘터리 스위치와 SoC의 NRST 라인에 연결된 패드(J3‑4 / 테스트 패드 P5) 양쪽 모두. GND로 당겨 리셋합니다.
Nicla Vision은 Arduino의 표준 더블 탭 리셋을 사용하여 Arduino 부트로더로 진입합니다 — 리셋 버튼을 빠르게 두 번 누르면 보드가 DFU 장치로 열거됩니다. OpenMV IDE는 이 모드를 사용하여 펌웨어를 다시 플래시합니다.
STM32 SWD 신호는 두 J2 헤더 사이에 위치한 일렬의 테스트 패드를 통해 보드 뒷면에 노출되어 있습니다. ST‑LINK 또는 J‑Link 어댑터를 부착하려면 2.54 mm (100‑mil) 헤더를 납땜하십시오:
P1 / P2 — PF0 (SDA) 및 PF1 (SCL)의 내부 PMIC I²C 버스. 이는 Nicla Vision에서
machine.I2C(2)이며 PMIC, 연료 게이지, ToF 통신을 전달합니다.P3 — TMS / SWDIO (PA13)
P4 — TCK / SWCLK (PA14)
P5 — NRST
P6 — TDO / SWO (PB3)
P7 — +1V8 레일 (SoC의 I/O 공급원 — 디버그 어댑터의 올바른 기준이기도 함).
P8 —
VOTP_PMIC— 공장 프로그래밍 전용. 연결하지 않은 채로 두어야 합니다.
모든 디버그 신호는 1.8 V 기준입니다 — 이 보드의 STM32H747 I/O 링은 +1V8 레일에서 동작합니다. 연결하기 전에 디버그 어댑터를 1.8 V 논리로 설정하십시오.
온보드 주변장치¶
LED¶
Nicla Vision에는 machine.LED 를 통해 소프트웨어로 제어 가능한 단일 사용자 RGB LED가 있습니다:
from machine import LED
LED("LED_RED").on()
LED("LED_GREEN").on()
LED("LED_BLUE").on()
보드 측면의 별도 DL2 CHARGE LED는 PMIC의 CHGB 출력에 직접 연결되어 있습니다 — USB / ESLOV / VIN으로부터 Li‑Po 배터리가 충전되는 동안 점등되며 사용자가 제어할 수 없습니다.
카메라 센서¶
GC2145는 csi — 카메라 센서 모듈을 통해 구동됩니다:
import csi
cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.QVGA)
cam.snapshot(time=2000) # let auto‑exposure settle
while True:
img = cam.snapshot()
작은 프레임 크기를 요청하면 GC2145 드라이버는 센서에서 비례적으로 작은 판독 창을 잘라냅니다 — 기본적으로 프레임 레이트를 유지하기 위해 판독‑대‑출력 다운스케일 비율은 3배로 제한됩니다. csi.IOCTL_SET_FOV_WIDE는 이 한계를 5배로 높이는데, 이는 작은 해상도로 스트리밍할 때 드라이버가 센서의 더 넓은 영역에서 판독한다는 것을 의미합니다. 그 결과 일부 처리량을 희생하는 대신 작은 프레임 크기에서 눈에 띄게 더 넓은 시야를 얻을 수 있습니다:
cam.ioctl(csi.IOCTL_SET_FOV_WIDE, True)
cam.ioctl(csi.IOCTL_GET_FOV_WIDE) # returns the current setting
M4 코어¶
Cortex‑M4 코어는 프로세서 간 통신을 위해 openamp 를 통해 노출됩니다. OpenMV 펌웨어는 M7에서만 실행되며 M4에는 자체 MicroPython 런타임이 없으므로, M4를 사용하려면 별도의 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를 정지시키면 전체 시스템 재부팅이 강제됩니다.
마이크¶
온보드 MP34DT06JTR PDM 마이크는 STM32의 DFSDM 주변장치를 통해 audio — 오디오 모듈 로 캡처됩니다. 각 버퍼는 부호 있는 16비트 PCM bytearray 로 도착하며, DSP를 위해 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와 경합하지 않습니다.
비행 시간 거리 측정 센서¶
온보드 ST VL53L1CB 비행 시간 거리 측정 센서는 내부 PMIC I²C 버스(I²C 2)에 위치합니다. 최대 약 4 m까지의 거리 측정값을 얻으려면 동결된(frozen) vl53l1x — VL53L1X ToF 거리 센서 드라이버 드라이버를 사용하십시오:
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)
배터리 연료 게이지¶
Maxim MAX17262 ModelGauge m5 연료 게이지는 Li‑Po 배터리의 전압, 전류, 온도, 충전 상태를 추적합니다. 이는 I²C 2의 주소 0x36에 위치합니다.
MAX17262는 내부 전류 감지를 갖추고 있으므로, 전류 레지스터는 외부 Rsense 계수를 적용할 필요 없이 마이크로암페어 단위로 직접 판독됩니다. 연료 게이지를 읽는 것은 무해합니다 — 제공되는 드라이버는 없지만, MAX17262 데이터시트 에 문서화된 레지스터를 직접 읽을 수 있습니다:
import time
import struct
from machine import I2C
FUEL_GAUGE = 0x36 # MAX17262
def read_reg(bus, addr, reg):
return struct.unpack("<H", bus.readfrom_mem(addr, reg, 2))[0]
def read_signed(bus, addr, reg):
v = read_reg(bus, addr, reg)
return v - 0x10000 if v & 0x8000 else v
bus = I2C(2)
while True:
# 0x05 RepCap — remaining capacity, raw × 0.5 mAh
rep_cap = read_reg(bus, FUEL_GAUGE, 0x05) * 0.5
# 0x06 RepSOC — state of charge, raw / 256 %
soc = read_reg(bus, FUEL_GAUGE, 0x06) / 256
# 0x08 Temp — die temperature, signed, raw / 256 °C
temp = read_signed(bus, FUEL_GAUGE, 0x08) / 256
# 0x09 VCell — battery voltage, raw × 78.125 µV
vcell = read_reg(bus, FUEL_GAUGE, 0x09) * 78.125 / 1_000_000
# 0x0A Current — signed, raw × 156.25 µA
current = read_signed(bus, FUEL_GAUGE, 0x0A) * 156.25 / 1000
# 0x0B AvgCurrent — averaged current
avg_curr = read_signed(bus, FUEL_GAUGE, 0x0B) * 156.25 / 1000
# 0x10 FullCapRep — learned full capacity, raw × 0.5 mAh
full_cap = read_reg(bus, FUEL_GAUGE, 0x10) * 0.5
# 0x11 TTE — time-to-empty (valid while discharging), raw × 5.625 s
tte_s = read_reg(bus, FUEL_GAUGE, 0x11) * 5.625
# 0x20 TTF — time-to-full (valid while charging), raw × 5.625 s
ttf_s = read_reg(bus, FUEL_GAUGE, 0x20) * 5.625
# 0x17 Cycles — charge-cycle counter, 1% per LSB
cycles = read_reg(bus, FUEL_GAUGE, 0x17) / 100
print("V: %.3f V" % vcell)
print("Capacity: %.1f / %.1f mAh (%.1f %%)" % (rep_cap, full_cap, soc))
print("Temp: %.1f C" % temp)
print("Current: %.1f mA (avg %.1f mA)" % (current, avg_curr))
print("TTE: %.0f s TTF: %.0f s" % (tte_s, ttf_s))
print("Cycles: %.2f" % cycles)
print()
time.sleep_ms(1000)
Current는 부호 있는 2의 보수입니다: 충전 중에는 양수, 방전 중에는 음수입니다. TTE는 전류가 음수일 때만 의미가 있고, TTF는 전류가 양수일 때만 의미가 있습니다.
전원 관리 IC¶
NXP MC34PF1550A0EP PMIC는 Nicla Vision의 모든 레귤레이터를 처리합니다 — +3V3 메인 레일, +1V8 SoC 코어 / I/O 레일, 레벨 시프터로 가는 VDDIO_EXT, 그리고 Li‑Po 충전기. 이는 I²C 2의 주소 0x08에 위치합니다.
경고
PMIC 레지스터를 읽는 것은 괜찮지만, 쓰는 것은 위험합니다. 벅 레귤레이터나 충전기 설정을 잘못 구성하면 보드, 배터리, 또는 둘 다 영구적으로 손상될 수 있습니다. 정확히 무엇을 하고 있는지 알지 못한다면 PMIC를 읽기 전용으로 취급하십시오.
연료 게이지가 알려줄 수 없는, PMIC가 알려주는 가장 유용한 정보는 충전기 상태 머신입니다 — 보드가 현재 USB / ESLOV / VIN으로 동작하고 있는지, Li‑Po가 충전 사이클의 어느 단계에 있는지, 충전기가 열 또는 워치독 결함 상태인지 등입니다. 충전기 레지스터는 PF1550의 메인 I²C 주소 공간에서 0x80 오프셋에 위치하므로(PF1550 데이터시트 §22.2 참조), 예를 들어 충전기 주소 0x04의 CHG_INT_OK는 PMIC 레지스터 0x84에서 읽습니다:
import time
from machine import I2C
PMIC = 0x08
# Charger state machine (low nibble of CHG_SNS, register 0x87)
CHG_STATES = {
0x0: "precharge",
0x1: "fast charge (constant current)",
0x2: "fast charge (constant voltage)",
0x3: "end of charge",
0x4: "done",
0x6: "timer fault",
0x7: "thermistor suspend",
0x8: "off — input invalid or charger disabled",
0x9: "battery overvoltage",
0xA: "thermal shutdown",
0xC: "linear mode (not charging)",
}
bus = I2C(2)
while True:
# 0x84 CHG_INT_OK — single-bit indicators
ok = bus.readfrom_mem(PMIC, 0x84, 1)[0]
vbus_ok = bool(ok & (1 << 5)) # bit 5 — VBUS valid (USB/ESLOV/VIN)
bat_ok = bool(ok & (1 << 2)) # bit 2 — battery OK
chg_ok = bool(ok & (1 << 3)) # bit 3 — charger actively charging
thm_ok = bool(ok & (1 << 7)) # bit 7 — thermistor in normal range
# 0x87 CHG_SNS — charger state + thermal regulation flag
chg_sns = bus.readfrom_mem(PMIC, 0x87, 1)[0]
state = CHG_STATES.get(chg_sns & 0x0F, "reserved")
treg = bool(chg_sns & (1 << 7)) # thermal regulation active
print("VBUS valid: ", vbus_ok)
print("battery OK: ", bat_ok)
print("charger active: ", chg_ok)
print("thermistor normal: ", thm_ok)
print("thermal reg active: ", treg)
print("state: ", state)
print()
time.sleep_ms(1000)
데이터시트에서 살펴볼 만한 다른 읽기 전용 레지스터(모두 충전기 오프셋 0x80): 0x80 CHG_INT (래치된 충전기 인터럽트 — 결함 플래그), 0x86 VBUS_SNS (OVLO / UVLO / DPM을 포함한 다중 비트 VBUS 상태), 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도 노출합니다. asyncio 친화적인 BLE를 위해 aioble — 비동기 BLE 를 사용하십시오 — 예를 들어, 주변장치로 광고하고 센트럴의 연결을 기다립니다:
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라고도 표시되어 있지만, 이 펌웨어에서 해당 핀은 machine.UART가 아니라 LPUART1로 라우팅됩니다. 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")
J2의 SCL/SDA 패드와 ESLOV 커넥터의 SCL_EXT/SDA_EXT 핀은 동일한 I²C 1 버스에 연결됩니다 — ESLOV 핀아웃은 위의 ESLOV 커넥터 를 참조하십시오.
동일한 하드웨어는 machine.I2CTarget 를 통해 타깃(슬레이브) 모드로도 사용하여 다른 I²C 컨트롤러에 메모리 영역을 노출할 수 있습니다:
from machine import I2CTarget
buf = bytearray(32)
target = I2CTarget(1, addr=0x42, mem=buf)
SPI¶
버스 |
MOSI |
MISO |
SCK |
CS |
|---|---|---|---|---|
SPI4 |
COPI |
CIPO |
SCLK |
CS |
from machine import SPI
from machine import Pin
spi = SPI(4, baudrate=10_000_000)
cs = Pin("CS", Pin.OUT, value=1) # CS is not driven by the SPI peripheral
cs.value(0)
spi.write(b"hello")
cs.value(1)
ADC¶
Nicla Vision은 A0, A1, A2에 3개의 12비트 ADC 채널을 노출합니다. 세 채널 모두 1.8 V 기준입니다 — read_u16은 핀의 0–1.8 V 범위에 걸쳐 0–65535를 반환합니다:
from machine import ADC
import time
adc = ADC("A0")
while True:
voltage = adc.read_u16() * 1.8 / 65535
print(voltage)
time.sleep_ms(100)
경고
Nicla Vision의 ADC 입력은 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 4종 핀(SCLK/CIPO/COPI/CS)은 machine.SPI(4)가 사용 중일 때는 PWM으로 구동할 수도 없습니다.
소프트웨어 비트뱅잉 버스¶
추가 버스가 필요하다면 machine.SoftI2C 와 machine.SoftSPI 가 모든 GPIO에서 동작합니다.
열화상 센서 (보드 외부)¶
펌웨어에는 외부에 배선된 열화상 이미저를 위한 fir — 열 센서 드라이버 (fir == far infrared, 원적외선) 드라이버가 포함되어 있습니다:
MLX90621 — 16 × 4 IR 어레이
MLX90640 — 32 × 24 IR 어레이
MLX90641 — 16 × 12 IR 어레이
AMG8833 — 8 × 8 IR 어레이
모듈을 보드의 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 는 하드웨어 타이머 슬롯을 소비하지 않고 주기적 또는 일회성 콜백을 예약합니다. 가상(소프트웨어) 타이머를 사용하려면 id로 -1을 전달하십시오:
from machine import Timer
one_shot = Timer(-1)
one_shot.init(period=5_000, mode=Timer.ONE_SHOT,
callback=lambda t: print("once"))
periodic = Timer(-1)
periodic.init(period=2_000, mode=Timer.PERIODIC,
callback=lambda t: print("tick"))
주기 값은 밀리초 단위입니다. 슬롯을 정지하고 해제하려면 deinit() 를 호출하십시오.
실시간 클록¶
machine.RTC 는 리셋 전반에 걸쳐 벽시계 시간을 유지합니다:
from machine import RTC
rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0)) # Y, M, D, weekday, h, m, s, subsec
print(rtc.datetime())
워치독¶
machine.WDT 는 애플리케이션이 멈추면 보드를 리셋합니다. 일단 시작되면 정지하거나 재구성할 수 없습니다 — 메인 루프 내부에서 주기적으로 피드하십시오:
from machine import WDT
wdt = WDT(timeout=5_000) # 5 second window
while True:
# ...do work...
wdt.feed()
부팅 및 런타임 정보¶
펌웨어 업데이트 (DFU)¶
Nicla Vision은 Arduino의 표준 더블 탭 리셋을 사용하여 Arduino 부트로더로 진입합니다. 리셋 버튼을 빠르게 두 번 누르면 — 보드가 USB를 통해 DFU 장치로 다시 열거되고 OpenMV IDE가 새 펌웨어 이미지를 플래시할 수 있습니다.
실행 중인 스크립트는 machine.bootloader() 를 호출하여 필요할 때 부트로더로 다시 진입할 수 있습니다:
import machine
machine.bootloader()
파일시스템 및 부팅 순서¶
Nicla Vision 펌웨어는 부팅 시 최대 두 개의 파일시스템을 마운트합니다:
내부 플래시 — 항상
/flash에 마운트됩니다. 기본적으로main.py와README.txt를 보유하며, 최초 부팅 시 생성됩니다.ROMFS — 읽기 전용, 메모리 매핑된 파일시스템으로
/rom에 위치하며 시작 시 MicroPython이 자동으로 마운트합니다.
마운트 후 작업 디렉터리는 /flash로 설정됩니다. 그런 다음 인터프리터는 해당 디렉터리에서 스크립트를 실행합니다:
boot.py는 모든 소프트 리셋(콜드 부트, REPL에서Ctrl‑D, 또는 실행 중인 스크립트가 반환될 때마다)에서 실행됩니다.main.py는boot.py직후에 콜드 부트에서만 실행됩니다. 이후의 소프트 리셋은boot.py를 다시 실행하지만 곧바로 REPL로 떨어집니다 —main.py를 다시 실행하려면 보드를 완전히 리셋해야 합니다.
갓 플래시된 보드에 기본 제공되는 main.py는 단지 사용자 RGB LED의 파랑 채널을 하트비트로 깜박일 뿐입니다(짧은 펄스 두 번, 짧은 간격). 따라서 호스트를 연결하지 않고도 펌웨어가 정상적으로 부팅되었는지 알 수 있습니다.
sys.path는 두 파일시스템과 그 lib/ 하위 디렉터리를 모두 포함하도록 확장되므로, 임포트 가능한 모듈은 /flash/lib 또는 /rom/lib에 둘 수 있습니다.
USB로 연결되면 /flash는 호스트에서 USB 대용량 저장 장치 드라이브로도 열거되어, boot.py, main.py, 그 외 다른 파일을 직접 편집할 수 있습니다. 호스트가 캐시된 쓰기를 플러시하도록 카메라를 리셋하기 전에 드라이브를 꺼내십시오.
참고
OS는 이 드라이브를 수동적인 블록 장치로 취급하므로, 카메라에서 실행되는 코드가 생성하거나 수정한 파일은 호스트가 드라이브를 다시 마운트할 때까지 나타나지 않습니다. OS와 카메라가 동시에 같은 파일시스템에 쓰면 OS가 우선하여 카메라가 만든 변경 사항을 덮어씁니다. 스크립트가 기록하는 모든 데이터에는 SD 카드를 사용하고, 호스트에서 해당 파일을 읽기 전에 다시 마운트하십시오.
참고
호스트가 USB 대용량 저장 장치 드라이브에서 읽거나 쓰는 동안 사용자 RGB LED의 빨강 채널이 잠시 점등될 수 있습니다 — 이는 결함이 아니라 펌웨어가 구동하는 활동 표시기입니다.
저장 용량¶
Nicla Vision은 다음을 갖추고 출하됩니다:
/flash— 11 MB FAT 파일시스템, 읽기/쓰기 가능./rom— 4 MB 읽기 전용 메모리 매핑 ROMFS, 제로 카피 mmap 접근의 이점을 누리는 스크립트와 ML 모델을 함께 출하하는 데 사용됩니다.
하드 폴트 표시기¶
사용자 RGB LED가 모든 색상을 빠르게 순환하고 있다면 — 뚜렷한 색조라기보다는 반짝이는 흰색 LED처럼 보일 만큼 빠르게 — 펌웨어가 복구 불가능한 하드 폴트에 도달한 것입니다. 복구하려면 펌웨어를 다시 플래시하십시오; 다시 플래시해도 도움이 되지 않으면 보드가 물리적으로 손상되었을 수 있습니다.
소프트웨어 라이브러리¶
전체 모듈 목록은 라이브러리 색인 을 참조하십시오 — Nicla Vision 빌드에 고유한 모듈이 무엇인지도 포함되어 있습니다.