v3.9.0

v3.9.0 is a major release. It adds the nRF port with the Arduino Nano 33 BLE Sense (camera, PDM audio module, ulab, frozen sensor drivers), brings FLIR Lepton plus MLX90641 / MLX90621 thermal sensors and a heavily reworked fir module, OV5640 autofocus ioctls, and the new image.ImageIO streaming type. The legacy CMSIS-NN nn module and the old ImageReader / ImageWriter classes were removed — read the breaking changes below.

Highlights

  • Arduino Nano 33 BLE Sense — new nRF52840 port with camera, a PDM audio module, ulab, and frozen sensor drivers.

  • Thermal — FLIR Lepton, MLX90641, and MLX90621 support with a reworked fir module (palettes, mirroring, scaling, radiometry, FFC).

  • OV5640 autofocus — new sensor.IOCTL_*_AUTO_FOCUS ioctls.

  • image.ImageIO — a unified image stream type (memory or file; read/write/seek/size/close) replacing ImageReader / ImageWriter.

  • Breaking: the CMSIS-NN nn module and image.ImageReader / image.ImageWriter were removed, and find_lines() / fir behavior changed — see the breaking changes.

New features

  • nRF port / Arduino Nano 33 BLE Sense — new nRF52840 port and board support, with a new audio module (audio.init(), audio.start_streaming(), audio.stop_streaming()), ulab enabled, and frozen apds9960 / lps22h / lsm9ds1 / hts221 sensor drivers.

  • image.ImageIO — a new image-stream type supporting both memory and file streams with read() / write() / seek() / size() / close(), plus ImageIO read/write/memory examples.

  • FLIR Lepton — added FIR_LEPTON support with fir.radiometric(), fir.trigger_ffc(), and fir.register_vsync_cb().

  • Thermal sensors — added MLX90641 (FIR_MLX90641) and MLX90621 thermopile support (official Melexis drivers).

  • fir palettes / orientation — added fir.PALETTE_RAINBOW / PALETTE_IRONBOW / GRAYSCALE / RGB565 constants, and fir.read_ir() now accepts hmirror / vflip / transpose.

  • OV5640 autofocus — added sensor.IOCTL_TRIGGER_AUTO_FOCUS / IOCTL_PAUSE_AUTO_FOCUS / IOCTL_RESET_AUTO_FOCUS / IOCTL_WAIT_ON_AUTO_FOCUS (OpenMV 2/3/4/4 Plus/PT/Portenta).

  • Reorganized the Arduino examples into per-board directories.

Other changes and improvements

  • Switched to compressed MicroPython error messages (shorter exception strings); fir.init()’s type argument now auto-detects via an I2C bus scan when omitted; the xalloc exception now reports the number of bytes requested; UART 8 was enabled on the Portenta; FIR examples were consolidated into thermal_camera.py / thermal_overlay.py / thermal_overlay_lcd.py. To fit flash, image.get_similarity() and selective search were disabled on the OpenMV 4 build, and the image library can now be built without a filesystem (for filesystem-less boards).

Bug fixes

Camera and sensors:

  • Fixed the OV5640 PCLK calculation, added missing I2C IRQ handlers (fixing I2C transfer hangs), reworked the cambus I2C read/write for reliability, made the Lepton I2C bus selectable, moved cambus bus-recovery pins to per-board config, retry the cambus scan once before failing, and got the OpenMV PT (Lepton + camera shared I2C) working.

Thermal:

  • Fixed the max-value computation in fir get_ir() / draw_ir() and image.get_similarity() (FLT_MIN-FLT_MAX), AMG8833 12→16-bit handling, and MLX90621 accuracy (official Melexis driver).

Display, audio, and system:

  • Moved STM32 SPI LCD transfers to HAL SPI callbacks (display reliability), fixed Nano 33 audio.init() (HF oscillator + PDM ratio so the microphone works), the H7 timer state with the new HAL, nRF gc_collect and early board init/deinit, and stopped printing the spurious “uh oh, no preference for overlapping detection” message during find_apriltags() / find_rects().

Hardware and board support

  • Arduino Nano 33 BLE Sense — new nRF52840 board (camera, PDM audio, ulab, frozen sensor drivers).

  • FLIR Lepton, MLX90641, and MLX90621 thermal sensors.

  • OV5640 autofocus — OpenMV 2/3/4/4 Plus/PT/Portenta.

  • Portenta — UART 8 enabled.

Breaking API changes

User-visible API breaks between v3.8.0 and v3.9.0. Scope: Python C-modules in modules/ and Python libraries in scripts/libraries/.

Each change is tagged with its impact:

  • major — affects most scripts that used the feature; you will need to port code.

  • minor — narrow API; only affects scripts that used it.

  • behavior — same API, different results; re-check tuned scripts.

Changes are grouped by impact in that order. If you just want to port your code, jump to the migration checklist at the end. Each commit hash links to its diff on GitHub.

CMSIS-NN nn module removed (major)

The CMSIS-NN nn module was removed, including nn.load(), net.forward(), net.search(), and the nn_class helper. Model inference moves to the TensorFlow Lite (tf) module. Scripts that loaded .network models with nn must be ported to tf with a TensorFlow Lite model.

Commits: fbc767b36

ImageReader / ImageWriter replaced by image.ImageIO (major)

image.ImageReader / image.ImageWriter and their next_frame() / add_frame() methods were removed and replaced with the new image.ImageIO type, which supports both memory and file streams via read() / write() / seek() / size() / close(). Code using the old reader/writer classes must be ported to image.ImageIO (see the renamed imageio_read.py / imageio_write.py examples).

Commits: 783a78754

fir.draw_ir() scale keyword removed (minor)

fir.draw_ir() was rewritten on top of the new image drawing pipeline. The scale=(min, max) keyword was removed, and hint, x_scale, y_scale, roi, and positional x/y offset arguments were added. Scripts that passed scale=(min, max) to fir.draw_ir() must drop it and use the new arguments.

Commits: 0a29103b1

find_lines() approximation (behavior)

image.find_lines() now approximates gradient magnitude as (abs(gx) + abs(gy)) / 2 and skips magnitudes below 126. This is faster but changes the set of detected lines and accumulator values, so re-check and re-tune threshold / theta_margin / rho_margin.

Commits: 902ae3c98

fir.snapshot() reworked (behavior)

fir.snapshot() was substantially reworked with a new keyword API (hmirror, vflip, transpose, x_scale, y_scale, x_size, y_size, scale, rgb_channel, alpha, color_palette, hint, pixformat, copy_to_fb), and the bundled examples were rewritten. The previous positional/pixformat-only behavior changed; port FIR scripts to the new keyword form (see the updated thermopile-shield examples).

Commits: 53f2248b8

fir.init() raises on failure (behavior)

fir.init() now raises (and cleanly de-inits) when the thermal sensor is not detected, instead of silently continuing. Wrap fir.init() in try / except (or ensure the sensor is connected) where you previously relied on it not raising.

Commits: 4b2f972f3

Migration checklist

For a clean port to v3.9.0 the typical work is:

  1. Port CMSIS-NN nn model inference to the TensorFlow Lite tf module (the nn removal).

  2. Replace image.ImageReader / image.ImageWriter with image.ImageIO (the ImageIO change).

  3. Drop the scale=(min, max) keyword from fir.draw_ir() and use the new arguments (the draw_ir change).

  4. Re-tune find_lines() parameters against the approximate magnitude metric (the find_lines change).

  5. Port FIR scripts to the new fir.snapshot() keyword API (the fir.snapshot change) and handle fir.init() raising on a missing sensor (the fir.init change).

All other scripts run unchanged.