MicroPython Programming Quick Reference Cheat Sheet

micropython cheat sheets

MicroPython Programming Quick Reference

MicroPython Platform and Compatibility

MicroPython is a compact implementation of Python 3 designed for microcontrollers and other resource-constrained systems. It provides Python syntax, built-in data types, exception handling, modules and hardware-control interfaces.

MicroPython is not identical to desktop CPython. Some standard-library modules are absent, reduced or replaced with embedded-specific equivalents.

Platform Typical MicroPython support
Raspberry Pi Pico / Pico W RP2040 port
Raspberry Pi Pico 2 / Pico 2 W RP2350 port
ESP32 ESP32-family port
ESP8266 ESP8266 port
STM32 Selected STM32 boards
Other microcontrollers Depends on available ports and firmware builds

The availability of GPIO, ADC, PWM, networking, Bluetooth, timers and other peripherals depends on the selected microcontroller, firmware build and board.

Hardware examples in this reference use the standard machine API. Pin numbers are illustrative and must be checked against the actual board.

Program Files and Execution

MicroPython commonly uses two startup files.

File Purpose
boot.py Early board configuration
main.py Main application executed after startup
Other .py files Imported modules and application code

On ports using this startup convention, boot.py runs before main.py.

Avoid placing long-running loops or unnecessary delays in boot.py, as these can make recovery and interactive access more difficult.

Basic programme

print("MicroPython running")counter = 0while counter < 5:    print(counter)    counter += 1

Interactive REPL

The Read-Evaluate-Print Loop allows Python statements to be entered directly.

>>> 2 + 35>>> import sys>>> sys.platform

The result of sys.platform identifies the running MicroPython port.

Common REPL controls include:

Control Typical action
Ctrl+C Interrupt a running programme
Ctrl+D Soft reset in the normal REPL
Ctrl+E Enter paste mode on supported REPLs
Ctrl+B Return from raw REPL mode

Terminal software may intercept some key combinations.

Python Syntax Reference

Variables and data types

count = 10voltage = 3.3enabled = Truename = "Sensor"values = [10, 20, 30]settings = {"interval": 1000}
Type Example Purpose
int 42 Integer
float 3.14 Floating-point number
bool True Boolean
str “Hello” Text
bytes b”\x01\x02″ Immutable byte sequence
bytearray bytearray(8) Mutable byte buffer
list [1, 2, 3] Mutable sequence
tuple (1, 2) Immutable sequence
dict {“x”: 1} Key-value mapping
set {1, 2, 3} Collection of unique values

Integer representation and floating-point precision vary by MicroPython build and architecture.

Conditions

temperature = 28if temperature > 30:    print("High")elif temperature < 10:    print("Low")else:    print("Normal")

Loops

for index in range(5):    print(index)count = 0while count < 10:    count += 1

Functions

def calculate_voltage(raw, reference, maximum):    return raw * reference / maximumvoltage = calculate_voltage(2048, 3.3, 4095)

Exception handling

try:    value = int("123")except ValueError:    print("Invalid number")finally:    print("Finished")

Use specific exception classes where possible rather than catching every exception.

Common Built-in Functions

Function Purpose
print() Display output
len() Return collection length
range() Generate integer sequence
int() Convert to integer
float() Convert to floating-point
str() Convert to string
bytes() Create immutable bytes
bytearray() Create mutable byte buffer
type() Return object type
isinstance() Check object type
enumerate() Iterate with index
zip() Combine iterables
min() / max() Find minimum or maximum
sum() Sum iterable values
abs() Absolute value
round() Round a number
hex() / bin() Convert integer to formatted string
open() Open a file on supported filesystems

Some CPython built-ins and optional arguments may be unavailable.

Modules and Imports

import machineimport timeimport osimport sysfrom machine import Pin, ADC, PWM

Common modules include:

Module Function
machine Hardware interfaces
time Delays and time measurements
os Filesystem operations
sys Interpreter information
gc Garbage collection
math Mathematical functions
struct Binary data packing
json JSON encoding and decoding
socket Network sockets, where supported
network Network interface configuration
asyncio Cooperative asynchronous programming
micropython MicroPython-specific features

Module availability and supported functions depend on firmware.

GPIO Input and Output

The machine.Pin class provides digital input and output control.

Digital output

from machine import Pinled = Pin(15, Pin.OUT)led.value(1)led.value(0)

Pin 15 is an illustrative GPIO number, not a universal onboard LED assignment.

Digital input

from machine import Pinbutton = Pin(14, Pin.IN, Pin.PULL_UP)if button.value() == 0:    print("Pressed")

This assumes a switch connected between GPIO14 and ground.

Internal pull-up and pull-down availability varies by pin and device.

Common Pin operations

Operation Function
Configure output Pin(n, Pin.OUT)
Configure input Pin(n, Pin.IN)
Enable pull-up Pin(n, Pin.IN, Pin.PULL_UP)
Read pin pin.value()
Write pin pin.value(1)
Set high pin.on()
Set low pin.off()
Toggle pin.toggle() where supported
from machine import Pinfrom time import sleep_msled = Pin(15, Pin.OUT)while True:    led.toggle()    sleep_ms(500)

The selected GPIO must support output and have an appropriate LED circuit attached.

Timing and Delays

MicroPython provides millisecond and microsecond timing functions.

import timetime.sleep(1)time.sleep_ms(100)time.sleep_us(50)
Function Purpose
sleep(seconds) Delay in seconds
sleep_ms(ms) Delay in milliseconds
sleep_us(us) Delay in microseconds
ticks_ms() Monotonic millisecond tick counter
ticks_us() Monotonic microsecond tick counter
ticks_diff(a, b) Calculate wraparound-safe tick difference
ticks_add(ticks, delta) Add an interval to a tick value

Non-blocking interval measurement

import timeprevious = time.ticks_ms()while True:    now = time.ticks_ms()    if time.ticks_diff(now, previous) >= 1000:        previous = now        print("One-second interval")

The loop does not deliberately sleep, so it continuously consumes processor time.

For larger applications, insert suitable idle handling or use cooperative scheduling.

Do not subtract tick-counter values directly. Tick counters wrap, and ticks_diff() handles this correctly for intervals within its supported range.

ADC Reading

The machine.ADC class provides analogue-to-digital conversion on supported pins.

from machine import ADC, Pinadc = ADC(Pin(26))raw = adc.read_u16()print(raw)

GPIO26 is a suitable ADC input on the Raspberry Pi Pico, but this pin assignment is not portable to ESP32 or other boards.

ADC functions

Function Purpose
ADC(Pin(n)) Create ADC interface on supported pin
read_u16() Read scaled 16-bit ADC value
read_uv() Read microvolt value where supported
atten() Configure attenuation on selected ports
width() Configure ADC width on selected ports

read_u16() returns a value in the nominal range 0–65535, even when the hardware ADC has fewer than 16 bits of native resolution.

Approximate voltage calculation

raw = adc.read_u16()voltage = raw * 3.3 / 65535

This calculation assumes a 3.3 V full-scale input range.

It is only an approximation. The actual conversion relationship depends on ADC reference, attenuation, calibration, input circuitry and board design.

On ESP32 devices, ADC attenuation and non-linearity require particular attention.

PWM Output

PWM generates a periodic digital waveform with a configurable frequency and duty cycle.

from machine import Pin, PWMpwm = PWM(Pin(15), freq=1000)pwm.duty_u16(32768)

This requests approximately 1 kHz PWM with a 50% duty cycle.

PWM functions

Function Purpose
PWM(Pin(n), freq=f) Create PWM output
pwm.freq() Read frequency
pwm.freq(f) Set frequency
pwm.duty_u16(value) Set scaled duty cycle
pwm.duty_ns(value) Set pulse width in nanoseconds, where supported
pwm.deinit() Release PWM resource

The duty_u16() range is 0–65535.

pwm.duty_u16(0)       # 0%pwm.duty_u16(32768)   # Approximately 50%pwm.duty_u16(65535)   # 100%

The actual frequency and duty-cycle resolution depend on hardware timers and clock configuration.

PWM period calculation

Period (seconds) = 1 / Frequency (Hz)

For 1 kHz:

Period = 1 / 1000
Period = 1 ms

I2C Communication

The machine.I2C class provides I2C master operation on supported hardware.

Raspberry Pi Pico example

from machine import Pin, I2Ci2c = I2C(    0,    scl=Pin(1),    sda=Pin(0),    freq=100000)print(i2c.scan())

This configuration applies to a Raspberry Pi Pico using I2C0 with GP1 as SCL and GP0 as SDA.

Common I2C methods

Method Purpose
i2c.scan() Find responding 7-bit addresses
i2c.writeto(addr, data) Write bytes
i2c.readfrom(addr, n) Read bytes
i2c.readfrom_into(addr, buf) Read into existing buffer
i2c.writeto_mem(addr, reg, data) Write device register
i2c.readfrom_mem(addr, reg, n) Read device register

Register read

address = 0x48register = 0x00data = i2c.readfrom_mem(address, register, 2)print(data)

This is a transaction example; the register address and data length must match the connected device.

I2C requires suitable pull-up resistors on SDA and SCL. Internal GPIO pull-ups are generally not a substitute for correctly sized external I2C pull-ups.

SPI Communication

SPI provides synchronous serial communication using clock, data and optional chip-select signals.

Raspberry Pi Pico example

from machine import Pin, SPIspi = SPI(    0,    baudrate=1000000,    polarity=0,    phase=0,    sck=Pin(18),    mosi=Pin(19),    miso=Pin(16))cs = Pin(17, Pin.OUT, value=1)cs.value(0)spi.write(b"\x9F")response = spi.read(3)cs.value(1)print(response)

This demonstrates a command followed by three received bytes. The command 0x9F is commonly used to request JEDEC identification from compatible SPI flash devices.

SPI methods

Method Purpose
spi.write(data) Transmit bytes
spi.read(n) Receive bytes
spi.readinto(buffer) Receive into buffer
spi.write_readinto(tx, rx) Simultaneous transmit and receive
spi.init(…) Reconfigure SPI
spi.deinit() Release peripheral where supported

Chip-select control is commonly handled using a separate GPIO.

UART Communication

UART provides asynchronous serial communication.

Raspberry Pi Pico example

from machine import UART, Pinuart = UART(    0,    baudrate=115200,    tx=Pin(0),    rx=Pin(1))uart.write(b"Hello\r\n")if uart.any():    data = uart.read()    print(data)

Common UART methods

Method Purpose
uart.any() Check available receive data
uart.read() Read available bytes
uart.read(n) Read up to n bytes
uart.readline() Read a line
uart.write(data) Transmit bytes
uart.init(…) Reconfigure UART
uart.deinit() Release UART where supported

UART pin assignments and available peripheral instances vary between boards.

Microcontroller UART pins normally use logic-level signalling, not RS-232 voltage levels.

Hardware Timers and Interrupts

Hardware timers can execute callbacks at configured intervals.

from machine import Timertimer = Timer()

Timer construction is port-dependent. Some platforms require a numeric timer identifier, while others support virtual timers.

A typical periodic configuration is:

timer.init(    period=1000,    mode=Timer.PERIODIC,    callback=callback)

Here, callback must be a previously defined function.

Interrupt-safe callback pattern

from machine import Timerimport micropythonmicropython.alloc_emergency_exception_buf(100)ticks = 0def timer_callback(timer):    global ticks    ticks += 1

The callback performs minimal work.

Whether a timer callback executes as a hard interrupt or through scheduled execution depends on the port and timer configuration.

Interrupt restrictions

For hard interrupt callbacks:

  • Avoid allocating memory.
  • Avoid creating strings or lists.
  • Avoid filesystem operations.
  • Avoid blocking delays.
  • Avoid network operations.
  • Keep execution time short.

Use micropython.schedule() where supported to defer work outside hard interrupt context. Its scheduling queue is finite, so applications must handle the possibility that scheduling fails when the queue is full.

Asynchronous Programming

MicroPython supports cooperative asynchronous programming through asyncio on supported firmware builds.

Basic asynchronous tasks

import asyncioasync def blink_message():    while True:        print("Running")        await asyncio.sleep_ms(500)async def main():    await blink_message()asyncio.run(main())

Concurrent tasks

import asyncioasync def task_a():    while True:        print("A")        await asyncio.sleep_ms(1000)async def task_b():    while True:        print("B")        await asyncio.sleep_ms(1500)async def main():    asyncio.create_task(task_a())    await task_b()asyncio.run(main())

Tasks cooperate by yielding control through await.

A long blocking function prevents other tasks from running until it returns or yields.

Memory Management

MicroPython normally uses automatic garbage collection.

The gc module provides direct memory-management functions.

import gcgc.collect()print(gc.mem_free())print(gc.mem_alloc())
Function Purpose
gc.collect() Run garbage collection
gc.mem_free() Report free managed heap memory
gc.mem_alloc() Report allocated managed heap memory
gc.enable() Enable automatic collection
gc.disable() Disable automatic collection

The reported heap is not necessarily the microcontroller’s total available RAM.

Reduce memory allocations

Prefer reusable buffers when repeatedly processing binary data.

buffer = bytearray(64)while True:    # Reuse buffer for repeated operations    break

For hardware interfaces, methods such as readinto() can avoid creating a new bytes object on each transaction.

Avoid repeatedly concatenating large strings or constructing temporary lists in memory-constrained loops.

Filesystem Operations

Many MicroPython boards provide a flash-based filesystem.

with open("data.txt", "w") as file:    file.write("123\n")

Read the file:

with open("data.txt", "r") as file:    content = file.read()print(content)

Filesystem functions

import osprint(os.listdir())print(os.getcwd())
Operation Function
List files os.listdir()
Current directory os.getcwd()
Create directory os.mkdir(“logs”)
Remove file os.remove(“data.txt”)
Rename file os.rename(“old.txt”, “new.txt”)
File information os.stat(“data.txt”)

Filesystem availability, capacity and wear characteristics depend on the port and storage medium.

Avoid frequent writes to flash for high-rate logging. Buffer data and write at controlled intervals where practical.

Wi-Fi Networking

Wi-Fi is available only on supported hardware and firmware builds.

The following pattern applies to MicroPython ports implementing the conventional network.WLAN station interface.

import networkimport timewlan = network.WLAN(network.STA_IF)wlan.active(True)wlan.connect("YOUR_SSID", "YOUR_PASSWORD")start = time.ticks_ms()while not wlan.isconnected():    if time.ticks_diff(time.ticks_ms(), start) > 10000:        raise OSError("Wi-Fi connection timeout")    time.sleep_ms(100)print(wlan.ifconfig())

The example provides a connection timeout but does not implement reconnection or recovery.

Common WLAN operations

Method Purpose
wlan.active(True) Activate interface
wlan.connect(ssid, password) Connect to access point
wlan.isconnected() Check connection
wlan.ifconfig() Inspect IP configuration
wlan.disconnect() Disconnect
wlan.scan() Scan nearby networks where supported
wlan.status() Inspect connection status

Status codes and advanced interface methods vary by port.

Do not assume every ESP32, RP2040 or RP2350 board includes wireless hardware.

JSON Data Handling

The json module supports structured data exchange.

import jsonreading = {    "temperature": 24.5,    "humidity": 52}encoded = json.dumps(reading)decoded = json.loads(encoded)print(decoded["temperature"])
Function Purpose
json.dumps(obj) Convert object to JSON string
json.loads(text) Parse JSON string
json.dump(obj, file) Write JSON to stream, where supported
json.load(file) Read JSON from stream, where supported

MicroPython JSON support may differ from CPython in optional arguments and advanced features.

Debugging and System Information

Inspect the runtime

import sysimport osimport gcprint(sys.platform)print(sys.version)print(os.listdir())gc.collect()print(gc.mem_free())

Inspect hardware

import machineprint(machine.freq())print(machine.unique_id())

machine.freq() behaviour and supported arguments vary by port.

machine.unique_id() returns a device-specific identifier. Avoid publishing it unnecessarily.

Inspect available modules

help("modules")

The available module list reflects the installed firmware.

For an imported object:

from machine import Pinhelp(Pin)

This is useful when a particular firmware build differs from an example.

Common MicroPython Errors

Error Typical cause Corrective action
ImportError Module unavailable Check firmware and supported modules
AttributeError Unsupported method Inspect API for selected port
NameError Undefined variable Check spelling and scope
TypeError Incorrect argument type Check function parameters
ValueError Invalid value Check pin number or parameter range
OSError Hardware or I/O failure Check peripheral configuration
MemoryError Insufficient heap memory Reduce allocations and inspect memory
SyntaxError Invalid Python syntax Check indentation and statements
IndentationError Incorrect indentation Use consistent indentation
KeyboardInterrupt Execution interrupted Inspect loop or callback behaviour

An OSError from I2C may indicate an absent device, incorrect address, missing pull-ups or electrical problems.

An OSError from networking may indicate a disconnected interface or failed socket operation.

The exception type alone does not identify the exact hardware fault.

MicroPython and CPython Differences

Feature MicroPython consideration
Standard library Reduced or modified
Hardware access Provided through embedded-specific modules
Memory Usually substantially more constrained
Threads Port-dependent
Filesystem May use internal flash
Floating-point precision Build-dependent
Native extensions Different from CPython
Package installation Depends on firmware and available tools
Timing Interpreter and garbage collection affect execution
Interrupt callbacks Additional memory and execution restrictions

MicroPython supports a substantial subset of Python 3, but desktop Python packages cannot be assumed to work without modification.

Performance and Reliability Notes

Avoid unnecessary blocking

Long sleep() calls prevent the current execution context from processing other work.

For responsive applications, use tick-based scheduling, hardware interrupts or asyncio.

Reuse memory

Repeatedly allocating objects in a fast loop increases garbage-collection activity.

Preallocate byte buffers and reuse objects where possible.

Protect shared state

Variables accessed by interrupt callbacks and normal code may require careful synchronisation.

A read-modify-write operation is not automatically atomic merely because it is written as one Python statement.

Handle peripheral failures

I2C, SPI, UART and network operations can fail.

Use appropriate exception handling and timeouts rather than assuming every transaction succeeds.

Avoid excessive flash writes

Flash storage has finite write endurance.

Store configuration only when it changes, and avoid writing sensor readings to flash at unnecessarily high rates.

Quick Command Reference

Task Command
Import hardware module import machine
Configure output Pin(n, Pin.OUT)
Configure input Pin(n, Pin.IN)
Read GPIO pin.value()
Set GPIO high pin.on()
Set GPIO low pin.off()
Delay milliseconds time.sleep_ms(n)
Read elapsed ticks time.ticks_ms()
Compare tick values time.ticks_diff(a, b)
Read ADC adc.read_u16()
Set PWM frequency pwm.freq(hz)
Set PWM duty pwm.duty_u16(value)
Scan I2C bus i2c.scan()
Write SPI bytes spi.write(data)
Read UART data uart.read()
Run garbage collection gc.collect()
Check free heap gc.mem_free()
List files os.listdir()
Check Wi-Fi connection wlan.isconnected()
Inspect platform sys.platform
Soft reset machine.soft_reset()

Deployment Checklist

  1. Install firmware built for the exact microcontroller or development board.
  2. Confirm the MicroPython port and version.
  3. Check that required hardware modules are available.
  4. Verify GPIO numbering and peripheral pin assignments.
  5. Confirm input and output voltage compatibility.
  6. Test hardware interfaces individually before combining them.
  7. Handle I/O errors and communication timeouts.
  8. Avoid memory allocation inside hard interrupt callbacks.
  9. Use wraparound-safe tick calculations.
  10. Monitor heap memory during long-running operation.
  11. Minimise unnecessary flash writes.
  12. Keep startup code recoverable.
  13. Test behaviour after power cycling and soft resets.
  14. Verify the application continues operating correctly after peripheral or network failures.

Related posts

MicroPython Data Types and Variables Cheat Sheet

MicroPython vs Python 3 Differences Cheat Sheet