v3.3.0

v3.3.0 is a huge release. It adds full FLIR Lepton thermal-camera support with a new sensor.ioctl() interface and color palettes, a tv SPI video-output module, global-shutter triggered mode, a big batch of new image drawing/analysis methods (gamma_corr(), draw_ellipse(), draw_edges(), many blob properties), and new ToF / motor / linalg libraries. The cpufreq API was reworked and sensor.set_framesize() now raises — read the breaking changes below.

Highlights

  • FLIR Lepton — full thermal-camera support via the new sensor.ioctl() interface, color palettes, and image.to_rainbow().

  • tv module — SPI TV / composite video output.

  • Global-shutter triggered mode — MT9V034 triggered capture via sensor.ioctl().

  • Imaginggamma_corr(), draw_ellipse(), draw_edges(), draw_image() alpha blending, and many new blob properties.

  • New libraries — VL53L1X ToF distance, TB6612 motor driver, micro-linalg.

  • Breaking: the cpufreq API was reworked, sensor.set_framesize() now raises on failure, sensor.alloc_extra_fb() dropped Bayer/JPEG, and image.replace() positional args shifted — see the breaking changes.

New features

  • FLIR Lepton — added sensor.ioctl() for sensor-specific control and a full set of Lepton ioctls (radiometry, refresh/resolution, run-command, set/get attribute, FPA/AUX temperature in °C, measurement mode/range, width/height), sensor.set_color_palette() / sensor.get_color_palette() with sensor.PALETTE_RAINBOW / PALETTE_IRONBOW, image.to_rainbow(), and Lepton example scripts (27-Lepton).

  • Triggered modeIOCTL_SET_TRIGGERED_MODE / IOCTL_GET_TRIGGERED_MODE for MT9V034 global-shutter triggered capture, with high-FPS and triggered-mode examples.

  • tv module — added SPI TV / composite video output bindings.

  • Imaging — added image.gamma_corr(), image.draw_ellipse(), image.draw_edges(), draw_image() alpha blending, a mask= keyword on clear(), re-added mask_rectangle() / mask_circle() / mask_ellipse(), rotation / hmirror / vflip keywords on draw_string() / draw_text(), a transpose keyword (and assign / set aliases) on replace(), copy() x_scale / y_scale plus crop() / scale(), an Image() constructor from dimensions, the sensor.BINARY pixformat, exported color-space conversion functions, and many new blob properties (corners, perimeter, roundness, elongation, extent, compactness, solidity, convexity, enclosing_circle, enclosed_ellipse, rotation).

  • Libraries — added the vl53l1x ToF distance-sensor driver, the tb6612 motor driver (with DC-motor and stepper Motor-Shield examples), and a micro-linalg library (ulinalg / umatrix).

  • Upgraded FatFS to FF13C (exFAT-capable).

Other changes and improvements

  • Improved the default JPEG quality (mid-range of low–high instead of a hardcoded value); in-place image ops no longer require repeating the image as the first argument; draw_string() accepts non-integer scale values.

Bug fixes

Camera and sensors:

  • Fixed Lepton 3.5 startup hang (timeout + recovery) and reset reliability, MT9V034 set_framesize() before set_pixformat() (call order no longer matters), MT9V034 WVGA on the STM32H7, the MT9V034 auto-exposure range and shadow-register updates, and the H7 ADC bug.

Imaging:

  • Fixed an invalid memory access in find_apriltags(), copy() when copying a scaled image to the main framebuffer, to_grayscale() / to_rgb565() framebuffer allocation, the keypoint object len(), JPEG MCU boundary handling, binary() threshold-list parsing, and draw_keypoints() accepting keypoint tuples.

System:

  • Fixed fb_alloc mark/free imbalance leaks across image / fir / lcd / tv / nn methods, made py_assert free framebuffer memory on caught exceptions (#417), cleared the UART overrun (ORE) flag so overruns no longer wedge UART reads, fixed the RTC IRQ handler, and fixed the Windows cascade_convert.py tool.

Hardware and board support

  • FLIR Lepton thermal camera.

  • TV shield — SPI TV / composite video output.

  • Global-shutter (MT9V034) triggered mode.

Breaking API changes

User-visible API breaks between v3.2.0 and v3.3.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.

cpufreq API reworked (major)

The cpufreq module was reworked for H7 support. The cpufreq.CPUFREQ_120MHZ / 144 / 168 / 192 / 216MHZ constants and cpufreq.get_frequency() were removed. cpufreq.set_frequency() now takes a plain MHz integer (e.g. cpufreq.set_frequency(120)), and cpufreq.get_current_frequencies() / cpufreq.get_supported_frequencies() were added.

Commits: 6babf84a1

image.replace() positional arguments shifted (minor)

image.replace() gained a transpose argument, shifting the positional mask argument from position 4 to position 5. Code that passed mask positionally (e.g. img.replace(src, hmirror, vflip, mask)) must switch to the keyword form img.replace(src, mask=mask).

Commits: dbe7bf059

sensor.alloc_extra_fb() no longer accepts Bayer/JPEG (minor)

sensor.alloc_extra_fb() no longer accepts sensor.BAYER or sensor.JPEG (it now also supports sensor.BINARY). Code that allocated extra framebuffers in Bayer or JPEG format must use GRAYSCALE / RGB565 (or allocate the buffer another way).

Commits: f9e6b3fe0

sensor.set_framesize() raises on failure (behavior)

sensor.set_framesize() now raises a ValueError when the framesize is unsupported instead of returning False. Code that checked the False return value must catch the ValueError exception instead.

Commits: b0442633e

Migration checklist

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

  1. Port cpufreq code to integer-MHz set_frequency() and get_current_frequencies() / get_supported_frequencies() (the cpufreq rework).

  2. Pass mask to image.replace() as a keyword (the replace change).

  3. Allocate extra framebuffers as GRAYSCALE / RGB565 instead of Bayer/JPEG (the alloc_extra_fb change).

  4. Catch ValueError around sensor.set_framesize() instead of checking for False (the set_framesize change).

All other scripts run unchanged.