OpenMV Cam RT1062

La OpenMV Cam RT1062 es una placa de visión artificial de bajo consumo construida en torno al NXP i.MX RT1062 (Cortex‑M7 a 600 MHz). La placa combina red USB‑C de alta velocidad, Wi‑Fi/Bluetooth y Ethernet 10/100 con un sensor OV5640 de 5 MP montado en un soporte extraíble. La cámara solo consume ~30 µA de una batería LiPo en sueño profundo, lo que la hace muy adecuada para proyectos alimentados por batería.

OpenMV Cam RT1062

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

Aspectos destacados

  • NXP i.MX RT1062 Cortex‑M7 a 600 MHz.

  • 32 MB de SDRAM externa (16 bits a 160 MHz, 320 MB/s) más 1 MB de SRAM interna y 16 MB de memoria flash QSPI (133 MHz 4 bits SDR, 66 MB/s de lectura); 4 KB de EEPROM en R6+.

  • Sensor de obturador rodante OV5640 de 5 MP.

  • IMU integrada (acelerómetro de 3 ejes de 12 bits, ±2/4/8 g).

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

  • Zócalo microSD: SD hasta 2 GB, SDHC hasta 32 GB, SDXC hasta 2 TB.

  • Cargador LiPo (500 mA en R6+, 100 mA en R4/R5), RTC con pads para batería de respaldo. El sueño profundo consume ~30 µA con batería.

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

  • LED RGB de usuario, botón SW de usuario, botón de encendido por hardware (máquina de estados de sueño profundo / despertar) y un LED de estado independiente para carga / USB / alimentación VIN.

Advertencia

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

Diagrama de pines

Diagrama de pines OpenMV Cam RT1062 OV5640

Referencia de pines

Nombre del pin

Función

P0

SPI1 MOSI / PWM2 B3

P1

SPI1 MISO / CAN0 TX

P2

SPI1 SCLK / PWM2 B3

P3

SPI1 SS / CAN0 RX

P4

I2C1 SCL / UART1 TX / PWM1 X2

P5

I2C1 SDA / UART1 RX / PWM1 X3

P6

ADC

P7

PWM2 A0

P8

PWM2 B0

P9

PWM1 A3

P10

PWM1 B3 / E/S de sincronización de fotogramas

P11

despertar (activo en bajo, conectar a GND para despertar)

P12

RESET: lleva a GND para reiniciar la placa (no es un GPIO)

P13

E/S digital

P14

E/S digital

ON/OFF

pad de cabecera que replica el botón de encendido por hardware (activo en bajo)

SW

botón de usuario (activo en bajo)

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

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 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. Asegúrate de que solo haya un controlador activo a la vez.

Nota

ON/OFF 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 desplazadores de nivel para poder funcionar sobre el riel RAW. Si realmente necesitas un comportamiento GPIO directo de 3,3 V en ON/OFF o P11 (por ejemplo, para controlarlos desde un MCU de 3,3 V sin pasar por el desplazador), la placa expone pads de jumper de pull‑up y de 0 ohmios que permiten omitir el desplazador. Esta es una modificación de hardware avanzada: la mayoría de los usuarios deberían dejarla como está.

Nota

P13 y P14 son GPIO simples de forma predeterminada sin función especial. Los pads se pueden reencaminar opcionalmente a otras señales reflujando los puentes de soldadura de resistencia de 0 ohmios en la parte posterior de la placa:

  • P13 ↔ estado CHG / JTAG TRSTB

  • P14 ↔ estado ST / JTAG TDI

La mayoría de los usuarios no tocarán estos jumpers: déjalos en el valor predeterminado de GPIO a menos que necesites específicamente lectura de gestión de energía o JTAG.

Pines de alimentación

  • 3.3V: riel regulado de 3,3 V. Solo salida en la RT1062: no introduzcas 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 activo (3,6 V – 5 V). Transporta cualquiera de las fuentes activas (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 introducir energía 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 elige automáticamente cuál de USB o VIN tiene la tensión más alta 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 posterior de la placa tiene pads de soldadura para una batería de respaldo del RTC de 3,3 V externa. Conectar una pila de botón a estos pads mantiene el RTC en funcionamiento mientras el resto de la placa está sin alimentación.

Truco

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

Pines de Ethernet

La RT1062 expone los pares MDI del PHY Ethernet de 10/100 Mb/s en pads dedicados junto a la cabecera GPIO. Los pines MDI no son seguros para cablear directamente a un RJ45: se requiere magnética Ethernet (un transformador de aislamiento, ya sea integrado en un magjack o en el shield) entre el PHY y el cable. El shield PoE de OpenMV los 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.

  • ETH_TXP / ETH_TXN: par de transmisión.

  • ETH_RXP / ETH_RXN: par de recepción.

Nota

La cabecera también expone cuatro pads serigrafiados como Reserved. Son compatibles en huella con los pares de Ethernet gigabit de la OpenMV N6 (DC P/N y DD P/N), de modo que el mismo shield de Ethernet / PoE se puede conectar a cualquiera de las dos placas. El PHY de la RT1062 solo funciona a 10/100 Mb/s, por lo que esos cuatro pads no tienen conectividad eléctrica: déjalos sin conectar.

Pines de recuperación y depuración

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

  • SBL: lleva a 3,3 V mientras alimentas la placa para entrar en modo de gestor de arranque ROM (Serial Boot Loader). OpenMV IDE usa este modo para reprogramar el gestor de arranque (bootloader) integrado.

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

Nota

La RT1062 solo expone depuración SWD a través de este conector de forma predeterminada. JTAG completo no está disponible de fábrica.

Periféricos integrados

LEDs

La RT1062 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 de alimentación.

    En 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

La RT1062 tiene dos botones:

  • SW: botón de usuario de propósito general. Legible desde el código como una entrada GPIO normal activa en bajo:

    from machine import Pin
    
    sw = Pin("SW", Pin.IN)
    print(sw.value())
    
  • Botón de encendido: controlado por una máquina de estados de controlador de energía dedicada en la placa RT1062, completamente en hardware. No está expuesto al código de usuario; el controlador decide qué hacer según cuánto tiempo se mantenga pulsado:

    • Mantener pulsado ~5 s mientras la placa está en funcionamiento → la máquina de estados pasa a sueño profundo.

    • Mantener pulsado ~1 s mientras la placa está en sueño profundo → la máquina de estados vuelve a encender el sistema.

    Llevar el pad de cabecera ON/OFF a nivel bajo tiene el mismo efecto que pulsar el botón de encendido integrado: útil para cablear un interruptor externo o controlar la línea desde otro microcontrolador.

Pines de estado de alimentación

Tres entradas de estado activas en bajo del chip de gestión de energía integrado:

  • PG: bajo cuando hay alimentación VIN o USB presente. Siempre conectado.

  • ST: bajo cuando la placa funciona con VIN, alto cuando funciona con alimentación USB. No conectado de forma predeterminada.

  • CHG: bajo mientras se carga una batería LiPo conectada. No conectado de forma predeterminada.

from machine import Pin

power_ok = not Pin("PG", Pin.IN).value()

Sensor de la cámara

El OV5640 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.QVGA)
cam.snapshot(time=2000)       # let auto‑exposure settle

while True:
    img = cam.snapshot()

El OV5640 tiene un compresor JPEG integrado. Establece csi.CSI.pixformat en csi.JPEG y el sensor entrega fotogramas comprimidos directamente a la cámara a través del bus de la cámara, lo que hace prácticas las capturas de alta resolución: csi.HD (1280×720), csi.FHD (1920×1080) y los 5 MP completos csi.WQXGA2 (2592×1944) se transmiten todos como JPEG. Ajusta la compresión con csi.CSI.quality (0-100, mayor = fotogramas más grandes, más detalle):

cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)

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

Aprendizaje automático

ml — Aprendizaje automático ejecuta modelos TFLite cuantizados en el Cortex‑M7 con kernels CMSIS‑NN: lo suficientemente rápido para detectores compactos a unos pocos fotogramas por segundo. Los modelos en el sistema de archivos de solo lectura /rom se cargan directamente desde la memoria flash sin copiarlos a la RAM. Aquí tienes un detector BlazeFace de 128×128 que superpone la cara detectada y sus seis puntos de referencia en cada fotograma:

import csi
import time
import ml
from ml.postprocessing.mediapipe import BlazeFace

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

# Load built-in face detection model
model = ml.Model("/rom/blazeface_front_128.tflite", postprocess=BlazeFace(threshold=0.4))
print(model)

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

    # faces is a list of ((x, y, w, h), score, keypoints) tuples
    for r, score, keypoints in model.predict([img]):
        ml.utils.draw_predictions(img, [r], ("face",), ((0, 0, 255),), format=None)

        # keypoints is a ndarray of shape (6, 2)
        # 0 - right eye (x, y)
        # 1 - left eye (x, y)
        # 2 - nose (x, y)
        # 3 - mouth (x, y)
        # 4 - right ear (x, y)
        # 5 - left ear (x, y)
        ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))

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

IMU

El firmware de la RT1062 no conecta el acelerómetro integrado al módulo imu — sensor imu. En su lugar, comunícate con él directamente a través del bus I²C interno: el chip se encuentra en la dirección 0x15 y empaqueta tres canales de aceleración con signo de 12 bits más un byte de temperatura de 8 bits a partir del registro 0x03:

import machine
import time

ADDR     = 0x15
DATA_REG = 0x03
LSB_PER_G = 1024.0    # ±2 g range

def s12(hi, lo):
    v = ((hi << 8) | lo) >> 4
    return v - 0x1000 if v & 0x800 else v

bus = machine.I2C(2)
print("Devices on I²C2:", bus.scan())

while True:
    d = bus.readfrom_mem(ADDR, DATA_REG, 7)
    x = s12(d[0], d[1]) / LSB_PER_G
    y = s12(d[2], d[3]) / LSB_PER_G
    z = s12(d[4], d[5]) / LSB_PER_G
    temp_c = d[6] * 0.586 + 25.0
    print("x=%+.2fg  y=%+.2fg  z=%+.2fg  T=%.1f°C" % (x, y, z, temp_c))
    time.sleep_ms(100)

EEPROM

Las placas R6 y posteriores incluyen una EEPROM I²C genérica de 4 KB en el mismo bus interno que el acelerómetro. (Las revisiones anteriores no la tienen: llamar a estos fragmentos en R4/R5 agotará el tiempo de espera por falta de un ACK I²C.) Usa la API estándar machine.I2C readfrom_mem / writeto_mem con una dirección de memoria de 16 bits:

import machine
import time

EEPROM_ADDR = 0x50            # default address
PAGE_SIZE   = 32              # bytes per page (both read and write)
EEPROM_SIZE = 4096

bus = machine.I2C(2)

# Dump the entire 4 KB one page at a time
data = bytearray()
for offset in range(0, EEPROM_SIZE, PAGE_SIZE):
    data += bus.readfrom_mem(EEPROM_ADDR, offset, PAGE_SIZE, addrsize=16)
print(len(data), "bytes")

# Write a small payload back at offset 0 (fits in one page)
bus.writeto_mem(EEPROM_ADDR, 0, b"hello, world", addrsize=16)
time.sleep_ms(10)             # ~5 ms write cycle after each page

# Read it back
print(bus.readfrom_mem(EEPROM_ADDR, 0, 12, addrsize=16))

Tanto las lecturas como las escrituras deben permanecer dentro de una página de 32 bytes. Divide cualquier transferencia más grande en una llamada por página y añade el retardo del ciclo de escritura de ~5 ms entre escrituras consecutivas.

Wi‑Fi

El módulo integrado de la familia CYW43 se expone a través de network — configuración de red como una interfaz de estación. Tras conectar, 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 módulo inalámbrico 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-RT1062")
        print("Connected:", conn.device)
        await conn.disconnected()

asyncio.run(run())

Ethernet

Cuando se conecta un RJ45 (con magnética) a los pads MDI, el PHY 10/100 aparece como una interfaz LAN. DHCP se ejecuta automáticamente una vez que el enlace se establece:

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 es utilizable 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 4 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

UART1

P4

P5

from machine import UART

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

I²C

Bus

SCL

SDA

I2C1

P4

P5

from machine import I2C

i2c = I2C(1, 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(1, addr=0x42, mem=buf)

SPI

Bus

MOSI

MISO

SCK

CS

SPI1

P0

P1

P2

P3

from machine import SPI
from machine import Pin

spi = SPI(1, 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

P1

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

El único pin ADC de usuario es P6, que está a escala completa a ~3,3 V:

from machine import ADC
import time

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

PWM

Pin

Canal FlexPWM

P0

PWM2 B3

P2

PWM2 B3

P4

PWM1 X2

P5

PWM1 X3

P7

PWM2 A0

P8

PWM2 B0

P9

PWM1 A3

P10

PWM1 B3

Controla cualquiera de ellos mediante machine.PWM:

from machine import Pin, PWM

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

Buses bit‑banged por software

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

Sensor térmico (externo a la placa)

El firmware incluye el controlador fir — controlador de sensor térmico (fir == infrarrojo lejano) para cámaras térmicas cableadas 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 4: cablea el módulo a P4 (SCL) y P5 (SDA).

Temporización

time

El módulo time cubre retardos bloqueantes, ticks monótonos 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 período están en milisegundos. Llama a deinit() para detener y liberar la ranura.

Reloj en tiempo real

machine.RTC mantiene la hora del reloj a lo largo de los reinicios y (con la batería de respaldo opcional de 3,3 V cableada a los pads traseros, ver Pines de alimentación) a lo largo de una pérdida total de energía:

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 gestor de arranque USB

En cada encendido, la cámara ejecuta un breve gestor de arranque (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 gestor de arranque cede el control a boot.py y luego a main.py.

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

import machine

machine.bootloader()

Sistema de archivos y orden de arranque

El firmware de la RT1062 monta hasta tres sistemas de archivos en el arranque:

  • Memoria flash interna: siempre montada en /flash. Contiene main.py y README.txt de forma predeterminada; se crea en el primer arranque.

  • Tarjeta microSD: si se inserta una tarjeta, se monta en /sdcard.

  • ROMFS: sistema de archivos de solo lectura mapeado en memoria en /rom que se usa para distribuir grandes recursos de datos (por ejemplo, modelos de IA) que se benefician del acceso sin copia. MicroPython lo monta automáticamente al arrancar, antes de que se ejecute cualquier código 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 ejecuta entonces los scripts desde ese directorio:

  • boot.py se ejecuta en cada reinicio por software (arranque en frío, Ctrl‑D desde el REPL o cuando el script en ejecución finaliza).

  • main.py se ejecuta solo en el arranque en frío, inmediatamente después de boot.py. Los reinicios por software 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 de la memoria 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 predeterminado que viene en una placa recién flasheada simplemente parpadea el canal azul del LED RGB de usuario como latido (dos pulsos cortos, una pausa breve), de modo que puedas saber que el firmware arrancó correctamente sin ningún host conectado.

sys.path se amplía 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

Como el sistema operativo 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 sistema operativo como la OpenMV Cam escriben en el mismo sistema de archivos al mismo tiempo, el sistema operativo ganará y sobrescribirá los cambios hechos por la cámara. Usa la tarjeta SD para cualquier dato que el script escriba de vuelta, y vuelve a montarla 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: se trata de un indicador de actividad impulsado por el firmware, no de un fallo.

Tamaños de almacenamiento

La RT1062 viene con:

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

  • /rom: ROMFS de solo lectura mapeado en memoria de 8 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 que se inserte (cuando esté presente), lectura/escritura.

Indicador de fallo grave (hard fault)

Si el LED RGB de usuario está ciclando rápidamente por todos los colores, lo suficientemente rápido como para que tienda a parecer un LED blanco parpadeante en lugar de tonos distintos, el firmware ha encontrado un fallo grave (hard fault) irrecuperable. Vuelve a flashear el firmware para recuperarlo; si reflashear no ayuda, la placa puede 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 compilación de la RT1062.