OpenMV N6

La OpenMV N6 se basa en el STMicroelectronics STM32N657 (Cortex‑M55 @ 800 MHz) con una NPU integrada de 1 GHz capaz de 600 GOPS INT8. La placa combina la NPU con el sensor de obturador global PAG7936 de 1 MP montado en un soporte extraíble, Ethernet gigabit, USB‑C de alta velocidad, Wi‑Fi y Bluetooth 5.1, y ejecuta inferencia YOLOv8/YOLOv11 a 30 FPS junto con la transmisión de vídeo en directo.

OpenMV N6

Para ver la hoja de datos completa, fotos y dimensiones, consulta la página del producto OpenMV N6.

Aspectos destacados

  • STM32N657 Cortex‑M55 a 800 MHz (1280 DMIPS) con SIMD ARM Helium de 128 bits — rendimiento vectorial de 6,4 gigaops.

  • NPU de 1 GHz, 600 GOPS INT8 — ejecuta detección YOLOv8/YOLOv11 a 30 FPS.

  • ISP para RAW Bayer de hasta 5MP, GPU 2D para escalado y rotación 3D, codificación H.264 a 1080p y códec JPEG por hardware.

  • 64 MB de SDRAM externa (16 bits @ 200 MHz DDR, 800 MB/s) más 4,2 MB de SRAM interna y 32 MB de flash octal (200 MHz DDR, 400 MB/s).

  • Sensor de obturador global a color PAG7936 de 1 MP.

  • IMU integrada (acelerómetro + giroscopio) y micrófono para fusión de audio y movimiento.

  • USB‑C de alta velocidad (480 Mb/s, límite de corriente de 1,5 A), Ethernet gigabit (compatible con PoE mediante shield), Wi‑Fi a/b/g/n + Bluetooth 5.1 (antena de chip u opción U.FL).

  • Conector microSD — SD hasta 2 GB, SDHC hasta 32 GB, SDXC hasta 2 TB.

  • Cargador LiPo (carga rápida de 500 mA), ADC de voltaje de batería, RTC con 8 KB de RAM de respaldo y un pin dedicado para batería de respaldo.

  • 18 pines de E/S, todos con salida de 3,3 V / tolerantes a 3,3 V, 20 mA por pin, con capacidad de interrupción.

  • LED RGB de usuario, botón de usuario y un LED de estado independiente para carga / USB / alimentación VIN.

Advertencia

Los pines de E/S de la N6 no son tolerantes a 5 V. No conectes el dispositivo directamente a un MCU de 5 V como el Arduino Mega. Alimenta la N6 únicamente a través de VIN.

Distribución de pines

Distribución de pines de la OpenMV N6 PAG7936

Referencia de pines

Nombre del pin

Función

P0

SPI2 MOSI / I2S2 SDO

P1

SPI2 MISO / I2S2 SDI

P2

SPI2 SCLK / UART4 TX / CAN1 TX / I2S2 CK

P3

SPI2 SS / UART4 RX / CAN1 RX / I2S2 WS

P4

I2C2 SCL / UART3 TX / TIM2 CH3 / I3C2 SCL

P5

I2C2 SDA / UART3 RX / TIM2 CH4 / I3C2 SDA

P6

TIM12 CH1 (sin ADC en este pin — consulta P6_ADC)

P6_ADC

entrada ADC dedicada de 12 bits (conectada internamente a P6)

P7

TIM4 CH1

P8

TIM4 CH2

P9

TIM17 CH1

P10

TIM15 CH2 / E/S de sincronización de fotogramas

P11

despertar (activo en bajo, WKUP3)

P12

RESET — conecta a GND para reiniciar la placa (no es un GPIO)

P13

UART7 RX

P14

UART7 TX

P15

SPI4 CS

P16

SPI4 SCK

P17

SPI4 MISO

P18

SPI4 MOSI

SW

botón de usuario (activo en bajo)

ONOFF (SW2)

botón de despertar de sueño profundo (activo en bajo, WKUP2)

ST

bajo con alimentación VIN, alto con alimentación USB

CHG

activo en bajo; bajo mientras se carga una batería LiPo conectada

PG

activo en bajo; bajo cuando hay alimentación VIN o USB presente

BAT_ADC

canal ADC interno que mide el voltaje de la batería LiPo conectada

LED_RED

canal rojo del LED RGB (activo en bajo)

LED_GREEN

canal verde del LED RGB (activo en bajo)

LED_BLUE

canal azul del LED RGB (activo en bajo)

Nota

La línea de sincronización de fotogramas P10 es un bus compartido. Está cableada al MCU, al pin de disparo / exposición del sensor de la cámara y a la cabecera de usuario, todo a la vez. La dirección la define la aplicación — el MCU, el sensor o una señal externa pueden controlarla según cómo esté configurado el sensor (algunos sensores pueden usar el mismo pin como entrada de disparo o salida de exposición). Asegúrate de que solo haya un controlador activo a la vez.

Nota

ONOFF y P11 están referenciados al riel RAW siempre activo (no al riel conmutado de 3,3 V), por lo que siguen funcionando mientras el resto de la placa está en modo de sueño profundo / bajo consumo. Ambas entradas son activas en bajo.

Estos pines pasan por convertidores de nivel para poder operar en el riel RAW. Si necesitas imprescindiblemente un comportamiento GPIO directo de 3,3 V en ONOFF o P11 (por ejemplo, para controlarlos desde un MCU de 3,3 V sin pasar por el convertidor), la placa expone almohadillas de pull‑up y de puente de 0 ohmios que permiten omitir el convertidor. Se trata de una modificación de hardware avanzada — la mayoría de los usuarios deberían dejarla intacta.

Nota

Los pines P15–P18 se comparten con el PHY de Ethernet Gigabit, que está cableado y activo por defecto. Para usar estos pines como E/S de usuario debes resoldar la resistencia de 0 ohmios de la parte trasera de la placa a la posición GPIO. Esto solo deshabilita Ethernet gigabit — Ethernet de 10/100 Mb/s sigue funcionando en sus pines dedicados.

Pines de alimentación

  • 3.3V — riel regulado de 3,3 V. Solo salida en la N6 — no inyectes alimentación externa en este pin. Hasta 1 A disponible para shields.

  • VIN — entrada de 5 V. Alimenta la placa y el cargador LiPo integrado.

  • RAW — entrada/salida, siempre activa (3,6 V – 5 V). Transporta la fuente que esté activa (VIN, USB o batería conectada) y también puede usarse como entrada. Debes alimentar RAW a través de un diodo en serie al inyectar alimentación en él — de lo contrario la corriente fluirá de vuelta hacia VIN/USB y dañará la fuente o la protección integrada.

  • GND — tierra común.

Nota

El chip de gestión de energía integrado selecciona automáticamente cuál de USB o VIN tiene el voltaje más alto para alimentar la placa y el cargador de batería. Si hay una LiPo conectada, se carga con el margen sobrante, y el controlador recurre a la batería para mantener la placa en funcionamiento si VIN/USB caen o se desconectan.

Nota

La parte trasera de la placa tiene almohadillas de soldadura para una batería de respaldo RTC externa de 3,3 V. Conectar una pila de botón a estas almohadillas mantiene en funcionamiento el RTC y los 8 KB de RAM de respaldo mientras el resto de la placa está sin alimentación.

Truco

Usa el estimador de duración de batería para modelar cuánto durará la N6 con una batería para un ciclo de trabajo activo / sueño profundo determinado.

Pines de Ethernet

La N6 expone los pares MDI del PHY de Ethernet en almohadillas dedicadas junto a la cabecera GPIO. Los pines MDI no se pueden cablear de forma segura directamente a un RJ45 — la magnética de Ethernet (un transformador de aislamiento, ya sea integrado en un magjack o en el shield) es obligatoria entre el PHY y el cable. El shield PoE de OpenMV la incluye; si fabricas tu propio conector, usa un RJ45 con magnética integrada o un transformador externo.

  • ETH_LED — LED de enlace/actividad. Activo en bajo cuando hay un enlace activo; parpadea con el tráfico.

  • DA P / DA N — par A (TX en 10/100, usado por todas las velocidades).

  • DB P / DB N — par B (RX en 10/100, usado por todas las velocidades).

  • DC P / DC N — par C, usado solo en gigabit.

  • DD P / DD N — par D, usado solo en gigabit.

10/100 Mb/s solo necesita los pares A y B. Gigabit necesita los cuatro pares A–D.

Pines de recuperación y depuración

  • RESET — conecta a GND para reiniciar la placa. Al soltarlo, el MCU arranca normalmente.

  • BOOT0 — conecta a 3,3 V mientras alimentas la placa para entrar en el modo de bootloader ROM. OpenMV IDE usa este modo para reflashear el bootloader integrado.

  • BOOT1 — interruptor que pone la placa en modo desarrollador para usarla con las herramientas de ST (un ST‑LINK conectado a la cabecera ARM SWD/JTAG de 10 pines). Déjalo deshabilitado para el funcionamiento normal con el firmware y las herramientas de OpenMV.

Se incluye una cabecera dedicada ARM SWD/JTAG de 10 pines, compatible con adaptadores ST‑LINK y SEGGER J‑Link.

Periféricos integrados

LEDs

La N6 tiene dos LEDs RGB:

  • LED RGB de usuario — controlable por software, expuesto como LED_RED, LED_GREEN y LED_BLUE:

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • LED de alimentación — controlado directamente por el hardware de gestión de energía integrado, sin control por software. Úsalo para ver de un vistazo qué está haciendo la fuente.

    Durante el funcionamiento:

    Canal

    Significado

    Azul

    VIN está alimentando la placa (apagado con USB)

    Verde

    alimentación USB o VIN presente

    Rojo

    cargando una batería LiPo conectada

    En sueño profundo todos los canales están apagados excepto el rojo, que sigue encendido mientras se carga una LiPo.

Botones de usuario

La N6 tiene dos botones:

  • SW — botón de usuario de propósito general. Activo cuando se conecta a bajo.

  • ONOFF (SW2) — botón de despertar. El único botón que puede sacar la placa del sueño profundo.

from machine import Pin

sw    = Pin("SW",    Pin.IN)   # user button
onoff = Pin("ONOFF", Pin.IN)   # SW2 — wakes from deep sleep
print(sw.value(), onoff.value())

Para poner la placa en sueño profundo y que ONOFF (SW2) la despierte, simplemente llama a machine.deepsleep() — no se requiere ninguna configuración de despertar, el botón está cableado directamente a la entrada WKUP2:

import machine

machine.deepsleep()   # press ONOFF (SW2) to wake the board

También puedes cablear ONOFF como un interruptor de encendido por software. Dispara en el flanco de subida — la línea se estabiliza en alto después de que el usuario suelta el botón, por lo que la siguiente pulsación es inequívocamente un evento de despertar:

import machine
from machine import Pin

def power_off(_):
    machine.deepsleep()

Pin("ONOFF", Pin.IN).irq(power_off, Pin.IRQ_RISING)

# ...rest of the application runs here. Press ONOFF once to sleep,
# press it again to wake.

Pines de estado de alimentación

Tres entradas de estado activas en bajo permiten que el firmware vea qué está haciendo el chip de gestión de energía integrado:

  • ST — bajo cuando la placa funciona con VIN, alto cuando funciona con alimentación USB.

  • CHG — bajo mientras se carga una batería LiPo conectada.

  • PG — bajo cuando hay alimentación VIN o USB presente.

from machine import Pin

on_vin    = not Pin("ST",  Pin.IN).value()
charging  = not Pin("CHG", Pin.IN).value()
power_ok  = not Pin("PG",  Pin.IN).value()

Sensor de cámara

El PAG7936 se controla a través del módulo csi — sensores de cámara:

import csi

cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.HD)         # 1280×800
cam.snapshot(time=2000)       # let auto‑exposure settle

while True:
    img = cam.snapshot()

El sensor está montado en un módulo extraíble — cámbialo por cualquiera de los otros módulos de cámara de OpenMV (obturador global, térmico, mayor resolución, etc.) sin modificar el resto de la placa.

El PAG7936 admite el modo disparado — la integración de píxeles se alinea exactamente con cada llamada a csi.CSI.snapshot en lugar del reloj de fotogramas de funcionamiento libre, lo cual resulta útil para sincronizar la captura con un evento externo u otro sensor. Habilítalo mediante csi.CSI.ioctl con csi.IOCTL_SET_TRIGGERED_MODE. La velocidad de fotogramas cae a aproximadamente la mitad del modo de funcionamiento libre porque la lectura ya no se solapa con la integración del siguiente fotograma:

cam.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True)

NPU

La NPU Neural‑ART de 1 GHz de la N6 (600 GOPS INT8) se expone a través del módulo ml — Aprendizaje automático. Los modelos almacenados en el sistema de archivos de solo lectura /rom se cargan directamente desde la flash sin copiarse a la RAM, por lo que incluso los detectores grandes caben cómodamente junto al búfer de fotogramas (frame buffer) en directo. Ejecuta un detector YOLOv8 en cada fotograma y dibuja las predicciones sobre la imagen en directo:

import csi
import time
import ml
from ml.postprocessing.ultralytics import YoloV8

# Initialize the sensor.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)

# Load YOLO V8 model from ROM FS.
model = ml.Model("/rom/yolov8n_192.tflite", postprocess=YoloV8(threshold=0.4))
print(model)

# Visualization parameters.
n = len(model.labels)
model_class_colors = [
    (int(255 * i // n), int(255 * (n - i - 1) // n), 255)
    for i in range(n)
]

clock = time.clock()
while True:
    clock.tick()
    img = csi0.snapshot()

    # boxes is a list of list per class of ((x, y, w, h), score) tuples
    boxes = model.predict([img])

    # Draw bounding boxes around the detected objects
    for i, class_detections in enumerate(boxes):
        rects = [r for r, score in class_detections]
        labels = [model.labels[i] for j in range(len(rects))]
        colors = [model_class_colors[i] for j in range(len(rects))]
        ml.utils.draw_predictions(img, rects, labels, colors, format=None)

    print(clock.fps(), "fps")

Micrófono

El micrófono integrado se captura a través de audio — Módulo de audio. Cada búfer llega como un bytearray PCM de 16 bits con signo, lo que facilita enormemente alimentarlo a ulab/numpy para un DSP rápido. Un detector de sonoridad sencillo — imprime cada vez que el volumen RMS supera un umbral:

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

El acelerómetro + giroscopio integrado bajo el módulo de cámara se expone a través de 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)

Wi‑Fi

El CYW43439 integrado se expone mediante network — configuración de red como una interfaz de estación. Tras conectarse, ipconfig("addr4") devuelve el par (ip, netmask):

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

El mismo CYW43439 también expone Bluetooth 5.1. Usa aioble — BLE asíncrono para BLE compatible con asyncio — por ejemplo, anunciarse como periférico y esperar a que un central se conecte:

import asyncio
import aioble

async def run():
    while True:
        conn = await aioble.advertise(250_000, name="OpenMV-N6")
        print("Connected:", conn.device)
        await conn.disconnected()

asyncio.run(run())

Ethernet

Cuando se conecta un RJ45 (con magnética) a las almohadillas MDI, el PHY gigabit aparece como una interfaz LAN. El DHCP se ejecuta automáticamente una vez que el enlace se activa:

import network, time

lan = network.LAN()
lan.active(True)
while not lan.isconnected():
    time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])

Tarjeta microSD

Cuando se inserta una tarjeta, se monta automáticamente en /sdcard y se puede usar a través del sistema de archivos habitual:

import os

for entry in os.listdir("/sdcard"):
    print(entry)

Referencia de buses

GPIO

Usa machine.Pin para leer o controlar cualquiera de los pines serigrafiados. Las salidas son CMOS de 3,3 V y pueden absorber/suministrar hasta 20 mA por pin.

from machine import Pin

out = Pin("P0", Pin.OUT)
out.on()
out.off()
out.value(1)

inp = Pin("P1", Pin.IN, Pin.PULL_UP)
print(inp.value())

Cualquier pin de entrada también puede disparar una interrupción en las transiciones de flanco:

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

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

UART

Bus

TX

RX

UART3

P4

P5

UART4

P2

P3

UART7

P14

P13

from machine import UART

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

I²C

Bus

SCL

SDA

I2C2

P4

P5

from machine import I2C

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

El mismo hardware también puede usarse en modo destino (esclavo) a través de machine.I2CTarget para exponer una región de memoria a otro controlador I²C:

from machine import I2CTarget

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

SPI

Bus

MOSI

MISO

SCK

CS

SPI2

P0

P1

P2

P3

SPI4

P18

P17

P16

P15

from machine import SPI
from machine import Pin

spi = SPI(2, baudrate=10_000_000)
cs = Pin("P3", Pin.OUT, value=1)   # CS is not driven by the SPI peripheral

cs.value(0)
spi.write(b"hello")
cs.value(1)

CAN

Bus

TX

RX

CAN1

P2

P3

Nota

CAN aún no es compatible con esta placa en el firmware v5.0.0.

from machine import CAN

can = CAN(1, 500_000)
can.set_filters(None)
can.send(0x123, b"\xDE\xAD\xBE\xEF")
print(can.recv())

ADC

Ambos canales ADC pasan por un divisor de voltaje con búfer de amplificador operacional antes de llegar al MCU, por lo que read_u16() se mapea a un voltaje de entrada de fondo de escala diferente en cada pin.

Pin

Fondo de escala

Notas

P6_ADC

~3,3 V

almohadilla de propósito general, conectada internamente a P6

BAT_ADC

~5,0 V

canal interno para la batería LiPo

from machine import ADC
import time

adc = ADC("P6_ADC")
bat = ADC("BAT_ADC")

while True:
    print("P6:", adc.read_u16() * 3.3 / 65535, "V")
    print("BAT:", bat.read_u16() * 5.0 / 65535, "V")
    time.sleep_ms(100)

PWM

Pin

Temporizador / canal

P4

TIM2 CH3

P5

TIM2 CH4

P6

TIM12 CH1

P7

TIM4 CH1

P8

TIM4 CH2

P9

TIM17 CH1

P10

TIM15 CH2

Controla cualquiera de ellos mediante machine.PWM:

from machine import Pin, PWM

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

Buses por software (bit‑banged)

machine.SoftI2C y machine.SoftSPI funcionan en cualquier GPIO si necesitas un bus adicional.

Sensor térmico (externo)

El firmware incluye el controlador fir — controlador de sensor térmico (fir == infrarrojo lejano) para sensores térmicos cableados externamente:

  • MLX90621 — matriz IR de 16 × 4

  • MLX90640 — matriz IR de 32 × 24

  • MLX90641 — matriz IR de 16 × 12

  • AMG8833 — matriz IR de 8 × 8

Cablea el módulo al bus I²C de la placa y lee fotogramas con 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())

El controlador fir solo se comunica con el sensor a través de I²C 2 — cablea el módulo a P4 (SCL) y P5 (SDA).

Temporización

time

El módulo time cubre los retardos bloqueantes, los ticks monotónicos y la medición de tiempo transcurrido:

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)

Temporizadores virtuales

machine.Timer programa funciones de retorno (callbacks) periódicas o de un solo disparo sin consumir una ranura de temporizador por hardware. Pasa -1 como id para usar un temporizador virtual (por software):

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

Los valores de periodo están en milisegundos. Llama a deinit() para detenerlo y liberar la ranura.

Reloj en tiempo real

machine.RTC mantiene la hora del reloj de pared a través de los reinicios y (con la batería de respaldo opcional de 3,3 V conectada a las almohadillas traseras, consulta Pines de alimentación) a través de una pérdida total de alimentación:

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

El RTC también funciona durante el sueño profundo, por lo que puedes usarlo como fuente de despertar para machine.deepsleep().

Watchdog

machine.WDT reinicia la placa si la aplicación se cuelga. Una vez iniciado no se puede detener ni reconfigurar — aliméntalo periódicamente dentro de tu bucle principal:

from machine import WDT

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

Información de arranque y de ejecución

Ventana del bootloader USB

En cada encendido, la cámara ejecuta un breve bootloader (unos segundos) que permite a OpenMV IDE actualizar el firmware sin que el usuario tenga que entrar en modo DFU. Una vez que expira la ventana, el bootloader cede el control a boot.py y luego a main.py.

Un script en ejecución puede volver a entrar en el bootloader bajo demanda llamando a machine.bootloader():

import machine

machine.bootloader()

Sistema de archivos y orden de arranque

El firmware de la N6 monta hasta tres sistemas de archivos al arrancar:

  • Flash interna — siempre montada en /flash. Contiene main.py y README.txt por defecto; se crea en el primer arranque.

  • Tarjeta microSD — si hay una tarjeta insertada, se monta en /sdcard.

  • ROMFS — sistema de archivos de solo lectura mapeado en memoria en /rom usado para distribuir grandes recursos de datos (por ejemplo, modelos de IA) que se benefician del acceso sin copia. MicroPython lo monta automáticamente al inicio, antes de que se ejecute cualquier Python de usuario.

Tras el montaje, el directorio de trabajo se establece en /sdcard cuando la tarjeta está presente, de lo contrario en /flash. El intérprete entonces ejecuta los scripts desde ese directorio:

  • boot.py se ejecuta en cada reinicio suave (arranque en frío, Ctrl‑D desde el REPL, o cada vez que el script en ejecución retorna).

  • main.py se ejecuta solo en el arranque en frío, inmediatamente después de boot.py. Los reinicios suaves posteriores vuelven a ejecutar boot.py pero pasan directamente al REPL — para volver a ejecutar main.py tienes que reiniciar completamente la placa.

Colocar un boot.py o main.py en la tarjeta SD anula la copia en flash sin tocarla — ambos archivos se buscan en el directorio de arranque (/sdcard cuando la tarjeta está montada, de lo contrario /flash).

El main.py por defecto que se incluye en una placa recién flasheada simplemente hace parpadear el canal azul del LED RGB de usuario a modo de latido (dos pulsos cortos, una pausa breve), de modo que puedes saber que el firmware arrancó correctamente sin ningún host conectado.

sys.path se extiende para incluir los tres sistemas de archivos y sus subdirectorios lib/, de modo que los módulos importables pueden residir en /flash/lib, /sdcard/lib o /rom/lib.

Para forzar al sistema a ignorar una tarjeta SD insertada (por ejemplo, para ejecutar el main.py de la flash incluso con una tarjeta presente), crea un archivo vacío llamado SKIPSD en la raíz de /flash.

Cuando está conectada por USB, el sistema de archivos de arranque (/sdcard si hay una tarjeta presente, de lo contrario /flash) también se enumera como una unidad de almacenamiento masivo USB en el host, lo que te permite editar boot.py, main.py y cualquier otro archivo directamente. Expulsa la unidad antes de reiniciar la cámara para que el host vacíe sus escrituras en caché.

Nota

Dado que el SO trata la unidad como un dispositivo de bloques pasivo, los archivos creados o modificados por el código que se ejecuta en la OpenMV Cam no aparecerán hasta que el host vuelva a montar la unidad. Si tanto el SO como la OpenMV Cam escriben en el mismo sistema de archivos al mismo tiempo, el SO ganará y sobrescribirá los cambios realizados por la cámara. Usa la tarjeta SD para cualquier dato que el script escriba de vuelta, y vuelve a montar antes de leer esos archivos desde el host.

Nota

El canal rojo del LED RGB de usuario puede encenderse brevemente mientras el host lee o escribe en la unidad de almacenamiento masivo USB — esto es un indicador de actividad gestionado por el firmware, no un fallo.

Tamaños de almacenamiento

La N6 viene con:

  • /flash — sistema de archivos FAT de 4 MB, lectura/escritura.

  • /rom — ROMFS de solo lectura mapeado en memoria de 24 MB, usado para distribuir scripts y modelos de ML que se benefician del acceso mmap sin copia.

  • /sdcard — el tamaño completo de la tarjeta microSD insertada (cuando está presente), lectura/escritura.

Indicador de fallo grave (hard fault)

Si el LED RGB de usuario está recorriendo rápidamente todos los colores — lo bastante rápido como para que tienda a parecer un LED blanco parpadeante en lugar de tonos distintos — el firmware ha encontrado un fallo grave irrecuperable. Reflashea el firmware para recuperarlo; si reflashear no ayuda, la placa podría estar dañada físicamente.

Bibliotecas de software

Consulta el índice de la biblioteca para ver la lista completa de módulos — incluidos los que son exclusivos de la versión para la N6.