.. _changelog_v5_0_1: v5.0.1 ====== v5.0.1 is a maintenance release on top of v5.0.0 — the legacy ``sensor`` module becomes a Python compatibility layer over :mod:`csi`, images loaded into the frame buffer now preview like camera frames, the JPEG encoders lose their 1 MB output limit and handle overflow correctly, and there is a batch of camera, protocol, networking, and ML-library fixes. It introduces **no breaking API changes** for scripts written against :mod:`csi`; the handful of behavior changes are listed under :ref:`breaking API changes `. .. contents:: On this page :backlinks: none :local: :depth: 1 Highlights ---------- - **The** ``sensor`` **module is now a frozen Python module** built on :mod:`csi`. It prints a deprecation warning on import; a few functions the :mod:`csi` module cannot support now raise ``OSError``. See :ref:`the sensor module changes `. - **Loaded images preview like camera frames.** An image placed in the frame buffer with ``copy_to_fb=True`` (:class:`image.Image`, :meth:`image.ImageIO.read`, :func:`fir.snapshot`, :func:`tof.snapshot`) is flushed to the IDE — with anything drawn on it — when the next image overwrites the frame buffer, instead of immediately. See :ref:`the preview changes `. - **JPEG encoder overhaul.** The 1 MB output-buffer cap is gone (the buffer is sized from free memory), overflow on both the software and hardware paths is handled instead of writing truncated files, and saving a compressed image under the other compressed extension raises instead of writing garbage. - **New** :func:`protocol.poll` and **six new CBOR widgets** (``text``, ``lineedit``, ``pushbutton``, ``spinbox``, ``radio``, ``waveform``) for :class:`protocol.CBORChannel`. - **YOLO Pro post-processor**, **FLIR Lepton 3.1R / UW** support, **IMU burst reads**, **CAN on the OpenMV N6**, and a **networking-capable simulator** target. New features ------------ - :class:`YoloPro ` — a new post-processor for Edge Impulse YOLO Pro object-detection models, plus a ``yolo_pro_detector.py`` example. (`f3f150ebd `__, `ea7bbb398 `__) - :func:`protocol.poll` — run one iteration of the protocol task on demand, for custom transports that are not driven by the USB interrupt or the ``poll_ms`` timer. :func:`protocol.init` can also be called again to re-initialize the stack. (`c00c215f9 `__, `f849ffb1b `__) - **More CBOR channel widgets** — :meth:`protocol.CBORChannel.add` gains ``text`` (static string), ``lineedit`` (writable string), ``pushbutton`` (momentary action), ``spinbox`` (stepped numeric entry), ``radio`` (option group) and ``waveform`` (1D time-series with ``sample_rate``, ``series`` and ``typecode`` arguments; assign interleaved sample bytes to stream it). (`8016d29ba `__) - :data:`csi.CUSTOM` — :meth:`csi.CSI.framesize` now returns a usable constant after a custom ``(w, h)`` resolution has been set, instead of an anonymous integer. (`af8841654 `__) - **IMU burst read** — :func:`imu.__read_reg` accepts an optional writable buffer and fills it from consecutive registers in one transaction. (`244ca480a `__) - **FLIR Lepton 3.1R and Lepton UW** are recognized by the Lepton driver, including their radiometric gain modes. (`0fc356632 `__) - **Simulator networking** — the ``MPS2_AN500`` QEMU target now has lwIP and a user-mode NIC, with ``requests``, ``mqtt`` and ``sensor`` frozen in, and a networking unit test. (`23546dfb1 `__, `61d187305 `__, `15096c3a2 `__) - **OpenAI-compatible API example** — ``openai_compatible.py`` snapshots a JPEG and posts it to a chat-completions endpoint for scene description. (`79033c6aa `__) - **SX126x LoRa examples** — micropython-lib's ``lora-sx126x`` driver (with ``lora-sync`` / ``lora-async``) is frozen into the OpenMV RT1062 firmware, with sender/receiver/ping-pong/image-stream examples for wiring an SX1261 or SX1262 module to the SPI bus. This is community-contributed support; OpenMV does not sell LoRa hardware. (`19576e1b1 `__) Other changes and improvements ------------------------------ - ``requests`` **library rewrite** — chunked transfer responses are decoded, a ``timeout`` argument (default 5 s) is exposed, JSON and string bodies are serialized/encoded correctly, headers are parsed case-insensitively and the status line by position, the caller's ``headers`` dict is copied (so ``auth`` no longer leaks into later requests), and the body is read in blocks into a ``bytearray``. (`889f0b096 `__) - ``mqtt`` imports :mod:`ssl` lazily, so the module and plain (non-TLS) connections work on builds without SSL support. (`c2e0899e8 `__) - **JPEG output buffer sized from free memory** instead of a fixed 1 MB cap; the encoders trim the buffer to the encoded size before the image is written out, so large-sensor captures at high quality no longer fail. (`aa1ca6776 `__) - **ML post-processing cleanup** — bounding-box generation is standardized across the Darknet, Edge Impulse and Ultralytics post-processors, and the YOLOv8 output is transposed after thresholding so it is stored one row per detection like the other models. (`b5c7853f2 `__, `c45f99cad `__) - **PAG7936 safe shutdown** — a new sensor halt flag puts the PAG7936 to sleep before RESET/PWDN toggle, fixing lock-ups when the sensor is used on an extension cable. The driver also selects its MIPI CSI-2 or parallel register set from the sensor's I2C address at runtime instead of at build time. (`10026530c `__, `f6acf14ec `__, `5f0251c74 `__) - ``ImageIO`` playback pacing now services pending events while waiting for the inter-frame interval instead of sleeping in ``WFI``. (`a54790193 `__) - **MicroPython submodule updates** — full networking support on the QEMU port, ``machine.mem_backup`` on STM32 via backup SRAM/BKP registers, SDIO hardware flow control kept disabled on STM32F4, and MPU attribute reuse for non-cacheable regions. (`31ada5626 `__, `ab61d27a6 `__, `06bddf13a `__) - ``differential-translation.py`` captures through its :class:`csi.CSI` object instead of the deprecated ``sensor`` module, and example import spacing was normalized. (`68c866e7f `__, `9ceff4513 `__) Bug fixes --------- Camera and sensors: - Setting two custom ``(w, h)`` resolutions in a row left the sensor at the first size while :meth:`csi.CSI.width` / :meth:`~csi.CSI.height` reported the second; the "no change" fast path now excludes custom sizes. (`cfbb70156 `__) - :meth:`csi.CSI.lens_correction` parsed ``radi`` and ``coef`` as booleans, so the values passed to the driver were not the ones given. (`ab44b3a77 `__) - PAG7936: setting exposure and gain back-to-back clobbered each other (both share one manual mode and the read-back registers lag a frame); the driver now seeds the manual registers only when entering manual mode and writes just the control being set. (`e7a18c0a0 `__) - PAG7936 and PS5520 BAYER capture on the OpenMV N6 failed with "Failed to initialize the CSI interface" at any size other than full resolution, because the N6 ISP cannot rescale raw Bayer. The sensors now run at a native mode matching the requested size for BAYER (PS5520: VGA, HD, SXGA-M, FHD, QHD, WQXGA2; QVGA has no native mode and is unsupported). (`fe6790055 `__, `b7622b245 `__) Image encoding and saving: - Software JPEG encoder: output-buffer overflow was always fatal because the realloc path was disabled; it now grows the buffer (by half its size at a time) when it owns it, falls back cleanly when memory runs out, and trims the result. ``jpeg_write`` / ``mjpeg_write`` no longer write the buffer out after a failed encode. (`28e1110be `__) - Hardware JPEG encoders (STM32): overflow returned a partially encoded image with the allocation size, producing truncated files with no EOI marker (e.g. a 5 MP capture at quality 100 with a blank lower half). They now report overflow, free the buffer on failure, and trim it on success. (`22ce9619c `__) - The VC8000 encoder silently produced 4:2:0 chroma for every request; non-4:2:0 subsampling now falls back to the HW codec that supports it. (`71f2be7f2 `__) - :meth:`image.Image.save` of a PNG image as ``.jpg`` wrote up to 1 MB of uninitialized heap, and of a JPEG image as ``.png`` wrote an empty file. Both now raise; an image already in the target format is still copied as-is. (`6c1fdf822 `__) - ``png_write`` now checks the compressor's return value and compresses before creating the file, so a failure no longer leaves an empty file behind. (`557f52d66 `__) Image module: - :meth:`image.Image.get_pixel` with ``rgbtuple=True`` on BAYER and YUV images wrote the converted pixel past a stack local at a caller-controlled offset. (`13f2a17b6 `__) - :meth:`gif.Gif.add_frame` dropped an unreachable Bayer/YUV conversion branch; only GRAYSCALE and RGB565 images are accepted, as the Python API already enforced. (`f20d99d96 `__) Protocol: - Registering a dynamic channel with every slot already in use caused an out-of-bounds write; the channel ID is now checked first, and the reserved channel IDs are statically asserted to fit the channel table. (`68f635d1f `__) - Dynamic channel objects survived a soft reset in root pointers, so the GC kept scanning stale heap blocks from the previous run; the table is now cleared on init. (`ef0ebb03b `__, `e23641145 `__) Ports: - i.MX RT: added the missing CAN and Encoder de-initialization on soft reset. (`7cb9d3dc2 `__) Hardware and board support -------------------------- - **OpenMV N6** — CAN is now enabled (:class:`machine.CAN`). (`294f0febd `__, `91e1c9573 `__) - **OpenMV AE3** — the ``sdcard`` SPI driver is frozen in for the microSD socket on the :doc:`AE3 Battery Shield `. (`a258f4814 `__) - **OpenMV RT1062** — ``lora-sx126x`` / ``lora-sync`` / ``lora-async`` frozen in (see New features). - **FLIR Lepton 3.1R / UW** — recognized by the Lepton driver on all Lepton-capable boards. - **PAG7936** — safe-shutdown halt, runtime interface selection, exposure/gain fix, and BAYER capture on the N6. - **PS5520** — BAYER capture on the N6 at native sizes. - **Simulator (MPS2_AN500)** — networking. - **All boards** — the ``sensor`` compatibility module is frozen into every board's manifest. .. _v5_0_1_breaking: Breaking API changes -------------------- v5.0.1 introduces **no breaking changes to the** :mod:`csi` **or** :mod:`image` **APIs**. Scripts that ran on v5.0.0 run unchanged, with the following behavior changes. .. _v5_0_1_s1: ``sensor`` module *(behavior)* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The native ``sensor`` module (``modules/py_csi.c``) was removed and replaced by a frozen Python module that implements the same API on top of :mod:`csi`. See :mod:`sensor`. *Commit:* `5e3d40631 `__ - ``import sensor`` prints ``WARNING: The sensor module is deprecated and will be removed in a future release. Please use the csi module instead.`` to the terminal. - The hidden :class:`csi.CSI` object is created on import, so a missing camera now raises at ``import sensor`` rather than at ``sensor.reset()``. - These functions now raise ``OSError`` because :mod:`csi` has no equivalent: ``get_fb()``, ``alloc_extra_fb()``, ``dealloc_extra_fb()``, ``set_auto_rotation()``, ``get_auto_rotation()``, ``disable_delays()``, ``disable_full_flush()``. (The two ``*_extra_fb`` functions already raised in v5.0.0.) Use ``csi.CSI(delays=False)`` / ``csi.CSI(fflush=False)`` for the last two. - Framesizes that :mod:`csi` does not export (``QQCIF``, ``QQSIF``, ``QQQQVGA``, ``HQQQQVGA``, ``HQQQVGA``, ``HQQVGA``, ``B64X32``, ``B64X64``, ``B128X64``, ``B128X128``, ``B160X160``, ``B320X320``, ``LCD``, ``QQVGA2``) are now ``(w, h)`` tuples passed through as custom resolutions. ``get_framesize()`` returns the tuple that was set while the camera is still at that size, so equality checks against the constants keep working. - ``ioctl()`` forwards at most four arguments after the request. - ``sleep()`` / ``shutdown()`` raise ``OSError`` on failure as before (the :mod:`csi` ``RuntimeError`` is translated). Migrate to :mod:`csi` — see the :ref:`v5.0.0 migration table `. .. _v5_0_1_s2: Frame-buffer image loading *(behavior)* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions that load an image into the frame buffer — :class:`image.Image` with ``copy_to_fb=True``, :meth:`image.Image.copy` / :meth:`image.Image.scale` and the ``to_*`` conversions with ``copy_to_fb=True``, :meth:`image.ImageIO.read`, :func:`fir.snapshot` and :func:`tof.snapshot` with ``copy_to_fb=True`` — used to push the new image to the IDE preview immediately, so anything drawn on the returned image was never seen. They now mark the frame buffer as pending and flush it, with everything drawn on it, right before the next image overwrites it — the same behavior as :meth:`csi.CSI.snapshot`. *Commits:* `87b6db5ee `__, `7b1a35c2f `__, `f773c740d `__ Loops that read a stream of images need no change and now show their drawing. A script that loads a **single** image and stops must flush it explicitly: .. code-block:: python img = image.Image("example.bmp", copy_to_fb=True) img.flush() # new: send it to the IDE preview now time.sleep_ms(1000) .. _v5_0_1_s3: ML library *(behavior)* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Only affects code that subclasses or copies the shipped post-processors. :class:`~ml.postprocessing.ultralytics.YoloV8` now transposes the model output after thresholding so surviving detections are stored one **row** per box (``bb[:, 4:]``), matching the Darknet and Edge Impulse post-processors, instead of one column per box (``bb[4:, :]``). The public ``((x, y, w, h), score)`` results are unchanged. *Commits:* `c45f99cad `__, `b5c7853f2 `__ .. _v5_0_1_s4: ``protocol`` module *(minor)* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :func:`protocol.poll` is back. v5.0.0 removed it when the protocol task moved to the timer; it returns as an explicit way to drive the task for custom transports. Nothing else changed — scripts that never called it are unaffected. *Commit:* `c00c215f9 `__ .. _v5_0_1_tooling: Build / tooling *(tooling)* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ None of this affects MicroPython scripts. ``py_image.c`` was split, with the descriptor objects (cascade, keypoints, LBP, keypoint match) moving to ``py_image_descriptor.c`` and the statistics objects (similarity, statistics, percentile, threshold, histogram) to ``py_image_stats.c``. The imlib encoder API was aligned with the rest of imlib: ``jpeg_compress`` / ``png_compress`` return ``0`` on success and ``-1`` on error, and ``jpeg_compress`` lost its ``realloc`` argument (resizing is gated on buffer ownership). ``OMV_PROTOCOL_MAX_CHANNELS`` became ``OMV_PROTOCOL_CHANNEL_MAX`` in ``omv_protocol_channel.h``, and ports now call ``py_protocol_init0()`` on init. The ``OMV_PAG7936_MIPI_CSI2`` board define is gone (the interface is selected at runtime). CI dependency bumps and an empty-release-changelog fix round it out. See the `firmware repository `__ history for fork-relevant detail. Migration checklist ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - **Still on** ``import sensor``? It works, with a warning. Move to :mod:`csi` (:ref:`v5.0.0 migration `); replace ``disable_delays`` / ``disable_full_flush`` with the ``csi.CSI()`` constructor arguments and drop ``get_fb`` / auto-rotation calls. - **Load a single image with** ``copy_to_fb=True`` **and expect to see it?** Add ``img.flush()`` after loading. - **Copied the YOLOv8 post-processor?** Index the thresholded output by row (``bb[:, 4:]``) rather than by column. - **Compare** ``csi0.framesize()`` **after setting a tuple?** It now returns :data:`csi.CUSTOM`. - Everything else: reflash and run.