13.3.1.6. Referencia de la API

La superficie pública del paquete openmv es la clase Camera para comunicarse con una cámara y la jerarquía OMVException para los errores de protocolo. Ambas se documentan en esta página.

13.3.1.6.1. La clase Camera

class openmv.Camera(port: str, *, baudrate: int = 921600, crc: bool = True, seq: bool = True, ack: bool = True, events: bool = True, timeout: float = 1.0, max_retry: int = 3, max_payload: int = 4096, drop_rate: float = 0.0)

El proxy del lado del host para una cámara OpenMV accesible a través de USB serie.

Parámetros:
  • port – Ruta del dispositivo serie. En Linux, /dev/ttyACMx para USB CDC y /dev/ttyUSBx para un puente USB-a-UART. En macOS, /dev/tty.usbmodem... o /dev/cu.usbmodem.... En Windows, COMx.

  • baudrate – Velocidad en baudios del puerto serie. A través de USB, 921600 es el valor mágico que cambia la cámara del REPL de MicroPython al protocolo OpenMV: cualquier otro valor en un enlace USB deja la cámara en modo REPL, por lo que debe usarse el valor predeterminado. A través de un enlace UART el valor es la velocidad en baudios real de la línea y puede establecerse libremente en ambos lados.

  • crc – Habilita la validación CRC en cada paquete.

  • seq – Habilita números de secuencia por paquete.

  • ack – Requiere acuse de recibo de los paquetes.

  • events – Habilita las notificaciones de eventos desde la cámara.

  • timeout – Tiempo de espera por operación en segundos.

  • max_retry – Número de reintentos antes de lanzar un error ante un paquete fallido.

  • max_payload – Tamaño máximo de carga útil negociado en bytes. La cámara puede negociar un valor menor.

  • drop_rate – Probabilidad de descartar un paquete, solo para pruebas, en [0.0, 1.0]. Déjelo en 0.0 en producción.

La clase admite el protocolo de gestor de contexto; with Camera(port) as cam: llama a connect() al entrar y a disconnect() al salir.

13.3.1.6.2. Conexión

Camera.connect() None

Abre el puerto serie y realiza el handshake del protocolo. El estado en caché (lista de canales, información del sistema, información de versión) se rellena como efecto secundario. Lo llama automáticamente el gestor de contexto.

Camera.disconnect() None

Cierra el puerto serie y libera el transporte. Se llama automáticamente cuando el gestor de contexto sale.

Camera.is_connected() bool
Devuelve:

True si el puerto serie está abierto.

Camera.reset() None

Reinicia la cámara. La conexión se pierde porque la cámara se reinicia.

Camera.boot() None

Salta la cámara a su bootloader. La conexión se pierde porque la cámara se reinicia.

Camera.update_capabilities() None

Renegocia las capacidades del protocolo (CRC, comprobación de secuencia, ACK, eventos, carga útil máxima) con la cámara. La cámara informa de la carga útil máxima que puede manejar; la solicitud del host se recorta a ese valor y los ajustes acordados se envían de vuelta. Lo llama automáticamente connect(): no hay razón para llamarlo desde el código de usuario salvo que los flags del constructor deban renegociarse en una conexión existente.

Camera.poll_events() None

Ejecuta una vez la ruta de recepción del transporte para consumir cualquier evento pendiente de la cámara sin enviar un comando. Útil en programas de larga duración que pasan minutos sin otra E/S y quieren mostrar los eventos de registro de canales con prontitud.

13.3.1.6.3. Ejecución de scripts

Camera.exec(script: str) None

Sube script (una cadena de código fuente Python) al búfer de stdin de la cámara y comienza a ejecutarlo.

Parámetros:

script – Código fuente de MicroPython a ejecutar.

Camera.stop() None

Interrumpe el script en ejecución. Equivale al botón Stop del IDE.

Camera.read_stdout() str | None

Lee los bytes que el script en ejecución haya escrito en stdout desde la última llamada.

Devuelve:

La salida como una cadena decodificada, o None si no hay datos esperando.

13.3.1.6.4. Streaming

Camera.streaming(enable: bool, raw: bool = False, resolution: tuple[int, int] | None = None) None

Activa o desactiva el flujo de fotogramas y elige el formato de transmisión.

Parámetros:
  • enableTrue habilita el streaming, False lo deshabilita.

  • raw – Cuando es False (predeterminado), la cámara comprime cada fotograma en JPEG antes de colocarlo en el canal de flujo y read_frame() lo descomprime en el host. Cuando es True, la cámara envía el búfer de píxeles capturado sin comprimir: la opción correcta en cámaras sin soporte JPEG por hardware, donde la compresión por software es el paso más lento del bucle.

  • resolution(width, height) al que la cámara reduce cada fotograma sin procesar antes de enviarlo, ya que los fotogramas sin comprimir son mucho más grandes que los comprimidos en JPEG. Obligatorio cuando raw=True; se ignora en caso contrario.

Camera.read_frame() dict | None

Lee el último fotograma del canal de flujo.

Devuelve:

None si no hay ningún fotograma esperando, o un diccionario con las claves width (int, píxeles), height (int, píxeles), format (int, el identificador de formato de píxel que declaró la cámara), depth (int, el tamaño de la imagen comprimida en bytes para fotogramas JPEG / PNG; sin uso para formatos sin comprimir), data (bytes, RGB888 de longitud width * height * 3) y raw_size (int, bytes que la cámara envió por USB antes de la decodificación).

13.3.1.6.5. Canales personalizados

Camera.has_channel(name: str) bool
Devuelve:

True si existe en la cámara un canal registrado con name.

Camera.channel_size(name: str) int
Devuelve:

Número de bytes que el canal indicado tiene disponibles actualmente, o 0 cuando el canal está vacío o no existe.

Camera.channel_read(name: str, size: int | None = None) bytes | None

Lee de un canal personalizado.

Parámetros:
  • name – Nombre del canal registrado por el script del lado de la cámara.

  • size – Bytes a leer, o None para leer todo lo que esté disponible.

Devuelve:

Los bytes, o None si el canal no existe.

Camera.channel_write(name: str, data: bytes) bool

Escribe data en un canal personalizado. Las escrituras mayores que la carga útil se dividen automáticamente en varios paquetes.

Parámetros:
  • name – Nombre del canal registrado por el script del lado de la cámara.

  • data – Carga útil de tipo bytes a enviar.

Devuelve:

True si el canal existe y la escritura se envió, False en caso contrario.

Camera.read_status() dict[str, bool]

Sondea cada canal registrado.

Devuelve:

Diccionario que asigna el nombre de canal a un booleano de «hay datos listos para leer».

Camera.update_channels() None

Actualiza la lista de canales en caché desde la cámara. Se ejecuta automáticamente la próxima vez que se realiza una búsqueda de canal por nombre tras la llegada de un evento de registro de canal; una aplicación que quiera conocer de inmediato un canal recién registrado puede llamar a esto directamente.

Camera.get_channel(name: str | None = None, channel_id: int | None = None) int | str | None

Busca un canal ya sea por nombre (devolviendo su ID numérico) o por ID (devolviendo su nombre). Antes refresca la caché de canales mediante update_channels() si hay eventos de registro de canal pendientes.

Parámetros:
  • name – Nombre de canal a resolver a un ID.

  • channel_id – ID de canal a resolver a un nombre.

Devuelve:

El ID o nombre correspondiente, o None cuando el canal no existe. Debe proporcionarse uno de name o channel_id.

13.3.1.6.6. Introspección del dispositivo

Camera.version() dict

Devuelve las ternas de versión de protocolo, bootloader y firmware de la cámara. Se almacenan en caché tras connect(). Cada terna es una tupla (major, minor, patch) de int:

  • protocol_version: la versión del protocolo de cable de OpenMV que implementa la cámara.

  • bootloader_version: la imagen del bootloader residente en la memoria flash.

  • firmware_version: el firmware de MicroPython que se está ejecutando actualmente.

Camera.system_info() dict

Devuelve la información de capacidades de hardware y memoria de la cámara. Se almacena en caché tras connect(). Las claves del diccionario devuelto se reparten en cuatro grupos.

Identidad

  • cpu_id: identificador de CPU de 32 bits.

  • device_id: tupla de 3 palabras de 32 bits, el número de serie único del dispositivo grabado en el silicio.

  • chip_id: tupla de 3 palabras de 32 bits, una entrada por cada sensor de imagen conectado a la cámara.

  • usb_vid: ID de proveedor USB.

  • usb_pid: ID de producto USB.

Tamaños de memoria (todos en kilobytes)

  • flash_size_kb: memoria flash interna total.

  • ram_size_kb: RAM total.

  • framebuffer_size_kb: RAM reservada para la captura de imágenes.

  • stream_buffer_size_kb: RAM reservada para el canal de flujo que envía fotogramas al host.

Flags de capacidad (un booleano por característica, todos llamados <feature>_present)

  • gpu_present: unidad de procesamiento gráfico.

  • npu_present: unidad de procesamiento neuronal.

  • isp_present: procesador de señal de imagen.

  • venc_present: codificador de vídeo.

  • jpeg_present: codificador JPEG por hardware.

  • dram_present: DRAM externa.

  • crc_present: acelerador CRC.

  • pmu_present: unidad de monitorización de rendimiento.

  • wifi_present: radio Wi-Fi.

  • bt_present: radio Bluetooth.

  • sd_present: ranura para tarjeta SD.

  • eth_present: PHY Ethernet.

  • multicore_present: múltiples núcleos de CPU.

Otros

  • usb_highspeed: booleano, True cuando el USB se enumeró en modo de alta velocidad (USB 2.0 HS, 480 Mbps).

  • pmu_eventcnt: número de contadores de eventos de la PMU disponibles; 0 cuando no hay PMU.

Camera.print_system_info() None

Registra el bloque de información del sistema formateado en logging con nivel INFO. La CLI usa esto al conectarse.

13.3.1.6.7. Diagnósticos

Camera.host_stats() dict
Devuelve:

Los contadores de la capa de transporte registrados en el lado del host: sent, received, checksum, sequence.

Camera.device_stats() dict
Devuelve:

Los contadores de la capa de transporte registrados en el lado de la cámara: sent, received, checksum, sequence, retransmit, transport, sent_events, max_ack_queue_depth.

13.3.1.6.8. Profiler

El profiler informa de los recuentos de llamadas por función y de los tiempos de ejecución mínimo / máximo / total de los módulos de firmware instrumentados: actualmente image, ml y ulab. La entrada y la salida de las funciones se interceptan en tiempo de compilación; el tiempo de ejecución muestrea un contador monótono de microsegundos en cada una, acumula el resultado por función y expone la tabla al host a través del canal profile.

El profiler solo se incluye en el firmware cuando se pasa PROFILE_ENABLE=1 a make. Las imágenes de firmware de serie no lo incluyen: el flag -finstrument-functions que la compilación añade a los módulos rastreados tiene una sobrecarga en tiempo de ejecución no trivial, por lo que las compilaciones de profiling se producen a partir del código fuente para la sesión de depuración específica que las necesite. Cuando el firmware no se compiló con el flag, el canal profile no se registra y todos los métodos del profiler de esta página retornan en silencio sin hacer nada.

La Performance Monitoring Unit (PMU) de Arm es el bloque de contadores por hardware del Cortex-M55: un pequeño conjunto de contadores configurables que rastrean recuentos de ciclos, aciertos y fallos de caché, comportamiento de bifurcaciones y otros eventos definidos por la arquitectura sin ralentizar el código bajo medición. En las cámaras que cuentan con una – la AE3 y la N6, las dos cámaras de la gama OpenMV construidas en torno al M55 – el profiler muestrea estos contadores junto con los datos de tiempo y los totales de eventos aparecen en cada registro por función. Las cámaras sin PMU siguen produciendo registros de tiempo; los campos de eventos vuelven como cero y profiler_event() es una operación sin efecto.

Camera.profiler_mode(exclusive: bool = False) None

Cambia entre tiempo inclusivo y exclusivo. El tiempo inclusivo imputa el tiempo de las funciones llamadas a la función que llama; el tiempo exclusivo no.

Parámetros:

exclusiveTrue selecciona el tiempo exclusivo, False selecciona el inclusivo.

Camera.profiler_reset(config: list | None = None) None

Borra todos los contadores del profiler. config=None también restaura la asignación de eventos de la PMU predeterminada.

Parámetros:

config – Reservado para futuras anulaciones de configuración por contador. Pase None para mantener los valores predeterminados.

Camera.profiler_event(counter_num: int, event_id: int) None

Vincula uno de los slots de contador de la PMU a un evento de hardware específico.

Parámetros:
  • counter_num – Índice del contador.

  • event_id – Identificador de evento definido por la arquitectura.

Camera.read_profile() list[dict] | None

Devuelve los registros del profiler por función recopilados desde el último reinicio. Cada registro es un diccionario con address, caller, call_count, min_ticks, max_ticks, total_ticks, total_cycles y una tupla events dimensionada al pmu_eventcnt de la cámara.

Devuelve:

Lista de diccionarios de registros, o None si el canal del profiler no está disponible o no se han recopilado datos.

13.3.1.6.9. Creación de subclases y detalles internos de los canales

Los métodos documentados arriba cubren todos los usos comunes del paquete. Unos pocos patrones – gestionar eventos del lado de la cámara a los que el host quiere reaccionar, bloquear un canal para un intercambio de varios pasos, comunicarse con canales que transportan datos estructurados en lugar de flujos de bytes, o ejecutar comandos de control específicos de un canal – necesitan métodos que Camera mantiene con el prefijo de un guion bajo. Estos nombres son privados por convención (Python no aplica name-mangling a ellos), y se espera que las aplicaciones que los necesiten o bien creen una subclase de Camera o bien llamen a los métodos directamente.

Creación de subclases para reaccionar a eventos. Cada evento que emite la cámara llega a través de Camera._handle_event(). Crear una subclase de Camera y sobrescribir el método es la forma en que una aplicación reacciona a los eventos que lanza su script del lado de la cámara; la página Eventos recorre el patrón completo.

Camera._handle_event(channel_id: int, event: int) None

Despacha un evento de la cámara. Lo llama la capa de transporte cada vez que llega un paquete de evento. Sobrescríbalo en una subclase para añadir manejo específico de la aplicación; llame a super()._handle_event(...) para mantener el comportamiento predeterminado (actualización de la lista de canales en CHANNEL_REGISTERED, seguimiento de fotograma listo en el canal stream, registro de inicio / parada del canal stdin).

Parámetros:
  • channel_id0 para eventos del sistema, en caso contrario el ID del canal registrado.

  • event – Identificador del evento; los valores provienen del enum EventType para los eventos del sistema y de lo que el backend del canal del lado de la cámara haya elegido para los eventos de canal.

Una subclase que añade sus propios métodos de comunicación de protocolo debería decorarlos con retry_if_failed() para que hereden el mismo comportamiento de resincronización y reintento que tiene todo método incluido en esta página.

static Camera.retry_if_failed(func)

Decorador. Envuelve un método de instancia de modo que reintente una vez cuando el transporte lanza ResyncException. Cualquier método que llame a _send_cmd_wait_resp() (directamente o a través de uno de los envoltorios _channel_*) debería llevar este decorador:

class MyCamera(Camera):
    @Camera.retry_if_failed
    def my_custom_command(self, payload):
        return self._send_cmd_wait_resp(Opcode.MY_CMD,
                                        0, payload)

El bloqueo de canales garantiza que el estado del canal no cambie entre dos operaciones relacionadas (un _channel_size() seguido de un _channel_read(), por ejemplo, en un canal que sigue añadiendo datos). read_frame() y read_profile() lo usan internamente; una aplicación que opera un canal personalizado con acceso de varios pasos hace lo mismo.

Camera._channel_lock(channel_id: int) bool

Adquiere un bloqueo exclusivo sobre un canal. Las demás operaciones del host sobre el mismo canal se bloquean hasta que se libera el bloqueo.

Parámetros:

channel_id – ID numérico del canal, resuelto normalmente con get_channel().

Devuelve:

True cuando se concedió el bloqueo.

Camera._channel_unlock(channel_id: int) bool

Libera un bloqueo tomado previamente con _channel_lock(). Siempre se empareja con una llamada de bloqueo; use try / finally para asegurarse de que el desbloqueo ocurra incluso cuando la lectura intermedia lanza una excepción.

Parámetros:

channel_id – ID numérico del canal, resuelto normalmente con get_channel().

Los canales estructurados transportan registros estructurados en lugar de un flujo de bytes plano. El canal del profiler es el ejemplo incluido: su forma es (record_count, record_size) y un host que quiera saber cuántos registros están esperando lee la forma en lugar del tamaño en bytes.

Camera._channel_shape(channel_id: int) tuple[int, ...]

Lee el descriptor de forma de un canal.

Parámetros:

channel_id – ID numérico del canal, resuelto normalmente con get_channel().

Devuelve:

Tupla de enteros de 32 bits sin signo que describe la disposición del canal. El significado es específico de cada canal.

Los comandos de control específicos de un canal – iniciar, parar, reiniciar, configurar – viajan en un único opcode (CHANNEL_IOCTL) con un número de comando específico del canal y una carga útil opcional de struct.pack. Los métodos incluidos como stop(), exec() y streaming() son finos envoltorios alrededor de llamadas a _channel_ioctl() contra los canales stdin y stream; un canal personalizado del lado de la cámara que defina su propio menú de ioctl se opera de la misma manera.

Camera._channel_ioctl(channel_id: int, cmd: int, fmt: str | None = None, *args) bytes | None

Emite un comando ioctl en un canal.

Parámetros:
  • channel_id – ID numérico del canal, resuelto normalmente con get_channel().

  • cmd – Número de comando definido por el backend del canal del lado de la cámara.

  • fmt – Cadena de formato struct opcional para la tupla de argumentos. Pase None para los ioctl que no toman argumentos.

  • args – Valores que coinciden con fmt.

Devuelve:

La carga útil que devolvió el canal, o None.

Las variantes de flujo de bytes por ID de los métodos públicos de canal omiten la búsqueda de nombre a ID y aceptan un offset de byte explícito: útil para leer un fragmento del medio de un búfer grande (los registros del canal profile, por ejemplo).

Camera._channel_size(channel_id: int) int
Parámetros:

channel_id – ID numérico del canal, resuelto normalmente con get_channel().

Devuelve:

Bytes disponibles actualmente en el canal.

Camera._channel_read(channel_id: int, offset: int, length: int) bytes

Lee length bytes a partir de offset. Las lecturas de varios paquetes se reensamblan automáticamente.

Parámetros:
  • channel_id – ID numérico del canal, resuelto normalmente con get_channel().

  • offset – Desplazamiento en bytes desde el que empezar a leer.

  • length – Número de bytes a leer.

Camera._channel_write(channel_id: int, data: bytes, offset: int = 0) None

Escribe data en el offset indicado. Las escrituras de varios paquetes se dividen en paquetes automáticamente.

Parámetros:
  • channel_id – ID numérico del canal, resuelto normalmente con get_channel().

  • data – Carga útil de tipo bytes a escribir.

  • offset – Desplazamiento en bytes desde el que empezar a escribir.

Las primitivas de protocolo son el nivel más bajo que expone la clase – las entradas en bruto de enviar-un-comando, obtener-la-lista-de-canales-en-bruto y resincronización manual sobre las que finalmente se construye todo lo anterior. Una aplicación recurre a ellas al enviar un opcode que la clase no envuelve ya, o al implementar una recuperación personalizada en una subclase.

Camera._send_cmd_wait_resp(opcode: int, channel: int = 0, data: bytes = b'') bytes | None

Envía un comando de protocolo y espera la respuesta de la cámara. La primitiva sobre la que se construye todos los demás métodos de esta sección.

Parámetros:
  • opcode – Número de comando. El enum Opcode incluido enumera los códigos con los que viene el firmware, pero el parámetro es solo un entero: una compilación de firmware personalizada puede definir y responder a los suyos propios.

  • channel – ID del canal, o 0 para comandos del sistema.

  • data – Carga útil específica del comando.

Devuelve:

Carga útil de respuesta, o None para comandos como Opcode.SYS_RESET y Opcode.SYS_BOOT que cierran la conexión.

Camera._channel_list() dict

Obtiene la lista de canales actual de la cámara sin tocar los diccionarios en caché channels_by_id y channels_by_name que rellena update_channels(). Útil para una subclase que quiera inspeccionar el estado de los canales de la cámara directamente.

Devuelve:

Diccionario que asigna el ID de canal a {'name': str, 'flags': int}.

Camera._resync() None

Vuelve a ejecutar el handshake del protocolo desde cero. Lo llama automáticamente connect() en la conexión inicial y cada método público que captura una OMVException del transporte. Una aplicación que implemente su propio bucle de recuperación en una subclase puede llamarlo directamente tras gestionar el error subyacente.

13.3.1.6.10. Excepciones

exception openmv.OMVException

Clase base de todos los errores de nivel de protocolo. Las tres subclases siguientes heredan todas de ella, de modo que un único except OMVException cubre toda la superficie de errores.

exception openmv.TimeoutException

La cámara no respondió dentro del tiempo de espera configurado. Subclase de OMVException.

exception openmv.ChecksumException

El CRC de un paquete no coincidió. Se lanza después de que el protocolo haya agotado su presupuesto de reintentos. Subclase de OMVException.

exception openmv.SequenceException

Un paquete llegó con un número de secuencia inesperado tras los reintentos. Subclase de OMVException.