15.3.1.6. API reference

The public surface of the openmv package is the Camera class for talking to a cam and the OMVException hierarchy for protocol errors. Both are documented on this page.

15.3.1.6.1. The Camera class

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)

The host-side proxy for an OpenMV cam reached over USB serial.

Parameters:
  • port – Serial device path. On Linux, /dev/ttyACMx for USB CDC and /dev/ttyUSBx for a USB-to-UART bridge. On macOS, /dev/tty.usbmodem... or /dev/cu.usbmodem.... On Windows, COMx.

  • baudrate – Serial baud rate. Over USB, 921600 is the magic value that switches the cam from the MicroPython REPL to the OpenMV protocol – any other value on a USB link leaves the cam in REPL mode, so the default must be used. Over a UART link the value is the actual line baud rate and can be set freely on both sides.

  • crc – Enable CRC validation on every packet.

  • seq – Enable per-packet sequence numbers.

  • ack – Require packet acknowledgement.

  • events – Enable event notifications from the cam.

  • timeout – Per-operation timeout in seconds.

  • max_retry – Number of retries before raising on a failed packet.

  • max_payload – Maximum negotiated payload size in bytes. The cam may negotiate down.

  • drop_rate – Test-only probability of dropping a packet, in [0.0, 1.0]. Leave at 0.0 in production.

The class supports the context-manager protocol; with Camera(port) as cam: calls connect() on entry and disconnect() on exit.

15.3.1.6.2. Connection

Camera.connect() None

Open the serial port and perform the protocol handshake. Cached state (channel list, system info, version info) is populated as a side effect. Called automatically by the context manager.

Camera.disconnect() None

Close the serial port and release the transport. Called automatically when the context manager exits.

Camera.is_connected() bool
Returns:

True if the serial port is open.

Camera.reset() None

Reset the cam. The connection is dropped because the cam reboots.

Camera.boot() None

Jump the cam into its bootloader. The connection is dropped because the cam reboots.

Camera.update_capabilities() None

Renegotiate the protocol capabilities (CRC, sequence checking, ACKs, events, max payload) with the cam. The cam reports the maximum payload it can handle; the host’s request is clipped to that and the agreed settings are pushed back. Called automatically by connect() – there is no reason to call it from user code unless the constructor flags need to be renegotiated on an existing connection.

Camera.poll_events() None

Run the transport’s receive path once to consume any pending events from the cam without sending a command. Useful in long-running programs that go minutes without other I/O and want to surface channel-registration events promptly.

15.3.1.6.3. Script execution

Camera.exec(script: str) None

Upload script (a Python source string) into the cam’s stdin buffer and start running it.

Parameters:

script – MicroPython source to execute.

Camera.stop() None

Interrupt the running script. Equivalent to the IDE’s Stop button.

Camera.read_stdout() str | None

Read whatever bytes the running script has written to stdout since the last call.

Returns:

The output as a decoded string, or None if no data is waiting.

15.3.1.6.4. Streaming

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

Turn the frame stream on or off and pick the on-the-wire format.

Parameters:
  • enableTrue enables streaming, False disables it.

  • raw – When False (default), the cam JPEG-compresses each frame before placing it in the stream channel and read_frame() decompresses on the host. When True, the cam sends the captured pixel buffer uncompressed – the right choice on cams without hardware JPEG support, where software compression is the slowest step in the loop.

  • resolution(width, height) target the cam scales each raw frame down to before sending, since uncompressed frames are much larger than JPEG-compressed ones. Required when raw=True; ignored otherwise.

Camera.read_frame() dict | None

Read the latest frame from the stream channel.

Returns:

None if no frame is waiting, or a dict with keys width (int, pixels), height (int, pixels), format (int, the pixel-format identifier the cam declared), depth (int, the compressed image size in bytes for JPEG / PNG frames; unused for uncompressed formats), data (bytes, RGB888 of length width * height * 3), and raw_size (int, bytes the cam sent over USB before decode).

15.3.1.6.5. Custom channels

Camera.has_channel(name: str) bool
Returns:

True if a channel registered with name exists on the cam.

Camera.channel_size(name: str) int
Returns:

Number of bytes the named channel currently has available, or 0 when the channel is empty or does not exist.

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

Read from a custom channel.

Parameters:
  • name – Channel name registered by the cam-side script.

  • size – Bytes to read, or None to read whatever is available.

Returns:

The bytes, or None if the channel does not exist.

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

Write data to a custom channel. Larger-than-payload writes are automatically split across packets.

Parameters:
  • name – Channel name registered by the cam-side script.

  • data – Bytes-like payload to send.

Returns:

True if the channel exists and the write was sent, False otherwise.

Camera.read_status() dict[str, bool]

Poll every registered channel.

Returns:

Dict mapping channel name to a boolean of “data is ready to read”.

Camera.update_channels() None

Refresh the cached channel list from the cam. Runs automatically the next time a channel-by-name lookup is performed after a channel-registration event arrives; an application that wants to learn a newly-registered channel immediately can call this directly.

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

Look up a channel either by name (returning its numeric ID) or by ID (returning its name). Refreshes the channel cache via update_channels() first if channel-registration events are pending.

Parameters:
  • name – Channel name to resolve to an ID.

  • channel_id – Channel ID to resolve to a name.

Returns:

The corresponding ID or name, or None when the channel does not exist. One of name or channel_id must be supplied.

15.3.1.6.6. Device introspection

Camera.version() dict

Return the cam’s protocol, bootloader, and firmware version triples. Cached after connect(). Each triple is a (major, minor, patch) tuple of int:

  • protocol_version – the version of the OpenMV wire protocol the cam implements.

  • bootloader_version – the bootloader image resident in flash.

  • firmware_version – the MicroPython firmware currently running.

Camera.system_info() dict

Return the cam’s hardware capability and memory information. Cached after connect(). The returned dict’s keys fall into four groups.

Identity

  • cpu_id – 32-bit CPU identifier.

  • device_id – 3-tuple of 32-bit words, the unique device serial baked into the silicon.

  • chip_id – 3-tuple of 32-bit words, one entry per image sensor connected to the cam.

  • usb_vid – USB vendor ID.

  • usb_pid – USB product ID.

Memory sizes (all in kilobytes)

  • flash_size_kb – total internal flash.

  • ram_size_kb – total RAM.

  • framebuffer_size_kb – RAM reserved for image capture.

  • stream_buffer_size_kb – RAM reserved for the stream channel that ships frames to the host.

Capability flags (one boolean per feature, all named <feature>_present)

  • gpu_present – graphics processing unit.

  • npu_present – neural processing unit.

  • isp_present – image signal processor.

  • venc_present – video encoder.

  • jpeg_present – JPEG hardware encoder.

  • dram_present – external DRAM.

  • crc_present – CRC accelerator.

  • pmu_present – performance monitoring unit.

  • wifi_present – Wi-Fi radio.

  • bt_present – Bluetooth radio.

  • sd_present – SD card slot.

  • eth_present – Ethernet PHY.

  • multicore_present – multiple CPU cores.

Other

  • usb_highspeed – boolean, True when USB enumerated in high-speed (USB 2.0 HS, 480 Mbps) mode.

  • pmu_eventcnt – number of PMU event counters available; 0 when no PMU.

Camera.print_system_info() None

Log the formatted system-information block to logging at INFO level. The CLI uses this on connection.

15.3.1.6.7. Diagnostics

Camera.host_stats() dict
Returns:

The transport-layer counters tracked on the host side: sent, received, checksum, sequence.

Camera.device_stats() dict
Returns:

The transport-layer counters tracked on the cam side: sent, received, checksum, sequence, retransmit, transport, sent_events, max_ack_queue_depth.

15.3.1.6.8. Profiler

The profiler reports per-function call counts and min / max / total execution times for the instrumented firmware modules – currently image, ml, and ulab. Function entry and exit are intercepted at compile time; the runtime samples a monotonic microsecond counter on each, accumulates the result per function, and exposes the table to the host through the profile channel.

The profiler is only built into the firmware when PROFILE_ENABLE=1 is passed to make. Stock firmware images do not include it – the -finstrument-functions flag the build adds to the tracked modules has non-trivial runtime overhead, so profiling builds are produced from source for the specific debugging session that needs them. When the firmware was not built with the flag, the profile channel is not registered and every profiler method on this page returns silently without doing anything.

The Arm Performance Monitoring Unit (PMU) is the Cortex-M55’s hardware counter block – a small set of configurable counters that track cycle counts, cache hits and misses, branch behaviour, and other architecture-defined events without slowing the code under measurement. On cams that have one – the AE3 and the N6, the two cams in the OpenMV lineup built around the M55 – the profiler samples these counters alongside the timing data and the event totals show up in each per-function record. Cams without a PMU still produce timing records; the event fields come back as zero, and profiler_event() is a no-op.

Camera.profiler_mode(exclusive: bool = False) None

Switch between inclusive and exclusive timing. Inclusive timing charges callees’ time to the caller; exclusive timing does not.

Parameters:

exclusiveTrue selects exclusive timing, False selects inclusive.

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

Clear all profile counters. config=None also restores the default PMU event assignment.

Parameters:

config – Reserved for future per-counter configuration overrides. Pass None to keep the defaults.

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

Bind one of the PMU counter slots to a specific hardware event.

Parameters:
  • counter_num – Counter index.

  • event_id – Architecture-defined event identifier.

Camera.read_profile() list[dict] | None

Return the per-function profile records collected since the last reset. Each record is a dict with address, caller, call_count, min_ticks, max_ticks, total_ticks, total_cycles, and an events tuple sized to the cam’s pmu_eventcnt.

Returns:

List of record dicts, or None if the profile channel is not available or no data has been collected.

15.3.1.6.9. Subclassing and channel internals

The methods documented above cover every common use of the package. A few patterns – handling cam-side events the host wants to react to, locking a channel for a multi-step exchange, talking to channels that carry shaped data instead of byte streams, or driving channel-specific control commands – need methods that Camera keeps prefixed with an underscore. These names are private by convention (Python does not name-mangle them), and applications that need them are expected to either subclass Camera or call the methods directly.

Subclassing to react to events. Every event the cam emits arrives through Camera._handle_event(). Subclassing Camera and overriding the method is the way an application reacts to events its cam-side script raises; the Events page walks the full pattern.

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

Dispatch one event from the cam. Called by the transport layer whenever an event packet arrives. Override in a subclass to add application-specific handling; call super()._handle_event(...) to keep the default behaviour (channel-list refresh on CHANNEL_REGISTERED, frame-ready tracking on the stream channel, stdin-channel start / stop logging).

Parameters:
  • channel_id0 for system events, otherwise the registered channel ID.

  • event – Event identifier; values come from the EventType enum for system events and from whatever the cam-side channel backend chose for channel events.

A subclass that adds its own protocol-talking methods should decorate them with retry_if_failed() so they inherit the same resync-and-retry behaviour every shipped method on this page has.

static Camera.retry_if_failed(func)

Decorator. Wraps an instance method so that it retries once when the transport raises ResyncException. Any method that calls into _send_cmd_wait_resp() (directly or through one of the _channel_* wrappers) should carry this decorator:

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

Channel locking ensures the channel’s state does not change between two related operations (a _channel_size() followed by a _channel_read(), for example, on a channel that keeps appending data). read_frame() and read_profile() use this internally; an application driving a custom channel with multi-step access does the same.

Camera._channel_lock(channel_id: int) bool

Acquire an exclusive lock on a channel. Other host operations on the same channel block until the lock is released.

Parameters:

channel_id – Numeric channel ID, typically resolved with get_channel().

Returns:

True when the lock was granted.

Camera._channel_unlock(channel_id: int) bool

Release a lock previously taken with _channel_lock(). Always paired with a lock call; use try / finally to make sure the unlock happens even when the read in between raises.

Parameters:

channel_id – Numeric channel ID, typically resolved with get_channel().

Shaped channels carry structured records rather than a flat byte stream. The profiler channel is the shipped example: its shape is (record_count, record_size) and a host that wants to know how many records are waiting reads the shape rather than the byte size.

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

Read the shape descriptor of a channel.

Parameters:

channel_id – Numeric channel ID, typically resolved with get_channel().

Returns:

Tuple of unsigned 32-bit integers describing the channel’s layout. The meaning is channel-specific.

Channel-specific control commands – start, stop, reset, configure – ride a single opcode (CHANNEL_IOCTL) with a channel-specific command number and an optional struct.pack payload. The shipped methods like stop(), exec(), and streaming() are thin wrappers around _channel_ioctl() calls against the stdin and stream channels; a custom cam-side channel that defines its own ioctl menu is driven the same way.

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

Issue an ioctl command on a channel.

Parameters:
  • channel_id – Numeric channel ID, typically resolved with get_channel().

  • cmd – Command number defined by the cam-side channel backend.

  • fmt – Optional struct format string for the argument tuple. Pass None for ioctls that take no arguments.

  • args – Values matching fmt.

Returns:

Whatever payload the channel returned, or None.

By-ID byte-stream variants of the public channel methods skip the name-to-ID lookup and accept an explicit byte offset – useful for reading a chunk from the middle of a large buffer (the profile channel records, for example).

Camera._channel_size(channel_id: int) int
Parameters:

channel_id – Numeric channel ID, typically resolved with get_channel().

Returns:

Bytes currently available on the channel.

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

Read length bytes starting at offset. Multi-packet reads are reassembled automatically.

Parameters:
  • channel_id – Numeric channel ID, typically resolved with get_channel().

  • offset – Byte offset to start reading from.

  • length – Number of bytes to read.

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

Write data at the given offset. Multi-packet writes are split across packets automatically.

Parameters:
  • channel_id – Numeric channel ID, typically resolved with get_channel().

  • data – Bytes-like payload to write.

  • offset – Byte offset to start writing at.

Protocol primitives are the lowest level the class exposes – the raw send-a-command, fetch-the-raw- channel-list, and manual-resync entries everything above is eventually built on. An application reaches for them when sending an opcode the class does not already wrap, or when implementing custom recovery in a subclass.

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

Send a protocol command and wait for the cam’s response. The primitive every other method in this section is built on.

Parameters:
  • opcode – Command number. The shipped Opcode enum lists the codes the firmware ships with, but the parameter is just an integer – a custom firmware build can define and respond to its own.

  • channel – Channel ID, or 0 for system commands.

  • data – Command-specific payload.

Returns:

Response payload, or None for commands like Opcode.SYS_RESET and Opcode.SYS_BOOT that drop the connection.

Camera._channel_list() dict

Fetch the current channel list from the cam without touching the cached channels_by_id and channels_by_name dictionaries that update_channels() populates. Useful for a subclass that wants to inspect the cam’s channel state directly.

Returns:

Dict mapping channel ID to {'name': str, 'flags': int}.

Camera._resync() None

Re-run the protocol handshake from scratch. Called automatically by connect() on initial connection and by every public method that catches an OMVException from the transport. An application implementing its own recovery loop in a subclass may call this directly after handling the underlying error.

15.3.1.6.10. Exceptions

exception openmv.OMVException

Base class for every protocol-level error. The three subclasses below all inherit from it, so a single except OMVException covers the entire error surface.

exception openmv.TimeoutException

The cam did not respond within the configured timeout. Subclass of OMVException.

exception openmv.ChecksumException

A packet’s CRC did not match. Raised after the protocol has exhausted its retry budget. Subclass of OMVException.

exception openmv.SequenceException

A packet arrived with an unexpected sequence number after retries. Subclass of OMVException.