MicroPython v1.26
machine.I2CTarget, the float-accuracy overhaul, native emitter wins, plus STM32N6 and ESP32-C2.
Released August 9, 2025
machine.I2CTarget — Your MCU Answers, Not Just Asks
MicroPython has supported I2C as a controller for years. v1.26 inverts the relationship:
your MicroPython board can now be an I2C device, responding to
reads and writes from another controller. Bind a bytearray as a register
file for the simple case, or hook into IRQ callbacks to implement arbitrary protocols.
buf = bytearray(16)from machine import Pin, I2CTarget # Buffer mode — an I2C register/memory device backed by a bytearray buf = bytearray(16) target = I2CTarget(0, scl=Pin(1), sda=Pin(0), addr=0x10, mem=buf) # A controller on another board can now read/write this bytearray over I2C: # i2c.writeto_mem(0x10, 0x05, b'\x42') -> buf[5] becomes 0x42 # i2c.readfrom_mem(0x10, 0x05, 1) -> b'\x42'
I2CTarget Port Support
All ports gaining machine.I2CTarget in v1.26.
Float Accuracy — repr Round-Trips for Real
Before v1.26, only ~28% of single-precision floats round-tripped correctly through
repr → float → original value. v1.26 rewrites
float printing and formatting; that number is now 98.5%. Double
precision improved from 38% to 99.8%. The same fix means floats
survive a save/load cycle through .mpy files.
Edit and run real MicroPython below. The output you see is generated by the same improved float-printing routines that ship in v1.26.
v1.26 also folds float constants at compile time: const(2 * math.pi)
now evaluates in the compiler, not at runtime. And in object representation C
(where floats are stored within the immediate object value, losing the bottom
two bits), a heuristic now reconstructs those bits to reduce the bias toward zero.
Native & Viper Emitters — Every Architecture Got a Tune-Up
The native code emitters now produce more compact loads and stores across ARM, Thumb, Xtensa, RISC-V 32, x86 and x64. Thumb v1 (RP2040) gains long jumps greater than 12 bits, allowing larger Python functions to compile native. The inline Xtensa assembler now implements most of the LX3 opcode set.
@micropython.native now compile on
RP2040 boards that previously hit branch-range limits. Inline Xtensa
(@micropython.asm_xtensa) gains addx2, subx2,
ssl, ssr, and most other LX3 opcodes — bringing the
inline assembler much closer to feature-parity with hand-written ESP32 firmware.
machine.Counter & machine.Encoder — Hardware Pulse Counting
A new esp32.PCNT class wraps the ESP32 hardware pulse-counter
peripheral, and ships with cross-port-style APIs machine.Counter
(single-channel) and machine.Encoder (quadrature). Drag the dial
below to feel how a quadrature encoder works.
Drag the dial to rotate
from machine import Pin, Encoder enc = Encoder(0, phase_a=Pin(4), phase_b=Pin(5)) while True: print(enc.value()) # signed count, sign indicates direction
Counter and Encoder classes live under
machine.* but are currently implemented only on the esp32 port
(via esp32.PCNT). The same pattern — introducing a feature on one
port and standardising it across all of them later — is exactly what v1.28 did
with machine.PWM and machine.CAN.
Python Language Tweaks
Five small core-language additions in v1.26. Pick one from the dropdown to load the example into the editor, then run it live.
STM32N6 & ESP32-C2
Two new microcontrollers added in v1.26 — one chasing high-end ML inference on the edge, the other chasing low-cost RISC-V wireless.
STM32N6
800 MHzSTMicroelectronics' new high-performance MCU with built-in machine-learning accelerators. v1.26 supports USB, XSPI memory-mapped external flash, a filesystem, basic peripherals and deep sleep.
ESP32-C2 (ESP8684)
RISC-VEspressif's small, low-cost RISC-V MCU with WiFi and BLE. MicroPython on the C2 supports a REPL, filesystem, GPIO, I2C, ADC, PWM, timers, WiFi and BLE.
Highlights
Other notable improvements in v1.26.
DTLS server support
The mbedTLS backend now handles HelloVerify and Anti Replay protection, enabling proper DTLS servers.
lwIP UDP queue
Multiple incoming UDP and raw packets can now be queued, replacing the previous single-packet buffer. More robust UDP protocols.
framebuf ROM blits
FrameBuffer.blit() now accepts read-only data, so custom fonts and
bitmaps can live in flash instead of RAM.
time module range standardised
time(), localtime() and mktime() now
cover at least 1970–2099 on every platform, regardless of the underlying
epoch.
VM avoids slice allocations
buf[a:b] = c on bytearrays/memoryviews no longer heap-allocates
the slice — works inside hard IRQs and reduces GC churn.
mpremote fs tree
New mpremote fs tree command (with -s/-h
for sizes), and df now uses no-arg vfs.mount() for a
much better mount summary.
Compressed error messages on rp2
Enabled by default, saving ~3 kB of firmware on RP2040 / RP2350 builds.
sys.implementation._thread
New attribute reports the threading model in use — either GIL or unsafe/no-GIL — so portable code can adapt.
nrf enable_irq() — breaking change
Signature is now enable_irq(state) matching all other ports.
Previously enable_irq(). Affects nrf boards only.
Zephyr v4.0.0 + new peripherals
PWM support added; UARTs gain ring-buffered IRQ-driven I/O; SoftI2C/SoftSPI
enabled; boot.py/main.py now run at startup.
WebAssembly FFI improvements
JsProxy equality, better has/get
proxying, correct self-binding for JavaScript methods, and reuse of proxy
references for stable identity on the Python side.
__all__ in star imports
from mod import * now respects a module-level
__all__. PEP 487 __set_name__ is also supported.
New Boards
10 new board definitions across 4 ports.
esp32
samd
stm32
zephyr
By the Numbers
v1.26 in numbers. esp32 grew most, driven by ESP-IDF v5.4.2 plus the new I2CTarget.