Fact-checked by Grok 2 weeks ago

MicroPython

MicroPython is a lean and efficient implementation of the Python 3 programming language, designed specifically for microcontrollers and other resource-constrained environments, incorporating a small subset of the Python standard library to enable lightweight scripting on embedded hardware. Developed as an open-source project under the MIT license, MicroPython was created by Australian programmer Damien George, who launched a successful Kickstarter campaign on November 13, 2013, raising £97,803 to fund the initial development of the pyboard, a compact electronic circuit board that runs the interpreter. The project originated from George's frustration with the complexity of C programming for microcontrollers during his university studies, aiming to bring Python's high-level syntax and ease of use to embedded systems. Since its inception, MicroPython has evolved through community contributions on GitHub, achieving compatibility with Python 3.4 syntax and select features from later versions, such as async/await, while maintaining a focus on performance and minimal resource usage; as of September 2025, the latest stable release is v1.26.1. Among its notable features, MicroPython provides an interactive read-eval-print loop (REPL) with capabilities like tab completion and auto-indentation, alongside support for advanced language constructs including closures, list comprehensions, generators, and exception handling. It includes hardware-oriented modules, such as the "machine" module for low-level I/O access, and fits within tight constraints—requiring as little as 256 KB of flash memory and 16 KB of RAM—while offering fast boot times and experimental multithreading support. The interpreter runs on diverse platforms, including the original STM32F405-based pyboard (with a 168 MHz ARM Cortex-M4 processor, 1 MB flash, and 192 KB RAM), as well as ports for popular microcontrollers like ESP8266, ESP32, and Raspberry Pi RP2040, spanning architectures such as ARM, Xtensa, and x86. This versatility has made MicroPython a popular choice for Internet of Things (IoT) applications, robotics, and educational projects, emphasizing rapid prototyping without sacrificing efficiency.

History

Origins and Kickstarter Launch

MicroPython was conceived in early 2013 by Damien P. George, an Australian programmer and enthusiast then pursuing undergraduate studies at the . Motivated by the challenges of programming microcontrollers with low-level languages like C, George aimed to bring the accessibility and expressiveness of to embedded systems, enabling for and applications. On April 29, 2013, he wrote the first line of code as a private experiment to implement a streamlined version of 3 optimized for devices with severe resource constraints, specifically targeting a footprint of 256 KB for code space and 16 KB of . To accelerate development and produce affordable hardware, launched a crowdfunding campaign on on November 13, 2013, titled "Micro Python: Python for microcontrollers." The campaign's primary goal was to raise £15,000 to manufacture the Pyboard—a compact development board featuring an STM32F405 , USB connectivity, and Python's interactive REPL—while releasing the software as open-source under the . Stretch goals included adding (£40,000), Ethernet (£50,000), and wireless support (£60,000), reflecting ambitions to expand connectivity options. The effort exceeded expectations, securing £97,803 from 1,931 backers over 30 days, which funded initial production and community growth. By the campaign's start, had already built early prototypes of the Pyboard, hand-assembling two iterations of the using services from EuroCircuits, resulting in fully operational boards capable of running basic scripts. Public demonstrations were showcased in the video, illustrating practical applications such as blinking an LED with a simple for loop and controlling a servo motor via the board's GPIO pins, highlighting MicroPython's potential to simplify programming without sacrificing performance. These prototypes validated the core concept, paving the way for broader adoption.

Key Milestones and Releases

MicroPython's development gained momentum following its successful campaign launched in November 2013, which funded the creation of an open-source implementation for microcontrollers and the production of the initial pyboard hardware. The project's first official release, version 1.0, occurred on May 3, 2014, marking the debut of a lean 3 interpreter optimized for resource-constrained embedded systems, with initial support for microcontrollers through the stmhal port on the pyboard. This initial version laid the foundation for subsequent ports and enhancements, focusing primarily on ARM-based microcontrollers. Early milestones centered on expanding hardware compatibility. Version 1.3 in August 2014 provided enhancements to the stmhal port, enabling deployment on a wide range of boards. The ESP8266 port followed in November 2014 with version 1.3.7, bringing capabilities to low-cost devices and broadening the project's appeal for networked applications. By 2016, development of the port began, with official integration in May 2018 via version 1.9.4, which added support for the more powerful with dual-core processing, , and enhanced peripherals. Significant community-driven variants emerged in the late . In 2017, forked MicroPython to create CircuitPython, emphasizing ease-of-use for beginners with features like reloading and a focus on educational hardware such as SAMD-based boards. In April 2019, released an official MicroPython image for the Mindstorms kit, built on the ev3dev operating system and Pybricks runtime, allowing Python programming for education without modifying the brick's . The project continued to evolve with key hardware integrations in the 2020s. Version 1.14, released in February 2021, introduced the RP2 port for the , supporting its dual Cortex-M0+ cores, PIO state machines, and USB capabilities, which quickly became popular for custom projects. Subsequent releases added features like BLE support in 2019 (v1.12) and the mip in 2023 (v1.20.0) for easier library installation. Recent developments have emphasized advanced and portability. Version 1.23.0 in May 2024 introduced dynamic USB device support, allowing runtime configuration of USB interfaces on supported ports like and , along with new modules such as openamp for inter-processor communication, tls for secure networking, vfs for virtual file systems, and a revamped port for browser-based execution. The stable release, version 1.26.1 on September 11, 2025, included patches for native USB on , support for new MCUs like STM32N6 and -C2, and enhancements to I2C target mode. In February 2025, a presentation at highlighted MicroPython's growing role in environments, showcasing integrations for larger systems beyond traditional s.

Core Features

Python Compatibility and Portability

MicroPython implements the core syntax and semantics of 3.4, along with select features from later versions such as Python 3.5 and beyond, enabling developers to write code that is largely interchangeable with standard (). This includes full support for advanced language constructs like closures via the nonlocal keyword, list comprehensions for concise iterable creation, using yield for memory-efficient iteration, and comprehensive with try/except blocks that mirror behavior. While minor behavioral differences exist—such as context managers in not always calling __exit__ if the does not complete—these ensure reliable operation in resource-constrained environments without altering fundamental idioms. The in MicroPython provides a subset of CPython's modules, focusing on essential functionality for systems while omitting or simplifying those reliant on a full operating system. Core modules like os for basic operations and time for timing functions are included as drop-in replacements, but with reduced scope to fit constraints. For interaction, the machine module offers portable abstractions, such as machine.Pin for GPIO control, machine.I2C for inter-integrated circuit communication, and machine.[SPI](/page/SPI) for , allowing code to interface with peripherals consistently across ports without low-level specifics. A key aspect of MicroPython's design is its emphasis on code portability, achieved through a unified that compiles and runs on diverse microcontrollers without requiring operating system modifications. Developers use cross-compilation tools, such as the mpy-cross and platform-specific Makefiles, to build from a single source tree organized into ports (e.g., for , , or ), ensuring that application-level scripts remain hardware-agnostic. This contrasts with full , which assumes a hosted ; MicroPython is optimized for bare-metal execution, prioritizing real-time responsiveness and minimal over complete feature parity.

Modules and Interactive REPL

MicroPython provides a collection of built-in modules that form the core of its runtime environment, offering essential functionality for applications. These include a subset of the , adapted for resource-constrained devices, such as json for data serialization, math for mathematical operations, and time for timing and delays. This selection prioritizes implementations to minimize memory and storage usage while maintaining compatibility with common idioms. In addition to standard library modules, MicroPython includes port-specific and hardware-oriented extensions, such as uasyncio for asynchronous programming, which enables non-blocking I/O operations suitable for real-time tasks on microcontrollers. Other examples encompass bluetooth for low-energy wireless communication and machine for direct hardware control, like pin manipulation and PWM signals. These modules extend Python's capabilities to interact with the underlying hardware without requiring low-level C programming. The module loading system in MicroPython is optimized for flash-based storage, where the import mechanism searches directories in sys.path for .py files, .mpy bytecode files, or frozen modules embedded in the firmware. Frozen modules store Python source or precompiled bytecode directly in the firmware, allowing seamless imports like import mymodule while reducing runtime compilation overhead. For efficiency, .mpy files—generated via the mpy-cross cross-compiler—contain bytecode or native that loads faster from than interpreting raw Python source, conserving on devices with limited resources. Compatibility checks ensure .mpy files match the MicroPython version and architecture, raising errors like ValueError for mismatches. The interactive Read-Eval-Print Loop (REPL) serves as the primary interface for development and , accessible over USB or serial connections to the board. Upon connection, users encounter a (typically >>>) where expressions and statements can be entered and executed immediately. Key features include auto-indentation, which adds four spaces after colons in control structures like if or for and executes multiline input upon double Enter; auto-completion via to list attributes (e.g., machine.<Tab> suggests Pin); and paste mode (entered with Ctrl-E) to disable indentation for bulk code pasting, exiting with Ctrl-D. For advanced use, raw REPL mode (entered with Ctrl-A) provides low-level access without line buffering, ideal for programmatic interaction or high-speed data transfer, and exits with Ctrl-B. Programs can be interrupted with Ctrl-C, raising a KeyboardInterrupt to return to the prompt, while Ctrl-D performs a soft reset. Special commands like help('modules') list available built-in modules, aiding exploration. This setup facilitates an efficient development workflow: code is edited on a host machine using tools like text editors or , uploaded to the device's filesystem via serial tools (e.g., ampy or rshell), and executed instantly in the REPL for testing. Frozen modules or .mpy files can be pre-integrated during builds for production, streamlining deployment on flash-limited .

Performance Limitations

MicroPython operates within the severe constraints of microcontroller environments, typically requiring a minimum of 256 KB of for the firmware and 16 KB of for execution. These limits restrict the ability to handle large structures, such as extensive or dictionaries, which would exceed available space and lead to errors. Additionally, full collection is constrained in low- scenarios, where fragmentation can prevent effective reclamation, often necessitating manual calls to gc.collect() that may take several milliseconds and still yield limited results. The interpreted nature of MicroPython's bytecode execution results in significantly slower performance compared to native C code, particularly in computational tasks like hashing or , with slowdowns often ranging from tens to hundreds of times or more. For instance, benchmarks on show MicroPython up to approximately 1,900 times slower than optimized C implementations for SHA-256 hashing of 1024-byte inputs (as of 2023). While ports like those for architectures include optimizations such as the @micropython.native and @micropython.viper decorators—which compile functions to faster machine-like code—these provide only partial mitigation, achieving roughly 2x speedups with @micropython.native over pure and greater gains with @micropython.viper for integer-heavy operations, but still falling short of native efficiency. MicroPython's compatibility with standard is partial, targeting a Python 3.4 baseline with selective adoption of later features, leading to omissions in advanced language constructs. Full support for Python 3.5+ asynchronous programming, including comprehensive async/await syntax and types, is limited to a basic implementation via the uasyncio module, which lacks the depth of CPython's and for complex concurrent I/O. Threading is similarly restricted, with the _thread module providing only experimental multithreading that is not fully documented or stable, unsuitable for production use in resource-constrained settings. Furthermore, MicroPython does not include a built-in (IDE) or interactive , relying instead on external tools for code inspection and error tracing. To address these limitations, developers can employ workarounds such as via QSTRs (accessed through the micropython module's qstr_info), which reduces RAM usage by storing unique strings as indices rather than full copies, speeding up comparisons in performance-critical sections. Avoiding is another key strategy, as deep call stacks quickly exhaust limited resources; iterative alternatives using loops or explicit stacks are recommended to prevent overflows and maintain responsiveness. These techniques, combined with pre-allocation of buffers like bytearray objects, help optimize execution within the available footprint without altering the core runtime.

Language Implementation

Syntax and Semantics

MicroPython's syntax closely mirrors that of Python 3.4, incorporating selected features from later versions while maintaining core rules for readability and structure. This includes the use of significant whitespace for defining code blocks, a hallmark of Python's design philosophy. The language supports standard lexical elements such as keywords, identifiers, literals, and operators, ensuring that most valid Python 3 code parses correctly in MicroPython, subject to resource constraints. Code blocks in MicroPython are delimited by indentation rather than braces, following Python conventions. Statements that introduce a block—such as if, for, while, function definitions with def, and exception handlers—end with a colon (:), after which the subsequent lines must use consistent indentation, typically four spaces. Inconsistent indentation raises an IndentationError. For example, a simple function definition demonstrates this:
def greet(name):
    print("Hello, " + name)
    if name == "world":
        print("!")
    else:
        print(".")
This structure enforces clear hierarchy without explicit delimiters. MicroPython supports the full suite of Python operators for , , logical operations, and more. Arithmetic operators include addition (+), subtraction (-), multiplication (*), true division (/), floor division (//), and modulo (%). operators are ==, !=, <, >, <=, and >=, while logical operators are and, or, and not. Floor division (//) always truncates toward negative infinity, consistent with Python 3 semantics; for instance, 5 // 2 yields 2, and -5 // 2 yields -3. An example combining these:
a = 10
b = 3
result = (a + b) * 2 // (a - b)  # Evaluates to 9
if result > 5 and b != 0:
    [print](/page/Print)("Condition met")
These operations behave identically to Python 3 unless constrained by limits. Control structures in MicroPython enable conditional execution and iteration, aligning with Python 3 . The if statement evaluates a and executes the block if true, optionally followed by elif for additional checks and else for the fallback:
x = 7
if x < 5:
    print("Small")
elif x < 10:
    print("Medium")
else:
    print("Large")
Loops include for, which iterates over iterables like ranges or lists:
for i in range(3):
    print(i)  # Outputs: 0 1 2
The while loop continues as long as the condition holds:
count = 0
while count < 3:
    print(count)
    count += 1  # Outputs: 0 1 2
Exception handling uses try, except, else, and finally: the try block attempts code, except catches specified exceptions, else runs if no exception occurs, and finally executes regardless:
try:
    value = 10 / 0
except ZeroDivisionError:
    print("Division by zero")
else:
    print("Success")
finally:
    print("Cleanup")
These structures support breaking flow with break, continue, and return. Semantically, MicroPython diverges from full Python 3 in resource-constrained environments, omitting advanced features like metaclasses, which are not implemented to preserve memory and simplicity. Dynamic introspection is limited; for example, locals() excludes local variables for optimization, treating them as fixed array slots, and eval() operates without local scope access. Integers (int) provide arbitrary precision, matching Python 3's unbounded nature, but practical size is capped by available RAM, typically 16-512 KB on microcontrollers, preventing excessively large computations.

Bytecode and Compilation

MicroPython compiles source code files (with a .py extension) into using a cross-compiler known as mpy-cross, which runs on the host machine to generate portable .mpy files containing the precompiled . This process allows modules to be imported directly on the target device without requiring , thereby reducing usage during execution. For efficiency on resource-constrained hardware, can also be "frozen" directly into the binary during the build process, enabling boot-time loading from without additional steps. The format in MicroPython consists of a sequence of opcodes designed for -based execution, where operands are pushed and popped from an evaluation to perform operations. This format is stored in a compact .mpy that includes metadata such as the version, file name, and the itself, optimized for minimal on systems. To further reduce memory overhead, the employs optimizations like pooling, where repeated literals are substituted with references to a shared pool using the built-in const() function, avoiding redundant storage of immutable values such as numbers or strings. During execution, the MicroPython virtual machine (VM) interprets the bytecode instructions sequentially, managing a for temporary values and the for object allocation. The VM supports inline caching mechanisms within the interpreter to accelerate attribute lookups and calls by storing recent resolution results directly in the bytecode stream, improving on repeated operations without full recompilation. For performance-critical code, MicroPython provides decorators such as @micropython.native and @micropython.viper to generate optimized native ahead-of-time for supported architectures including , Thumb, Xtensa, , x86, and x64, as improved in v1.26 (August 2025). The core implementation relies on interpretation across all ports. Decompiling .mpy files to recover readable is challenging due to the format, but tools like the official mpy-tool.py script from the MicroPython repository can parse and dump the opcodes for analysis or . Specialized efforts, such as those presented in security research, have developed custom reconstructors to extract data structures and from frozen modules, though no standard tool like uncompyle6 (designed for ) fully supports MicroPython's variant without modification.

Libraries and Extensions

MicroPython includes a subset of the standard library, adapted for resource-constrained environments, providing essential functionality for systems programming. Core modules such as builtins offer fundamental types and exceptions, while sys enables access to system-specific parameters like manipulation and information. These libraries form the foundation for basic script execution and runtime introspection. For operations, MicroPython provides io for handling and file-like objects, and os for basic filesystem interactions such as listing and removal, though limited by the underlying hardware's capabilities. Data processing is supported through modules like json for encoding and decoding data, and urllib for simple URL fetching and HTTP requests, facilitating network-enabled applications without full overhead. Hardware interfacing libraries include machine.Pin for GPIO control, allowing pin configuration as inputs or outputs with callbacks, and network for or Ethernet setup and operations on supported ports. Custom extensions enhance MicroPython's capabilities beyond the standard set, either as pure Python modules or compiled C modules for performance-critical tasks. Pure Python libraries can be written and imported like standard modules, offering portability across ports, while C extensions are compiled into the firmware using build tools like Make or , integrating directly via user-defined modules with functions and classes exposed to Python. For instance, the ujson module provides an optimized JSON implementation in C, offering faster parsing and serialization compared to the pure Python json alternative, suitable for high-throughput data handling in embedded scenarios. Port-specific libraries address hardware-unique features. On ESP32 ports, the esp32 module includes functions for low-power modes, such as configuring deep sleep wake sources via wake_on_ext0 for external pin triggers or gpio_deep_sleep_hold to retain GPIO states during sleep, optimizing battery life in IoT devices. For RP2040-based boards like the Raspberry Pi Pico, the rp2 module exposes the Programmable I/O (PIO) subsystem through classes like StateMachine, allowing custom assembly programs for high-speed peripherals via the @rp2.asm_pio decorator, enabling efficient protocol implementations without CPU intervention. Unlike full , MicroPython lacks a built-in like , so libraries are distributed as source .py files, pre-compiled .mpy bytecode files for faster loading and smaller size, or frozen into firmware during build. Custom or third-party libraries are manually uploaded to the device's filesystem using tools such as ampy for command-line over /USB or rshell for interactive access and bulk operations, ensuring compatibility with the target port's constraints.

Hardware Support

Supported Architectures and Ports

MicroPython primarily targets resource-constrained microcontrollers but also includes ports for desktop simulation. The core supported architectures encompass the ARM Cortex-M series, Xtensa processors, RISC-V, and x86 for development environments. These ports enable deployment on a diverse array of 32-bit hardware, from low-end designs to systems with integrated wireless capabilities. The ARM Cortex-M architecture forms the backbone of many MicroPython ports, supporting variants like Cortex-M0, M0+, M3, M4, M7, and M33. Notable implementations include the STM32 family from STMicroelectronics, which powers various development boards; the RP2040 and RP2350 dual-core Cortex-M0+ and Cortex-M33 in the Raspberry Pi Pico and Pico 2 (RP2350 released 2024); the nRF51 Cortex-M0 in the BBC micro:bit for educational use; and the SAMD21 Cortex-M0+ in boards like the Arduino Zero. These ports run in bare-metal mode, directly on the hardware without an underlying operating system, and require minimal resources: typically 256 KB of flash storage and 16 KB of RAM for the core runtime, with 128 KB of RAM recommended for a functional REPL and basic scripting. RISC-V support was significantly extended in MicroPython v1.24 (October 2024), including native code generation for and ports for devices like the and RP2350 ( cores). Xtensa architecture support is provided through dedicated ports for Espressif's and microcontrollers, which integrate and . These ports leverage the Xtensa LX106 and LX6 cores, respectively, and are optimized for applications, offering built-in network modules alongside the standard MicroPython features. For testing and development, the Unix port runs on x86/x64 systems such as , macOS, and Windows (via or ), emulating microcontroller behavior with file system access and standard I/O. This port facilitates rapid prototyping without hardware. A prominent variant is CircuitPython, an education-oriented of MicroPython maintained by Adafruit, which emphasizes plug-and-play peripherals, automatic file reloading, and broader support for sensors and displays through its library ecosystem.

Execution Methods and Booting

MicroPython supports multiple methods for loading and executing code on resource-constrained devices. The primary interactive method is the Read-Eval-Print Loop (REPL), an interactive interpreter accessible via serial connection (typically USB or UART) that allows real-time input, evaluation, and printing of code. File-based scripts, stored as .py files on the device's filesystem (such as internal or ), can be executed manually using the exec(open('script.py').read()) command or automatically during boot. Frozen modules consist of pre-compiled embedded directly into the during the build process, enabling efficient execution from without runtime or filesystem dependency, which is particularly useful for devices lacking persistent storage. Code upload occurs primarily via USB using tools like mpremote for transferring files to the filesystem (e.g., mpremote cp local.py :remote.py) or executing scripts in RAM without storage (mpremote run script.py); Device Firmware Upgrade (DFU) mode, supported on certain ports, facilitates flashing and code integration during builds. The booting process commences with a or , triggering the unit (MCU) to load the from non-volatile , which handles initial initialization including clock setup and memory mapping. The then determines the boot mode and loads the MicroPython (VM), starting with the execution of a _boot.py script that mounts the filesystem. In normal boot mode, this is followed by running boot.py for custom configuration (which must complete without looping) and then main.py as the primary application script; if main.py is absent or exits cleanly, the REPL launches for interactive use. The process ensures minimal resource overhead, with bytecode for scripts compiled on-the-fly or loaded from storage to initialize the environment. MicroPython implements distinct boot modes to support standard operation, recovery, and maintenance. Normal boot mode executes the full sequence of startup scripts (boot.py and main.py) from the filesystem, enabling user-defined initialization. Safe boot mode, available on most ports, bypasses these scripts to prevent faulty code from interfering with recovery, directly entering the REPL with default settings for filesystem editing or diagnostics. Filesystem boot mode, supported on select ports, provides raw access to storage for factory resets or low-level operations, often resetting the filesystem while entering safe mode. Entry into these modes typically involves hardware-specific actions, such as holding a boot button during reset to select the mode based on timing. Error handling during execution or boot emphasizes reliability on systems. Faults, such as errors in startup scripts, may trigger visual indicators like specific LED blink patterns (e.g., three blinks for an failure on supported ) to signal issues without console output. Programmatic recovery is facilitated by the machine.reset() function, which performs a soft to restart the interpreter and VM while preserving certain state like network connections, avoiding a full . Developers are encouraged to wrap main scripts in try-except blocks to catch exceptions and return to the REPL, ensuring the system remains accessible.

Specific Devices and Boards

The Pyboard serves as the reference development board for MicroPython, featuring the STM32F405RGT6 microcontroller based on a Cortex-M4F core running at 168 MHz, with 1024 KiB of internal and 192 KiB of . It includes a micro USB connector for power and , a micro slot for storage expansion, an integrated Freescale MMA7660 for motion sensing, and four servo ports alongside RGBY LEDs for visual feedback. The board provides access to 30 (GPIO) pins, enabling versatile interfacing with external components. Beyond the Pyboard, MicroPython supports a range of other development boards with distinct hardware integrations. The port accommodates boards equipped with Espressif's Xtensa dual-core LX6 processor operating up to 240 MHz, 528 KiB of , integrated , and (BLE) capabilities, facilitating wireless connectivity in applications. The ESP32-C6 uses a single-core processor at 160 MHz, 512 KiB of , and supports and BLE. The , as found in the , utilizes a dual-core Cortex-M0+ configuration at 133 MHz (overclockable), 264 KiB of , and eight programmable I/O (PIO) state machines that allow custom peripheral emulation without dedicated hardware. The RP2350, in the 2 (released ), features dual-core Cortex-M33 or Hazard3 at up to 150 MHz, 520 KiB of , and enhanced PIO. Olimex boards, such as the ESP32-POE series and -H407 variants, extend support to Ethernet-enabled designs and power-optimized microcontrollers, often incorporating USB, displays, and interfaces for industrial and embedded use cases. Device setup on these boards begins with pin mapping through the machine.Pin class, which initializes GPIO pins by specifying an identifier ( or ) and mode, such as input (Pin.IN) or output (Pin.OUT), with options for pull-up resistors and initial values to configure hardware interfaces reliably. Analog-to-digital conversion () is handled via machine.ADC wrapped around a Pin object for reading sensor voltages, while digital-to-analog conversion (DAC) uses machine.DAC for generating analog outputs on supported pins, and (PWM) is enabled through machine.PWM on a Pin to control devices like motors and LEDs by adjusting duty cycles. For hardware expansion, MicroPython provides machine.I2C and machine.[SPI](/page/SPI) classes to interface with sensors and peripherals, supporting hardware-accelerated two-wire I2C communication (SCL and SDA lines) for multi-device buses or bit-banged software implementations, and four-wire (SCK, MOSI, , CS) for high-speed data transfer, both requiring appropriate pull-up resistors and pin assignments. These boards are designed for compatibility with breadboards, allowing GPIO pins to connect directly to prototyping setups for adding sensors like temperature or motion detectors without .
BoardMCUCore/FrequencyMemory (Flash/RAM)Key Features
Pyboard v1.1Cortex-M4F/168 MHz1024 KiB/192 KiBUSB, SD slot, , 30 GPIO
Xtensa LX6 dual-coreUp to 240 MHzExternal/528 KiB, BLE
ESP32-C6RISC-V single-core160 MHzExternal/512 KiB, BLE
(Pico) Cortex-M0+ dual133 MHz (overclockable)External/264 KiBPIO state machines
RP2350 (Pico 2) Cortex-M33 or dualUp to 150 MHzExternal/520 KiBEnhanced PIO, security features
Olimex (e.g., -POE)/ seriesVariesVariesEthernet, USB, display

Applications and Examples

Programming Examples

MicroPython provides straightforward programming interfaces for interacting with hardware peripherals, allowing developers to write concise scripts for common tasks on embedded devices. The following examples illustrate basic operations using core modules like machine, time, network, and uasyncio, demonstrating how to control GPIO pins, read analog inputs, establish network connections, and manage asynchronous tasks. These snippets are executable on supported boards such as the , , or Pyboard, with pin numbers adjusted according to the specific .

Blinking an LED

A fundamental example in MicroPython involves blinking an LED connected to a GPIO pin, which showcases digital output control using the machine.Pin class and timing with the time module. This operation toggles the pin state in a loop, turning the LED on and off at regular intervals. On boards like the , GPIO 25 is often used for an onboard LED; for other devices, connect an external LED with a current-limiting to an appropriate GPIO pin. The following code creates a Pin object in output mode, sets it high to turn the LED on, waits 500 milliseconds, sets it low to turn the LED off, and repeats indefinitely:
from machine import Pin
from time import [sleep](/page/Sleep)

led = Pin(25, Pin.OUT)  # Adjust pin number for your board

while True:
    led.[value](/page/Value)(1)  # Turn LED on
    [sleep](/page/Sleep)(0.5)
    led.[value](/page/Value)(0)  # Turn LED off
    [sleep](/page/Sleep)(0.5)
This script runs continuously until interrupted (e.g., via Ctrl+C in the REPL). The Pin.OUT mode configures the pin for output, and value(1) or value(0) sets the . For alternative toggle methods, led.toggle() can be used instead of explicit value settings, reducing length while achieving the same effect.

Reading a Sensor with ADC

MicroPython's machine.ADC class enables reading analog sensor values, such as from a , by converting continuous voltages (typically 0-3.3V) into discrete digital values (0-65535 for 16-bit resolution). A serves as a simple variable example, where rotating the knob changes the input voltage proportionally. Connect the 's middle pin to an ADC-capable GPIO (e.g., GPIO 26 on or GPIO 34 on ), with the outer pins to and 3.3V. The code below initializes the ADC on the specified pin, reads the raw value in a loop, converts it to voltage, and prints the result every second:
from machine import [ADC](/page/ADC)
from time import [sleep](/page/Sleep)

adc = [ADC](/page/ADC)(26)  # Adjust pin number for your board (must support [ADC](/page/ADC))

while True:
    raw_value = adc.read_u16()  # Read 16-bit value (0-65535)
    voltage = (raw_value / 65535) * 3.3  # Convert to volts (assuming 3.3V reference)
    print(f"Raw: {raw_value}, Voltage: {voltage:.2f}V")
    [sleep](/page/Sleep)(1)
The read_u16() method samples the input rapidly, providing a that scales linearly with the applied voltage. Division by normalizes the value, multiplied by the reference voltage (3.3V on most MicroPython ports) to obtain the actual voltage; some ports offer read_uv() for direct microvolt readings with built-in . This approach is essential for interfacing with analog like or detectors, where raw values are mapped to physical units based on sensor specifications.

WiFi Connection on ESP32

On ESP32-based boards, the network module facilitates connectivity in station mode, allowing the device to join an existing access point for . This is achieved by creating a WLAN , activating it, and providing the network credentials (SSID and password). The connection status can be verified via the isconnected() , enabling scripts to wait until associated before proceeding with network-dependent tasks like HTTP requests. The example script connects to a specified and prints the assigned upon success:
import network

wlan = network.WLAN(network.STA_IF)  # Create [station](/page/Station) interface
wlan.active(True)  # Activate the interface
wlan.connect('your_ssid', 'your_password')  # Replace with actual credentials

while not wlan.isconnected():
    pass  # Wait for [connection](/page/Connection)

print('Connected. [IP](/page/IP):', wlan.[ifconfig](/page/Ifconfig)()[0])
Replace 'your_ssid' and 'your_password' with the target details. The STA_IF constant specifies client mode, and ifconfig()[0] retrieves the IPv4 address post-connection. This setup is foundational for applications, as it enables subsequent use of sockets or higher-level protocols like urequests for data exchange. For , avoid hardcoding credentials in production; instead, use files or secure input methods.

Asynchronous Task with uasyncio

MicroPython's uasyncio library (aliased as asyncio) supports for concurrent operations without blocking the main , ideal for handling multiple interactions efficiently on resource-constrained devices. A simple example involves scheduling independent coroutines to blink two LEDs at different rates, demonstrating task creation and non-blocking sleeps. This requires boards with GPIO support, such as the Pyboard or , using pins configured via machine.Pin. The code defines an asynchronous blink function, creates tasks for two LEDs, and runs them for 10 seconds:
import asyncio
from [machine](/page/Machine) import Pin

async def blink(led, period_ms):
    while True:
        led.on()
        await asyncio.sleep_ms(5)  # Brief on-time for visibility
        led.off()
        await asyncio.sleep_ms(period_ms)

async def main():
    led1 = Pin(1, Pin.OUT)  # Adjust pins for your board
    led2 = Pin(2, Pin.OUT)
    asyncio.create_task(blink(led1, 700))  # Task 1: 700ms period
    asyncio.create_task(blink(led2, 400))  # Task 2: 400ms period
    await asyncio.sleep_ms(10000)  # Run for 10 seconds

asyncio.run(main())
The async def keyword defines coroutines, await asyncio.sleep_ms() yields control without halting other tasks, and create_task() schedules them on the event loop. asyncio.run() starts the scheduler. This scales to more complex scenarios, like simultaneous polling and communication, while maintaining low overhead compared to threading. Pins 1 and 2 are examples; on Pyboard, pyb.LED(1) and pyb.LED(2) can substitute for built-in LEDs.

Implementations and Use Cases

MicroPython finds extensive application in (IoT) projects, particularly those leveraging the for its built-in and capabilities. Weather stations are a common implementation, where boards integrate sensors such as the BME280 to monitor temperature, humidity, and atmospheric pressure, often displaying data via a local or transmitting it to remote dashboards. For smart home devices, MicroPython enables control of appliances like power outlets through , allowing local network commands or integration with cloud services for automated responses, such as adjusting lighting based on sensor inputs. Cloud integration is facilitated by libraries like umqtt.simple, enabling devices to connect to platforms such as AWS Core for secure data exchange and remote management. In education, MicroPython powers interactive learning tools, notably the , which supports projects where students program simple robots to navigate obstacles or respond to environmental inputs using the device's and GPIO pins. This platform is integrated into school curricula worldwide, with resources like Arm's lessons using MicroPython on to teach core programming concepts including loops, conditionals, and functions in an accessible, hardware-tied manner. Platforms such as further extend this by offering MicroPython-based courses on for creating wearables like pedometers or communication devices, fostering problem-solving skills among K-12 students. For embedded systems, MicroPython serves as lightweight in resource-constrained devices, including drones and wearables. In drones, such as the pyDrone based on ESP32-S3, MicroPython handles flight control, , and camera integration, allowing customizable autonomous behaviors through scripts. Wearables benefit from its efficiency, with projects creating fitness trackers or interactive badges that process motion data and LED outputs on battery-powered hardware. As of 2025, updates to MicroPython ports, including runtime-defined USB device support on , enable advanced gadget modes like or HID , simplifying deployment and in these systems. The MicroPython community thrives through open-source contributions on , with numerous open issues and pull requests reflecting active development of libraries and ports for diverse . The Unix port facilitates integration with environments, running MicroPython scripts alongside native tools for testing and simulation, as it supports standard systems including distributions for rapid prototyping without dedicated .

References

  1. [1]
    MicroPython - Python for microcontrollers
    MicroPython is a lean and efficient implementation of the Python 3 programming language that includes a small subset of the Python standard library
  2. [2]
    Micro Python: Python for microcontrollers - Kickstarter
    Nov 13, 2013 · Damien George is raising funds for Micro Python: Python for microcontrollers on Kickstarter! The Python language made lean and fast to run ...
  3. [3]
    [PDF] Google Season of Docs 2023 MicroPython Case Study
    The mentors for this season were Damien George (MicroPython creator and core developer) and Matt Trentini (MicroPython community member and contributor) ...
  4. [4]
    Interview With [Damien George], Creator Of The Micro Python Project
    Nov 27, 2013 · Damien George just created Micro Python (Kickstarter alert!), a lean and fast implementation of the Python scripting language that is optimized to run on a ...
  5. [5]
  6. [6]
    Happy 6th Birthday MicroPython! @micropython #micropython
    Apr 29, 2019 · Here are some important milestone dates we checked with the creator, Damien! 29th April 2013: first line of code written (in private, before ...
  7. [7]
    [PDF] MicroPython: a journey from Kickstarter to Space - Damien P. George
    MicroPython: a journey from Kickstarter to Space. Damien P. George ... Motivation for MicroPython. Electronics circuits ... ▷ 30th April 2013: start! ▷ 17th ...
  8. [8]
    [PDF] MicroPython on Kickstarter
    Kickstarter Launch at 13 November 2013 with funding goal 15 000. GBP ... Damien George was added to the Python Software Fellow roster in 3rd Quarter 2017.
  9. [9]
    MicroPython differences from CPython — MicroPython latest documentation
    ### Summary of MicroPython Implementation and Differences from CPython
  10. [10]
    Core language — MicroPython latest documentation
    MicroPython language and implementation · MicroPython differences from CPython · Python 3.5 · Python 3.6 · Python 3.7 · Python 3.8 · Python 3.9 · Python 3.10 ...
  11. [11]
    MicroPython libraries — MicroPython latest documentation
    This chapter describes modules (function and class libraries) which are built into MicroPython. This documentation in general aspires to describe all modules ...
  12. [12]
    machine — functions related to the hardware — MicroPython latest documentation
    ### Summary of `machine.reset()`, Soft Reset, and Boot-Related Functions in MicroPython
  13. [13]
    Porting MicroPython — MicroPython latest documentation
    ### Summary of Code Portability and Cross-Compilation in MicroPython
  14. [14]
    MicroPython .mpy files — MicroPython latest documentation
    MicroPython .mpy files are a binary container format with code objects (bytecode and native machine code) stored internally in a nested hierarchy. The code for ...
  15. [15]
    MicroPython on microcontrollers
    There are two ways to achieve this: frozen modules and frozen bytecode. Frozen modules store the Python source with the firmware. Frozen bytecode uses the ...
  16. [16]
    The MicroPython Interactive Interpreter Mode (aka REPL)
    The MicroPython REPL is an interactive prompt (read-eval-print-loop) with auto-indent, auto-completion, and the ability to interrupt programs with Ctrl-C.
  17. [17]
    Maximising MicroPython speed
    Generators are not supported. If raise is used an argument must be supplied. The background scheduler (see micropython.schedule ) ...
  18. [18]
    MicroPython differences from CPython
    MicroPython implements Python 3.4 and some select features of Python 3.5 and above. The sections below describe the current status of these features.Core language · Syntax · Python 3.10 · Builtin types
  19. [19]
    asyncio — asynchronous I/O scheduler - MicroPython documentation
    Tasks can be waited on using await task , which will wait for the task to complete and return the return value of the task. Tasks should not be created directly ...Missing: uasyncio | Show results with:uasyncio
  20. [20]
    _thread – multithreading support — MicroPython latest documentation
    This module implements multithreading support. This module is highly experimental and its API is not yet fully settled and not yet described in this ...
  21. [21]
    qstr - MicroPython string interning
    In MicroPython, a QSTR (uniQue STRing) is an interned string that saves RAM/ROM by avoiding duplicate copies. It's an index into a linked list of QSTR pools.
  22. [22]
    MicroPython language and implementation
    The MicroPython differences from CPython chapter describes differences between MicroPython and CPython (which mostly concern standard library and types, but ...MicroPython on microcontrollers · The MicroPython Interactive... · Glossary
  23. [23]
    Syntax — MicroPython latest documentation
    ### Summary of MicroPython Syntax and Semantics
  24. [24]
  25. [25]
    Loops | Arduino Documentation
    Dec 18, 2024 · In MicroPython, loops help you perform repetitive tasks efficiently and are an awesome tool to keep in your coder's toolbox. In this guide, we ...
  26. [26]
    metaclass · Issue #6094 · micropython/micropython - GitHub
    May 30, 2020 · metaclasses are not really a user-facing feature but rather useful to implement things that are user facing.
  27. [27]
  28. [28]
    Optimizations — MicroPython latest documentation
    MicroPython optimizes by using frozen bytecode, local variable stack, and const variables to save RAM and ensure efficient execution.Missing: pooling | Show results with:pooling
  29. [29]
    Register-based virtual machine? · Issue #2790 - GitHub
    Jan 14, 2017 · A register-based bytecode would probably be faster, and possibly be more compact, than MicroPython's current stack-based approach. The ...
  30. [30]
    Cache Optimisations in MicroPython - YouTube
    Oct 26, 2021 · Damien George discusses recent improvements to cache optimisations in MicroPython. Presented at the September Melbourne MicroPython Meetup: ...Missing: inline VM
  31. [31]
    os – basic “operating system” services - MicroPython documentation
    The os module contains functions for filesystem access and mounting, terminal redirection and duplication, and the uname and urandom functions.
  32. [32]
    MicroPython external C modules
    When developing modules for use with MicroPython you may find you run into limitations with the Python environment, often due to an inability to access certain ...Missing: performance | Show results with:performance
  33. [33]
    functionality specific to the ESP32 - MicroPython documentation
    Returns information about running ESP-IDF/FreeRTOS tasks, which include MicroPython threads. ... The value passed in must support the buffer protocol, e.g. bytes, ...
  34. [34]
    rp2: RP2040 Specific Functionality - MicroPython Docs
    The rp2 module contains functions and classes specific to the RP2040, as used in the Raspberry Pi Pico. See the RP2040 Python datasheet for more information.Class StateMachine – access... · Class DMA – access to the...
  35. [35]
  36. [36]
    dhylands/rshell: Remote Shell for MicroPython - GitHub
    A simple shell which runs on the host and uses MicroPython's raw-REPL to send python snippets to the pyboard in order to get filesystem information.Missing: ampy | Show results with:ampy
  37. [37]
    Overview — MicroPython latest documentation
    **Summary of MicroPython Documentation (https://docs.micropython.org/en/latest/):**
  38. [38]
    General information about the SAMD port — MicroPython latest ...
    Architecture: ARM Cortex M4 · CPU frequency: up to 120MHz · Total RAM available: up to 256 kB · Internal FlashROM: up to 1 MB Some boards provide additional ...
  39. [39]
    MicroPython - Raspberry Pi Documentation
    The official documentation around the RP2040 port of MicroPython. RP2 Library. The official documentation about the rp2 module in MicroPython. Which hardware am ...Missing: 2021 | Show results with:2021
  40. [40]
    Tutorials - BBC micro:bit MicroPython documentation
    The version of Python that runs on the BBC micro:bit is called MicroPython. This documentation includes lessons for teachers and API documentation for ...
  41. [41]
    Quick reference for the UNIX and Windows ports
    If MICROPYPATH is not defined, the search path will be ~/.micropython/lib:/usr/lib/micropython ( ~/.micropython/lib for Windows port) or the value of the ...<|control11|><|separator|>
  42. [42]
    CircuitPython
    CircuitPython is a programming language designed to simplify experimenting and learning to code on low-cost microcontroller boards.CircuitPython · Awesome CircuitPython · Downloads · Libraries
  43. [43]
    Reset and Boot Sequence — MicroPython latest documentation
    Reset and Boot Sequence . A device running MicroPython follows a particular boot sequence to start up and initialise itself after a reset.Missing: methods | Show results with:methods
  44. [44]
    MicroPython manifest files
    MicroPython has a feature that allows Python code to be “frozen” into the firmware, as an alternative to loading code from the filesystem. This has the ...
  45. [45]
    MicroPython remote control: mpremote
    The mpremote command line tool provides an integrated set of utilities to remotely interact with, manage the filesystem on, and automate a MicroPython device ...Missing: IDE | Show results with:IDE<|control11|><|separator|>
  46. [46]
    General information about the pyboard - MicroPython documentation
    Boot modes​​ If you power up normally, or press the reset button, the pyboard will boot into standard mode: the boot.py file will be executed first, then the USB ...Missing: methods process
  47. [47]
    6. Reset and boot modes — MicroPython latest documentation
    The first thing to try is to boot in safe mode: this temporarily skips execution of boot.py and main.py and gives default WLAN settings. If you have ...Missing: methods | Show results with:methods
  48. [48]
    MicroPython - Python for microcontrollers
    ### MicroPython Pyboard Feature Table
  49. [49]
    The pyboard hardware — MicroPython latest documentation
    Datasheets for the components on the pyboard · The microcontroller: STM32F405RGT6 (link to manufacturer's site) · The accelerometer: Freescale MMA7660 (800kiB ...
  50. [50]
    General information about the ESP32 port — MicroPython latest ...
    MicroPython tries to provide a generic port which would run on as many boards/modules as possible, but there may be limitations.Missing: history RP2040
  51. [51]
    General information about the RP2xxx port — MicroPython latest ...
    The RP2040 microcontroller is manufactured on a 40 nm silicon process in a 7x7mm QFN-56 SMD package. The key features include: 133 MHz dual ARM Cortex-M0+ cores ...Missing: 2021 | Show results with:2021
  52. [52]
    MicroPython - Python for microcontrollers
    ### Olimex Boards Supported by MicroPython and Hardware Highlights
  53. [53]
    class Pin – control I/O pins — MicroPython latest documentation
    The pin class has methods to set the mode of the pin (IN, OUT, etc) and methods to get and set the digital logic level. For analog control of a pin, see the ADC ...Missing: PWM | Show results with:PWM
  54. [54]
    class I2C – a two-wire serial protocol - MicroPython documentation
    I2C is a two-wire protocol for communicating between devices. At the physical level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.Missing: SPI | Show results with:SPI
  55. [55]
  56. [56]
    class ADC – analog to digital conversion - MicroPython documentation
    The ADC class provides an interface to analog-to-digital converters, and represents a single endpoint that can sample a continuous voltage and convert it to a ...
  57. [57]
    class WLAN – control built-in WiFi interfaces — MicroPython latest ...
    Create a WLAN network interface object. Supported interfaces are network.WLAN.IF_STA (station aka client, connects to upstream WiFi access points) and network. ...
  58. [58]
    MicroPython: ESP32/ESP8266 BME280 Web Server (Weather Station)
    Build a BME280 sensor web server with the ESP32 and ESP8266 NodeMCU to display temperature, humidity, and pressure readings using MicroPython firmware.
  59. [59]
    MicroPython: Controlling Smart Power Outlets using an ESP32
    Using this tutorial, you'll be able to control locally (LAN) most of the low-cost smart power outlets using an ESP32 programmed in MicroPython.Missing: integration | Show results with:integration
  60. [60]
    Using MicroPython to get started with AWS IoT Core
    Apr 25, 2023 · This blog walks you through how to configure an ESP32 based microcontroller to connect to AWS IoT Core using MicroPython.Using Micropython To Get... · Walkthrough · Prerequisites
  61. [61]
    Micro:bit Educational Foundation | micro:bit
    Free online micro:bit courses for teachers ... We help you pick the programming tool that's right for you, from block coding to text-based programming with Python ...Let's code · Get started · Projects · Teach
  62. [62]
    Introduction to Programming Using micro:python – Arm®
    Learn about all programming techniques in the English GCSE Computer Science curriculum using micro:python to program a micro:bit.
  63. [63]
    micro:bit Programming Course - Tynker.com
    Program micro:bit using MicroPython to create pedometers, wearable bracelets, and 2-way communication radios. Tynker gets kids coding with confidence.
  64. [64]
    pyDrone - An ESP32-S3 drone running MicroPython firmware
    Jul 2, 2025 · 01Studio's pyDrone is a little different as it's based on an ESP32-S3-WROOM-1 module and runs MicroPython firmware instead of the ESP32-Drone firmware.
  65. [65]
    Five Wearable Projects with micro:bit - SparkFun Education Blog
    Apr 26, 2018 · Here are a few projects we've found that use the micro : bit for costumes, fitness tracking, and more.
  66. [66]
  67. [67]
    Getting Started — MicroPython latest documentation
    This guide covers a step-by-step process on setting up version control, obtaining and building a copy of the source code for a port, building the documentation ...Missing: microcontrollers | Show results with:microcontrollers