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 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 csi; the handful of behavior changes are listed under breaking API changes.
Highlights#
The
sensormodule is now a frozen Python module built oncsi. It prints a deprecation warning on import; a few functions thecsimodule cannot support now raiseOSError. See the sensor module changes.Loaded images preview like camera frames. An image placed in the frame buffer with
copy_to_fb=True(image.Image,image.ImageIO.read(),fir.snapshot(),tof.snapshot()) is flushed to the IDE — with anything drawn on it — when the next image overwrites the frame buffer, instead of immediately. See 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
protocol.poll()and six new CBOR widgets (text,lineedit,pushbutton,spinbox,radio,waveform) forprotocol.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#
YoloPro— a new post-processor for Edge Impulse YOLO Pro object-detection models, plus ayolo_pro_detector.pyexample. (f3f150ebd, ea7bbb398)protocol.poll()— run one iteration of the protocol task on demand, for custom transports that are not driven by the USB interrupt or thepoll_mstimer.protocol.init()can also be called again to re-initialize the stack. (c00c215f9, f849ffb1b)More CBOR channel widgets —
protocol.CBORChannel.add()gainstext(static string),lineedit(writable string),pushbutton(momentary action),spinbox(stepped numeric entry),radio(option group) andwaveform(1D time-series withsample_rate,seriesandtypecodearguments; assign interleaved sample bytes to stream it). (8016d29ba)csi.CUSTOM—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 —
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_AN500QEMU target now has lwIP and a user-mode NIC, withrequests,mqttandsensorfrozen in, and a networking unit test. (23546dfb1, 61d187305, 15096c3a2)OpenAI-compatible API example —
openai_compatible.pysnapshots a JPEG and posts it to a chat-completions endpoint for scene description. (79033c6aa)SX126x LoRa examples — micropython-lib’s
lora-sx126xdriver (withlora-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#
requestslibrary rewrite — chunked transfer responses are decoded, atimeoutargument (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’sheadersdict is copied (soauthno longer leaks into later requests), and the body is read in blocks into abytearray. (889f0b096)mqttimportsssllazily, 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)
ImageIOplayback pacing now services pending events while waiting for the inter-frame interval instead of sleeping inWFI. (a54790193)MicroPython submodule updates — full networking support on the QEMU port,
machine.mem_backupon 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.pycaptures through itscsi.CSIobject instead of the deprecatedsensormodule, 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 whilecsi.CSI.width()/height()reported the second; the “no change” fast path now excludes custom sizes. (cfbb70156)csi.CSI.lens_correction()parsedradiandcoefas 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_writeno 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)
image.Image.save()of a PNG image as.jpgwrote up to 1 MB of uninitialized heap, and of a JPEG image as.pngwrote an empty file. Both now raise; an image already in the target format is still copied as-is. (6c1fdf822)png_writenow 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:
image.Image.get_pixel()withrgbtuple=Trueon BAYER and YUV images wrote the converted pixel past a stack local at a caller-controlled offset. (13f2a17b6)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 (
machine.CAN). (294f0febd, 91e1c9573)OpenMV AE3 — the
sdcardSPI driver is frozen in for the microSD socket on the AE3 Battery Shield. (a258f4814)OpenMV RT1062 —
lora-sx126x/lora-sync/lora-asyncfrozen 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
sensorcompatibility module is frozen into every board’s manifest.
Breaking API changes#
v5.0.1 introduces no breaking changes to the csi or image APIs. Scripts that ran on v5.0.0 run unchanged, with the following behavior changes.
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 csi. See sensor.
Commit: 5e3d40631
import sensorprintsWARNING: The sensor module is deprecated and will be removed in a future release. Please use the csi module instead.to the terminal.The hidden
csi.CSIobject is created on import, so a missing camera now raises atimport sensorrather than atsensor.reset().These functions now raise
OSErrorbecausecsihas no equivalent:get_fb(),alloc_extra_fb(),dealloc_extra_fb(),set_auto_rotation(),get_auto_rotation(),disable_delays(),disable_full_flush(). (The two*_extra_fbfunctions already raised in v5.0.0.) Usecsi.CSI(delays=False)/csi.CSI(fflush=False)for the last two.Framesizes that
csidoes 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()raiseOSErroron failure as before (thecsiRuntimeErroris translated).
Migrate to csi — see the v5.0.0 migration table.
Frame-buffer image loading (behavior)#
Functions that load an image into the frame buffer — image.Image with copy_to_fb=True, image.Image.copy() / image.Image.scale() and the to_* conversions with copy_to_fb=True, image.ImageIO.read(), fir.snapshot() and 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 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:
img = image.Image("example.bmp", copy_to_fb=True)
img.flush() # new: send it to the IDE preview now
time.sleep_ms(1000)
ML library (behavior)#
Only affects code that subclasses or copies the shipped post-processors. 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.
protocol module (minor)#
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
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 tocsi(v5.0.0 migration); replacedisable_delays/disable_full_flushwith thecsi.CSI()constructor arguments and dropget_fb/ auto-rotation calls.Load a single image with
copy_to_fb=Trueand expect to see it? Addimg.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 returnscsi.CUSTOM.Everything else: reflash and run.