OpenMV Cam M4¶
La OpenMV Cam M4 es una placa de visión artificial Cortex‑M4 compacta construida en torno al STMicroelectronics STM32F427 a 180 MHz, con 256 KB de SRAM interna y 1 MB de memoria flash interna. El sensor OV7725 incluido captura fotogramas en escala de grises o RGB565 de 320×240, y el conector de usuario de 9 pines expone periféricos UART, I²C, SPI, CAN, ADC/DAC y PWM.
Nota
El OV7725 era el sensor estándar en las placas M4 de producción. Las primeras variantes de la M4 se suministraron con el OmniVision OV2640 en su lugar — la misma cadena de previsualización QVGA, pero el OV2640 también puede capturar fotogramas JPEG de hasta UXGA (1600×1200). Ambos sensores se controlan a través de la misma API csi — sensores de cámara.
Para ver la hoja de datos completa, fotos y dimensiones, consulta la página del producto OpenMV Cam M4.
Aspectos destacados¶
STMicroelectronics STM32F427 Cortex‑M4 a 180 MHz.
256 KB de SRAM interna — sin SDRAM externa.
1 MB de memoria flash interna (sin memoria flash QSPI externa).
Sensor OV7725 (u OV2640 en las primeras variantes de la M4) — escala de grises de 8 bits o RGB565 de 320×240; el OV2640 puede además capturar JPEG de hasta UXGA (1600×1200).
USB de velocidad completa (12 Mb/s) — aparece como VCP + almacenamiento masivo USB ante el host.
Zócalo microSD — SD hasta 2 GB, SDHC hasta 32 GB, SDXC hasta 2 TB.
9 pines de E/S, tolerantes a 5 V con salida de 3,3 V, 25 mA por pin (120 mA en total en todo el conector), con capacidad de interrupción. P6 no es tolerante a 5 V cuando se usa en modo ADC o DAC.
LED RGB de usuario y dos LED IR de 850 nm de alta potencia para iluminación activa en visión con poca luz.
Nota
La M4 no tiene chip de gestión de energía a bordo: no hay conector de batería, ni cargador de batería, ni ADC de voltaje de batería, ni LED de carga / estado de energía, ni botón físico de encendido. Alimenta la placa desde USB o VIN.
Disposición de pines¶
Referencia de pines¶
Nombre del pin |
Función |
|---|---|
P0 |
SPI2 MOSI |
P1 |
SPI2 MISO |
P2 |
SPI2 SCK / CAN2 TX |
P3 |
SPI2 NSS (CS) / CAN2 RX |
P4 |
I2C2 SCL / UART3 TX / TIM2 CH3 |
P5 |
I2C2 SDA / UART3 RX / TIM2 CH4 |
P6 |
ADC / DAC / TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
RESET |
conectar a GND para reiniciar la placa |
BOOT0 |
conectar a 3,3 V al encender para DFU / gestor de arranque ROM |
SWCLK |
reloj ARM SWD (acceso del depurador) |
SWDIO |
datos ARM SWD (acceso del depurador) |
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) |
LED_IR |
LED IR de alta potencia (ambos canales se controlan juntos) |
Pines de alimentación¶
3.3V — riel regulado de 3,3 V. Hasta 250 mA disponibles para los shields (menos si la tarjeta microSD está en uso). A diferencia de las cámaras más nuevas, este pin es bidireccional — consulta la advertencia más abajo.
VIN — entrada de 3,6 – 5 V. Alimenta la placa a través del regulador a bordo.
GND — tierra común.
Nota
Cuando hay tanto USB como VIN presentes, el que tenga el voltaje más alto alimenta la placa — los diodos a bordo simplemente eligen el riel más fuerte.
Advertencia
Puedes alimentar la M4 introduciendo 3,3 V directamente en el pin 3.3V si no quieres pasar por el regulador a bordo. En ese caso, no apliques también VIN o alimentación USB al mismo tiempo — retroalimentar el regulador mientras otra fuente está activa puede dañar y destruir permanentemente la cámara.
Truco
Usa el estimador de duración de batería para modelar cuánto tiempo funcionará la M4 con una batería para un ciclo de trabajo activo / suspensión profunda determinado.
Pines de recuperación y depuración¶
RESET — conectar a GND para reiniciar la placa. Soltarlo permite que el MCU arranque normalmente.
BOOT0 — conectar a 3,3 V mientras se alimenta la placa para entrar en el gestor de arranque ROM del STM32 (modo DFU). OpenMV IDE usa este modo para reprogramar el gestor de arranque a bordo.
SWCLK y SWDIO se exponen como pines de conector ordinarios (no como un conector SWD dedicado). Conecta RESET, SWCLK, SWDIO, GND y 3,3 V a un adaptador ST‑LINK o SEGGER J‑Link para depurar la placa.
Periféricos a bordo¶
LED¶
La M4 tiene un único LED RGB de usuario más un par de LED IR de 850 nm de alta potencia:
LED RGB de usuario — controlable por software, expuesto como
LED_RED,LED_GREENyLED_BLUE:from machine import LED LED("LED_RED").on() LED("LED_GREEN").on() LED("LED_BLUE").on()
LED IR — ambos LED se controlan juntos a través del pin
LED_IR.LED_IRestá cableado como activo en alto en el hardware, mientras que el firmware trata todos los demás LED a bordo como activos en bajo, así que usalow()/high()en lugar deon()/off()(que invertirían el sentido):from machine import LED ir = LED("LED_IR") ir.low() # turn IR illumination ON ir.high() # turn IR illumination OFF
Sensor de la cámara¶
El sensor incluido (OV7725 en las placas estándar, OV2640 en las primeras variantes) 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()
En la M4 el sensor está soldado a la placa — no se encuentra en un módulo intercambiable.
Nota
En las placas OV7725, el pin FSIN (sincronización de fotograma) del sensor está cableado al MCU, pero no se ha añadido soporte de firmware para él.
En las placas OV2640, los pines STROBE, FREX (exposición de fotograma) y EXPST (reinicio de exposición) del sensor están cableados al MCU, pero no se ha añadido soporte de firmware para ellos.
Conectores de servo¶
La cara posterior de la placa tiene dos pads de soldadura de conector de servo que exponen el conector de servo estándar de 3 pines (señal / VIN / GND) para P7 y P8. Los pines de señal se asignan directamente a los canales 1 y 2 de TIM4 (los mismos canales que usa pyb.Servo), y el pin V+ de cada conector está cableado directamente a VIN, de modo que los servos toman su corriente del riel de entrada en lugar del regulador de 3,3 V.
Suelda un par de conectores de 3 pines en ángulo recto en los pads y conecta dos servos de hobby para controlar un soporte de panorámica e inclinación:
from pyb import Servo
pan = Servo(1) # P7 — TIM4 CH1
tilt = Servo(2) # P8 — TIM4 CH2
pan.angle(0)
tilt.angle(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 normal:
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, tolerantes a 5 V en el lado de entrada, y pueden absorber/suministrar hasta 25 mA por pin (120 mA en total en todo el conector).
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 borde:
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 |
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 |
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 |
|---|---|---|
CAN2 |
P2 |
P3 |
from machine import CAN
can = CAN(2, 500_000)
can.set_filters(None)
can.send(0x123, b"\xDE\xAD\xBE\xEF")
print(can.recv())
ADC y DAC¶
P6 es el único pin analógico de usuario. Puede usarse como entrada ADC de 12 bits o como salida DAC.
ADC — fondo de escala a 3,3 V en el pin:
from machine import ADC import time adc = ADC("P6") while True: voltage = adc.read_u16() * 3.3 / 65535 print(voltage) time.sleep_ms(100)
DAC — a través de
pyb.DAC. El valor de 8 bits cubre 0–3,3 V:from pyb import DAC dac = DAC("P6") voltage = 1.65 dac.write(int(voltage / 3.3 * 255))
En modo ADC o DAC, P6 es tolerante solo a 3,3 V — no le apliques 5 V.
PWM¶
Pin |
Temporizador / canal |
|---|---|
P4 |
TIM2 CH3 |
P5 |
TIM2 CH4 |
P6 |
TIM2 CH1 |
P7 |
TIM4 CH1 |
P8 |
TIM4 CH2 |
Nota
TIM1 está reservado por el firmware para generar el reloj de píxeles del sensor de la cámara, así que los canales de TIM1 que están físicamente en P0/P1/P2 no se pueden usar para PWM de usuario sin inutilizar la cámara.
TIM4 se comparte con pyb.Servo — instanciar un servo reconfigura todo el temporizador para operar a 50 Hz, así que no mezcles machine.PWM en P7/P8 con pyb.Servo en el mismo script.
Controla cualquiera de ellos mediante machine.PWM:
from machine import Pin, PWM
pwm = PWM(Pin("P7"), 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 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
Conecta 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 — conecta el módulo a P4 (SCL) y P5 (SDA).
Temporización¶
time¶
El módulo time cubre retardos bloqueantes, ticks monotónicos y 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 de 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 de pared a través de los reinicios:
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 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 M4 monta hasta tres sistemas de archivos en el arranque:
Memoria flash interna — siempre montada en
/flash. Contienemain.pyyREADME.txtde forma predeterminada; se crea en el primerísimo 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 activos de datos (p. ej., modelos de IA) que se benefician del acceso sin copia (zero‑copy). MicroPython lo monta automáticamente al inicio, antes de que se ejecute cualquier código Python de usuario.
Tras el montaje, el directorio de trabajo se establece en /sdcard cuando hay tarjeta presente, de lo contrario en /flash. El intérprete ejecuta entonces los scripts desde ese directorio:
boot.pyse ejecuta en cada reinicio suave (arranque en frío,Ctrl‑Ddesde el REPL, o siempre que el script en ejecución retorne).main.pyse ejecuta solo en el arranque en frío, inmediatamente después deboot.py. Los reinicios suaves posteriores vuelven a ejecutarboot.pypero pasan directamente al REPL — para volver a ejecutarmain.pytienes que reiniciar por completo 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 predeterminado que viene en una placa recién flasheada simplemente parpadea el canal azul del LED RGB de usuario como un 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 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
Dado que 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 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 M4 viene con:
/flash— sistema de archivos FAT de 32 KB, lectura/escritura./rom— ROMFS de 128 KB de solo lectura mapeada en memoria./sdcard— el tamaño completo de la tarjeta microSD que esté insertada (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 bastante rápido como para parecer un LED blanco parpadeante en lugar de tonos distintos — el firmware ha sufrido un fallo grave irrecuperable. Reprograma el firmware para recuperarlo; si reprogramarlo no ayuda, la placa puede estar físicamente dañada.
Bibliotecas de software¶
Consulta el índice de bibliotecas para ver la lista completa de módulos — incluyendo cuáles son exclusivos de la compilación de la M4.