Micropython Docs
Micropython Docs
Release latest
1 MicroPython libraries 1
1.1 Python standard libraries and micro-libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 array – arrays of numeric data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1.2 asyncio — asynchronous I/O scheduler . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.3 binascii – binary/ASCII conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.4 builtins – builtin functions and exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.1.5 cmath – mathematical functions for complex numbers . . . . . . . . . . . . . . . . . . . . . 11
1.1.6 collections – collection and container types . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.1.7 errno – system error codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.1.8 gc – control the garbage collector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.1.9 gzip – gzip compression & decompression . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.1.10 hashlib – hashing algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.1.11 heapq – heap queue algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.1.12 io – input/output streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.1.13 json – JSON encoding and decoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.1.14 marshal – Python object serialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.1.15 math – mathematical functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.1.16 os – basic “operating system” services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.1.17 platform – access to underlying platform’s identifying data . . . . . . . . . . . . . . . . . . 25
1.1.18 random – generate random numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.1.19 re – simple regular expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.1.20 select – wait for events on a set of streams . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.1.21 socket – socket module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.1.22 ssl – SSL/TLS module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.1.23 struct – pack and unpack primitive data types . . . . . . . . . . . . . . . . . . . . . . . . 38
1.1.24 sys – system specific functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.1.25 time – time related functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.1.26 zlib – zlib compression & decompression . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.1.27 _thread – multithreading support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.2 MicroPython-specific libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.2.1 bluetooth — low-level Bluetooth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.2.2 btree – simple BTree database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
1.2.3 cryptolib – cryptographic ciphers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
1.2.4 deflate – deflate compression & decompression . . . . . . . . . . . . . . . . . . . . . . . 61
1.2.5 framebuf — frame buffer manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
1.2.6 machine — functions related to the hardware . . . . . . . . . . . . . . . . . . . . . . . . . 66
1.2.7 micropython – access and control MicroPython internals . . . . . . . . . . . . . . . . . . . 101
1.2.8 neopixel — control of WS2812 / NeoPixel LEDs . . . . . . . . . . . . . . . . . . . . . . 104
1.2.9 network — network configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
1.2.10 openamp – provides standard Asymmetric Multiprocessing (AMP) support . . . . . . . . . . 118
i
1.2.11 uctypes – access binary data in a structured way . . . . . . . . . . . . . . . . . . . . . . . 120
1.2.12 vfs – virtual filesystem control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
1.2.13 WM8960 – Driver for the WM8960 codec . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
1.3 Port-specific libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
1.3.1 Libraries specific to the pyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
1.3.2 Libraries specific to the WiPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
1.3.3 Libraries specific to the ESP8266 and ESP32 . . . . . . . . . . . . . . . . . . . . . . . . . . 187
1.3.4 Libraries specific to the RP2040 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.3.5 Libraries specific to Zephyr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
1.4 Extending built-in libraries from Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
ii
2.9.1 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
2.9.2 Writing manifest files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
2.9.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
2.10 Package management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
2.10.1 Installing packages with mip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
2.10.2 Installing packages with mpremote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
2.10.3 Installing packages manually . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
2.10.4 Writing & publishing packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
2.10.5 Freezing packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
2.11 Inline assembler for Thumb2 architectures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
2.11.1 Document conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
2.11.2 Instruction categories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
2.11.3 Usage examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
2.11.4 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
2.12 Working with filesystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
2.12.1 VFS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
2.12.2 Block devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
2.12.3 Filesystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
2.13 The pyboard.py tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
2.13.1 Running a command on the device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
2.13.2 Running a script on the device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
2.13.3 Filesystem access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
2.13.4 Using the pyboard library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
2.14 MicroPython 2.0 Migration Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
2.14.1 Hardware and peripherals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
2.14.2 OS & filesystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
2.14.3 CPython compatibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
iii
3.8.9 Calling super() getter property in subclass will return a property object, not the value . . . . . 314
3.8.10 Error messages for methods may display unexpected argument counts . . . . . . . . . . . . . 314
3.8.11 Function objects do not have the __module__ attribute . . . . . . . . . . . . . . . . . . . . 315
3.8.12 User-defined attributes for functions are not supported . . . . . . . . . . . . . . . . . . . . . 315
3.8.13 Context manager __exit__() not called in a generator which does not run to completion . . . . 316
3.8.14 Local variables aren’t included in locals() result . . . . . . . . . . . . . . . . . . . . . . . . . 316
3.8.15 Code running in eval() function doesn’t have access to local variables . . . . . . . . . . . . . 317
3.8.16 __all__ is unsupported in __init__.py in MicroPython. . . . . . . . . . . . . . . . . . . . . . 317
3.8.17 __path__ attribute of a package has a different type (single string instead of list of strings) in
MicroPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
3.8.18 MicroPython doesn’t support namespace packages split across filesystem. . . . . . . . . . . . 318
3.9 Builtin types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
3.9.1 Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
3.9.2 bytearray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
3.9.3 bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
3.9.4 dict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
3.9.5 float . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
3.9.6 int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
3.9.7 list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
3.9.8 memoryview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
3.9.9 str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
3.9.10 tuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
3.10 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
3.10.1 Positional-only Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
3.10.2 array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
3.10.3 builtins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
3.10.4 json . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
3.10.5 os . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
3.10.6 random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
3.10.7 struct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
3.10.8 sys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
iv
4.6.1 Frozen bytecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
4.6.2 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
4.6.3 Allocation of memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
4.7 MicroPython string interning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
4.7.1 Compile-time QSTR generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
4.7.2 Run-time QSTR generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
4.8 Maps and Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
4.8.1 Open addressing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
4.8.2 Linear probing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
4.9 The public C API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
4.10 Extending MicroPython in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
4.10.1 MicroPython external C modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
4.10.2 Native machine code in .mpy files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
4.11 Porting MicroPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
4.11.1 Minimal MicroPython firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
4.11.2 MicroPython Configurations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
4.11.3 Support for standard input/output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
4.11.4 Building and running . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
4.11.5 Adding a module to the port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
v
6.12 PWM (pulse width modulation) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
6.13 ADC (analog to digital conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
6.14 DAC (digital to analog conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
6.15 UART (serial bus) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
6.16 SPI bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
6.17 I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
6.18 I2S bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
6.19 CAN bus (controller area network) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
6.20 Internal accelerometer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
vi
8 Quick reference for the ESP32 445
8.1 General information about the ESP32 port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
8.1.1 Multitude of boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
8.1.2 Technical specifications and SoC datasheets . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
8.2 MicroPython tutorial for ESP32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
8.2.1 Getting started with MicroPython on the ESP32 . . . . . . . . . . . . . . . . . . . . . . . . 447
8.2.2 Pulse Width Modulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
8.2.3 Accessing peripherals directly via registers . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
8.2.4 Factory reset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
8.3 Installing MicroPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
8.4 General board control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
8.5 Networking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
8.5.1 WLAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
8.5.2 LAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
8.6 Delay and timing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
8.7 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
8.8 Pins and GPIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
8.9 UART (serial bus) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
8.10 PWM (pulse width modulation) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
8.11 DAC (digital to analog conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
8.12 ADC (analog to digital conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
8.13 Software SPI bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462
8.14 Hardware SPI bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
8.15 Software I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
8.16 Hardware I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
8.17 I2S bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
8.18 Real time clock (RTC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
8.19 WDT (Watchdog timer) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
8.20 Deep-sleep mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
8.21 SD card . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
8.22 RMT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
8.23 OneWire driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
8.24 NeoPixel and APA106 driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
8.25 Capacitive touch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
8.26 DHT driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
8.27 WebREPL (web browser interactive prompt) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
vii
9.14 Software I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
9.15 Hardware I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
9.16 I2S bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
9.17 Real time clock (RTC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
9.18 WDT (Watchdog timer) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
9.19 OneWire driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
9.20 NeoPixel and APA106 driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
viii
11.1.4 Telnet REPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
11.1.5 Local file system and FTP access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
11.1.6 FileZilla settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
11.1.7 Upgrading the firmware Over The Air . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
11.1.8 Boot modes and safe boot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
11.1.9 The heartbeat LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
11.1.10 Details on sleep modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
11.1.11 Additional details for machine.Pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
11.1.12 Additional details for machine.I2C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
11.1.13 Known issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
11.2 WiPy tutorials and examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
11.2.1 Introduction to the WiPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 513
11.2.2 Getting a MicroPython REPL prompt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
11.2.3 Getting started with Blynk and the WiPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
11.2.4 WLAN step by step . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
11.2.5 Hardware timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518
11.2.6 Reset and boot modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
11.3 General board control (including sleep modes) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520
11.4 Pins and GPIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520
11.5 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520
11.6 PWM (pulse width modulation) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
11.7 ADC (analog to digital conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
11.8 UART (serial bus) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
11.9 SPI bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
11.10 I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
11.11 Watchdog timer (WDT) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
11.12 Real time clock (RTC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
11.13 SD card . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
11.14 WLAN (WiFi) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
11.15 Telnet and FTP server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
11.16 Heart beat LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
ix
14.1 General information about Renesas RA port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
14.1.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
14.2 MicroPython tutorial for Renesas RA port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
14.2.1 Getting started with MicroPython on the Renesas RA . . . . . . . . . . . . . . . . . . . . . 536
14.2.2 Using peripherals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
14.2.3 Write a program in internal file system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538
14.2.4 Reset and boot mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
14.2.5 Trouble Shooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
14.3 Installing MicroPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
14.4 General board control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
14.5 Delay and timing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
14.6 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
14.7 Pins and GPIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
14.8 UART (serial bus) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
14.9 Real time clock (RTC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
14.10 ADC (analog to digital conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
14.11 SPI bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
14.12 I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
14.13 PWM (pulse width modulation) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
14.14 WDT (Watchdog timer) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
14.15 SDCard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
14.16 OneWire driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
14.17 NeoPixel and APA106 driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
x
15.6 Delay and timing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595
15.7 Clock and time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
15.8 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
15.9 Pins and GPIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
15.10 UART (serial bus) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
15.11 PWM (pulse width modulation) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
15.11.1 PWM Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598
15.11.2 PWM Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598
15.11.3 PWM Pin Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598
15.12 ADC (analog to digital conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 598
15.12.1 ADC Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599
15.12.2 ADC Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599
15.13 DAC (digital to analog conversion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599
15.13.1 DAC Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
15.13.2 DAC Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
15.14 Software SPI bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
15.15 Hardware SPI bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
15.16 Software I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
15.17 Hardware I2C bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
15.18 OneWire driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
15.19 DHT driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
15.20 Driving an APA102 LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
15.21 Driving a Neopixel LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603
15.22 Transferring files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603
xi
xii
CHAPTER
ONE
MICROPYTHON LIBRARIES
Á Warning
• Most Python standard library modules implement a subset of the functionality of the equivalent Python module,
and in a few cases provide some MicroPython-specific extensions (e.g. array , os)
• Due to resource constraints or other limitations, some ports or firmware versions may not include all the func-
tionality documented here.
• To allow for extensibility, some built-in modules can be extended from Python code loaded onto the device
filesystem.
This chapter describes modules (function and class libraries) which are built into MicroPython. This documentation in
general aspires to describe all modules and functions/classes which are implemented in the MicroPython project. However,
MicroPython is highly configurable, and each port to a particular board/embedded system may include only a subset of
the available MicroPython libraries.
With that in mind, please be warned that some functions/classes in a module (or even the entire module) described in this
documentation may be unavailable in a particular build of MicroPython on a particular system. The best place to find
general information of the availability/non-availability of a particular feature is the “General Information” section which
contains information pertaining to a specific MicroPython port.
On some ports you are able to discover the available, built-in libraries that can be imported by entering the following at
the REPL:
help('modules')
Beyond the built-in libraries described in this documentation, many more modules from the Python standard library, as
well as further MicroPython extensions to it, can be found in micropython-lib.
1
MicroPython Documentation, Release latest
Classes
[
class array.array(typecode , iterable ) ]
Create array with elements of given type. Initial contents of the array are given by iterable. If it is not provided, an
empty array is created.
In addition to the methods below, array objects also implement the buffer protocol. This means the contents of the
entire array can be accessed as raw bytes via a memoryview or other interfaces which use this protocol.
append(val)
Append new element val to the end of array, growing it.
extend(iterable)
Append new elements as contained in iterable to the end of array, growing it.
__getitem__(index)
Indexed read of the array, called as a[index] (where a is an array). Returns a value if index is an int and
an array if index is a slice. Negative indices count from the end and IndexError is thrown if the index is
out of range.
Note: __getitem__ cannot be called directly (a.__getitem__(index) fails) and is not present in
__dict__, however a[index] does work.
__setitem__(index, value)
Indexed write into the array, called as a[index] = value (where a is an array). value is a single value
if index is an int and an array if index is a slice. Negative indices count from the end and IndexError is
thrown if the index is out of range.
Note: __setitem__ cannot be called directly (a.__setitem__(index, value) fails) and is not present
in __dict__, however a[index] = value does work.
__len__()
Returns the number of items in the array, called as len(a) (where a is an array).
Note: __len__ cannot be called directly (a.__len__() fails) and the method is not present in __dict__,
however len(a) does work.
__add__(other)
Return a new array that is the concatenation of the array with other, called as a + other (where a and
other are both arrays).
Note: __add__ cannot be called directly (a.__add__(other) fails) and is not present in __dict__,
however a + other does work.
__iadd__(other)
Concatenates the array with other in-place, called as a += other (where a and other are both arrays).
Equivalent to extend(other).
Note: __iadd__ cannot be called directly (a.__iadd__(other) fails) and is not present in __dict__,
however a += other does work.
__repr__()
Returns the string representation of the array, called as str(a) or repr(a)` (where a is an array). Returns
the string "array(<type>, [<elements>])", where <type> is the type code letter for the array and
<elements> is a comma separated list of the elements of the array.
Note: __repr__ cannot be called directly (a.__repr__() fails) and is not present in __dict__, however
str(a) and repr(a) both work.
import asyncio
# Running on a pyboard
from pyb import LED
asyncio.run(main(LED(1), LED(2)))
Core functions
asyncio.create_task(coro)
Create a new task from the given coroutine and schedule it to run.
Returns the corresponding Task object.
asyncio.current_task()
Return the Task object associated with the currently running task.
asyncio.run(coro)
Create a new task from the given coroutine and run it until it completes.
Returns the value returned by coro.
asyncio.sleep(t )
Sleep for t seconds (can be a float).
This is a coroutine.
asyncio.sleep_ms(t )
Sleep for t milliseconds.
This is a coroutine, and a MicroPython extension.
Additional functions
asyncio.wait_for(awaitable, timeout )
Wait for the awaitable to complete, but cancel it if it takes longer than timeout seconds. If awaitable is not a task
then a task will be created from it.
If a timeout occurs, it cancels the task and raises asyncio.TimeoutError: this should be trapped by the caller.
The task receives asyncio.CancelledError which may be ignored or trapped using try...except or try.
..finally to run cleanup code.
class Task
class asyncio.Task
This object wraps a coroutine into a running task. 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, rather use create_task to create them.
Task.cancel()
Cancel the task by injecting asyncio.CancelledError into it. The task may ignore this exception. Cleanup
code may be run by trapping it, or via try ... finally.
class Event
class asyncio.Event
Create a new event which can be used to synchronise tasks. Events start in the cleared state.
Event.is_set()
Returns True if the event is set, False otherwise.
Event.set()
Set the event. Any tasks waiting on the event will be scheduled to run.
Note: This must be called from within a task. It is not safe to call this from an IRQ, scheduler callback, or other
thread. See ThreadSafeFlag .
Event.clear()
Clear the event.
Event.wait()
Wait for the event to be set. If the event is already set then it returns immediately.
This is a coroutine.
class ThreadSafeFlag
class asyncio.ThreadSafeFlag
Create a new flag which can be used to synchronise a task with code running outside the asyncio loop, such as other
threads, IRQs, or scheduler callbacks. Flags start in the cleared state.
ThreadSafeFlag.set()
Set the flag. If there is a task waiting on the flag, it will be scheduled to run.
ThreadSafeFlag.clear()
Clear the flag. This may be used to ensure that a possibly previously-set flag is clear before waiting for it.
ThreadSafeFlag.wait()
Wait for the flag to be set. If the flag is already set then it returns immediately. The flag is automatically reset upon
return from wait.
A flag may only be waited on by a single task at a time.
This is a coroutine.
class Lock
class asyncio.Lock
Create a new lock which can be used to coordinate tasks. Locks start in the unlocked state.
In addition to the methods below, locks can be used in an async with statement.
Lock.locked()
Returns True if the lock is locked, otherwise False.
Lock.acquire()
Wait for the lock to be in the unlocked state and then lock it in an atomic way. Only one task can acquire the lock
at any one time.
This is a coroutine.
Lock.release()
Release the lock. If any tasks are waiting on the lock then the next one in the queue is scheduled to run and the
lock remains locked. Otherwise, no tasks are waiting an the lock becomes unlocked.
Server.close()
Close the server.
Server.wait_closed()
Wait for the server to close.
This is a coroutine.
Event Loop
asyncio.get_event_loop()
Return the event loop used to schedule and run tasks. See Loop.
asyncio.new_event_loop()
Reset the event loop and return it.
Note: since MicroPython only has a single event loop this function just resets the loop’s state, it does not create a
new one.
class asyncio.Loop
This represents the object which schedules and runs tasks. It cannot be created, use get_event_loop instead.
Loop.create_task(coro)
Create a task from the given coro and return the new Task object.
Loop.run_forever()
Run the event loop until stop() is called.
Loop.run_until_complete(awaitable)
Run the given awaitable until it completes. If awaitable is not a task then it will be promoted to one.
Loop.stop()
Stop the event loop.
Loop.close()
Close the event loop.
Loop.set_exception_handler(handler)
Set the exception handler to call when a Task raises an exception that is not caught. The handler should accept two
arguments: (loop, context).
Loop.get_exception_handler()
Get the current exception handler. Returns the handler, or None if no custom handler is set.
Loop.default_exception_handler(context )
The default exception handler that is called.
Loop.call_exception_handler(context )
Call the current exception handler. The argument context is passed through and is a dictionary containing keys:
'message', 'exception', 'future'.
Functions
binascii.hexlify(data , sep )[ ]
Convert the bytes in the data object to a hexadecimal representation. Returns a bytes object.
If the additional argument sep is supplied it is used as a separator between hexadecimal values.
binascii.unhexlify(data)
Convert hexadecimal data to binary representation. Returns bytes string. (i.e. inverse of hexlify)
binascii.a2b_base64(data)
Decode base64-encoded data, ignoring invalid characters in the input. Conforms to RFC 2045 s.6.8. Returns a
bytes object.
binascii.b2a_base64(data, *, newline=True)
Encode binary data in base64 format, as in RFC 3548. Returns the encoded data followed by a newline character
if newline is true, as a bytes object.
[
binascii.crc32(data , value ) ]
Compute CRC-32, the 32-bit checksum of data, starting with an initial CRC of value. The default initial CRC is
zero. The algorithm is consistent with the ZIP file checksum.
all()
any()
bin()
class bool
class bytearray
See CPython documentation: bytearray.
class bytes
See CPython documentation: bytes.
callable()
chr()
classmethod()
compile()
class complex
delattr(obj, name)
The argument name should be a string, and this function deletes the named attribute from the object given by obj.
class dict
dir()
divmod()
enumerate()
eval()
exec()
filter()
class float
class frozenset
getattr()
globals()
hasattr()
hash()
hex()
id()
input()
class int
® Note
The optional signed kwarg from CPython is not supported. MicroPython currently converts negative
integers as signed, and positive as unsigned. (Details.)
isinstance()
issubclass()
iter()
len()
class list
locals()
map()
max()
class memoryview
See CPython documentation: memoryview.
min()
next()
class object
oct()
open()
ord()
pow()
print()
property()
range()
repr()
reversed()
round()
class set
setattr()
class slice
The slice builtin is the type that slice objects have.
sorted()
staticmethod()
class str
sum()
super()
class tuple
type()
zip()
Exceptions
exception AssertionError
exception AttributeError
exception Exception
exception ImportError
exception IndexError
exception KeyboardInterrupt
See CPython documentation: KeyboardInterrupt.
See also in the context of Soft Bricking (failure to boot).
exception KeyError
exception MemoryError
exception NameError
exception NotImplementedError
exception OSError
exception RuntimeError
exception StopIteration
exception SyntaxError
exception SystemExit
See CPython documentation: SystemExit.
On non-embedded ports (i.e. Windows and Unix), an unhandled SystemExit exits the MicroPython process in a
similar way to CPython.
On embedded ports, an unhandled SystemExit currently causes a Soft Reset of MicroPython.
exception TypeError
See CPython documentation: TypeError.
exception ValueError
exception ZeroDivisionError
Functions
cmath.cos(z)
Return the cosine of z.
cmath.exp(z)
Return the exponential of z.
cmath.log(z)
Return the natural logarithm of z. The branch cut is along the negative real axis.
cmath.log10(z)
Return the base-10 logarithm of z. The branch cut is along the negative real axis.
cmath.phase(z)
Returns the phase of the number z, in the range (-pi, +pi].
cmath.polar(z)
Returns, as a tuple, the polar form of z.
cmath.rect(r, phi)
Returns the complex number with modulus r and phase phi.
cmath.sin(z)
Return the sine of z.
cmath.sqrt(z)
Return the square-root of z.
Constants
cmath.e
base of the natural logarithm
cmath.pi
the ratio of a circle’s circumference to its diameter
Classes
pop()
Remove and return an item from the right side of the deque. Raises IndexError if no items are present.
popleft()
Remove and return an item from the left side of the deque. Raises IndexError if no items are present.
extend(iterable)
Extend the deque by appending all the items from iterable to the right of the deque. Raises IndexError if
overflow checking is enabled and there is no more room in the deque.
collections.namedtuple(name, fields)
This is factory function to create a new namedtuple type with a specific name and set of fields. A namedtuple is a
subclass of tuple which allows to access its fields not just by numeric index, but also with an attribute access syntax
using symbolic field names. Fields is a sequence of strings specifying field names. For compatibility with CPython
it can also be a a string with space-separated field named (but this is less efficient). Example of use:
class collections.OrderedDict(...)
dict type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over,
keys/items are returned in the order they were added:
Output:
z 1
a 2
w 5
b 3
Constants
EEXIST, EAGAIN, etc.
Error codes, based on ANSI C/POSIX standard. All error codes start with “E”. As mentioned above, inventory of
the codes depends on MicroPython port. Errors are usually accessible as exc.errno where exc is an instance of
OSError. Usage example:
try:
os.mkdir("my_dir")
except OSError as exc:
if exc.errno == errno.EEXIST:
print("Directory already exists")
errno.errorcode
Dictionary mapping numeric error codes to strings with symbolic error code (see above):
>>> print(errno.errorcode[errno.EEXIST])
EEXIST
Functions
gc.enable()
Enable automatic garbage collection.
gc.disable()
Disable automatic garbage collection. Heap memory can still be allocated, and garbage collection can still be
initiated manually using gc.collect().
gc.collect()
Run a garbage collection.
gc.mem_alloc()
Return the number of bytes of heap RAM that are allocated by Python code.
® Difference to CPython
gc.mem_free()
Return the number of bytes of heap RAM that is available for Python code to allocate, or -1 if this amount is not
known.
® Difference to CPython
[
gc.threshold( amount ) ]
Set or query the additional GC allocation threshold. Normally, a collection is triggered only when a new allocation
cannot be satisfied, i.e. on an out-of-memory (OOM) condition. If this function is called, in addition to OOM,
a collection will be triggered each time after amount bytes have been allocated (in total, since the previous time
such an amount of bytes have been allocated). amount is usually specified as less than the full heap size, with
the intention to trigger a collection earlier than when the heap becomes exhausted, and in the hope that an early
collection will prevent excessive memory fragmentation. This is a heuristic measure, the effect of which will vary
from application to application, as well as the optimal value of the amount parameter.
Calling the function without argument will return the current value of the threshold. A value of -1 means a disabled
allocation threshold.
® Difference to CPython
This function is a MicroPython extension. CPython has a similar function - set_threshold(), but due to
different GC implementations, its signature and semantics are different.
® Note
Prefer to use deflate.DeflateIO instead of the functions in this module as it provides a streaming interface to
compression and decompression which is convenient and more memory efficient when working with reading or writing
compressed data to a file, socket, or stream.
Availability:
• This module is not present by default in official MicroPython firmware releases as it duplicates functionality
available in the deflate module.
• A copy of this module can be installed (or frozen) from micropython-lib (source). See Package management for
more information. This documentation describes that module.
• Compression support will only be available if compression support is enabled in the built-in deflate module.
Functions
gzip.open(filename, mode, / )
Wrapper around built-in open() returning a GzipFile instance.
gzip.decompress(data, / )
Decompresses data into a bytes object.
gzip.compress(data, / )
Compresses data into a bytes object.
Classes
class gzip.GzipFile(*, fileobj, mode)
This class can be used to wrap a fileobj which is any stream-like object such as a file, socket, or stream (including
io.BytesIO). It is itself a stream and implements the standard read/readinto/write/close methods.
When the mode argument is "rb", reads from the GzipFile instance will decompress the data in the underlying
stream and return decompressed data.
If compression support is enabled then the mode argument can be set to "wb", and writes to the GzipFile instance
will be compressed and written to the underlying stream.
By default the GzipFile class will read and write data using the gzip file format, including a header and footer with
checksum and a window size of 512 bytes.
The file, compresslevel, and mtime arguments are not supported. fileobj and mode must always be specified as
keyword arguments.
Examples
A typical use case for gzip.GzipFile is to read or write a compressed file from storage:
import gzip
# Reading:
with open("data.gz", "rb") as f:
with gzip.GzipFile(fileobj=f, mode="rb") as g:
# Use g.read(), g.readinto(), etc.
# Writing:
with open("data.gz", "wb") as f:
with gzip.GzipFile(fileobj=f, mode="wb") as g:
# Use g.write(...) etc
For guidance on working with gzip sources and choosing the window size see the note at the end of the deflate documen-
tation.
This module implements binary data hashing algorithms. The exact inventory of available algorithms depends on a board.
Among the algorithms which may be implemented:
• SHA256 - The current generation, modern hashing algorithm (of SHA2 series). It is suitable for cryptographically-
secure purposes. Included in the MicroPython core and any board is recommended to provide this, unless it has
particular code size constraints.
• SHA1 - A previous generation algorithm. Not recommended for new usages, but SHA1 is a part of number of
Internet standards and existing applications, so boards targeting network connectivity and interoperability will try
to provide this.
• MD5 - A legacy algorithm, not considered cryptographically secure. Only selected boards, targeting interoperability
with legacy applications, will offer this.
Constructors
Methods
hash.update(data)
Feed more binary data into hash.
hash.digest()
Return hash for all data passed through hash, as a bytes object. After this method is called, more data cannot be
fed into the hash any longer.
hash.hexdigest()
This method is NOT implemented. Use binascii.hexlify(hash.digest()) to achieve a similar effect.
Functions
heapq.heappush(heap, item)
Push the item onto the heap.
heapq.heappop(heap)
Pop the first item from the heap, and return it. Raise IndexError if heap is empty.
The returned item will be the smallest item in the heap.
heapq.heapify(x)
Convert the list x into a heap. This is an in-place operation.
Conceptual hierarchy
® Difference to CPython
Conceptual hierarchy of stream base classes is simplified in MicroPython, as described in this section.
(Abstract) base stream classes, which serve as a foundation for behaviour of all the concrete classes, adhere to few di-
chotomies (pair-wise classifications) in CPython. In MicroPython, they are somewhat simplified and made implicit to
achieve higher efficiencies and save resources.
An important dichotomy in CPython is unbuffered vs buffered streams. In MicroPython, all streams are currently un-
buffered. This is because all modern OSes, and even many RTOSes and filesystem drivers already perform buffering on
their side. Adding another layer of buffering is counter- productive (an issue known as “bufferbloat”) and takes precious
memory. Note that there still cases where buffering may be useful, so we may introduce optional buffering support at a
later time.
But in CPython, another important dichotomy is tied with “bufferedness” - it’s whether a stream may incur short
read/writes or not. A short read is when a user asks e.g. 10 bytes from a stream, but gets less, similarly for writes.
In CPython, unbuffered streams are automatically short operation susceptible, while buffered are guarantee against them.
The no short read/writes is an important trait, as it allows to develop more concise and efficient programs - something
which is highly desirable for MicroPython. So, while MicroPython doesn’t support buffered streams, it still provides
for no-short-operations streams. Whether there will be short operations or not depends on each particular class’ needs,
but developers are strongly advised to favour no-short-operations behaviour for the reasons stated above. For example,
MicroPython sockets are guaranteed to avoid short read/writes. Actually, at this time, there is no example of a short-
operations stream class in the core, and one would be a port-specific class, where such a need is governed by hardware
peculiarities.
The no-short-operations behaviour gets tricky in case of non-blocking streams, blocking vs non-blocking behaviour being
another CPython dichotomy, fully supported by MicroPython. Non-blocking streams never wait for data either to arrive
or be written - they read/write whatever possible, or signal lack of data (or ability to write data). Clearly, this conflicts with
“no-short-operations” policy, and indeed, a case of non-blocking buffered (and this no-short-ops) streams is convoluted
in CPython - in some places, such combination is prohibited, in some it’s undefined or just not documented, in some
cases it raises verbose exceptions. The matter is much simpler in MicroPython: non-blocking stream are important for
efficient asynchronous operations, so this property prevails on the “no-short-ops” one. So, while blocking streams will
avoid short reads/writes whenever possible (the only case to get a short read is if end of file is reached, or in case of error
(but errors don’t return short data, but raise exceptions)), non-blocking streams may produce short data to avoid blocking
the operation.
The final dichotomy is binary vs text streams. MicroPython of course supports these, but while in CPython text streams
are inherently buffered, they aren’t in MicroPython. (Indeed, that’s one of the cases for which we may introduce buffering
support.)
Note that for efficiency, MicroPython doesn’t provide abstract base classes corresponding to the hierarchy above, and it’s
not possible to implement, or subclass, a stream class in pure Python.
Functions
io.open(name, mode='r', **kwargs)
Open a file. Builtin open() function is aliased to this function. All ports (which provide access to file system) are
required to support mode parameter, but support for other arguments vary by port.
Classes
class io.BytesIO(alloc_size)
Create an empty StringIO/BytesIO object, preallocated to hold up to alloc_size number of bytes. That means
that writing that amount of bytes won’t lead to reallocation of the buffer, and thus won’t hit out-of-memory situation
or lead to memory fragmentation. These constructors are a MicroPython extension and are recommended for usage
only in special cases and in system-level libraries, not for end-user applications.
® Difference to CPython
Functions
json.dump(obj, stream, separators=None)
Serialise obj to a JSON string, writing it to the given stream.
If specified, separators should be an (item_separator, key_separator) tuple. The default is (', ', ':
'). To get the most compact JSON representation, you should specify (',', ':') to eliminate whitespace.
json.dumps(obj, separators=None)
Return obj represented as a JSON string.
The arguments have the same meaning as in dump.
json.load(stream)
Parse the given stream, interpreting it as a JSON string and deserialising the data to a Python object. The resulting
object is returned.
Parsing continues until end-of-file is encountered. A ValueError is raised if the data in stream is not correctly
formed.
json.loads(str)
Parse the JSON str and return an object. Raises ValueError if the string is not correctly formed.
Functions
marshal.dumps(value, / )
Convert the given value to binary format and return a corresponding bytes object.
Currently, code objects are the only supported values that can be converted.
marshal.loads(data, / )
Convert the given bytes-like data to its corresponding Python object, and return it.
Functions
math.acos(x)
Return the inverse cosine of x.
math.acosh(x)
Return the inverse hyperbolic cosine of x.
math.asin(x)
Return the inverse sine of x.
math.asinh(x)
Return the inverse hyperbolic sine of x.
math.atan(x)
Return the inverse tangent of x.
math.atan2(y, x)
Return the principal value of the inverse tangent of y/x.
math.atanh(x)
Return the inverse hyperbolic tangent of x.
math.ceil(x)
Return an integer, being x rounded towards positive infinity.
math.copysign(x, y)
Return x with the sign of y.
math.cos(x)
Return the cosine of x.
math.cosh(x)
Return the hyperbolic cosine of x.
math.degrees(x)
Return radians x converted to degrees.
math.erf(x)
Return the error function of x.
math.erfc(x)
Return the complementary error function of x.
math.exp(x)
Return the exponential of x.
math.expm1(x)
Return exp(x) - 1.
math.fabs(x)
Return the absolute value of x.
math.floor(x)
Return an integer, being x rounded towards negative infinity.
math.fmod(x, y)
Return the remainder of x/y.
math.frexp(x)
Decomposes a floating-point number into its mantissa and exponent. The returned value is the tuple (m, e) such
that x == m * 2**e exactly. If x == 0 then the function returns (0.0, 0), otherwise the relation 0.5 <=
abs(m) < 1 holds.
math.gamma(x)
Return the gamma function of x.
math.isfinite(x)
Return True if x is finite.
math.isinf(x)
Return True if x is infinite.
math.isnan(x)
Return True if x is not-a-number
math.ldexp(x, exp)
Return x * (2**exp).
math.lgamma(x)
Return the natural logarithm of the gamma function of x.
math.log(x)
math.log(x, base)
With one argument, return the natural logarithm of x.
With two arguments, return the logarithm of x to the given base.
math.log10(x)
Return the base-10 logarithm of x.
math.log2(x)
Return the base-2 logarithm of x.
math.modf(x)
Return a tuple of two floats, being the fractional and integral parts of x. Both return values have the same sign as
x.
math.pow(x, y)
Returns x to the power of y.
math.radians(x)
Return degrees x converted to radians.
math.sin(x)
Return the sine of x.
math.sinh(x)
Return the hyperbolic sine of x.
math.sqrt(x)
Return the square root of x.
math.tan(x)
Return the tangent of x.
math.tanh(x)
Return the hyperbolic tangent of x.
math.trunc(x)
Return an integer, being x rounded towards 0.
Constants
math.e
base of the natural logarithm
math.pi
the ratio of a circle’s circumference to its diameter
General functions
os.uname()
Return a tuple (possibly a named tuple) containing information about the underlying machine and/or its operating
system. The tuple has five fields in the following order, each of them being a string:
• sysname – the name of the underlying system
• nodename – the network name (can be the same as sysname)
• release – the version of the underlying system
• version – the MicroPython version and build date
• machine – an identifier for the underlying hardware (eg board, CPU)
os.urandom(n)
Return a bytes object with n random bytes. Whenever possible, it is generated by the hardware random number
generator.
Filesystem access
os.chdir(path)
Change current directory.
os.getcwd()
Get the current directory.
[ ]
os.ilistdir( dir )
This function returns an iterator which then yields tuples corresponding to the entries in the directory that it is
listing. With no argument it lists the current directory, otherwise it lists the directory given by dir.
The tuples have the form (name, type, inode[, size]):
• name is a string (or bytes if dir is a bytes object) and is the name of the entry;
• type is an integer that specifies the type of the entry, with 0x4000 for directories and 0x8000 for regular files;
• inode is an integer corresponding to the inode of the file, and may be 0 for filesystems that don’t have such a
notion.
• Some platforms may return a 4-tuple that includes the entry’s size. For file entries, size is an integer repre-
senting the size of the file or -1 if unknown. Its meaning is currently undefined for directory entries.
[ ]
os.listdir( dir )
With no argument, list the current directory. Otherwise list the given directory.
os.mkdir(path)
Create a new directory.
os.remove(path)
Remove a file.
os.rmdir(path)
Remove a directory.
os.rename(old_path, new_path)
Rename a file.
os.stat(path)
Get the status of a file or directory.
os.statvfs(path)
Get the status of a filesystem.
Returns a tuple with the filesystem information in the following order:
• f_bsize – file system block size
• f_frsize – fragment size
• f_blocks – size of fs in f_frsize units
• f_bfree – number of free blocks
• f_bavail – number of free blocks for unprivileged users
• f_files – number of inodes
• f_ffree – number of free inodes
• f_favail – number of free inodes for unprivileged users
• f_flag – mount flags
• f_namemax – maximum filename length
Parameters related to inodes: f_files, f_ffree, f_avail and the f_flags parameter may return 0 as they
can be unavailable in a port-specific implementation.
os.sync()
Sync all filesystems.
Filesystem mounting
The following functions and classes have been moved to the vfs module. They are provided in this module only for
backwards compatibility and will be removed in version 2 of MicroPython.
os.mount(fsobj, mount_point, *, readonly)
See vfs.mount.
os.umount(mount_point )
See vfs.umount.
class os.VfsFat(block_dev)
See vfs.VfsFat.
Functions
platform.platform()
Returns a string identifying the underlying platform. This string is composed of several substrings in the following
order, delimited by dashes (-):
• the name of the platform system (e.g. Unix, Windows or MicroPython)
• the MicroPython version
• the architecture of the platform
• the version of the underlying platform
• the concatenation of the name of the libc that MicroPython is linked to and its corresponding version.
For example, this could be "MicroPython-1.20.0-xtensa-IDFv4.2.4-with-newlib3.0.0".
platform.python_compiler()
Returns a string identifying the compiler used for compiling MicroPython.
platform.libc_ver()
Returns a tuple of strings (lib, version), where lib is the name of the libc that MicroPython is linked to, and version
the corresponding version of this libc.
® Note
® Note
The randrange(), randint() and choice() functions are only available if the MI-
CROPY_PY_RANDOM_EXTRA_FUNCS configuration option is enabled.
Other Functions
random.seed(n=None, / )
Initialise the random number generator module with the seed n which should be an integer. When no argument
(or None) is passed in it will (if supported by the port) initialise the PRNG with a true random number (usually a
hardware generated random number).
The None case only works if MICROPY_PY_RANDOM_SEED_INIT_FUNC is enabled by the port, otherwise it raises
ValueError.
random.choice(sequence)
Chooses and returns one item at random from sequence (tuple, list or any object that supports the subscript opera-
tion).
[...]
Match set of characters. Individual characters and ranges are supported, including negated sets (e.g. [^a-c]).
^
Match the start of the string.
$
Match the end of the string.
?
Match zero or one of the previous sub-pattern.
*
Match zero or more of the previous sub-pattern.
+
Match one or more of the previous sub-pattern.
??
Non-greedy version of ?, match zero or one, with the preference for zero.
*?
Non-greedy version of *, match zero or more, with the preference for the shortest match.
+?
Non-greedy version of +, match one or more, with the preference for the shortest match.
|
Match either the left-hand side or the right-hand side sub-patterns of this operator.
(...)
Grouping. Each group is capturing (a substring it captures can be accessed with match.group() method).
\d
Matches digit. Equivalent to [0-9].
\D
Matches non-digit. Equivalent to [^0-9].
\s
Matches whitespace. Equivalent to [ \t-\r].
\S
Matches non-whitespace. Equivalent to [^ \t-\r].
\w
Matches “word characters” (ASCII only). Equivalent to [A-Za-z0-9_].
\W
Matches non “word characters” (ASCII only). Equivalent to [^A-Za-z0-9_].
\
Escape character. Any other character following the backslash, except for those listed above, is taken literally.
For example, \* is equivalent to literal * (not treated as the * operator). Note that \r, \n, etc. are not handled
specially, and will be equivalent to literal letters r, n, etc. Due to this, it’s not recommended to use raw Python
strings (r"") for regular expressions. For example, r"\r\n" when used as the regular expression is equivalent to
"rn". To match CR character followed by LF, use "\r\n".
NOT SUPPORTED:
• counted repetitions ({m,n})
• named groups ((?P<name>...))
import re
regex.split("line1\rline2\nline3\r\n")
# Result:
# ['line1', 'line2', 'line3', '', '']
Functions
[
re.compile(regex_str , flags ) ]
Compile regular expression, return regex object.
re.match(regex_str, string)
Compile regex_str and match against string. Match always happens from starting position in a string.
re.search(regex_str, string)
Compile regex_str and search it in a string. Unlike match, this will search string for first position which matches
regex (which still may be 0 if regex is anchored).
re.sub(regex_str, replace, string, count=0, flags=0, / )
Compile regex_str and search for it in string, replacing all matches with replace, and returning the new string.
replace can be a string or a function. If it is a string then escape sequences of the form \<number> and \
g<number> can be used to expand to the corresponding group (or an empty string for unmatched groups). If
replace is a function then it must take a single argument (the match) and should return a replacement string.
If count is specified and non-zero then substitution will stop after this many substitutions are made. The flags
argument is ignored.
Note: availability of this function depends on MicroPython port.
re.DEBUG
Flag value, display debug information about compiled expression. (Availability depends on MicroPython port.)
Regex objects
Compiled regular expression. Instances of this class are created using re.compile().
regex.match(string)
regex.search(string)
regex.sub(replace, string, count=0, flags=0, / )
Similar to the module-level functions match(), search() and sub(). Using methods is (much) more efficient
if the same regex is applied to multiple strings.
regex.split(string, max_split=-1, / )
Split a string using regex. If max_split is given, it specifies maximum number of splits to perform. Returns list of
strings (there may be up to max_split+1 elements if it’s specified).
Match objects
Match objects as returned by match() and search() methods, and passed to the replacement function in sub().
match.group(index)
Return matching (sub)string. index is 0 for entire match, 1 and above for each capturing group. Only numeric
groups are supported.
match.groups()
Return a tuple containing all the substrings of the groups of the match.
Note: availability of this method depends on MicroPython port.
match.start( index ) [ ]
[
match.end( index ) ]
Return the index in the original string of the start or end of the substring group that was matched. index defaults to
the entire group, otherwise it will select a group.
Note: availability of these methods depends on MicroPython port.
[
match.span( index ) ]
Returns the 2-tuple (match.start(index), match.end(index)).
Note: availability of this method depends on MicroPython port.
Functions
select.poll()
Create an instance of the Poll class.
[
select.select(rlist, wlist, xlist , timeout ) ]
Wait for activity on a set of objects.
This function is provided by some MicroPython ports for compatibility and is not efficient. Usage of Poll is
recommended instead.
class Poll
Methods
[
poll.register(obj , eventmask ) ]
Register stream obj for polling. eventmask is logical OR of:
• select.POLLIN - data available for reading
• select.POLLOUT - more data can be written
Note that flags like select.POLLHUP and select.POLLERR are not valid as input eventmask (these are unso-
licited events which will be returned from poll() regardless of whether they are asked for). This semantics is per
POSIX.
eventmask defaults to select.POLLIN | select.POLLOUT.
It is OK to call this function multiple times for the same obj. Successive calls will update obj’s eventmask to the
value of eventmask (i.e. will behave as modify()).
poll.unregister(obj )
Unregister obj from polling.
poll.modify(obj, eventmask)
Modify the eventmask for obj. If obj is not registered, OSError is raised with error of ENOENT.
poll.poll(timeout=-1, / )
Wait for at least one of the registered objects to become ready or have an exceptional condition, with optional
timeout in milliseconds (if timeout arg is not specified or -1, there is no timeout).
Returns list of (obj, event, …) tuples. There may be other elements in tuple, depending on a platform and version,
so don’t assume that its size is 2. The event element specifies which events happened with a stream and is a combi-
nation of select.POLL* constants described above. Note that flags select.POLLHUP and select.POLLERR
can be returned at any time (even if were not asked for), and must be acted on accordingly (the corresponding
stream unregistered from poll and likely closed), because otherwise all further invocations of poll() may return
immediately with these flags set for this stream again.
In case of timeout, an empty list is returned.
® Difference to CPython
poll.ipoll(timeout=-1, flags=0, / )
Like poll.poll(), but instead returns an iterator which yields a callee-owned tuple. This function provides
an efficient, allocation-free way to poll on streams.
If flags is 1, one-shot behaviour for events is employed: streams for which events happened will have their event
masks automatically reset (equivalent to poll.modify(obj, 0)), so new events for such a stream won’t be
processed until new mask is set with poll.modify(). This behaviour is useful for asynchronous I/O schedulers.
® Difference to CPython
® Difference to CPython
For efficiency and consistency, socket objects in MicroPython implement a stream (file-like) interface directly. In
CPython, you need to convert a socket to a file-like object using makefile() method. This method is still supported
by MicroPython (but is a no-op), so where compatibility with CPython matters, be sure to use it.
Using getaddrinfo is the most efficient (both in terms of memory and processing power) and portable way to work
with addresses.
However, socket module (note the difference with native MicroPython socket module described here) provides
CPython-compatible way to specify addresses using tuples, as described below. Note that depending on a MicroPy-
thon port, socket module can be builtin or need to be installed from micropython-lib (as in the case of MicroPython
Unix port), and some ports still accept only numeric addresses in the tuple format, and require to use getaddrinfo
function to resolve domain names.
Summing up:
• Always use getaddrinfo when writing portable applications.
• Tuple addresses described below can be used as a shortcut for quick hacks and interactive use, if your port supports
them.
Tuple address format for socket module:
• IPv4: (ipv4_address, port), where ipv4_address is a string with dot-notation numeric IPv4 address, e.g. "8.8.
8.8", and port is and integer port number in the range 1-65535. Note the domain names are not accepted as
ipv4_address, they should be resolved first using socket.getaddrinfo().
• IPv6: (ipv6_address, port, flowinfo, scopeid), where ipv6_address is a string with colon-notation numeric IPv6 ad-
dress, e.g. "2001:db8::1", and port is an integer port number in the range 1-65535. flowinfo must be 0. scopeid
is the interface scope identifier for link-local addresses. Note the domain names are not accepted as ipv6_address,
they should be resolved first using socket.getaddrinfo(). Availability of IPv6 support depends on a MicroPy-
thon port.
Functions
socket.getaddrinfo(host, port, af=0, type=0, proto=0, flags=0, / )
Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a
socket connected to that service. Arguments af, type, and proto (which have the same meaning as for the socket()
function) can be used to filter which kind of addresses are returned. If a parameter is not specified or zero, all
combinations of addresses can be returned (requiring filtering on the user side).
The resulting list of 5-tuples has the following structure:
s = socket.socket()
# This assumes that if "type" is not specified, an address for
# SOCK_STREAM will be returned, which may be not true
s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])
s = socket.socket()
# Guaranteed to return an address which can be connect'ed to for
# stream operation.
s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1])
® Difference to CPython
CPython raises a socket.gaierror exception (OSError subclass) in case of error in this function. Mi-
croPython doesn’t have socket.gaierror and raises OSError directly. Note that error numbers of getad-
drinfo() form a separate namespace and may not match error numbers from the errno module. To distin-
guish getaddrinfo() errors, they are represented by negative numbers, whereas standard system errors are
positive numbers (error numbers are accessible using e.args[0] property from an exception object). The
use of negative values is a provisional detail which may change in the future.
socket.inet_ntop(af, bin_addr)
Convert a binary network address bin_addr of the given address family af to a textual representation:
socket.inet_pton(af, txt_addr)
Convert a textual network address txt_addr of the given address family af to a binary representation:
Constants
socket.AF_INET
socket.AF_INET6
Address family types. Availability depends on a particular MicroPython port.
socket.SOCK_STREAM
socket.SOCK_DGRAM
Socket types.
socket.IPPROTO_UDP
socket.IPPROTO_TCP
IP protocol numbers. Availability depends on a particular MicroPython port. Note that you don’t need to specify
these in a call to socket.socket(), because SOCK_STREAM socket type automatically selects IPPROTO_TCP,
and SOCK_DGRAM - IPPROTO_UDP. Thus, the only real use of these constants is as an argument to setsockopt().
socket.SOL_*
Socket option levels (an argument to setsockopt()). The exact inventory depends on a MicroPython port.
socket.SO_*
Socket options (an argument to setsockopt()). The exact inventory depends on a MicroPython port.
Constants specific to WiPy:
socket.IPPROTO_SEC
Special protocol value to create SSL-compatible socket.
class socket
Methods
socket.close()
Mark the socket closed and release all resources. Once that happens, all future operations on the socket object will
fail. The remote end will receive EOF indication if supported by protocol.
Sockets are automatically closed when they are garbage-collected, but it is recommended to close() them ex-
plicitly as soon you finished working with them.
socket.bind(address)
Bind the socket to address. The socket must not already be bound.
[
socket.listen( backlog ) ]
Enable a server to accept connections. If backlog is specified, it must be at least 0 (if it’s lower, it will be set to 0);
and specifies the number of unaccepted connections that the system will allow before refusing new connections. If
not specified, a default reasonable value is chosen.
socket.accept()
Accept a connection. The socket must be bound to an address and listening for connections. The return value is
a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and
address is the address bound to the socket on the other end of the connection.
socket.connect(address)
Connect to a remote socket at address.
socket.send(bytes)
Send data to the socket. The socket must be connected to a remote socket. Returns number of bytes sent, which
may be smaller than the length of data (“short write”).
socket.sendall(bytes)
Send all data to the socket. The socket must be connected to a remote socket. Unlike send(), this method will
try to send all of data, by sending data chunk by chunk consecutively.
The behaviour of this method on non-blocking sockets is undefined. Due to this, on MicroPython, it’s recommended
to use write() method instead, which has the same “no short writes” policy for blocking sockets, and will return
number of bytes sent on non-blocking sockets.
socket.recv(bufsize)
Receive data from the socket. The return value is a bytes object representing the data received. The maximum
amount of data to be received at once is specified by bufsize.
socket.sendto(bytes, address)
Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is
specified by address.
socket.recvfrom(bufsize)
Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object representing
the data received and address is the address of the socket sending the data.
socket.setsockopt(level, optname, value)
Set the value of the given socket option. The needed symbolic constants are defined in the socket module (SO_*
etc.). The value can be an integer or a bytes-like object representing a buffer.
socket.settimeout(value)
Note: Not every port supports this method, see below.
Set a timeout on blocking socket operations. The value argument can be a nonnegative floating point number
expressing seconds, or None. If a non-zero value is given, subsequent socket operations will raise an OSError
exception if the timeout period value has elapsed before the operation has completed. If zero is given, the socket
is put in non-blocking mode. If None is given, the socket is put in blocking mode.
Not every MicroPython port supports this method. A more portable and generic solution is to use select.poll
object. This allows to wait on multiple objects at the same time (and not just on sockets, but on generic stream
objects which support polling). Example:
# Instead of:
s.settimeout(1.0) # time in seconds
s.read(10) # may timeout
# Use:
poller = select.poll()
poller.register(s, select.POLLIN)
res = poller.poll(1000) # time in milliseconds
if not res:
# s is still not ready for input, i.e. operation timed out
® Difference to CPython
CPython raises a socket.timeout exception in case of timeout, which is an OSError subclass. MicroPython
raises an OSError directly instead. If you use except OSError: to catch the exception, your code will work
both in MicroPython and CPython.
socket.setblocking(flag)
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking, else to blocking
mode.
This method is a shorthand for certain settimeout() calls:
• sock.setblocking(True) is equivalent to sock.settimeout(None)
• sock.setblocking(False) is equivalent to sock.settimeout(0)
socket.makefile(mode='rb', buffering=0, / )
Return a file object associated with the socket. The exact returned type depends on the arguments given to make-
file(). The support is limited to binary modes only (‘rb’, ‘wb’, and ‘rwb’). CPython’s arguments: encoding, errors
and newline are not supported.
® Difference to CPython
As MicroPython doesn’t support buffered streams, values of buffering parameter is ignored and treated as if it
was 0 (unbuffered).
® Difference to CPython
Closing the file object returned by makefile() WILL close the original socket as well.
[
socket.read( size ) ]
Read up to size bytes from the socket. Return a bytes object. If size is not given, it reads all data available from the
socket until EOF; as such the method will not return until the socket is closed. This function tries to read as much
data as requested (no “short reads”). This may be not possible with non-blocking socket though, and then less data
will be returned.
[
socket.readinto(buf , nbytes ) ]
Read bytes into the buf. If nbytes is specified then read at most that many bytes. Otherwise, read at most len(buf)
bytes. Just as read(), this method follows “no short reads” policy.
Return value: number of bytes read and stored into buf.
socket.readline()
Read a line, ending in a newline character.
Return value: the line read.
socket.write(buf )
Write the buffer of bytes to the socket. This function will try to write all data to a socket (no “short writes”). This
may be not possible with a non-blocking socket though, and returned value will be less than the length of buf.
Return value: number of bytes written.
exception socket.error
MicroPython does NOT have this exception.
® Difference to CPython
CPython used to have a socket.error exception which is now deprecated, and is an alias of OSError. In
MicroPython, use OSError directly.
Functions
ssl.wrap_socket(sock, server_side=False, key=None, cert=None, cert_reqs=CERT_NONE, cadata=None,
server_hostname=None, do_handshake=True)
Wrap the given sock and return a new wrapped-socket object. The implementation of this function
is to first create an SSLContext and then call the SSLContext.wrap_socket method on that con-
text object. The arguments sock, server_side and server_hostname are passed through unchanged to
the method call. The argument do_handshake is passed through as do_handshake_on_connect. The
remaining arguments have the following behaviour:
• cert_reqs determines whether the peer (server or client) must present a valid certificate. Note that for
mbedtls based ports, ssl.CERT_NONE and ssl.CERT_OPTIONAL will not validate any certificate, only
ssl.CERT_REQUIRED will.
• cadata is a bytes object containing the CA certificate chain (in DER format) that will validate the peer’s
certificate. Currently only a single DER-encoded certificate is supported.
Depending on the underlying module implementation in a particular MicroPython port, some or all keyword argu-
ments above may be not supported.
class SSLContext
class ssl.SSLContext(protocol, / )
Create a new SSLContext instance. The protocol argument must be one of the PROTOCOL_* constants.
SSLContext.load_cert_chain(certfile, keyfile)
Load a private key and the corresponding certificate. The certfile is a string with the file path of the certificate. The
keyfile is a string with the file path of the private key.
® Difference to CPython
MicroPython extension: certfile and keyfile can be bytes objects instead of strings, in which case they are
interpreted as the actual certificate/key data.
SSLContext.load_verify_locations(cafile=None, cadata=None)
Load the CA certificate chain that will validate the peer’s certificate. cafile is the file path of the CA certificates.
cadata is a bytes object containing the CA certificates. Only one of these arguments should be provided.
SSLContext.get_ciphers()
Get a list of enabled ciphers, returned as a list of strings.
SSLContext.set_ciphers(ciphers)
Set the available ciphers for sockets created with this context. ciphers should be a list of strings in the IANA cipher
suite format .
SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None)
Takes a stream sock (usually socket.socket instance of SOCK_STREAM type), and returns an instance of
ssl.SSLSocket, wrapping the underlying stream. The returned object has the usual stream interface methods
like read(), write(), etc.
• server_side selects whether the wrapped socket is on the server or client side. A server-side SSL socket should
be created from a normal socket returned from accept() on a non-SSL listening server socket.
Á Warning
Some implementations of ssl module do NOT validate server certificates, which makes an SSL connection estab-
lished prone to man-in-the-middle attacks.
CPython’s wrap_socket returns an SSLSocket object which has methods typical for sockets, such as send, recv,
etc. MicroPython’s wrap_socket returns an object more similar to CPython’s SSLObject which does not have
these socket methods.
SSLContext.verify_mode
Set or get the behaviour for verification of peer certificates. Must be one of the CERT_* constants.
® Note
ssl.CERT_REQUIRED requires the device’s date/time to be properly set, e.g. using mpremote rtc --set or ntptime,
and server_hostname must be specified when on the client side.
Exceptions
ssl.SSLError
This exception does NOT exist. Instead its base class, OSError, is used.
DTLS support
® Difference to CPython
This module supports DTLS in client and server mode via the PROTOCOL_DTLS_CLIENT and PROTOCOL_DTLS_SERVER
constants that can be used as the protocol argument of SSLContext.
In this case the underlying socket is expected to behave as a datagram socket (i.e. like the socket opened with socket.
socket with socket.AF_INET as af and socket.SOCK_DGRAM as type).
DTLS is only supported on ports that use mbed TLS, and it is not enabled by default: it requires enabling
MBEDTLS_SSL_PROTO_DTLS in the specific port configuration.
Constants
ssl.PROTOCOL_TLS_CLIENT
ssl.PROTOCOL_TLS_SERVER
ssl.PROTOCOL_DTLS_CLIENT(when DTLS support is enabled )
(1) Requires long support when used with values larger than 30 bits.
(2) Requires floating point support.
® Difference to CPython
Functions
struct.calcsize(fmt )
Return the number of bytes needed to store the given fmt.
struct.pack(fmt, v1, v2, ...)
Pack the values v1, v2, … according to the format string fmt. The return value is a bytes object encoding the values.
struct.pack_into(fmt, buffer, offset, v1, v2, ...)
Pack the values v1, v2, … according to the format string fmt into a buffer starting at offset. offset may be negative
to count from the end of buffer.
struct.unpack(fmt, data)
Unpack from the data according to the format string fmt. The return value is a tuple of the unpacked values.
struct.unpack_from(fmt, data, offset=0, / )
Unpack from the data starting at offset according to the format string fmt. offset may be negative to count from the
end of data. The return value is a tuple of the unpacked values.
Functions
sys.exit(retval=0, / )
Terminate current program with a given exit code. Underlyingly, this function raises a SystemExit exception. If
an argument is given, its value given as an argument to SystemExit.
On embedded ports (i.e. all ports but Windows and Unix), an unhandled SystemExit currently causes a Soft Reset
of MicroPython.
sys.atexit(func)
Register func to be called upon termination. func must be a callable that takes no arguments, or None to disable
the call. The atexit function will return the previous value set by this function, which is initially None.
® Difference to CPython
This function is a MicroPython extension intended to provide similar functionality to the atexit module in
CPython.
sys.print_exception(exc, file=sys.stdout, / )
Print exception with a traceback to a file-like object file (or sys.stdout by default).
® Difference to CPython
This is simplified version of a function which appears in the traceback module in CPython. Unlike
traceback.print_exception(), this function takes just exception value instead of exception type, ex-
ception value, and traceback object; file argument should be positional; further arguments are not supported.
CPython-compatible traceback module can be found in micropython-lib.
sys.settrace(tracefunc)
Enable tracing of bytecode execution. For details see the CPython documentation.
This function requires a custom MicroPython build as it is typically not present in pre-built firmware (due to it
affecting performance). The relevant configuration option is MICROPY_PY_SYS_SETTRACE.
Constants
sys.argv
A mutable list of arguments the current program was started with.
sys.byteorder
The byte order of the system ("little" or "big").
sys.implementation
Object with information about the current Python implementation. For MicroPython, it has following attributes:
• name - string “micropython”
• version - tuple (major, minor, micro, releaselevel), e.g. (1, 22, 0, ‘’)
• _machine - string describing the underlying machine
• _mpy - supported mpy file-format version (optional attribute)
This object is the recommended way to distinguish MicroPython from other Python implementations (note that it
still may not exist in the very minimal ports).
Starting with version 1.22.0-preview, the fourth node releaselevel in implementation.version is either an empty string
or "preview".
® Difference to CPython
CPython mandates more attributes for this object, but the actual useful bare minimum is implemented in Mi-
croPython.
sys.maxsize
Maximum value which a native integer type can hold on the current platform, or maximum value representable by
MicroPython integer type, if it’s smaller than platform max value (that is the case for MicroPython ports without
long int support).
This attribute is useful for detecting “bitness” of a platform (32-bit vs 64-bit, etc.). It’s recommended to not compare
this attribute to some value directly, but instead count number of bits in it:
bits = 0
v = sys.maxsize
while v:
bits += 1
v >>= 1
if bits > 32:
# 64-bit (or more) platform
...
else:
# 32-bit (or less) platform
# Note that on 32-bit platform, value of bits may be less than 32
# (e.g. 31) due to peculiarities described above, so use "> 16",
# "> 32", "> 64" style of comparisons.
sys.modules
Dictionary of loaded modules. On some ports, it may not include builtin modules.
sys.path
A mutable list of directories to search for imported modules.
® Difference to CPython
On MicroPython, an entry with the value ".frozen" will indicate that import should search frozen modules at
that point in the search. If no frozen module is found then search will not look for a directory called .frozen,
instead it will continue with the next entry in sys.path.
sys.platform
The platform that MicroPython is running on. For OS/RTOS ports, this is usually an identifier of the OS, e.g.
"linux". For baremetal ports it is an identifier of a board, e.g. "pyboard" for the original MicroPython reference
board. It thus can be used to distinguish one board from another. If you need to check whether your program runs
on MicroPython (vs other Python implementation), use sys.implementation instead.
sys.ps1
sys.ps2
Mutable attributes holding strings, which are used for the REPL prompt. The defaults give the standard Python
prompt of >>> and ....
sys.stderr
Standard error stream.
sys.stdin
Standard input stream.
sys.stdout
Standard output stream.
sys.tracebacklimit
A mutable attribute holding an integer value which is the maximum number of traceback entries to store in an
exception. Set to 0 to disable adding tracebacks. Defaults to 1000.
Note: this is not available on all ports.
sys.version
Python language version that this implementation conforms to, as a string.
sys.version_info
Python language version that this implementation conforms to, as a tuple of ints.
® Difference to CPython
Only the first three version numbers (major, minor, micro) are supported and they can be referenced
only by index, not by name.
The time module provides functions for getting the current time and date, measuring time intervals, and for delays.
Time Epoch: Unix port uses standard for POSIX systems epoch of 1970-01-01 00:00:00 UTC. However, some embedded
ports use epoch of 2000-01-01 00:00:00 UTC. Epoch year may be determined with gmtime(0)[0].
Maintaining actual calendar date/time: This requires a Real Time Clock (RTC). On systems with underlying OS (in-
cluding some RTOS), an RTC may be implicit. Setting and maintaining actual calendar time is responsibility of OS/RTOS
and is done outside of MicroPython, it just uses OS API to query date/time. On baremetal ports however system time de-
pends on machine.RTC() object. The current calendar time may be set using machine.RTC().datetime(tuple)
function, and maintained by following means:
• By a backup battery (which may be an additional, optional component for a particular board).
• Using networked time protocol (requires setup by a port/user).
• Set manually by a user on each power-up (many boards then maintain RTC time across hard resets, though some
may require setting it again in such case).
If actual calendar time is not maintained with a system/MicroPython RTC, functions below which require reference to
current absolute time may behave not as expected.
Functions
[
time.gmtime( secs ) ]
[
time.localtime( secs ) ]
Convert the time secs expressed in seconds since the Epoch (see above) into an 8-tuple which contains: (year,
month, mday, hour, minute, second, weekday, yearday) If secs is not provided or None, then the
current time from the RTC is used.
The gmtime() function returns a date-time tuple in UTC, and localtime() returns a date-time tuple in local
time.
The format of the entries in the 8-tuple are:
• year includes the century (for example 2014).
• month is 1-12
• mday is 1-31
• hour is 0-23
• minute is 0-59
• second is 0-59
• weekday is 0-6 for Mon-Sun
• yearday is 1-366
time.mktime()
This is inverse function of localtime. It’s argument is a full 8-tuple which expresses a time as per localtime. It
returns an integer which is the number of seconds since Jan 1, 2000.
time.sleep(seconds)
Sleep for the given number of seconds. Some boards may accept seconds as a floating-point number to sleep for a
fractional number of seconds. Note that other boards may not accept a floating-point argument, for compatibility
with them use sleep_ms() and sleep_us() functions.
time.sleep_ms(ms)
Delay for given number of milliseconds, should be positive or 0.
This function will delay for at least the given number of milliseconds, but may take longer than that if other pro-
cessing must take place, for example interrupt handlers or other threads. Passing in 0 for ms will still allow this
other processing to occur. Use sleep_us() for more precise delays.
time.sleep_us(us)
Delay for given number of microseconds, should be positive or 0.
This function attempts to provide an accurate delay of at least us microseconds, but it may take longer if the system
has other higher priority processing to perform.
time.ticks_ms()
Returns an increasing millisecond counter with an arbitrary reference point, that wraps around after some value.
The wrap-around value is not explicitly exposed, but we will refer to it as TICKS_MAX to simplify discussion.
Period of the values is TICKS_PERIOD = TICKS_MAX + 1. TICKS_PERIOD is guaranteed to be a power of two,
but otherwise may differ from port to port. The same period value is used for all of ticks_ms(), ticks_us(),
ticks_cpu() functions (for simplicity). Thus, these functions will return a value in range [0 .. TICKS_MAX],
inclusive, total TICKS_PERIOD values. Note that only non-negative values are used. For the most part, you should
treat values returned by these functions as opaque. The only operations available for them are ticks_diff() and
ticks_add() functions described below.
Note: Performing standard mathematical operations (+, -) or relational operators (<, <=, >, >=) directly on these
value will lead to invalid result. Performing mathematical operations and then passing their results as arguments to
ticks_diff() or ticks_add() will also lead to invalid results from the latter functions.
time.ticks_us()
Just like ticks_ms() above, but in microseconds.
time.ticks_cpu()
Similar to ticks_ms() and ticks_us(), but with the highest possible resolution in the system. This is usually
CPU clocks, and that’s why the function is named that way. But it doesn’t have to be a CPU clock, some other timing
source available in a system (e.g. high-resolution timer) can be used instead. The exact timing unit (resolution) of
this function is not specified on time module level, but documentation for a specific port may provide more specific
information. This function is intended for very fine benchmarking or very tight real-time loops. Avoid using it in
portable code.
Availability: Not every port implements this function.
time.ticks_add(ticks, delta)
Offset ticks value by a given number, which can be either positive or negative. Given a ticks value, this function
allows to calculate ticks value delta ticks before or after it, following modular-arithmetic definition of tick val-
ues (see ticks_ms() above). ticks parameter must be a direct result of call to ticks_ms(), ticks_us(), or
ticks_cpu() functions (or from previous call to ticks_add()). However, delta can be an arbitrary integer
number or numeric expression. ticks_add() is useful for calculating deadlines for events/tasks. (Note: you
must use ticks_diff() function to work with deadlines.)
Examples:
time.ticks_diff(ticks1, ticks2)
Measure ticks difference between values returned from ticks_ms(), ticks_us(), or ticks_cpu() functions,
as a signed value which may wrap around.
The argument order is the same as for subtraction operator, ticks_diff(ticks1, ticks2) has the same
meaning as ticks1 - ticks2. However, values returned by ticks_ms(), etc. functions may wrap around, so
directly using subtraction on them will produce incorrect result. That is why ticks_diff() is needed, it imple-
ments modular (or more specifically, ring) arithmetic to produce correct result even for wrap-around values (as long
as they not too distant in between, see below). The function returns signed value in the range [-TICKS_PERIOD/2
.. TICKS_PERIOD/2-1] (that’s a typical range definition for two’s-complement signed binary integers). If the result
is negative, it means that ticks1 occurred earlier in time than ticks2. Otherwise, it means that ticks1 occurred after
ticks2. This holds only if ticks1 and ticks2 are apart from each other for no more than TICKS_PERIOD/2-1 ticks. If
that does not hold, incorrect result will be returned. Specifically, if two tick values are apart for TICKS_PERIOD/2-
1 ticks, that value will be returned by the function. However, if TICKS_PERIOD/2 of real-time ticks has passed
between them, the function will return -TICKS_PERIOD/2 instead, i.e. result value will wrap around to the negative
range of possible values.
Informal rationale of the constraints above: Suppose you are locked in a room with no means to monitor passing
of time except a standard 12-notch clock. Then if you look at dial-plate now, and don’t look again for another 13
hours (e.g., if you fall for a long sleep), then once you finally look again, it may seem to you that only 1 hour has
passed. To avoid this mistake, just look at the clock regularly. Your application should do the same. “Too long
sleep” metaphor also maps directly to application behaviour: don’t let your application run any single task for too
long. Run tasks in steps, and do time-keeping in between.
ticks_diff() is designed to accommodate various usage patterns, among them:
• Polling with timeout. In this case, the order of events is known, and you will deal only with positive results
of ticks_diff():
• Scheduling events. In this case, ticks_diff() result may be negative if an event is overdue:
Note: Do not pass time() values to ticks_diff(), you should use normal mathematical operations on them.
But note that time() may (and will) also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_
problem .
time.time()
Returns the number of seconds, as an integer, since the Epoch, assuming that underlying RTC is set and maintained
as described above. If an RTC is not set, this function returns number of seconds since a port-specific reference
point in time (for embedded boards without a battery-backed RTC, usually since power up or reset). If you want
to develop portable MicroPython application, you should not rely on this function to provide higher than second
precision. If you need higher precision, absolute timestamps, use time_ns(). If relative times are acceptable
then use the ticks_ms() and ticks_us() functions. If you need calendar time, gmtime() or localtime()
without an argument is a better choice.
® Difference to CPython
In CPython, this function returns number of seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-
point, usually having microsecond precision. With MicroPython, only Unix port uses the same Epoch, and if
floating-point precision allows, returns sub-second precision. Embedded hardware usually doesn’t have floating-
point precision to represent both long time ranges and subsecond precision, so they use integer value with second
precision. Some embedded hardware also lacks battery-powered RTC, so returns number of seconds since last
power-up or from other relative, hardware-specific point (e.g. reset).
time.time_ns()
Similar to time() but returns nanoseconds since the Epoch, as an integer (usually a big integer, so will allocate on
the heap).
® Note
Prefer to use deflate.DeflateIO instead of the functions in this module as it provides a streaming interface to
compression and decompression which is convenient and more memory efficient when working with reading or writing
compressed data to a file, socket, or stream.
Availability:
• From MicroPython v1.21 onwards, this module may not be present by default on all MicroPython firmware as it
duplicates functionality available in the deflate module.
• A copy of this module can be installed (or frozen) from micropython-lib (source). See Package management for
more information. This documentation describes that module.
• Requires the built-in deflate module (available since MicroPython v1.21)
• Compression support will only be available if compression support is enabled in the built-in deflate module.
Functions
zlib.decompress(data, wbits=15, / )
Decompresses data into a bytes object.
The wbits parameter works the same way as for zlib.compress() with the following additional valid values:
• 0: Automatically determine the window size from the zlib header (data must be in zlib format).
• 35 to 47: Auto-detect either the zlib or gzip format.
As for zlib.compress(), see the CPython documentation for zlib for more information about the wbits
parameter. As for zlib.compress(), MicroPython also supports smaller window sizes than CPython. See more
MicroPython-specific details in the deflate module documentation.
If the data to be decompressed requires a larger window size, it will fail during decompression.
zlib.compress(data, wbits=15, / )
Compresses data into a bytes object.
wbits allows you to configure the DEFLATE dictionary window size and the output format. The window size allows
you to trade-off memory usage for compression level. A larger window size will allow the compressor to reference
fragments further back in the input. The output formats are “raw” DEFLATE (no header/footer), zlib, and gzip,
where the latter two include a header and checksum.
The low four bits of the absolute value of wbits set the base-2 logarithm of the DEFLATE dictionary window size.
So for example, wbits=10, wbits=-10, and wbits=26 all set the window size to 1024 bytes. Valid window
sizes are 5 to 15 inclusive (corresponding to 32 to 32k bytes).
Negative values of wbits between -5 and -15 correspond to “raw” output mode, positive values between 5 and 15
correspond to zlib output mode, and positive values between 21 and 31 correspond to gzip output mode.
See the CPython documentation for zlib for more information about the wbits parameter. Note that
MicroPython allows for smaller window sizes, which is useful when memory is constrained while still achieving a
reasonable level of compression. It also speeds up the compressor. See more MicroPython-specific details in the
deflate module documentation.
® Note
® Note
This module is still under development and its classes, functions, methods and constants are subject to change.
class BLE
Constructor
class bluetooth.BLE
Returns the singleton BLE object.
Configuration
[
BLE.active( active, / )]
Optionally changes the active state of the BLE radio, and returns the current state.
The radio must be made active before using any other methods on this class.
BLE.config('param', / )
BLE.config(*, param=value, ...)
Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string,
and just one parameter is queried at a time. To set values use the keyword syntax, and one or more parameter can
be set at a time.
Currently supported values are:
• 'mac': The current address in use, depending on the current address mode. This returns a tuple of
(addr_type, addr).
• 'mtu': Get/set the MTU that will be used during a ATT MTU exchange. The resulting MTU will be the
minimum of this and the remote device’s MTU. ATT MTU exchange will not happen automatically (un-
less the remote device initiates it), and must be manually initiated with gattc_exchange_mtu. Use the
_IRQ_MTU_EXCHANGED event to discover the MTU for a given connection.
• 'bond': Sets whether bonding will be enabled during pairing. When enabled, pairing requests will set the
“bond” flag and the keys will be stored by both devices.
• 'mitm': Sets whether MITM-protection is required for pairing.
• 'io': Sets the I/O capabilities of this device.
Available options are:
_IO_CAPABILITY_DISPLAY_ONLY = const(0)
_IO_CAPABILITY_DISPLAY_YESNO = const(1)
_IO_CAPABILITY_KEYBOARD_ONLY = const(2)
_IO_CAPABILITY_NO_INPUT_OUTPUT = const(3)
_IO_CAPABILITY_KEYBOARD_DISPLAY = const(4)
• 'le_secure': Sets whether “LE Secure” pairing is required. Default is false (i.e. allow “Legacy Pairing”).
Event Handling
BLE.irq(handler, / )
Registers a callback for events from the BLE stack. The handler takes two arguments, event (which will be one
of the codes below) and data (which is an event-specific tuple of values).
Note: As an optimisation to prevent unnecessary allocations, the addr, adv_data, char_data, notify_data,
and uuid entries in the tuples are read-only memoryview instances pointing to bluetooth’s internal ringbuffer,
and are only valid during the invocation of the IRQ handler function. If your program needs to save one of these
values to access after the IRQ handler has returned (e.g. by saving it in a class instance or global variable), then it
needs to take a copy of the data, either by using bytes() or bluetooth.UUID(), like this:
For example, the IRQ handler for a scan result might inspect the adv_data to decide if it’s the correct device,
and only then copy the address data to be used elsewhere in the program. And to print data from within the IRQ
handler, print(bytes(addr)) will be needed.
An event handler showing all possible events:
_GATTS_NO_ERROR = const(0x00)
_GATTS_ERROR_READ_NOT_PERMITTED = const(0x02)
_GATTS_ERROR_WRITE_NOT_PERMITTED = const(0x03)
_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05)
_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08)
_GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f)
_PASSKEY_ACTION_NONE = const(0)
_PASSKEY_ACTION_INPUT = const(2)
_PASSKEY_ACTION_DISPLAY = const(3)
_PASSKEY_ACTION_NUMERIC_COMPARISON = const(4)
In order to save space in the firmware, these constants are not included on the bluetooth module. Add the ones that
you need from the list above to your program.
When scanning is stopped (either due to the duration finishing or when explicitly stopped), the _IRQ_SCAN_DONE
event will be raised.
Central Role
A central device can connect to peripherals that it has discovered using the observer role (see gap_scan) or with a known
address.
BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, min_conn_interval_us=None,
max_conn_interval_us=None, / )
Connect to a peripheral.
See gap_scan for details about address types.
To cancel an outstanding connection attempt early, call gap_connect(None).
On success, the _IRQ_PERIPHERAL_CONNECT event will be raised. If cancelling a connection attempt, the
_IRQ_PERIPHERAL_DISCONNECT event will be raised.
The device will wait up to scan_duration_ms to receive an advertising payload from the device.
The connection interval can be configured in microseconds using either or both of min_conn_interval_us and
max_conn_interval_us. Otherwise a default interval will be chosen, typically between 30000 and 50000 microsec-
onds. A shorter interval will increase throughput, at the expense of power usage.
Peripheral Role
A peripheral device is expected to send connectable advertisements (see gap_advertise). It will usually be acting as a
GATT server, having first registered services and characteristics using gatts_register_services.
When a central connects, the _IRQ_CENTRAL_CONNECT event will be raised.
GATT Server
A GATT server has a set of registered services. Each service may contain characteristics, which each have a value.
Characteristics can also contain descriptors, which themselves have values.
These values are stored locally, and are accessed by their “value handle” which is generated during service registration.
They can also be read from or written to by a remote client device. Additionally, a server can “notify” a characteristic to
a connected client via a connection handle.
A device in either central or peripheral roles may function as a GATT server, however in most cases it will be more
common for a peripheral device to act as the server.
Characteristics and descriptors have a default maximum size of 20 bytes. Anything written to them by a client will
be truncated to this length. However, any local write will increase the maximum size, so if you want to allow larger
writes from a client to a given characteristic, use gatts_write after registration. e.g. gatts_write(char_handle,
bytes(100)).
BLE.gatts_register_services(services_definition, / )
Configures the server with the specified services, replacing any existing services.
services_definition is a list of services, where each service is a two-element tuple containing a UUID and a list of
characteristics.
Each characteristic is a two-or-three-element tuple containing a UUID, a flags value, and optionally a list of
descriptors.
Each descriptor is a two-element tuple containing a UUID and a flags value.
The flags are a bitwise-OR combination of the flags defined below. These set both the behaviour of the characteristic
(or descriptor) as well as the security and privacy requirements.
The return value is a list (one element per service) of tuples (each element is a value handle). Characteristics and
descriptor handles are flattened into the same tuple, in the order that they are defined.
The following example registers two services (Heart Rate, and Nordic UART):
HR_UUID = bluetooth.UUID(0x180D)
HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
HR_SERVICE = (HR_UUID, (HR_CHAR,),)
UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_
,→READ | bluetooth.FLAG_NOTIFY,)
The three value handles (hr, tx, rx) can be used with gatts_read, gatts_write, gatts_notify , and
gatts_indicate.
_FLAG_AUX_WRITE = const(0x0100)
_FLAG_READ_ENCRYPTED = const(0x0200)
_FLAG_READ_AUTHENTICATED = const(0x0400)
_FLAG_READ_AUTHORIZED = const(0x0800)
_FLAG_WRITE_ENCRYPTED = const(0x1000)
_FLAG_WRITE_AUTHENTICATED = const(0x2000)
_FLAG_WRITE_AUTHORIZED = const(0x4000)
As for the IRQs above, any required constants should be added to your Python code.
BLE.gatts_read(value_handle, / )
Reads the local value for this handle (which has either been written by gatts_write or by a remote client).
BLE.gatts_write(value_handle, data, send_update=False, / )
Writes the local value for this handle, which can be read by a client.
If send_update is True, then any subscribed clients will be notified (or indicated, depending on what they’re sub-
scribed to and which operations the characteristic supports) about this write.
GATT Client
A GATT client can discover and read/write characteristics on a remote GATT server.
It is more common for a central role device to act as the GATT client, however it’s also possible for a peripheral to act as
a client in order to discover information about the central that has connected to it (e.g. to read the device name from the
device information service).
BLE.gattc_discover_services(conn_handle, uuid=None, / )
Query a connected server for its services.
Optionally specify a service uuid to query for that service only.
For each service discovered, the _IRQ_GATTC_SERVICE_RESULT event will be raised, followed by
_IRQ_GATTC_SERVICE_DONE on completion.
BLE.gattc_read(conn_handle, value_handle, / )
Issue a remote read to a connected server for the specified characteristic or descriptor handle.
When a value is available, the _IRQ_GATTC_READ_RESULT event will be raised. Additionally, the
_IRQ_GATTC_READ_DONE will be raised.
BLE.gattc_write(conn_handle, value_handle, data, mode=0, / )
Issue a remote write to a connected server for the specified characteristic or descriptor handle.
The argument mode specifies the write behaviour, with the currently supported values being:
• mode=0 (default) is a write-without-response: the write will be sent to the remote server but no confirmation
will be returned, and no event will be raised.
• mode=1 is a write-with-response: the remote server is requested to send a response/acknowledgement that it
received the data.
If a response is received from the remote server the _IRQ_GATTC_WRITE_DONE event will be raised.
BLE.gattc_exchange_mtu(conn_handle, / )
Initiate MTU exchange with a connected server, using the preferred MTU set using BLE.config(mtu=value).
The _IRQ_MTU_EXCHANGED event will be raised when MTU exchange completes.
Note: MTU exchange is typically initiated by the central. When using the BlueKitchen stack in the central role, it
does not support a remote peripheral initiating the MTU exchange. NimBLE works for both roles.
L2CAP connection-oriented-channels
This feature allows for socket-like data exchange between two BLE devices. Once the devices are connected
via GAP, either device can listen for the other to connect on a numeric PSM (Protocol/Service Multiplexer).
Note: This is currently only supported when using the NimBLE stack on STM32 and Unix (not ESP32).
Only one L2CAP channel may be active at a given time (i.e. you cannot connect while listening).
Active L2CAP channels are identified by the connection handle that they were established on and a CID
(channel ID).
Connection-oriented channels have built-in credit-based flow control. Unlike ATT, where devices negoti-
ate a shared MTU, both the listening and connecting devices each set an independent MTU which limits
the maximum amount of outstanding data that the remote device can send before it is fully consumed in
l2cap_recvinto.
BLE.l2cap_listen(psm, mtu, / )
Start listening for incoming L2CAP channel requests on the specified psm with the local MTU set to mtu.
When a remote device initiates a connection, the _IRQ_L2CAP_ACCEPT event will be raised, which gives the
listening server a chance to reject the incoming connection (by returning a non-zero integer).
Once the connection is accepted, the _IRQ_L2CAP_CONNECT event will be raised, allowing the server to obtain
the channel id (CID) and the local and remote MTU.
Note: It is not currently possible to stop listening.
BLE.l2cap_connect(conn_handle, psm, mtu, / )
Connect to a listening peer on the specified psm with local MTU set to mtu.
On successful connection, the _IRQ_L2CAP_CONNECT event will be raised, allowing the client to obtain the CID
and the local and remote (peer) MTU.
An unsuccessful connection will raise the _IRQ_L2CAP_DISCONNECT event with a non-zero status.
BLE.l2cap_disconnect(conn_handle, cid, / )
Disconnect an active L2CAP channel with the specified conn_handle and cid.
BLE.l2cap_send(conn_handle, cid, buf, / )
Send the specified buf (which must support the buffer protocol) on the L2CAP channel identified by conn_handle
and cid.
The specified buffer cannot be larger than the remote (peer) MTU, and no more than twice the size of the local
MTU.
This will return False if the channel is now “stalled”, which means that l2cap_send must not be called again
until the _IRQ_L2CAP_SEND_READY event is received (which will happen when the remote device grants more
credits, typically after it has received and processed the data).
BLE.l2cap_recvinto(conn_handle, cid, buf, / )
Receive data from the specified conn_handle and cid into the provided buf (which must support the buffer protocol,
e.g. bytearray or memoryview).
Returns the number of bytes read from the channel.
If buf is None, then returns the number of bytes available.
Note: After receiving the _IRQ_L2CAP_RECV event, the application should continue calling l2cap_recvinto
until no more bytes are available in the receive buffer (typically up to the size of the remote (peer) MTU).
Until the receive buffer is empty, the remote device will not be granted more channel credits and will be unable to
send any more data.
class UUID
Constructor
class bluetooth.UUID(value, / )
Creates a UUID instance with the specified value.
The value can be either:
• A 16-bit integer. e.g. 0x2908.
• A 128-bit UUID string. e.g. '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'.
# Prints b'two'
print(db[b"2"])
del db[b"2"]
# Prints:
# b"1"
# b"3"
for key in db:
print(key)
db.close()
Functions
btree.open(stream, *, flags=0, pagesize=0, cachesize=0, minkeypage=0)
Open a database from a random-access stream (like an open file). All other parameters are optional and keyword-
only, and allow to tweak advanced parameters of the database operation (most users will not need them):
• flags - Currently unused.
• pagesize - Page size used for the nodes in BTree. Acceptable range is 512-65536. If 0, a port-specific default
will be used, optimized for port’s memory usage and/or performance.
• cachesize - Suggested memory cache size in bytes. For a board with enough memory using larger values may
improve performance. Cache policy is as follows: entire cache is not allocated at once; instead, accessing a
new page in database will allocate a memory buffer for it, until value specified by cachesize is reached. Then,
these buffers will be managed using LRU (least recently used) policy. More buffers may still be allocated if
needed (e.g., if a database contains big keys and/or values). Allocated cache buffers aren’t reclaimed.
• minkeypage - Minimum number of keys to store per page. Default value of 0 equivalent to 2.
Returns a BTree object, which implements a dictionary protocol (set of methods), and some additional methods
described below.
Methods
btree.close()
Close the database. It’s mandatory to close the database at the end of processing, as some unwritten data may be
still in the cache. Note that this does not close underlying stream with which the database was opened, it should be
closed separately (which is also mandatory to make sure that data flushed from buffer to the underlying storage).
btree.flush()
Flush any data in cache to the underlying stream.
btree.__getitem__(key)
btree.get(key, default=None, / )
btree.__setitem__(key, val)
btree.__delitem__(key)
btree.__contains__(key)
Standard dictionary methods.
btree.__iter__()
A BTree object can be iterated over directly (similar to a dictionary) to get access to all keys in order.
[ [ [
btree.keys( start_key , end_key , flags]]])
btree.values([start_key[, end_key[, flags ]]])
btree.items([start_key[, end_key[, flags ]]])
These methods are similar to standard dictionary methods, but also can take optional parameters to iterate over a key
sub-range, instead of the entire database. Note that for all 3 methods, start_key and end_key arguments represent
key values. For example, values() method will iterate over values corresponding to they key range given. None
values for start_key means “from the first key”, no end_key or its value of None means “until the end of database”.
By default, range is inclusive of start_key and exclusive of end_key, you can include end_key in iteration by passing
flags of btree.INCL. You can iterate in descending key direction by passing flags of btree.DESC . The flags
values can be ORed together.
Constants
btree.INCL
A flag for keys(), values(), items() methods to specify that scanning should be inclusive of the end key.
btree.DESC
A flag for keys(), values(), items() methods to specify that scanning should be in descending direction of
keys.
[
encrypt(in_buf , out_buf ) ]
Encrypt in_buf. If no out_buf is given result is returned as a newly allocated bytes object. Otherwise, result
is written into mutable buffer out_buf. in_buf and out_buf can also refer to the same mutable buffer, in which
case data is encrypted in-place.
[
decrypt(in_buf , out_buf ) ]
Like encrypt(), but for decryption.
Classes
class deflate.DeflateIO(stream, format=AUTO, wbits=0, close=False, / )
This class can be used to wrap a stream which is any stream-like object such as a file, socket, or stream (including
io.BytesIO). It is itself a stream and implements the standard read/readinto/write/close methods.
The stream must be a blocking stream. Non-blocking streams are currently not supported.
The format can be set to any of the constants defined below, and defaults to AUTO which for decompressing will
auto-detect gzip or zlib streams, and for compressing it will generate a raw stream.
The wbits parameter sets the base-2 logarithm of the DEFLATE dictionary window size. So for example, setting
wbits to 10 sets the window size to 1024 bytes. Valid values are 5 to 15 inclusive (corresponding to window sizes
of 32 to 32k bytes).
If wbits is set to 0 (the default), then for compression a window size of 256 bytes will be used (as if wbits was set
to 8). For decompression, it depends on the format:
• RAW will use 256 bytes (corresponding to wbits set to 8).
• ZLIB (or AUTO with zlib detected) will use the value from the zlib header.
• GZIP (or AUTO with gzip detected) will use 32 kilobytes (corresponding to wbits set to 15).
See the window size notes below for more information about the window size, zlib, and gzip streams.
If close is set to True then the underlying stream will be closed automatically when the deflate.DeflateIO
stream is closed. This is useful if you want to return a deflate.DeflateIO stream that wraps another stream
and not have the caller need to know about managing the underlying stream.
If compression is enabled, a given deflate.DeflateIO instance supports both reading and writing. For example,
a bidirectional stream like a socket can be wrapped, which allows for compression/decompression in both directions.
Constants
deflate.AUTO
deflate.RAW
deflate.ZLIB
deflate.GZIP
Supported values for the format parameter.
Examples
A typical use case for deflate.DeflateIO is to read or write a compressed file from storage:
import deflate
# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
with open("data.gz", "wb") as f:
with deflate.DeflateIO(f, deflate.ZLIB) as d:
# Use d.write(...) etc
Because deflate.DeflateIO is a stream, it can be used for example with json.dump() and json.load() (and any
other places streams can be used):
If your source data is not in a stream format, you can use io.BytesIO to turn it into a stream suitable for use with
deflate.DeflateIO:
import deflate, io
Decompression
The zlib format includes a header which specifies the window size that was used to compress the data. This indicates the
maximum window size required to decompress this stream. If this header value is less than the specified wbits value (or
if wbits is unset), then the header value will be used.
The gzip format does not include the window size in the header, and assumes that all gzip compressors (e.g. the gzip
utility, or CPython’s implementation of gzip.GzipFile) use the maximum window size of 32kiB. For this reason, if
the wbits parameter is not set, the decompressor will use a 32 kiB window size (corresponding to wbits set to 15). This
means that to be able to decompress an arbitrary gzip stream, you must have at least this much RAM available. If you
control the source data, consider instead using the zlib format with a smaller window size.
The raw format has no header and therefore does not include any information about the window size. If wbits is not set,
then it will default to a window size of 256 bytes, which may not be large enough for a given stream. Therefore it is
recommended that you should always explicitly set wbits if using the raw format.
Compression
For compression, MicroPython will default to a window size of 256 bytes for all formats. This provides a reasonable
amount of compression with minimal memory usage and fast compression time, and will generate output that will work
with any decompressor.
class FrameBuffer
The FrameBuffer class provides a pixel buffer which can be drawn upon with pixels, lines, rectangles, ellipses, polygons,
text and even other FrameBuffers. It is useful when generating output for displays.
For example:
import framebuf
fbuf.fill(0)
(continues on next page)
Constructors
class framebuf.FrameBuffer(buffer, width, height, format, stride=width, / )
Construct a FrameBuffer object. The parameters are:
• buffer is an object with a buffer protocol which must be large enough to contain every pixel defined by the
width, height and format of the FrameBuffer.
• width is the width of the FrameBuffer in pixels
• height is the height of the FrameBuffer in pixels
• format specifies the type of pixel used in the FrameBuffer; permissible values are listed under Constants
below. These set the number of bits used to encode a color value and the layout of these bits in buffer. Where
a color value c is passed to a method, c is a small integer with an encoding that is dependent on the format of
the FrameBuffer.
• stride is the number of pixels between each horizontal line of pixels in the FrameBuffer. This defaults to width
but may need adjustments when implementing a FrameBuffer within another larger FrameBuffer or screen.
The buffer size must accommodate an increased step size.
One must specify valid buffer, width, height, format and optionally stride. Invalid buffer size or dimensions may
lead to unexpected errors.
FrameBuffer.vline(x, y, h, c)
The optional m parameter enables drawing to be restricted to certain quadrants of the ellipse. The LS four bits
determine which quadrants are to be drawn, with bit 0 specifying Q1, b1 Q2, b2 Q3 and b3 Q4. Quadrants are
numbered counterclockwise with Q1 being top right.
[ ]
FrameBuffer.poly(x, y, coords, c , f )
Given a list of coordinates, draw an arbitrary (convex or concave) closed polygon at the given x, y location using
the given color.
The coords must be specified as a array of integers, e.g. array('h', [x0, y0, x1, y1, ... xn, yn]).
The optional f parameter can be set to True to fill the polygon. Otherwise just a one pixel outline is drawn.
Drawing text
[ ]
FrameBuffer.text(s, x, y , c )
Write text to the FrameBuffer using the the coordinates as the upper-left corner of the text. The color of the text
can be defined by the optional argument but is otherwise a default value of 1. All characters have dimensions of
8x8 pixels and there is currently no way to change the font.
Other methods
FrameBuffer.scroll(xstep, ystep)
Shift the contents of the FrameBuffer by the given vector. This may leave a footprint of the previous colors in the
FrameBuffer.
FrameBuffer.blit(fbuf, x, y, key=-1, palette=None)
Draw another FrameBuffer on top of the current one at the given coordinates. If key is specified then it should be a
color integer and the corresponding color will be considered transparent: all pixels with that color value will not be
drawn. (If the palette is specified then the key is compared to the value from palette, not to the value directly from
fbuf.)
The palette argument enables blitting between FrameBuffers with differing formats. Typical usage is to render a
monochrome or grayscale glyph/icon to a color display. The palette is a FrameBuffer instance whose format is that
of the current FrameBuffer. The palette height is one pixel and its pixel width is the number of colors in the source
FrameBuffer. The palette for an N-bit source needs 2**N pixels; the palette for a monochrome source would have
2 pixels representing background and foreground colors. The application assigns a color to each pixel in the palette.
The color of the current pixel will be that of that palette pixel whose x position is the color of the corresponding
source pixel.
Constants
framebuf.MONO_VLSB
Monochrome (1-bit) color format This defines a mapping where the bits in a byte are vertically mapped with bit 0
being nearest the top of the screen. Consequently each byte occupies 8 vertical pixels. Subsequent bytes appear at
successive horizontal locations until the rightmost edge is reached. Further bytes are rendered at locations starting
at the leftmost edge, 8 pixels lower.
framebuf.MONO_HLSB
Monochrome (1-bit) color format This defines a mapping where the bits in a byte are horizontally mapped. Each
byte occupies 8 horizontal pixels with bit 7 being the leftmost. Subsequent bytes appear at successive horizontal
locations until the rightmost edge is reached. Further bytes are rendered on the next row, one pixel lower.
framebuf.MONO_HMSB
Monochrome (1-bit) color format This defines a mapping where the bits in a byte are horizontally mapped. Each
byte occupies 8 horizontal pixels with bit 0 being the leftmost. Subsequent bytes appear at successive horizontal
locations until the rightmost edge is reached. Further bytes are rendered on the next row, one pixel lower.
framebuf.RGB565
Red Green Blue (16-bit, 5+6+5) color format
framebuf.GS2_HMSB
Grayscale (2-bit) color format
framebuf.GS4_HMSB
Grayscale (4-bit) color format
framebuf.GS8
Grayscale (8-bit) color format
Memory access
The module exposes three objects used for raw memory access.
machine.mem8
Read/write 8 bits of memory.
machine.mem16
Read/write 16 bits of memory.
machine.mem32
Read/write 32 bits of memory.
Use subscript notation [...] to index these objects with the address of interest. Note that the address is the byte address,
regardless of the size of memory being accessed.
Example use (registers are specific to an stm32 microcontroller):
import machine
from micropython import const
GPIOA = const(0x48000000)
GPIO_BSRR = const(0x18)
GPIO_IDR = const(0x10)
# read PA3
value = (machine.mem32[GPIOA + GPIO_IDR] >> 3) & 1
# Disable interrupts
state = machine.disable_irq()
# Enable interrupts
machine.enable_irq(state)
machine.disable_irq()
Disable interrupt requests. Returns the previous IRQ state which should be considered an opaque value. This
return value should be passed to the enable_irq() function to restore interrupts to their original state, before
disable_irq() was called.
machine.enable_irq(state)
Re-enable interrupt requests. The state parameter should be the value that was returned from the most recent call
to the disable_irq() function.
[ ]
machine.freq( hz )
Returns the CPU frequency in hertz.
On some ports this can also be used to set the CPU frequency by passing in hz.
machine.idle()
Gates the clock to the CPU, useful to reduce power consumption at any time during short or long periods. Periph-
erals continue working and execution resumes as soon as any interrupt is triggered, or at most one millisecond after
the CPU was paused.
It is recommended to call this function inside any tight loop that is continuously checking for an external change
(i.e. polling). This will reduce power consumption without significantly impacting performance. To reduce power
consumption further then see the lightsleep(), time.sleep() and time.sleep_ms() functions.
machine.sleep()
® Note
[
machine.lightsleep( time_ms ) ]
[
machine.deepsleep( time_ms ) ]
Stops execution in an attempt to enter a low power state.
If time_ms is specified then this will be the maximum time in milliseconds that the sleep will last for. Otherwise
the sleep can last indefinitely.
With or without a timeout, execution may resume at any time if there are events that require processing. Such
events, or wake sources, should be configured before sleeping, like Pin change or RTC timeout.
The precise behaviour and power-saving capabilities of lightsleep and deepsleep is highly dependent on the under-
lying hardware, but the general properties are:
• A lightsleep has full RAM and state retention. Upon wake execution is resumed from the point where the
sleep was requested, with all subsystems operational.
• A deepsleep may not retain RAM or any other state of the system (for example peripherals or network in-
terfaces). Upon wake execution is resumed from the main script, similar to a hard or power-on reset. The
reset_cause() function will return machine.DEEPSLEEP and this can be used to distinguish a deepsleep
wake from other resets.
machine.wake_reason()
Get the wake reason. See constants for the possible return values.
Availability: ESP32, WiPy.
Miscellaneous functions
machine.unique_id()
Returns a byte string with a unique identifier of a board/SoC. It will vary from a board/SoC instance to another, if
underlying hardware allows. Length varies by hardware (so use substring of a full value if you expect a short ID).
In some MicroPython ports, ID corresponds to the network MAC address.
machine.time_pulse_us(pin, pulse_level, timeout_us=1000000, / )
Time a pulse on the given pin, and return the duration of the pulse in microseconds. The pulse_level argument
should be 0 to time a low pulse or 1 to time a high pulse.
If the current input value of the pin is different to pulse_level, the function first (*) waits until the pin input becomes
equal to pulse_level, then (**) times the duration that the pin is equal to pulse_level. If the pin is already equal to
pulse_level then timing starts straight away.
The function will return -2 if there was timeout waiting for condition marked (*) above, and -1 if there was timeout
during the main measurement, marked (**) above. The timeout is the same for both cases and given by timeout_us
(which is in microseconds).
machine.bitstream(pin, encoding, timing, data, / )
Transmits data by bit-banging the specified pin. The encoding argument specifies how the bits are encoded, and
timing is an encoding-specific timing specification.
The supported encodings are:
• 0 for “high low” pulse duration modulation. This will transmit 0 and 1 bits as timed pulses, starting with
the most significant bit. The timing must be a four-tuple of nanoseconds in the format (high_time_0,
low_time_0, high_time_1, low_time_1). For example, (400, 850, 800, 450) is the timing
specification for WS2812 RGB LEDs at 800kHz.
The accuracy of the timing varies between ports. On Cortex M0 at 48MHz, it is at best +/- 120ns, however on
faster MCUs (ESP8266, ESP32, STM32, Pyboard), it will be closer to +/-30ns.
® Note
For controlling WS2812 / NeoPixel strips, see the neopixel module for a higher-level API.
machine.rng()
Return a 24-bit software generated random number.
Availability: WiPy.
Constants
machine.IDLE
machine.SLEEP
machine.DEEPSLEEP
IRQ wake values.
machine.PWRON_RESET
machine.HARD_RESET
machine.WDT_RESET
machine.DEEPSLEEP_RESET
machine.SOFT_RESET
Reset causes.
machine.WLAN_WAKE
machine.PIN_WAKE
machine.RTC_WAKE
Wake-up reasons.
Classes
class Pin – control I/O pins
A pin object is used to control I/O pins (also known as GPIO - general-purpose input/output). Pin objects are commonly
associated with a physical pin that can drive an output voltage and read input voltages. 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 class.
A pin object is constructed by using an identifier which unambiguously specifies a certain I/O pin. The allowed forms of
the identifier and the physical pin that the identifier maps to are port-specific. Possibilities for the identifier are an integer,
a string or a tuple with port and pin number.
Usage Model:
Constructors
• value is valid only for Pin.OUT and Pin.OPEN_DRAIN modes and specifies initial output pin value if given,
otherwise the state of the pin peripheral remains unchanged.
• drive specifies the output power of the pin and can be one of: Pin.DRIVE_0, Pin.DRIVE_1, etc., increas-
ing in drive strength. The actual current driving capabilities are port dependent. Not all ports implement this
argument.
• alt specifies an alternate function for the pin and the values it can take are port dependent. This argument is
valid only for Pin.ALT and Pin.ALT_OPEN_DRAIN modes. It may be used when a pin supports more than
one alternate function. If only one pin alternate function is supported the this argument is not required. Not
all ports implement this argument.
As specified above, the Pin class allows to set an alternate function for a particular pin, but it does not specify any
further operations on such a pin. Pins configured in alternate-function mode are usually not used as GPIO but are
instead driven by other hardware peripherals. The only operation supported on such a pin is re-initialising, by calling
the constructor or Pin.init() method. If a pin that is configured in alternate-function mode is re-initialised with
Pin.IN, Pin.OUT, or Pin.OPEN_DRAIN, the alternate function will be removed from the pin.
Methods
Pin.off()
Set pin to “0” output level.
Pin.irq(handler=None, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, *, priority=1, wake=None, hard=False)
Configure an interrupt handler to be called when the trigger source of the pin is active. If the pin mode is Pin.IN
then the trigger source is the external value on the pin. If the pin mode is Pin.OUT then the trigger source is the
output buffer of the pin. Otherwise, if the pin mode is Pin.OPEN_DRAIN then the trigger source is the output
buffer for state ‘0’ and the external pin value for state ‘1’.
The arguments are:
• handler is an optional function to be called when the interrupt triggers. The handler must take exactly one
argument which is the Pin instance.
• trigger configures the event which can generate an interrupt. Possible values are:
– Pin.IRQ_FALLING interrupt on falling edge.
– Pin.IRQ_RISING interrupt on rising edge.
– Pin.IRQ_LOW_LEVEL interrupt on low level.
– Pin.IRQ_HIGH_LEVEL interrupt on high level.
These values can be OR’ed together to trigger on multiple events.
• priority sets the priority level of the interrupt. The values it can take are port-specific, but higher values
always represent higher priorities.
• wake selects the power mode in which this interrupt can wake up the system. It can be machine.IDLE,
machine.SLEEP or machine.DEEPSLEEP. These values can also be OR’ed together to make a pin generate
interrupts in more than one power mode.
• hard if true a hardware interrupt is used. This reduces the delay between the pin change and the handler
being called. Hard interrupt handlers may not allocate memory; see Writing interrupt handlers. Not all ports
support this argument.
This method returns a callback object.
The following methods are not part of the core Pin API and only implemented on certain ports.
Pin.low()
Set pin to “0” output level.
Availability: nrf, rp2, stm32 ports.
Pin.high()
Set pin to “1” output level.
Availability: nrf, rp2, stm32 ports.
[
Pin.mode( mode ) ]
Get or set the pin mode. See the constructor documentation for details of the mode argument.
Availability: cc3200, stm32 ports.
[
Pin.pull( pull ) ]
Get or set the pin pull state. See the constructor documentation for details of the pull argument.
Availability: cc3200, stm32 ports.
[
Pin.drive( drive ) ]
Get or set the pin drive strength. See the constructor documentation for details of the drive argument.
Availability: cc3200 port.
Pin.toggle()
Toggle output pin from “0” to “1” or vice-versa.
Availability: mimxrt, samd, rp2 ports.
Constants
The following constants are used to configure the pin objects. Note that not all constants are available on all ports.
Pin.IN
Pin.OUT
Pin.OPEN_DRAIN
Pin.ALT
Pin.ALT_OPEN_DRAIN
Pin.ANALOG
Selects the pin mode.
Pin.PULL_UP
Pin.PULL_DOWN
Pin.PULL_HOLD
Selects whether there is a pull up/down resistor. Use the value None for no pull.
Pin.DRIVE_0
Pin.DRIVE_1
Pin.DRIVE_2
Selects the pin drive strength. A port may define additional drive constants with increasing number corresponding
to increasing drive strength.
Pin.IRQ_FALLING
Pin.IRQ_RISING
Pin.IRQ_LOW_LEVEL
Pin.IRQ_HIGH_LEVEL
Selects the IRQ trigger type.
The Signal class is a simple extension of the Pin class. Unlike Pin, which can be only in “absolute” 0 and 1 states, a
Signal can be in “asserted” (on) or “deasserted” (off) states, while being inverted (active-low) or not. In other words, it
adds logical inversion support to Pin functionality. While this may seem a simple addition, it is exactly what is needed
to support wide array of simple digital devices in a way portable across different boards, which is one of the major
MicroPython goals. Regardless of whether different users have an active-high or active-low LED, a normally open or
normally closed relay - you can develop a single, nicely looking application which works with each of them, and capture
hardware configuration differences in few lines in the config file of your app.
Example:
# Now to light up both of them using Pin class, you'll need to set
# them to different values
led1_pin.value(1)
led2_pin.value(0)
# Even better:
led1.on()
led2.on()
Constructors
Methods
Signal.value( x ) [ ]
This method allows to set and get the value of the signal, depending on whether the argument x is supplied or not.
If the argument is omitted then this method gets the signal level, 1 meaning signal is asserted (active) and 0 - signal
inactive.
If the argument is supplied then this method sets the signal level. The argument x can be anything that converts to
a boolean. If it converts to True, the signal is active, otherwise it is inactive.
Correspondence between signal being active and actual logic level on the underlying pin depends on whether signal
is inverted (active-low) or not. For non-inverted signal, active status corresponds to logical 1, inactive - to logical
0. For inverted/active-low signal, active status corresponds to logical 0, while inactive - to logical 1.
Signal.on()
Activate signal.
Signal.off()
Deactivate signal.
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 discretised value.
For extra control over ADC sampling see machine.ADCBlock.
Example usage:
Constructors
Methods
The ADCBlock class provides access to an ADC peripheral which has a number of channels that can be used to sample
analog values. It allows finer control over configuration of machine.ADC objects, which do the actual sampling.
This class is not always available.
Example usage:
Constructors
Methods
ADCBlock.init(*, bits)
Configure the ADC peripheral. bits will set the resolution of the conversion process.
ADCBlock.connect(channel, *, ...)
ADCBlock.connect(source, *, ...)
ADCBlock.connect(channel, source, *, ...)
Connect up a channel on the ADC peripheral so it is ready for sampling, and return an ADC object that represents
that connection.
The channel argument must be an integer, and source must be an object (for example a Pin) which can be connected
up for sampling.
If only channel is given then it is configured for sampling.
If only source is given then that object is connected to a default channel ready for sampling.
If both channel and source are given then they are connected together and made ready for sampling.
Any additional keyword arguments are used to configure the returned ADC object, via its init method.
pwm.deinit()
Constructors
Methods
PWM.duty_u16( value ) [ ]
Get or set the current duty cycle of the PWM output, as an unsigned 16-bit value in the range 0 to 65535 inclusive.
With no arguments the duty cycle is returned.
With a single value argument the duty cycle is set to that value, measured as the ratio value / 65535.
[
PWM.duty_ns( value ) ]
Get or set the current pulse width of the PWM output, as a value in nanoseconds.
With no arguments the pulse width in nanoseconds is returned.
With a single value argument the pulse width is set to that value.
Limitations of PWM
• Not all frequencies can be generated with absolute accuracy due to the discrete nature of the computing hardware.
Typically the PWM frequency is obtained by dividing some integer base frequency by an integer divider. For
example, if the base frequency is 80MHz and the required PWM frequency is 300kHz the divider must be a non-
integer number 80000000 / 300000 = 266.67. After rounding the divider is set to 267 and the PWM frequency
will be 80000000 / 267 = 299625.5 Hz, not 300kHz. If the divider is set to 266 then the PWM frequency will be
80000000 / 266 = 300751.9 Hz, but again not 300kHz.
Some ports like the RP2040 one use a fractional divider, which allow a finer granularity of the frequency at higher
frequencies by switching the PWM pulse duration between two adjacent values, such that the resulting average
frequency is more close to the intended one, at the cost of spectral purity.
• The duty cycle has the same discrete nature and its absolute accuracy is not achievable. On most hardware platforms
the duty will be applied at the next frequency period. Therefore, you should wait more than “1/frequency” before
measuring the duty.
• The frequency and the duty cycle resolution are usually interdependent. The higher the PWM frequency the lower
the duty resolution which is available, and vice versa. For example, a 300kHz PWM frequency can have a duty
cycle resolution of 8 bit, not 16-bit as may be expected. In this case, the lowest 8 bits of duty_u16 are insignificant.
So:
and:
UART implements the standard UART/USART duplex serial communications protocol. At the physical level it consists
of 2 lines: RX and TX. The unit of communication is a character (not to be confused with a string character) which can
be 8 or 9 bits wide.
UART objects can be created and initialised using:
Constructors
Methods
– UART.INV_TX | UART.INV_RX will invert both lines (idle state at logic low).
• flow specifies which hardware flow control signals to use. The value is a bitmask.
– 0 will ignore hardware flow control signals.
– UART.RTS will enable receive flow control by using the RTS output pin to signal if the receive FIFO has
sufficient space to accept more data.
– UART.CTS will enable transmit flow control by pausing transmission when the CTS input pin signals that
the receiver is running low on buffer space.
– UART.RTS | UART.CTS will enable both, for full hardware flow control.
On the WiPy only the following keyword-only parameter is supported:
• pins is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order). Any of the pins can be
None if one wants the UART to operate with limited functionality. If the RTS pin is given the the RX pin
must be given as well. The same applies to CTS. When no pins are given, then the default set of TX and RX
pins is taken, and hardware flow control will be disabled. If pins is None, no pin assignment will be made.
® Note
It is possible to call init() multiple times on the same object in order to reconfigure UART on the fly. That
allows using single UART peripheral to serve different devices attached to different GPIO pins. Only one device
can be served at a time in that case. Also do not call deinit() as it will prevent calling init() again.
UART.deinit()
Turn off the UART bus.
® Note
You will not be able to call init() on the object after deinit(). A new instance needs to be created in that
case.
UART.any()
Returns an integer counting the number of characters that can be read without blocking. It will return 0 if there
are no characters available and a positive number if there are characters. The method may return 1 even if there is
more than one character available for reading.
For more sophisticated querying of available characters use select.poll:
poll = select.poll()
poll.register(uart, select.POLLIN)
poll.poll(timeout)
[
UART.read( nbytes ) ]
Read characters. If nbytes is specified then read at most that many bytes, otherwise read as much data as possible.
It may return sooner if a timeout is reached. The timeout is configurable in the constructor.
Return value: a bytes object containing the bytes read in. Returns None on timeout.
[
UART.readinto(buf , nbytes ) ]
Read bytes into the buf. If nbytes is specified then read at most that many bytes. Otherwise, read at most
len(buf) bytes. It may return sooner if a timeout is reached. The timeout is configurable in the constructor.
Return value: number of bytes read and stored into buf or None on timeout.
UART.readline()
Read a line, ending in a newline character. It may return sooner if a timeout is reached. The timeout is configurable
in the constructor.
Return value: the line read or None on timeout.
UART.write(buf )
Write the buffer of bytes to the bus.
Return value: number of bytes written or None on timeout.
UART.sendbreak()
Send a break condition on the bus. This drives the bus low for a duration longer than required for a normal
transmission of a character.
UART.flush()
Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout duration depends on
the tx buffer size and the baud rate. Unless flow control is enabled, a timeout should not occur.
® Note
For the esp8266 and nrf ports the call returns while the last byte is sent. If required, a one character wait time
has to be added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
UART.txdone()
Tells whether all data has been sent or no data transfer is happening. In this case, it returns True. If a data
transmission is ongoing it returns False.
® Note
For the esp8266 and nrf ports the call may return True even if the last byte of a transfer is still being sent. If
required, a one character wait time has to be added in the calling script.
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
UART.irq(handler=None, trigger=0, hard=False)
Configure an interrupt handler to be called when a UART event occurs.
The arguments are:
• handler is an optional function to be called when the interrupt event triggers. The handler must take exactly
one argument which is the UART instance.
• trigger configures the event(s) which can generate an interrupt. Possible values are a mask of one or more of
the following:
– UART.IRQ_RXIDLE interrupt after receiving at least one character and then the RX line goes idle.
– UART.IRQ_RX interrupt after each received character.
– UART.IRQ_TXIDLE interrupt after or while the last character(s) of a message are or have been sent.
– UART.IRQ_BREAK interrupt when a break state is detected at RX
• hard if true a hardware interrupt is used. This reduces the delay between the pin change and the handler
being called. Hard interrupt handlers may not allocate memory; see Writing interrupt handlers.
® Note
Constants
UART.RTS
UART.CTS
Flow control options.
Availability: esp32, mimxrt, renesas-ra, rp2, stm32.
UART.IRQ_RXIDLE
UART.IRQ_RX
UART.IRQ_TXIDLE
UART.IRQ_BREAK
IRQ trigger sources.
Availability: renesas-ra, stm32, esp32, rp2040, mimxrt, samd, cc3200.
SPI is a synchronous serial protocol that is driven by a controller. At the physical level, a bus consists of 3 lines: SCK,
MOSI, MISO. Multiple devices can share the same bus. Each device should have a separate, 4th signal, CS (Chip Select),
to select a particular device on a bus with which communication takes place. Management of a CS signal should happen
in user code (via machine.Pin class).
Both hardware and software SPI implementations exist via the machine.SPI and machine.SoftSPI classes. Hardware
SPI uses underlying hardware support of the system to perform the reads/writes and is usually efficient and fast but may
have restrictions on which pins can be used. Software SPI is implemented by bit-banging and can be used on any pin but
is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed.
Example usage:
try:
cs(0) # Select peripheral.
spi.write(b"12345678") # Write 8 bytes, and don't care about␣
,→received data.
finally:
cs(1) # Deselect peripheral.
try:
cs(0) # Select peripheral.
rxdata = spi.read(8, 0x42) # Read 8 bytes while writing 0x42 for each␣
,→byte.
finally:
cs(1) # Deselect peripheral.
rxdata = bytearray(8)
try:
cs(0) # Select peripheral.
spi.readinto(rxdata, 0x42) # Read 8 bytes inplace while writing 0x42 for␣
,→each byte.
finally:
cs(1) # Deselect peripheral.
txdata = b"12345678"
rxdata = bytearray(len(txdata))
try:
cs(0) # Select peripheral.
spi.write_readinto(txdata, rxdata) # Simultaneously write and read bytes.
finally:
cs(1) # Deselect peripheral.
Constructors
tialisation of the bus, if any). If extra arguments are given, the bus is initialised. See init for parameters of
initialisation.
class machine.SoftSPI(baudrate=500000, *, polarity=0, phase=0, bits=8, firstbit=MSB, sck=None, mosi=None,
miso=None)
Construct a new software SPI object. Additional parameters must be given, usually at least sck, mosi and miso, and
these are used to initialise the bus. See SPI.init for a description of the parameters.
Methods
Constants
SPI.CONTROLLER
for initialising the SPI bus to controller; this is only used for the WiPy
SPI.MSB
SoftSPI.MSB
set the first bit to be the most significant bit
SPI.LSB
SoftSPI.LSB
set the first bit to be the least significant bit
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.
I2C objects are created attached to a specific bus. They can be initialised when created, or initialised later on.
Printing the I2C object gives you information about its configuration.
Both hardware and software I2C implementations exist via the machine.I2C and machine.SoftI2C classes. Hardware
I2C uses underlying hardware support of the system to perform the reads/writes and is usually efficient and fast but may
have restrictions on which pins can be used. Software I2C is implemented by bit-banging and can be used on any pin but
is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed.
® Note
The I2C bus requires pull-up circuitry on both SDA and SCL for it’s operation. Usually these are resistors in the range
of 1 - 10 kOhm, connected from each SDA/SCL to Vcc. Without these, the behaviour is undefined and may range
from blocking, unexpected watchdog reset to just wrong values. Often, this pull-up circuitry is built-in already to the
MCU board or sensor breakout boards, but there is no rule for that. So please check in case of trouble. See also this
excellent learning guide by Adafruit about I2C wiring.
Example usage:
Constructors
General Methods
The following methods implement the primitive I2C controller bus operations and can be combined to make any I2C
transaction. They are provided if you need more control over the bus, otherwise the standard methods (see below) can be
used.
These methods are only available on the machine.SoftI2C class.
I2C.start()
Generate a START condition on the bus (SDA transitions to low while SCL is high).
I2C.stop()
Generate a STOP condition on the bus (SDA transitions to high while SCL is high).
I2C.readinto(buf, nack=True, / )
Reads bytes from the bus and stores them into buf. The number of bytes read is the length of buf. An ACK will be
sent on the bus after receiving all but the last byte. After the last byte is received, if nack is true then a NACK will
be sent, otherwise an ACK will be sent (and in this case the peripheral assumes more bytes are going to be read in
a later call).
I2C.write(buf )
Write the bytes from buf to the bus. Checks that an ACK is received after each byte and stops transmitting the
remaining bytes if a NACK is received. The function returns the number of ACKs that were received.
The following methods implement the standard I2C controller read and write operations that target a given peripheral
device.
I2C.readfrom(addr, nbytes, stop=True, / )
Read nbytes from the peripheral specified by addr. If stop is true then a STOP condition is generated at the end of
the transfer. Returns a bytes object with the data read.
I2C.readfrom_into(addr, buf, stop=True, / )
Read into buf from the peripheral specified by addr. The number of bytes read will be the length of buf. If stop is
true then a STOP condition is generated at the end of the transfer.
The method returns None.
I2C.writeto(addr, buf, stop=True, / )
Write the bytes from buf to the peripheral specified by addr. If a NACK is received following the write of a byte
from buf then the remaining bytes are not sent. If stop is true then a STOP condition is generated at the end of the
transfer, even if a NACK is received. The function returns the number of ACKs that were received.
I2C.writevto(addr, vector, stop=True, / )
Write the bytes contained in vector to the peripheral specified by addr. vector should be a tuple or list of objects with
the buffer protocol. The addr is sent once and then the bytes from each object in vector are written out sequentially.
The objects in vector may be zero bytes in length in which case they don’t contribute to the output.
If a NACK is received following the write of a byte from one of the objects in vector then the remaining bytes, and
any remaining objects, are not sent. If stop is true then a STOP condition is generated at the end of the transfer,
even if a NACK is received. The function returns the number of ACKs that were received.
Memory operations
Some I2C devices act as a memory device (or set of registers) that can be read from and written to. In this case there
are two addresses associated with an I2C transaction: the peripheral address and the memory address. The following
methods are convenience functions to communicate with such devices.
I2C.readfrom_mem(addr, memaddr, nbytes, *, addrsize=8)
Read nbytes from the peripheral specified by addr starting from the memory address specified by memaddr. The
argument addrsize specifies the address size in bits. Returns a bytes object with the data read.
I2S is a synchronous serial protocol used to connect digital audio devices. At the physical level, a bus consists of 3 lines:
SCK, WS, SD. The I2S class supports controller operation. Peripheral operation is not supported.
The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged.
Based on this feedback, the I2S class API and implementation may be changed.
I2S objects can be created and initialized using:
# ESP32
sck_pin = Pin(14) # Serial clock output
ws_pin = Pin(13) # Word clock output
sd_pin = Pin(12) # Serial data output
or
# PyBoards
sck_pin = Pin("Y6") # Serial clock output
ws_pin = Pin("Y5") # Word clock output
sd_pin = Pin("Y8") # Serial data output
audio_out = I2S(2,
sck=sck_pin, ws=ws_pin, sd=sd_pin,
mode=I2S.TX,
bits=16,
format=I2S.MONO,
rate=44100,
ibuf=20000)
audio_in = I2S(2,
sck=sck_pin, ws=ws_pin, sd=sd_pin,
mode=I2S.RX,
bits=32,
format=I2S.STEREO,
rate=22050,
ibuf=20000)
• blocking
• non-blocking
• asyncio
blocking:
non-blocking:
asyncio:
swriter = asyncio.StreamWriter(audio_out)
swriter.write(buf)
await swriter.drain()
sreader = asyncio.StreamReader(audio_in)
num_read = await sreader.readinto(buf)
Some codec devices like the WM8960 or SGTL5000 require separate initialization before they can operate with the I2S
class. For these, separate drivers are supplied, which also offer methods for controlling volume, audio processing and
other things. For these drivers see:
• WM8960 – Driver for the WM8960 codec
Constructor
class machine.I2S(id, *, sck, ws, sd, mck=None, mode, bits, format, rate, ibuf )
Construct an I2S object of the given id:
• id identifies a particular I2S bus; it is board and port specific
Keyword-only parameters that are supported on all ports:
• sck is a pin object for the serial clock line
• ws is a pin object for the word select line
• sd is a pin object for the serial data line
• mck is a pin object for the master clock line; master clock frequency is sampling rate * 256
• mode specifies receive or transmit
• bits specifies sample size (bits), 16 or 32
• format specifies channel format, STEREO or MONO
• rate specifies audio sampling rate (Hz); this is the frequency of the ws signal
• ibuf specifies internal buffer length (bytes)
For all ports, DMA runs continuously in the background and allows user applications to perform other operations
while sample data is transferred between the internal buffer and the I2S peripheral unit. Increasing the size of the
internal buffer has the potential to increase the time that user applications can perform non-I2S operations before
underflow (e.g. write method) or overflow (e.g. readinto method).
Methods
I2S.init(sck, ...)
see Constructor for argument descriptions
I2S.deinit()
Deinitialize the I2S bus
I2S.readinto(buf )
Read audio samples into the buffer specified by buf. buf must support the buffer protocol, such as bytearray or
array. “buf” byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample.
For Mono format, the left channel sample data is used. Returns number of bytes read
I2S.write(buf )
Write audio samples contained in buf. buf must support the buffer protocol, such as bytearray or array. “buf”
byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono
format, the sample data is written to both the right and left channels. Returns number of bytes written
I2S.irq(handler)
Set a callback. handler is called when buf is emptied (write method) or becomes full (readinto method).
Setting a callback changes the write and readinto methods to non-blocking operation. handler is called in
the context of the MicroPython scheduler.
static I2S.shift(*, buf, bits, shift )
bitwise shift of all samples contained in buf. bits specifies sample size in bits. shift specifies the number of
bits to shift each sample. Positive for left shift, negative for right shift. Typically used for volume control. Each bit
shift changes sample volume by 6dB.
Constants
I2S.RX
for initialising the I2S bus mode to receive
I2S.TX
for initialising the I2S bus mode to transmit
I2S.STEREO
for initialising the I2S bus format to stereo
I2S.MONO
for initialising the I2S bus format to mono
The RTC is an independent clock that keeps track of the date and time.
Example usage:
rtc = machine.RTC()
rtc.datetime((2020, 1, 21, 2, 10, 32, 36, 0))
print(rtc.datetime())
Constructors
Methods
[
RTC.datetime( datetimetuple ) ]
Get or set the date and time of the RTC.
With no arguments, this method returns an 8-tuple with the current date and time. With 1 argument (being an
8-tuple) it sets the date and time.
The 8-tuple has the following format:
(year, month, day, weekday, hours, minutes, seconds, subseconds)
The meaning of the subseconds field is hardware dependent.
RTC.init(datetime)
Initialise the RTC. Datetime is a tuple of the form:
(year, month, day, hour, minute, second, microsecond, tzinfo)
All eight arguments must be present. The microsecond and tzinfo values are currently ignored but might be
used in the future.
Availability: CC3200, ESP32, MIMXRT, SAMD. The rtc.init() method on the stm32 and renesas-ra ports just
(re-)starts the RTC and does not accept arguments.
RTC.now()
Get get the current datetime tuple.
Availability: WiPy.
RTC.deinit()
Resets the RTC to the time of January 1, 2015 and starts running it again.
RTC.alarm(id, time, *, repeat=False)
Set the RTC alarm. Time might be either a millisecond value to program the alarm to current time + time_in_ms
in the future, or a datetimetuple. If the time passed is in milliseconds, repeat can be set to True to make the alarm
periodic.
RTC.alarm_left(alarm_id=0)
Get the number of milliseconds left before the alarm expires.
RTC.alarm_cancel(alarm_id=0)
Cancel a running alarm.
The mimxrt port also exposes this function as RTC.cancel(alarm_id=0), but this is scheduled to be removed
in MicroPython 2.0.
RTC.irq(*, trigger, handler=None, wake=machine.IDLE )
Create an irq object triggered by a real time clock alarm.
• trigger must be RTC.ALARM0
• handler is the function to be called when the callback is triggered.
• wake specifies the sleep mode from where this interrupt can wake up the system.
[
RTC.memory( data ) ]
RTC.memory(data) will write data to the RTC memory, where data is any object which supports the buffer
protocol (including bytes, bytearray , memoryview and array.array ). RTC.memory() reads RTC memory
and returns a bytes object.
Data written to RTC user memory is persistent across restarts, including Soft Reset and machine.deepsleep().
The maximum length of RTC user memory is 2048 bytes by default on esp32, and 492 bytes on esp8266.
Availability: esp32, esp8266 ports.
Constants
RTC.ALARM0
irq trigger source
Hardware timers deal with timing of periods and events. Timers are perhaps the most flexible and heterogeneous kind of
hardware in MCUs and SoCs, differently greatly from a model to a model. MicroPython’s Timer class defines a baseline
operation of executing a callback with a given period (or once after some delay), and allow specific boards to define more
non-standard behaviour (which thus won’t be portable to other boards).
See discussion of important constraints on Timer callbacks.
® Note
Memory can’t be allocated inside irq handlers (an interrupt) and so exceptions raised within a handler don’t give much
information. See micropython.alloc_emergency_exception_buf() for how to get around this limitation.
If you are using a WiPy board please refer to machine.TimerWiPy instead of this class.
Constructors
Methods
def mycallback(t):
pass
# periodic at 1kHz
tim.init(mode=Timer.PERIODIC, freq=1000, callback=mycallback)
Keyword arguments:
• mode can be one of:
– Timer.ONE_SHOT - The timer runs once until the configured period of the channel expires.
– Timer.PERIODIC - The timer runs periodically at the configured frequency of the channel.
• freq - The timer frequency, in units of Hz. The upper bound of the frequency is dependent on the port.
When both the freq and period arguments are given, freq has a higher priority and period is ignored.
• period - The timer period, in milliseconds.
• callback - The callable to call upon expiration of the timer period. The callback must take one argument,
which is passed the Timer object. The callback argument shall be specified. Otherwise an exception will
occur upon timer expiration: TypeError: 'NoneType' object isn't callable
Timer.deinit()
Deinitialises the timer. Stops the timer, and disables the timer peripheral.
Constants
Timer.ONE_SHOT
Timer.PERIODIC
Timer operating mode.
The WDT is used to restart the system when the application crashes and ends up into a non recoverable state. Once started
it cannot be stopped or reconfigured in any way. After enabling, the application must “feed” the watchdog periodically to
prevent it from expiring and resetting the system.
Example usage:
Constructors
Methods
WDT.feed()
Feed the WDT to prevent it from resetting the system. The application should place this call in a sensible place
ensuring that the WDT is only fed after verifying that everything is functioning correctly.
Á Warning
The SD card class allows to configure and enable the memory card module of the WiPy and automatically mount it as
/sd as part of the file system. There are several pin combinations that can be used to wire the SD card socket to the WiPy
and the pins used can be specified in the constructor. Please check the pinout and alternate functions table. for more info
regarding the pins which can be remapped to be used with a SD card.
Example usage:
Constructors
Methods
SD cards are one of the most common small form factor removable storage media. SD cards come in a variety of sizes
and physical form factors. MMC cards are similar removable storage devices while eMMC devices are electrically similar
storage devices designed to be embedded into other systems. All three form share a common protocol for communication
with their host system and high-level support looks the same for them all. As such in MicroPython they are implemented
in a single class called machine.SDCard .
Both SD and MMC interfaces support being accessed with a variety of bus widths. When being accessed with a 1-bit
wide interface they can be accessed using the SPI protocol. Different MicroPython hardware platforms support different
widths and pin configurations but for most platforms there is a standard configuration for any given hardware. In general
constructing an SDCard object with without passing any parameters will initialise the interface to the default card slot for
the current hardware. The arguments listed below represent the common arguments that might need to be set in order to
use either a non-standard slot or a non-standard pin assignment. The exact subset of arguments supported will vary from
platform to platform.
class machine.SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None,
freq=20000000)
This class provides access to SD or MMC storage cards using either a dedicated SD/MMC interface hardware or
through an SPI channel. The class implements the block protocol defined by vfs.AbstractBlockDev . This
allows the mounting of an SD card to be as simple as:
vfs.mount(machine.SDCard(), "/sd")
Implementation-specific details
Different implementations of the SDCard class on different hardware support varying subsets of the options above.
PyBoard
The standard PyBoard has just one slot. No arguments are necessary or supported.
ESP32
The ESP32 provides two channels of SD/MMC hardware and also supports access to SD Cards through either of the two
SPI ports that are generally available to the user. As a result the slot argument can take a value between 0 and 3, inclusive.
Slots 0 and 1 use the built-in SD/MMC hardware while slots 2 and 3 use the SPI ports. Slot 0 supports 1, 4 or 8-bit wide
access while slot 1 supports 1 or 4-bit access; the SPI slots only support 1-bit access.
® Note
Slot 0 is used to communicate with on-board flash memory on most ESP32 modules and so will be
unavailable to the user.
® Note
Most ESP32 modules that provide an SD card slot using the dedicated hardware only wire up 1 data pin,
so the default value for width is 1.
The pins used by the dedicated SD/MMC hardware are fixed. The pins used by the SPI hardware can be reassigned.
® Note
If any of the SPI signals are remapped then all of the SPI signals will pass through a GPIO multiplexer
unit which can limit the performance of high frequency signals. Since the normal operating speed for
SD cards is 40MHz this can cause problems on some cards.
Slot 0 1 2 3
Signal Pin Pin Pin Pin
sck 6 14 18 14
cmd 11 15
cs 5 15
miso 19 12
mosi 23 13
D0 7 2
D1 8 4
D2 9 12
D3 10 13
D4 16
D5 17
D6 5
D7 18
cc3200
You can set the pins used for SPI access by passing a tuple as the pins argument.
Note: The current cc3200 SD card implementation names the this class machine.SD rather than machine.SDCard .
mimxrt
The SDCard module for the mimxrt port only supports access via dedicated SD/MMC peripheral (USDHC) in 4-bit mode
with 50MHz clock frequency exclusively. Unfortunately the MIMXRT1011 controller does not support the USDHC
peripheral. Hence this controller does not feature the machine.SDCard module.
Due to the decision to only support 4-bit mode with 50MHz clock frequency the interface has been simplified, and the
constructor signature is:
class machine.SDCard(slot=1)
The pins used for the USDHC peripheral have to be configured in mpconfigboard.h. Most of the controllers supported
by the mimxrt port provide up to two USDHC peripherals. Therefore the pin configuration is performed using the macro
MICROPY_USDHCx with x being 1 or 2 respectively.
#define MICROPY_USDHC1 \
{ \
.cmd = { GPIO_SD_B0_02_USDHC1_CMD}, \
.clk = { GPIO_SD_B0_03_USDHC1_CLK }, \
.cd_b = { GPIO_SD_B0_06_USDHC1_CD_B },\
.data0 = { GPIO_SD_B0_04_USDHC1_DATA0 },\
(continues on next page)
If the card detect pin is not used (cb_b pin) then the respective entry has to be filled with the following dummy value:
Based on the definition of macro MICROPY_USDHC1 and/or MICROPY_USDHC2 the machine.SDCard module either
supports one or two slots. If only one of the defines is provided, calling machine.SDCard() or machine.SDCard(1)
will return an instance using the respective USDHC peripheral. When both macros are defined, calling machine.
SDCard(2) returns an instance using USDHC2.
® Note
machine.USBDevice is currently only supported for esp32, rp2 and samd ports. Native USB support is also required,
and not every board supports native USB.
USBDevice provides a low-level Python API for implementing USB device functions using Python code.
Á Warning
This low-level API assumes familiarity with the USB standard. There are high-level usb driver modules in
micropython-lib which provide a simpler interface and more built-in functionality.
Terminology
• A “Runtime” USB device interface or driver is one which is defined using this Python API after MicroPython
initially starts up.
• A “Built-in” USB device interface or driver is one that is compiled into the MicroPython firmware, and is always
available. Examples are USB-CDC (serial port) which is usually enabled by default. Built-in USB-MSC (Mass
Storage) is an option on some ports.
Lifecycle
Managing a runtime USB interface can be tricky, especially if you are communicating with MicroPython over a built-in
USB-CDC serial port that’s part of the same USB device.
• A MicroPython soft reset will always clear all runtime USB interfaces, which results in the entire USB device
disconnecting from the host. If MicroPython is also providing a built-in USB-CDC serial port then this will re-
appear after the soft reset.
This means some functions (like mpremote run) that target the USB-CDC serial port will immediately fail if a
runtime USB interface is active, because the port goes away when mpremote triggers a soft reset. The operation
should succeed on the second try, as after the soft reset there is no more runtime USB interface.
• To configure a runtime USB device on every boot, it’s recommended to place the configuration code in the boot.py
file on the device VFS. On each reset this file is executed before the USB subsystem is initialised (and before
main.py), so it allows the board to come up with the runtime USB device immediately.
• For development or debugging, it may be convenient to connect a hardware serial REPL and disable the built-
in USB-CDC serial port entirely. Not all ports support this (currently only rp2). The custom build should be
configured with #define MICROPY_HW_USB_CDC (0) and #define MICROPY_HW_ENABLE_UART_REPL
(1).
Constructors
class machine.USBDevice
Construct a USBDevice object.
® Note
This object is a singleton, each call to this constructor returns the same object reference.
Methods
® Note
If a bus reset occurs (see USBDevice.reset()), xfer_cb is not called for any transfers that have not
already completed.
USBDevice.active(self, [value] / )
Returns the current active state of this runtime USB device as a boolean. The runtime USB device is “active” when
it is available to interact with the host, it doesn’t mean that a USB Host is actually present.
If the optional value argument is set to a truthy value, then the USB device will be activated.
If the optional value argument is set to a falsey value, then the USB device is deactivated. While the USB device
is deactivated, it will not be detected by the USB Host.
To simulate a disconnect and a reconnect of the USB device, call active(False) followed by active(True).
This may be necessary if the runtime device configuration has changed, so that the host sees the new device.
USBDevice.builtin_driver
This attribute holds the current built-in driver configuration, and must be set to one of the USBDevice.BUILTIN_
named constants defined on this object.
By default it holds the value USBDevice.BUILTIN_NONE.
Runtime USB device must be inactive when setting this field. Call the USBDevice.active() function to deac-
tivate before setting if necessary (and again to activate after setting).
If this value is set to any value other than USBDevice.BUILTIN_NONE then the following restrictions apply to the
USBDevice.config() arguments:
• desc_cfg should begin with the built-in USB interface descriptor data accessible via USBDevice.
builtin_driver attribute desc_cfg. Descriptors appended after the built-in configuration descrip-
tors should use interface, string and endpoint numbers starting from the max built-in values defined in
USBDevice.builtin_driver attributes itf_max, str_max and ep_max.
• The bNumInterfaces field in the built-in configuration descriptor will also need to be updated if any new
interfaces are appended to the end of desc_cfg.
• desc_strs should either be None or a list/dictionary where index values less than USBDevice.
builtin_driver.str_max are missing or have value None. This reserves those string indexes for the
built-in drivers. Placing a different string at any of these indexes overrides that string in the built-in driver.
USBDevice.remote_wakeup(self )
Wake up host if we are in suspend mode and the REMOTE_WAKEUP feature is enabled by the host. This has to
be enabled in the USB attributes, and on the host. Returns True if remote wakeup was enabled and active and the
host was woken up.
USBDevice.submit_xfer(self, ep, buffer / )
Submit a USB transfer on endpoint number ep. buffer must be an object implementing the buffer interface, with
read access for IN endpoints and write access for OUT endpoints.
® Note
ep cannot be the control Endpoint number 0. Control transfers are built up through successive executions of
control_xfer_cb, see above.
Returns True if successful, False if the transfer could not be queued (as USB device is not configured by host, or
because another transfer is queued on this endpoint.)
When the USB host completes the transfer, the xfer_cb callback is called (see above).
Raises OSError with reason MP_EINVAL If the USB device is not active.
USBDevice.stall(self, ep, [stall] / )
Calling this function gets or sets the STALL state of a device endpoint.
ep is the number of the endpoint.
If the optional stall parameter is set, this is a boolean flag for the STALL state.
The return value is the current stall state of the endpoint (before any change made by this function).
An endpoint that is set to STALL may remain stalled until this function is called again, or STALL may be cleared
automatically by the USB host.
Raises OSError with reason MP_EINVAL If the USB device is not active.
Constants
USBDevice.BUILTIN_NONE
USBDevice.BUILTIN_DEFAULT
USBDevice.BUILTIN_CDC
USBDevice.BUILTIN_MSC
USBDevice.BUILTIN_CDC_MSC
These constant objects hold the built-in descriptor data which is compiled into the MicroPython firmware.
USBDevice.BUILTIN_NONE and USBDevice.BUILTIN_DEFAULT are always present. Additional objects may
be present depending on the firmware build configuration and the actual built-in drivers.
® Note
CONST_X = const(123)
CONST_Y = const(2 * CONST_X + 1)
Constants declared this way are still accessible as global variables from outside the module they are declared in.
On the other hand, if a constant begins with an underscore then it is hidden, it is not available as a global variable,
and does not take up any memory during execution.
This const function is recognised directly by the MicroPython parser and is provided as part of the micropython
module mainly so that scripts can be written which run under both CPython and MicroPython, by following the
above pattern.
micropython.opt_level( level )[ ]
If level is given then this function sets the optimisation level for subsequent compilation of scripts, and returns
None. Otherwise it returns the current optimisation level.
• Assertions: at level 0 assertion statements are enabled and compiled into the bytecode; at levels 1 and higher
assertions are not compiled.
• Built-in __debug__ variable: at level 0 this variable expands to True; at levels 1 and higher it expands to
False.
• Source-code line numbers: at levels 0, 1 and 2 source-code line number are stored along with the bytecode
so that exceptions can report the line number they occurred at; at levels 3 and higher line numbers are not
stored.
The default optimisation level is usually level 0.
micropython.alloc_emergency_exception_buf(size)
Allocate size bytes of RAM for the emergency exception buffer (a good size is around 100 bytes). The buffer is
used to create exceptions in cases when normal RAM allocation would fail (eg within an interrupt handler) and
therefore give useful traceback information in these situations.
A good way to use this function is to put it at the start of your main script (eg boot.py or main.py) and then the
emergency exception buffer will be active for all the code following it.
[
micropython.mem_info( verbose ) ]
Print information about currently used memory. If the verbose argument is given then extra information is printed.
The information that is printed is implementation dependent, but currently includes the amount of stack and heap
used. In verbose mode it prints out the entire heap indicating which blocks are used and which are free.
micropython.qstr_info( verbose ) [ ]
Print information about currently interned strings. If the verbose argument is given then extra information is printed.
The information that is printed is implementation dependent, but currently includes the number of interned strings
and the amount of RAM they use. In verbose mode it prints out the names of all RAM-interned strings.
micropython.stack_use()
Return an integer representing the current amount of stack that is being used. The absolute value of this is not
particularly useful, rather it should be used to compute differences in stack usage at different points.
micropython.heap_lock()
micropython.heap_unlock()
micropython.heap_locked()
Lock or unlock the heap. When locked no memory allocation can occur and a MemoryError will be raised if any
heap allocation is attempted. heap_locked() returns a true value if the heap is currently locked.
These functions can be nested, ie heap_lock() can be called multiple times in a row and the lock-depth will
increase, and then heap_unlock() must be called the same number of times to make the heap available again.
Both heap_unlock() and heap_locked() return the current lock depth (after unlocking for the former) as a
non-negative integer, with 0 meaning the heap is not locked.
If the REPL becomes active with the heap locked then it will be forcefully unlocked.
Note: heap_locked() is not enabled on most ports by default, requires MI-
CROPY_PY_MICROPYTHON_HEAP_LOCKED.
micropython.kbd_intr(chr)
Set the character that will raise a KeyboardInterrupt exception. By default this is set to 3 during script execu-
tion, corresponding to Ctrl-C. Passing -1 to this function will disable capture of Ctrl-C, and passing 3 will restore
it.
This function can be used to prevent the capturing of Ctrl-C on the incoming stream of characters that is usually
used for the REPL, in case that stream is used for other purposes.
micropython.schedule(func, arg)
Schedule the function func to be executed “very soon”. The function is passed the value arg as its single argument.
“Very soon” means that the MicroPython runtime will do its best to execute the function at the earliest possible
time, given that it is also trying to be efficient, and that the following conditions hold:
• A scheduled function will never preempt another scheduled function.
• Scheduled functions are always executed “between opcodes” which means that all fundamental Python oper-
ations (such as appending to a list) are guaranteed to be atomic.
• A given port may define “critical regions” within which scheduled functions will never be executed. Functions
may be scheduled within a critical region but they will not be executed until that region is exited. An example
of a critical region is a preempting interrupt handler (an IRQ).
A use for this function is to schedule a callback from a preempting IRQ. Such an IRQ puts restrictions on the code
that runs in the IRQ (for example the heap may be locked) and scheduling a function to call later will lift those
restrictions.
On multi-threaded ports, the scheduled function’s behaviour depends on whether the Global Interpreter Lock (GIL)
is enabled for the specific port:
• If GIL is enabled, the function can preempt any thread and run in its context.
• If GIL is disabled, the function will only preempt the main thread and run in its context.
Note: If schedule() is called from a preempting IRQ, when memory allocation is not allowed and the callback to
be passed to schedule() is a bound method, passing this directly will fail. This is because creating a reference to
a bound method causes memory allocation. A solution is to create a reference to the method in the class constructor
and to pass that reference to schedule(). This is discussed in detail here reference documentation under “Creation
of Python objects”.
There is a finite queue to hold the scheduled functions and schedule() will raise a RuntimeError if the queue
is full.
Classes
class micropython.RingIO(size)
class micropython.RingIO(buffer)
Provides a fixed-size ringbuffer for bytes with a stream interface. Can be considered like a fifo queue variant of
io.BytesIO.
When created with integer size a suitable buffer will be allocated. Alternatively a bytearray or similar buffer
protocol object can be provided to the constructor for in-place use.
The classic ringbuffer algorithm is used which allows for any size buffer to be used however one byte will be
consumed for tracking. If initialised with an integer size this will be accounted for, for example RingIO(16) will
allocate a 17 byte buffer internally so it can hold 16 bytes of data. When passing in a pre-allocated buffer however
one byte less than its original length will be available for storage, eg. RingIO(bytearray(16)) will only hold
15 bytes of data.
A RingIO instance can be IRQ / thread safe when used to pass data in a single direction eg. when written to in
an IRQ and read from in a non-IRQ function (or vice versa). This does not hold if you try to eg. write to a single
instance from both IRQ and non-IRQ code, this would often cause data corruption.
any()
Returns an integer counting the number of characters that can be read.
[
read( nbytes ) ]
Read available characters. This is a non-blocking function. If nbytes is specified then read at
most that many bytes, otherwise read as much data as possible.
Return value: a bytes object containing the bytes read. Will be zero-length bytes object if no data
is available.
[
readline( nbytes ) ]
Read a line, ending in a newline character or return if one exists in the buffer, else return available
bytes in buffer. If nbytes is specified then read at most that many bytes.
Return value: a bytes object containing the line read.
[
readinto(buf , nbytes ) ]
Read available bytes into the provided buf. If nbytes is specified then read at most that many
bytes. Otherwise, read at most len(buf) bytes.
Return value: Integer count of the number of bytes read into buf.
write(buf )
Non-blocking write of bytes from buf into the ringbuffer, limited by the available space in the
ringbuffer.
Return value: Integer count of bytes written.
close()
No-op provided as part of standard stream interface. Has no effect on data in the ringbuffer.
® Note
This module is only included by default on the ESP8266, ESP32 and RP2 ports. On STM32 / Pyboard and others, you
can either install the neopixel package using mip, or you can download the module directly from micropython-lib
and copy it to the filesystem.
class NeoPixel
This class stores pixel data for a WS2812 LED strip connected to a pin. The application should set pixel data and then
call NeoPixel.write() when it is ready to update the strip.
For example:
import neopixel
Constructors
class neopixel.NeoPixel(pin, n, *, bpp=3, timing=1)
Construct an NeoPixel object. The parameters are:
• pin is a machine.Pin instance.
• n is the number of LEDs in the strip.
• bpp is 3 for RGB LEDs, and 4 for RGBW LEDs.
• timing is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz). You may also supply a timing tuple as
accepted by machine.bitstream().
Output methods
NeoPixel.write()
Writes the current pixel data to the strip.
Instantiate a network interface object. Parameters are network interface dependent. If there are more than one interface
of the same type, the first parameter should be id.
[
AbstractNIC.active( is_active ) ]
Activate (“up”) or deactivate (“down”) the network interface, if a boolean argument is passed. Otherwise, query
current state if no argument is provided. Most other methods require an active interface (behaviour of calling them
on inactive interface is undefined).
[
AbstractNIC.connect( service_id, key=None, *, ... ) ]
Connect the interface to a network. This method is optional, and available only for interfaces which are not “always
connected”. If no parameters are given, connect to the default (or the only) service. If a single parameter is given,
it is the primary identifier of a service to connect to. It may be accompanied by a key (password) required to access
said service. There can be further arbitrary keyword-only parameters, depending on the networking medium type
and/or particular device. Parameters can be used to: a) specify alternative service identifier types; b) provide
additional connection parameters. For various medium types, there are different sets of predefined/recommended
parameters, among them:
• WiFi: bssid keyword to connect to a specific BSSID (MAC address)
AbstractNIC.disconnect()
Disconnect from network.
AbstractNIC.isconnected()
Returns True if connected to network, otherwise returns False.
AbstractNIC.scan(*, ...)
Scan for the available network services/connections. Returns a list of tuples with discovered service parameters.
For various network media, there are different variants of predefined/ recommended tuple formats, among them:
• WiFi: (ssid, bssid, channel, RSSI, security, hidden). There may be further fields, specific to a particular
device.
The function may accept additional keyword arguments to filter scan results (e.g. scan for a particular service, on
a particular channel, for services of a particular set, etc.), and to affect scan duration and other parameters. Where
possible, parameter names should match those in connect().
[
AbstractNIC.status( param ) ]
Query dynamic status information of the interface. When called with no argument the return value describes the
network link status. Otherwise param should be a string naming the particular status parameter to retrieve.
The return types and values are dependent on the network medium/technology. Some of the parameters that may
be supported are:
• WiFi STA: use 'rssi' to retrieve the RSSI of the AP signal
• WiFi AP: use 'stations' to retrieve a list of all the STAs connected to the AP. The list contains tuples of
the form (MAC, RSSI).
AbstractNIC.ipconfig('param' )
AbstractNIC.ipconfig(param=value, ...)
Get or set interface-specific IP-configuration interface parameters. Supported parameters are the following (avail-
ability of a particular parameter depends on the port and the specific network interface):
• dhcp4 (True/False) obtain an IPv4 address, gateway and dns server via DHCP. This method does not
block and wait for an address to be obtained. To check if an address was obtained, use the read-only property
has_dhcp4.
• addr6 (e.g. fe80::1234:5678) obtain a list of current IPv6 addresses as (ip, state,
preferred_lifetime, valid_lifetime)-tuple. This include link-local, slaac and static addresses.
preferred_lifetime and valid_lifetime represent the remaining valid and preferred lifetime of each
IPv6 address, in seconds. state indicates the current state of the address:
– 0x08 - 0x0f indicates the address is tentative, counting the number of probes sent.
– 0x10 The address is deprecated (but still valid)
– 0x30 The address is preferred (and valid)
– 0x40 The address is duplicated and can not be used.
This method can be used to set a static IPv6 address, by setting this parameter to the address, like
fe80::1234:5678.
[
AbstractNIC.ifconfig( (ip, subnet, gateway, dns) ) ]
® Note
Get/set IP-level network interface parameters: IP address, subnet mask, gateway and DNS server. When called
with no arguments, this method returns a 4-tuple with the above information. To set the above values, pass a 4-tuple
with the required information. For example:
AbstractNIC.config('param' )
AbstractNIC.config(param=value, ...)
Get or set general network interface parameters. These methods allow to work with additional parameters beyond
standard IP configuration (as dealt with by ipconfig()). These include network-specific and hardware-specific
parameters. For setting parameters, the keyword argument syntax should be used, and multiple parameters can be
set at once. For querying, a parameter name should be quoted as a string, and only one parameter can be queried
at a time:
# Set WiFi access point name (formally known as SSID) and WiFi channel
ap.config(ssid='My AP', channel=11)
# Query params one by one
print(ap.config('ssid'))
print(ap.config('channel'))
This class provides a driver for WiFi network processors. Example usage:
import network
# enable station interface and connect to WiFi access point
nic = network.WLAN(network.WLAN.IF_STA)
nic.active(True)
nic.connect('your-ssid', 'your-key')
# now use sockets as usual
Constructors
class network.WLAN(interface_id )
Create a WLAN network interface object. Supported interfaces are network.WLAN.IF_STA (station aka client, con-
nects to upstream WiFi access points) and network.WLAN.IF_AP (access point, allows other WiFi clients to connect).
Availability of the methods below depends on interface type. For example, only STA interface may WLAN.connect()
to an access point.
Methods
[
WLAN.active( is_active ) ]
Activate (“up”) or deactivate (“down”) network interface, if boolean argument is passed. Otherwise, query current
state if no argument is provided. Most other methods require active interface.
WLAN.connect(ssid=None, key=None, *, bssid=None)
Connect to the specified wireless network, using the specified key. If bssid is given then the connection will be
restricted to the access-point with that MAC address (the ssid must also be specified in this case).
WLAN.disconnect()
Disconnect from the currently connected wireless network.
WLAN.scan()
Scan for the available wireless networks. Hidden networks – where the SSID is not broadcast – will also be scanned
if the WLAN interface allows it.
Scanning is only possible on STA interface. Returns list of tuples with the information about WiFi access points:
(ssid, bssid, channel, RSSI, security, hidden)
bssid is hardware address of an access point, in binary form, returned as bytes object. You can use binascii.
hexlify() to convert it to ASCII form.
WLAN.config('param' )
WLAN.config(param=value, ...)
Get or set general network interface parameters. These methods allow to work with additional parameters beyond
standard IP configuration (as dealt with by AbstractNIC.ipconfig()). These include network-specific and
hardware-specific parameters. For setting parameters, keyword argument syntax should be used, multiple param-
eters can be set at once. For querying, parameters name should be quoted as a string, and only one parameter can
be queries at time:
# Set WiFi access point name (formally known as SSID) and WiFi channel
ap.config(ssid='My AP', channel=11)
# Query params one by one
print(ap.config('ssid'))
print(ap.config('channel'))
Following are commonly supported parameters (availability of a specific parameter depends on network technology
type, driver, and MicroPython port).
Pa- Description
rame-
ter
mac MAC address (bytes)
ssid WiFi access point name (string)
chan- WiFi channel (integer). Depending on the port this may only be supported on the AP interface.
nel
hidden Whether SSID is hidden (boolean)
secu- Security protocol supported (enumeration, see module constants)
rity
key Access key (string)
host- The hostname that will be sent to DHCP (STA interfaces) and mDNS (if supported, both STA and
name AP). (Deprecated, use network.hostname() instead)
recon- Number of reconnect attempts to make (integer, 0=none, -1=unlimited)
nects
tx- Maximum transmit power in dBm (integer or float)
power
pm WiFi Power Management setting (see below for allowed values)
Constants
WLAN.PM_PERFORMANCE
WLAN.PM_POWERSAVE
WLAN.PM_NONE
Allowed values for the WLAN.config(pm=...) network interface parameter:
• PM_PERFORMANCE: enable WiFi power management to balance power savings and WiFi performance
• PM_POWERSAVE: enable WiFi power management with additional power savings and reduced WiFi perfor-
mance
• PM_NONE: disable wifi power management
® Note
This class is a non-standard WLAN implementation for the WiPy. It is available simply as network.WLAN on the
WiPy but is named in the documentation below as network.WLANWiPy to distinguish it from the more general
network.WLAN class.
This class provides a driver for the WiFi network processor in the WiPy. Example usage:
import network
import time
# setup as a station
wlan = network.WLAN(mode=WLAN.STA)
wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key'))
while not wlan.isconnected():
time.sleep_ms(50)
print(wlan.ipconfig("addr4"))
Constructors
® Note
The WLAN constructor is special in the sense that if no arguments besides the id are given, it will return the already
existing WLAN instance without re-configuring it. This is because WLAN is a system feature of the WiPy. If the already
existing instance is not initialized it will do the same as the other constructors an will initialize it with default values.
Methods
or:
# configure as an station
wlan.init(mode=WLAN.STA)
Constants
WLANWiPy.STA
WLANWiPy.AP
selects the WLAN mode
WLANWiPy.WEP
WLANWiPy.WPA
WLANWiPy.WPA2
selects the network security
WLANWiPy.INT_ANT
WLANWiPy.EXT_ANT
selects the antenna type
This class allows you to control WIZnet5x00 Ethernet adaptors based on the W5200 and W5500 chipsets. The particular
chipset that is supported by the firmware is selected at compile-time via the MICROPY_PY_NETWORK_WIZNET5K
option.
® Note
The esp32 port also supports WIZnet W5500 chipsets, but this port uses the network.LAN interface.
Example usage:
import network
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
print(nic.ipconfig("addr4"))
For this example to work the WIZnet5x00 module must have the following connections:
• MOSI connected to X8
• MISO connected to X7
• SCLK connected to X6
• nSS connected to X5
• nRESET connected to X4
It is possible to use other SPI buses and other pins for nSS and nRESET.
Constructors
Methods
This class implements most methods from AbstractNIC , which are documented there. Additional methods are:
WIZNET5K.regs()
Dump the WIZnet5x00 registers. Useful for debugging.
This class allows you to control the Ethernet interface. The PHY hardware type is board-specific.
Example usage, for a board with built-in LAN support:
import network
nic = network.LAN(0)
print(nic.ipconfig("addr4"))
Constructors
• ref_clk_mode specifies, whether the data clock is provided by the Ethernet controller or the PHY interface.
The default value is the one that matches the board. If set to LAN.OUT or Pin.OUT or True, the clock is
driven by the Ethernet controller, if set to LAN.IN or Pin.IN or False, the clock is driven by the PHY
interface.
For example, with the Seeed Arch Mix board you can use:
® Note
On esp32 port the constructor requires different arguments. See esp32 port reference.
Methods
[
LAN.active( state ) ]
With a parameter, it sets the interface active if state is true, otherwise it sets it inactive. Without a parameter, it
returns the state.
LAN.isconnected()
Returns True if the physical Ethernet link is connected and up. Returns False otherwise.
LAN.status()
Returns the LAN status.
[
LAN.ifconfig( (ip, subnet, gateway, dns) ) ]
Get/set IP address, subnet mask, gateway and DNS.
When called with no arguments, this method returns a 4-tuple with the above information.
To set the above values, pass a 4-tuple with the required information. For example:
LAN.config(config_parameters)
Sets or gets parameters of the LAN interface. The only parameter that can be retrieved is the MAC address, using:
mac = LAN.config("mac")
On the mimxrt port, suitable values for the phy_type constructor argument are: PHY_KSZ8081, PHY_DP83825,
PHY_DP83848, PHY_LAN8720, PHY_RTL8211F.
This class allows you to create a network connection over a serial port using the PPP protocol.
® Note
Currently only the esp32 port has PPP support enabled in the default firmware build. PPP support can
be enabled in custom builds of the stm32 and rp2 ports by enabling networking support and setting MI-
CROPY_PY_NETWORK_PPP_LWIP to 1.
Example usage:
import network
ppp = network.PPP(uart)
ppp.connect()
print(ppp.ipconfig("addr4"))
ppp.disconnect()
Constructors
class network.PPP(stream)
Create a PPP driver object.
Arguments are:
• stream is any object that supports the stream protocol, but is most commonly a machine.UART instance.
This stream object must have an irq() method and an IRQ_RXIDLE constant, for use by PPP.connect.
Methods
PPP.isconnected()
Returns True if the PPP link is connected and up. Returns False otherwise.
PPP.status()
Returns the PPP status.
PPP.config(config_parameters)
Sets or gets parameters of the PPP interface. The only parameter that can be retrieved and set is the underlying
stream, using:
stream = PPP.config("stream")
PPP.config(stream=stream)
PPP.ipconfig('param' )
PPP.ipconfig(param=value, ...)
See AbstractNIC.ipconfig .
[
PPP.ifconfig( (ip, subnet, gateway, dns) ) ]
See AbstractNIC.ifconfig .
PPP.poll()
Poll the underlying stream for data, and pass it up the PPP stack. This is called automatically if the stream is a
UART with a RXIDLE interrupt, so it’s not usually necessary to call it manually.
Constants
PPP.SEC_NONE
PPP.SEC_PAP
PPP.SEC_CHAP
The type of connection security.
Network functions
The following are functions available in the network module.
[
network.country( code ) ]
Get or set the two-letter ISO 3166-1 Alpha-2 country code to be used for radio compliance.
If the code parameter is provided, the country will be set to this value. If the function is called without parameters,
it returns the current country.
The default code "XX" represents the “worldwide” region.
network.hostname( name ) [ ]
Get or set the hostname that will identify this device on the network. It will be used by all interfaces.
This hostname is used for:
• Sending to the DHCP server in the client request. (If using DHCP)
• Broadcasting via mDNS. (If enabled)
If the name parameter is provided, the hostname will be set to this value. If the function is called without parameters,
it returns the current hostname.
A change in hostname is typically only applied during connection. For DHCP this is because the hostname is part of
the DHCP client request, and the implementation of mDNS in most ports only initialises the hostname once during
connection. For this reason, you must set the hostname before activating/connecting your network interfaces.
The length of the hostname is limited to 32 characters. MicroPython ports may choose to set a lower limit for
memory reasons. If the given name does not fit, a ValueError is raised.
The default hostname is typically the name of the board.
network.ipconfig('param' )
network.ipconfig(param=value, ...)
Get or set global IP-configuration parameters. Supported parameters are the following (availability of a particular
parameter depends on the port and the specific network interface):
• dns Get/set DNS server. This method can support both, IPv4 and IPv6 addresses.
• prefer (4/6) Specify which address type to return, if a domain name has both A and AAAA records. Note,
that this does not clear the local DNS cache, so that any previously obtained addresses might not change.
network.phy_mode( mode )[ ]
Get or set the PHY mode.
If the mode parameter is provided, the PHY mode will be set to this value. If the function is called without
parameters, it returns the current PHY mode.
The possible modes are defined as constants:
• MODE_11B – IEEE 802.11b,
• MODE_11G – IEEE 802.11g,
• MODE_11N – IEEE 802.11n.
Availability: ESP8266.
import openamp
rproc.start()
while True:
if ept.is_ready():
ept.send("data")
Functions
openamp.new_service_callback(ns_callback)
Set the new service callback.
The ns_callback argument is a function that will be called when the remote processor announces new services. At
that point the host processor can choose to create the announced endpoint, if this particular service is supported,
or ignore it if it’s not. If this function is not set, the host processor should first register the endpoint locally, and it
will be automatically bound when the remote announces the service.
Endpoint class
class openamp.Endpoint(name, callback, src=ENDPOINT_ADDR_ANY, dest=ENDPOINT_ADDR_ANY )
Construct a new RPMsg Endpoint. An endpoint is a bidirectional communication channel between two cores.
Arguments are:
• name is the name of the endpoint.
• callback is a function that is called when the endpoint receives data with the source address of the remote
point, and the data as bytes passed by reference.
• src is the endpoint source address. If none is provided one will be assigned to the endpoint by the library.
• dest is the endpoint destination address. If the endpoint is created from the new_service_callback, this must
be provided and it must match the remote endpoint’s source address. If the endpoint is registered locally,
before the announcement, the destination address will be assigned by the library when the endpoint is bound.
Endpoint.deinit()
Destroy the endpoint and release all of its resources.
Endpoint.is_ready()
Returns True if the endpoint is ready to send (i.e., has both a source and destination addresses)
Endpoint.send(src=-1, dest=-1, timeout=-1)
Send a message to the remote processor over this endpoint.
Arguments are:
• src is the source endpoint address of the message. If none is provided, the source address the endpoint is
bound to is used.
• dest is the destination endpoint address of the message. If none is provided, the destination address the
endpoint is bound to is used.
• timeout specifies the time in milliseconds to wait for a free buffer. By default the function is blocking.
RemoteProc class
class openamp.RemoteProc(entry)
The RemoteProc object provides processor Life Cycle Management (LCM) support, such as loading firmware,
starting and stopping a remote core.
The entry argument can be a path to firmware image, in which case the firmware is loaded from file to its target
memory, or an entry point address, in which case the firmware must be loaded already at the given address.
RemoteProc.start()
Starts the remote processor.
RemoteProc.stop()
Stops the remote processor. The exact behavior is platform-dependent. On the STM32H7 for example it’s not
possible to stop and then restart the Cortex-M4 core, so a complete system reset is performed on a call to this
function.
RemoteProc.shutdown()
Shutdown stops the remote processor and releases all of its resources. The exact behavior is platform-dependent,
however typically it disables power and clocks to the remote core. This function is also used as the finaliser (i.e.,
called when RemoteProc object is collected). Note that on the STM32H7, it’s not possible to stop and then restart
the Cortex-M4 core, so a complete system reset is performed on a call to this function.
Á Warning
uctypes module allows access to arbitrary memory addresses of the machine (including I/O and control registers).
Uncareful usage of it may lead to crashes, data loss, and even hardware malfunction.
µ See also
Module struct
Standard Python way to access binary data structures (doesn’t scale well to large and complex structures).
Usage examples:
import uctypes
print("machine:", hex(header.e_machine))
STRUCT1 = {
"data1": 0 | uctypes.UINT8,
"data2": 4 | uctypes.UINT32,
"ptr": (8 | uctypes.PTR, COORD),
}
WWDG.WWDG_CFR.WDGTB = 0b10
WWDG.WWDG_CR.WDGA = 1
print("Current counter:", WWDG.WWDG_CR.T)
{
"field1": <properties>,
"field2": <properties>,
...
}
Currently, uctypes requires explicit specification of offsets for each field. Offset are given in bytes from the structure
start.
Following are encoding examples for various field types:
• Scalar types:
in other words, the value is a scalar type identifier ORed with a field offset (in bytes) from the start of the structure.
• Recursive structures:
"sub": (offset, {
"b0": 0 | uctypes.UINT8,
"b1": 1 | uctypes.UINT8,
})
i.e. value is a 2-tuple, first element of which is an offset, and second is a structure descriptor dictionary (note: offsets
in recursive descriptors are relative to the structure it defines). Of course, recursive structures can be specified not
just by a literal dictionary, but by referring to a structure descriptor dictionary (defined earlier) by name.
• Arrays of primitive types:
i.e. value is a 2-tuple, first element of which is ARRAY flag ORed with offset, and second is scalar element type
ORed number of elements in the array.
• Arrays of aggregate types:
i.e. value is a 3-tuple, first element of which is ARRAY flag ORed with offset, second is a number of elements in
the array, and third is a descriptor of element type.
• Pointer to a primitive type:
i.e. value is a 2-tuple, first element of which is PTR flag ORed with offset, and second is a scalar element type.
• Pointer to an aggregate type:
i.e. value is a 2-tuple, first element of which is PTR flag ORed with offset, second is a descriptor of type pointed
to.
• Bitfields:
i.e. value is a type of scalar value containing given bitfield (typenames are similar to scalar types, but prefixes with
BF), ORed with offset for scalar value containing the bitfield, and further ORed with values for bit position and bit
length of the bitfield within the scalar value, shifted by BF_POS and BF_LEN bits, respectively. A bitfield position
is counted from the least significant bit of the scalar (having position of 0), and is the number of right-most bit of
a field (in other words, it’s a number of bits a scalar needs to be shifted right to extract the bitfield).
In the example above, first a UINT16 value will be extracted at offset 0 (this detail may be important when accessing
hardware registers, where particular access size and alignment are required), and then bitfield whose rightmost bit
is lsbit bit of this UINT16, and length is bitsize bits, will be extracted. For example, if lsbit is 0 and bitsize is 8, then
effectively it will access least-significant byte of UINT16.
Note that bitfield operations are independent of target byte endianness, in particular, example above will access
least-significant byte of UINT16 in both little- and big-endian structures. But it depends on the least significant bit
being numbered 0. Some targets may use different numbering in their native ABI, but uctypes always uses the
normalized numbering described above.
Module contents
class uctypes.struct(addr, descriptor, layout_type=NATIVE, / )
Instantiate a “foreign data structure” object based on structure address in memory, descriptor (encoded as a dic-
tionary), and layout type (see below).
uctypes.LITTLE_ENDIAN
Layout type for a little-endian packed structure. (Packed means that every field occupies exactly as many bytes as
defined in the descriptor, i.e. the alignment is 1).
uctypes.BIG_ENDIAN
Layout type for a big-endian packed structure.
uctypes.NATIVE
Layout type for a native structure - with data endianness and alignment conforming to the ABI of the system on
which MicroPython runs.
uctypes.sizeof(struct, layout_type=NATIVE, / )
Return size of data structure in bytes. The struct argument can be either a structure class or a specific instantiated
structure object (or its aggregate field).
uctypes.addressof(obj )
Return address of an object. Argument should be bytes, bytearray or other object supporting buffer protocol (and
address of this buffer is what actually returned).
uctypes.bytes_at(addr, size)
Capture memory at the given address and size as bytes object. As bytes object is immutable, memory is actually
duplicated and copied into bytes object, so if memory contents change later, created object retains original value.
uctypes.bytearray_at(addr, size)
Capture memory at the given address and size as bytearray object. Unlike bytes_at() function above, memory is
captured by reference, so it can be both written too, and you will access current value at the given memory address.
uctypes.UINT8
uctypes.INT8
uctypes.UINT16
uctypes.INT16
uctypes.UINT32
uctypes.INT32
uctypes.UINT64
uctypes.INT64
Integer types for structure descriptors. Constants for 8, 16, 32, and 64 bit types are provided, both signed and
unsigned.
uctypes.FLOAT32
uctypes.FLOAT64
Floating-point types for structure descriptors.
uctypes.VOID
VOID is an alias for UINT8, and is provided to conveniently define C’s void pointers: (uctypes.PTR, uctypes.
VOID).
uctypes.PTR
uctypes.ARRAY
Type constants for pointers and arrays. Note that there is no explicit constant for structures, it’s implicit: an
aggregate type without PTR or ARRAY flags is a structure.
Structure objects
Structure objects allow accessing individual fields using standard dot notation: my_struct.substruct1.field1. If
a field is of scalar type, getting it will produce a primitive value (Python integer or float) corresponding to the value
contained in a field. A scalar field can also be assigned to.
If a field is an array, its individual elements can be accessed with the standard subscript operator [] - both read and
assigned to.
If a field is a pointer, it can be dereferenced using [0] syntax (corresponding to C * operator, though [0] works in C
too). Subscripting a pointer with other integer values but 0 are also supported, with the same semantics as in C.
Summing up, accessing structure fields generally follows the C syntax, except for pointer dereference, when you need to
use [0] operator instead of *.
Limitations
1. Accessing non-scalar fields leads to allocation of intermediate objects to represent them. This means that special
care should be taken to layout a structure which needs to be accessed when memory allocation is disabled (e.g. from an
interrupt). The recommendations are:
• Avoid accessing nested structures. For example, instead of mcu_registers.peripheral_a.register1, de-
fine separate layout descriptors for each peripheral, to be accessed as peripheral_a.register1. Or just
cache a particular peripheral: peripheral_a = mcu_registers.peripheral_a. If a register consists of
multiple bitfields, you would need to cache references to a particular register: reg_a = mcu_registers.
peripheral_a.reg_a.
• Avoid other non-scalar data, like arrays. For example, instead of peripheral_a.register[0] use
peripheral_a.register0. Again, an alternative is to cache intermediate values, e.g. register0 =
peripheral_a.register[0].
2. Range of offsets supported by the uctypes module is limited. The exact range supported is considered an implemen-
tation detail, and the general suggestion is to split structure definitions to cover from a few kilobytes to a few dozen of
kilobytes maximum. In most cases, this is a natural situation anyway, e.g. it doesn’t make sense to define all registers of
an MCU (spread over 32-bit address space) in one structure, but rather a peripheral block by peripheral block. In some
extreme cases, you may need to split a structure in several parts artificially (e.g. if accessing native data structure with
multi-megabyte array in the middle, though that would be a very synthetic case).
Filesystem mounting
Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple “real” filesystems within this VFS.
Filesystem objects can be mounted at either the root of the VFS, or at a subdirectory that lives in the root. This allows
dynamic and flexible configuration of the filesystem that is seen by Python programs. Ports that have this functionality
provide the mount() and umount() functions, and possibly various filesystem implementations represented by VFS
classes.
vfs.mount(fsobj, mount_point, *, readonly)
Mount the filesystem object fsobj at the location in the VFS given by the mount_point string. fsobj can be a a VFS
object that has a mount() method, or a block device. If it’s a block device then the filesystem type is automatically
detected (an exception is raised if no filesystem was recognised). mount_point may be '/' to mount fsobj at the
root, or '/<name>' to mount it at a subdirectory under the root.
If readonly is True then the filesystem is mounted read-only.
During the mount process the method mount() is called on the filesystem object.
Will raise OSError(EPERM) if mount_point is already mounted.
vfs.umount(mount_point )
Unmount a filesystem. mount_point can be a string naming the mount location, or a previously-mounted filesystem
object. During the unmount process the method umount() is called on the filesystem object.
Will raise OSError(EINVAL) if mount_point is not found.
class vfs.VfsFat(block_dev)
Create a filesystem object that uses the FAT filesystem format. Storage of the FAT filesystem is provided by
block_dev. Objects created by this constructor can be mounted using mount().
static mkfs(block_dev)
Build a FAT filesystem on block_dev.
class vfs.VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32)
Create a filesystem object that uses the littlefs v1 filesystem format. Storage of the littlefs filesystem is provided by
block_dev, which must support the extended interface. Objects created by this constructor can be mounted using
mount().
See Working with filesystems for more information.
static mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
Build a Lfs1 filesystem on block_dev.
® Note
There are reports of littlefs v1 failing in certain situations, for details see littlefs issue 347.
The mtime argument enables modification timestamps for files, stored using littlefs attributes. This option can be
disabled or enabled differently each mount time and timestamps will only be added or updated if mtime is enabled,
otherwise the timestamps will remain untouched. Littlefs v2 filesystems without timestamps will work without
reformatting and timestamps will be added transparently to existing files once they are opened for writing. When
mtime is enabled os.stat on files without timestamps will return 0 for the timestamp.
See Working with filesystems for more information.
static mkfs(block_dev, readsize=32, progsize=32, lookahead=32)
Build a Lfs2 filesystem on block_dev.
® Note
There are reports of littlefs v2 failing in certain situations, for details see littlefs issue 295.
class vfs.VfsPosix(root=None)
Create a filesystem object that accesses the host POSIX filesystem. If root is specified then it should be a path in the
host filesystem to use as the root of the VfsPosix object. Otherwise the current directory of the host filesystem is
used.
Block devices
A block device is an object which implements the block protocol. This enables a device to support MicroPython filesys-
tems. The physical hardware is represented by a user defined class. The AbstractBlockDev class is a template for the
design of such a class: MicroPython does not actually provide that class, but an actual block device class must implement
the methods described below.
A concrete implementation of this class will usually allow access to the memory-like functionality of a piece of hardware
(like flash memory). A block device can be formatted to any supported filesystem and mounted using os methods.
See Working with filesystems for example implementations of block devices using the two variants of the block protocol
described below.
There are two compatible signatures for the readblocks and writeblocks methods (see below), in order to support
a variety of use cases. A given block device may implement one form or the other, or both at the same time. The second
form (with the offset parameter) is referred to as the “extended interface”.
Some filesystems (such as littlefs) that require more control over write operations, for example writing to sub-block regions
without erasing, may require that the block device supports the extended interface.
class vfs.AbstractBlockDev(...)
Construct a block device object. The parameters to the constructor are dependent on the specific block device.
readblocks(block_num, buf )
readblocks(block_num, buf, offset )
The first form reads aligned, multiples of blocks. Starting at the block given by the index block_num, read
blocks from the device into buf (an array of bytes). The number of blocks to read is given by the length of
buf, which will be a multiple of the block size.
The second form allows reading at arbitrary locations within a block, and arbitrary lengths. Starting at block
index block_num, and byte offset within that block of offset, read bytes from the device into buf (an array of
bytes). The number of bytes to read is given by the length of buf.
writeblocks(block_num, buf )
Control the block device and query its parameters. The operation to perform is given by op which
is one of the following integers:
• 1 – initialise the device (arg is unused)
• 2 – shutdown the device (arg is unused)
• 3 – sync the device (arg is unused)
• 4 – get a count of the number of blocks, should return an integer (arg is unused)
• 5 – get the number of bytes in a block, should return an integer, or None in which case the
default value of 512 is used (arg is unused)
• 6 – erase a block, arg is the block number to erase
As a minimum ioctl(4, ...) must be intercepted; for littlefs ioctl(6, ...) must also be intercepted.
The need for others is hardware dependent.
Prior to any call to writeblocks(block, ...) littlefs issues ioctl(6, block). This enables a device
driver to erase the block prior to a write if the hardware requires it. Alternatively a driver might intercept
ioctl(6, block) and return 0 (success). In this case the driver assumes responsibility for detecting the
need for erasure.
Unless otherwise stated ioctl(op, arg) can return None. Consequently an implementation can ignore
unused values of op. Where op is intercepted, the return value for operations 4 and 5 are as detailed above.
Other operations should return 0 on success and non-zero for failure, with the value returned being an OS-
Error errno code.
Constructor
class WM8960(i2c, sample_rate, *, bits=16, swap=SWAP_NONE, route=ROUTE_PLAYBACK_RECORD,
left_input=INPUT_MIC3, right_input=INPUT_MIC2, sysclk_source=SYSCLK_MCLK,
mclk_freq=None, primary=False, adc_sync=SYNC_DAC, protocol=BUS_I2S,
i2c_address=WM8960_I2C_ADDR)
Create a WM8960 driver object, initialize the device with default settings and return the WM8960 object.
Only the first two arguments are mandatory. All others are optional. The arguments are:
• i2c is the I2C bus object.
• sample_rate is the audio sample rate. Acceptable values are 8000, 11025, 12000, 16000, 22050, 24000,
32000, 44100, 48000, 96000, 192000 and 384000. Note that not every I2S hardware will support all values.
• bits is the number of bits per audio word. Acceptable value are 16, 20, 24, and 32.
• swap swaps the left & right channel, if set; see below for options.
• route Setting the audio path in the codec; see below for options.
• left_input sets the audio source for the left input channel; see below for options.
• right_input sets the audio source for the right input channel; see below for options.
• play_source sets the audio target for the output audio; see below for options.
• sysclk_source controls whether the internal master clock called “sysclk” is directly taken from the MCLK
input or derived from it using an internal PLL. It is usually not required to change this.
• mclk_freq sets the mclk frequency applied to the MCLK pin of the codec. If not set, default values are used.
• primary lets the WM8960 act as primary or secondary device. The default setting is False. When set to
False, sample_rate and bits are controlled by the MCU.
• adc_sync sets which input is used for the ADC sync signal. The default is using the DACLRC pin.
• protocol sets the communication protocol. The default is I2S. See below for all options.
• i2c_address sets the I2C address of the WM8960, with default 0x1A.
If mclk_freq is not set the following default values are used:
• sysclk_source == SYSCLK_PLL: 11.2896 MHz for sample rates of 44100, 22050 and 11015 Hz, and 12.288
Mhz for sample rates < 48000, otherwise sample_rate * 256.
• sysclk_source == SYSCLK_MCLK: sample_rate * 256.
If the MCLK signal is applied using, for example,. a separate oscillator, it must be specified for proper operation.
Methods
In addition to initialization, the driver provides some useful methods for controlling its operation:
WM8960.set_left_input(input_source)
Specify the source for the left input. The input source names are listed above.
WM8960.set_right_input(input_source)
Specify the source for the right input. The input source names are listed above.
WM8960.volume(module, volume_l=None, volume_r=None)
Sets or gets the volume of a certain module.
If no volume values are supplied, the actual volume tuple is returned.
If one or two values are supplied, it sets the volume of a certain module. If two values are provided, the first one is
used for the left channel, the second for the right channel. If only one value is supplied, it is used for both channels.
The value range is normalized to 0.0-100.0 with a logarithmic scale.
For a list of suitable modules and db/step, see the table below.
WM8960.set_module(module, active)
Enable or disable a module, with active being False or True. For the list of module names, see the table above.
Note that enabling MODULE_MONO_OUT is different from the WM8960.mono method. The first enables output 3,
while the WM8960.mono method sends a mono mix to the left and right output.
WM8960.enable_module(module)
Enable a module. For the list of module names, see the table above.
WM8960.disable_module(module)
Disable a module. For the list of module names, see the table above.
WM8960.expand_3d(level)
Enable Stereo 3D expansion. level is a number between 0 and 15. A value of 0 disables the expansion.
WM8960.mono(active)
If active is True, a Mono mix is sent to the left and right output channel. This is different from enabling the
MODULE_MONO_MIX, which enables output 3.
WM8960.alc_mode(channel, mode=ALC_MODE )
Enables or disables ALC mode. Parameters are:
• channel enables and sets the channel for ALC. The parameter values are:
– ALC_OFF: Switch ALC off
– ALS_RIGHT: Use the right input channel
– ALC_LEFT: Use the left input channel
– ALC_STEREO: Use both input channels.
• mode sets the ALC mode. Input values are:
– ALC_MODE: act as ALC
– ALC_LIMITER: act as limiter.
WM8960.alc_gain(target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78)
Set the target level, highest and lowest gain levels and the noise gate as dB level. Permitted ranges are:
• target: -22.5 to -1.5 dB
• max_gain: -12 to 30 dB
• min_gain: -17 to 25 dB
• noise_gate: -78 to -30 dB
Excess values are limited to the permitted ranges. A value of -78 or less for noise_gate disables the noise gate
function.
WM8960.alc_time(attack=24, decay=192, hold=0)
Set the dynamic characteristic of ALC. The times are given as millisecond values. Permitted ranges are:
• attack: 6 to 6140
• decay: 24 to 24580
• hold: 0 to 43000
Excess values are limited within the permitted ranges.
WM8960.deemphasis(active)
Enables or disables a deemphasis filter for playback, with active being False or True. This filter is applied only
for sample rates of 32000, 44100 and 48000. For other sample rates, the filter setting is silently ignored.
WM8960.deinit()
Disable all modules.
Examples
Run WM8960 in secondary mode (default):
i2c = I2C(0)
wm=wm8960.WM8960(i2c, 44100, primary=True, bits=16)
Record with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default):
Play with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default):
# The breakout board uses a fixed 24MHz MCLK. Therefore the internal
# PLL must be used as sysclk, which is the master audio clock.
# The Sparkfun board has the WS pins for RX and TX connected on the
# board. Therefore adc_sync must be set to sync_adc, to configure
# it's ADCLRC pin as input.
pyb.delay(ms)
Delay for the given number of milliseconds.
pyb.udelay(us)
Delay for the given number of microseconds.
pyb.millis()
Returns the number of milliseconds since the board was last reset.
The result is always a MicroPython smallint (31-bit signed number), so after 2^30 milliseconds (about 12.4 days)
this will start to return negative numbers.
Note that if pyb.stop() is issued the hardware counter supporting this function will pause for the duration of the
“sleeping” state. This will affect the outcome of pyb.elapsed_millis().
pyb.micros()
Returns the number of microseconds since the board was last reset.
The result is always a MicroPython smallint (31-bit signed number), so after 2^30 microseconds (about 17.8 min-
utes) this will start to return negative numbers.
Note that if pyb.stop() is issued the hardware counter supporting this function will pause for the duration of the
“sleeping” state. This will affect the outcome of pyb.elapsed_micros().
pyb.elapsed_millis(start )
Returns the number of milliseconds which have elapsed since start.
This function takes care of counter wrap, and always returns a positive number. This means it can be used to
measure periods up to about 12.4 days.
Example:
start = pyb.millis()
while pyb.elapsed_millis(start) < 1000:
# Perform some operation
pyb.elapsed_micros(start )
Returns the number of microseconds which have elapsed since start.
This function takes care of counter wrap, and always returns a positive number. This means it can be used to
measure periods up to about 17.8 minutes.
Example:
start = pyb.micros()
while pyb.elapsed_micros(start) < 1000:
# Perform some operation
pass
pyb.hard_reset()
Resets the pyboard in a manner similar to pushing the external RESET button.
pyb.bootloader()
Activate the bootloader without BOOT* pins.
pyb.fault_debug(value)
Enable or disable hard-fault debugging. A hard-fault is when there is a fatal error in the underlying system, like an
invalid memory access.
If the value argument is False then the board will automatically reset if there is a hard fault.
If value is True then, when the board has a hard fault, it will print the registers and the stack trace, and then cycle
the LEDs indefinitely.
The default value is disabled, i.e. to automatically reset.
pyb.disable_irq()
Disable interrupt requests. Returns the previous IRQ state: False/True for disabled/enabled IRQs respectively.
This return value can be passed to enable_irq to restore the IRQ to its original state.
pyb.enable_irq(state=True)
Enable interrupt requests. If state is True (the default value) then IRQs are enabled. If state is False then
IRQs are disabled. The most common use of this function is to pass it the value returned by disable_irq to exit
a critical section.
[ [ [ [
pyb.freq( sysclk , hclk , pclk1 , pclk2 ]]]])
If given no arguments, returns a tuple of clock frequencies: (sysclk, hclk, pclk1, pclk2). These correspond to:
• sysclk: frequency of the CPU
• hclk: frequency of the AHB bus, core memory and DMA
• pclk1: frequency of the APB1 bus
• pclk2: frequency of the APB2 bus
If given any arguments then the function sets the frequency of the CPU, and the buses if additional arguments are
given. Frequencies are given in Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that
not all values are supported and the largest supported frequency not greater than the given value will be selected.
Supported sysclk frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 72, 84, 96, 108, 120,
144, 168.
The maximum frequency of hclk is 168MHz, of pclk1 is 42MHz, and of pclk2 is 84MHz. Be sure not to set
frequencies above these values.
The hclk, pclk1 and pclk2 frequencies are derived from the sysclk frequency using a prescaler (divider). Supported
prescalers for hclk are: 1, 2, 4, 8, 16, 64, 128, 256, 512. Supported prescalers for pclk1 and pclk2 are: 1, 2, 4, 8.
A prescaler will be chosen to best match the requested frequency.
A sysclk frequency of 8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI (internal oscillator)
directly. The higher frequencies use the HSE to drive the PLL (phase locked loop), and then use the output of the
PLL.
Note that if you change the frequency while the USB is enabled then the USB may become unreliable. It is best
to change the frequency in boot.py, before the USB peripheral is started. Also note that sysclk frequencies below
36MHz do not allow the USB to function correctly.
pyb.wfi()
Wait for an internal or external interrupt.
This executes a wfi instruction which reduces power consumption of the MCU until any interrupt occurs (be it
internal or external), at which point execution continues. Note that the system-tick interrupt occurs once every
millisecond (1000Hz) so this function will block for at most 1ms.
pyb.stop()
Put the pyboard in a “sleeping” state.
This reduces power consumption to less than 500 uA. To wake from this sleep state requires an external interrupt
or a real-time-clock event. Upon waking execution continues where it left off.
See rtc.wakeup() to configure a real-time-clock wakeup event.
pyb.standby()
Put the pyboard into a “deep sleep” state.
This reduces power consumption to less than 50 uA. To wake from this sleep state requires a real-time-clock event,
or an external interrupt on X1 (PA0=WKUP) or X18 (PC13=TAMP1). Upon waking the system undergoes a hard
reset.
See rtc.wakeup() to configure a real-time-clock wakeup event.
Miscellaneous functions
pyb.have_cdc()
Return True if USB is connected as a serial device, False otherwise.
® Note
pyb.hid((buttons, x, y, z))
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to signal a HID mouse-motion event.
® Note
[
pyb.info( dump_alloc_table ) ]
Print out lots of information about the board.
pyb.main(filename)
Set the filename of the main script to run after boot.py is finished. If this function is not called then the default file
main.py will be executed.
It only makes sense to call this function from within boot.py.
pyb.mount(device, mountpoint, *, readonly=False, mkfs=False)
® Note
This function is deprecated. Mounting and unmounting devices should be performed by vfs.mount() and
vfs.umount() instead.
Mount a block device and make it available as part of the filesystem. device must be an object that provides the
block protocol. (The following is also deprecated. See vfs.AbstractBlockDev for the correct way to create a
block device.)
• readblocks(self, blocknum, buf)
• writeblocks(self, blocknum, buf) (optional)
• count(self)
• sync(self) (optional)
readblocks and writeblocks should copy data between buf and the block device, starting from block number
blocknum on the device. buf will be a bytearray with length a multiple of 512. If writeblocks is not defined
then the device is mounted read-only. The return value of these two functions is ignored.
count should return the number of blocks available on the device. sync, if implemented, should sync the data on
the device.
The parameter mountpoint is the location in the root of the filesystem to mount the device. It must begin with a
forward-slash.
If readonly is True, then the device is mounted read-only, otherwise it is mounted read-write.
If mkfs is True, then a new filesystem is created if one does not already exist.
pyb.repl_uart(uart )
Get or set the UART object where the REPL is repeated on.
pyb.rng()
Return a 30-bit hardware generated random number.
pyb.sync()
Sync all file systems.
pyb.unique_id()
Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU.
[ ]
pyb.usb_mode( modestr, port=-1, vid=0xf055, pid=-1, msc=(), hid=pyb.hid_mouse, high_speed=False)
If called with no arguments, return the current USB mode as a string.
If called with modestr provided, attempts to configure the USB mode. The following values of modestr are under-
stood:
• None: disables USB
• 'VCP': enable with VCP (Virtual COM Port) interface
• 'MSC': enable with MSC (mass storage device class) interface
• 'VCP+MSC': enable with VCP and MSC
• 'VCP+HID': enable with VCP and HID (human interface device)
• 'VCP+MSC+HID': enabled with VCP, MSC and HID (only available on PYBD boards)
For backwards compatibility, 'CDC' is understood to mean 'VCP' (and similarly for 'CDC+MSC' and
'CDC+HID').
The port parameter should be an integer (0, 1, …) and selects which USB port to use if the board supports multiple
ports. A value of -1 uses the default or automatically selected port.
The vid and pid parameters allow you to specify the VID (vendor id) and PID (product id). A pid value of -1 will
select a PID based on the value of modestr.
If enabling MSC mode, the msc parameter can be used to specify a list of SCSI LUNs to expose on the mass storage
interface. For example msc=(pyb.Flash(), pyb.SDCard()).
If enabling HID mode, you may also specify the HID details by passing the hid keyword parameter. It takes a tuple
of (subclass, protocol, max packet length, polling interval, report descriptor). By default it will set appropriate
values for a USB mouse. There is also a pyb.hid_keyboard constant, which is an appropriate tuple for a USB
keyboard.
The high_speed parameter, when set to True, enables USB HS mode if it is supported by the hardware.
Constants
pyb.hid_mouse
pyb.hid_keyboard
A tuple of (subclass, protocol, max packet length, polling interval, report descriptor) to set appropriate values for
a USB mouse or keyboard.
Classes
accel = pyb.Accel()
for i in range(10):
print(accel.x(), accel.y(), accel.z())
Constructors
class pyb.Accel
Create and return an accelerometer object.
Methods
Accel.filtered_xyz()
Get a 3-tuple of filtered x, y and z values.
Implementation note: this method is currently implemented as taking the sum of 4 samples, sampled from the 3
previous calls to this function along with the sample from the current call. Returned values are therefore 4 times
the size of what they would be from the raw x(), y() and z() calls.
Accel.tilt()
Get the tilt register.
Accel.x()
Get the x-axis value.
Accel.y()
Get the y-axis value.
Accel.z()
Get the z-axis value.
Hardware Note
The accelerometer uses I2C bus 1 to communicate with the processor. Consequently when readings are being taken pins
X9 and X10 should be unused (other than for I2C). Other devices using those pins, and which therefore cannot be used
concurrently, are UART 1 and Timer 4 channels 1 and 2.
Usage:
import pyb
Constructors
class pyb.ADC(pin)
Create an ADC object associated with the given pin. This allows you to then read analog values on that pin.
Methods
ADC.read()
Read the value on the analog pin and return it. The returned value will be between 0 and 4095.
ADC.read_timed(buf, timer)
Read analog values into buf at a rate set by the timer object.
buf can be bytearray or array.array for example. The ADC values have 12-bit resolution and are stored directly
into buf if its element size is 16 bits or greater. If buf has only 8-bit elements (eg a bytearray) then the sample
resolution will be reduced to 8 bits.
timer should be a Timer object, and a sample is read each time the timer triggers. The timer must already be
initialised and running at the desired sampling frequency.
To support previous behaviour of this function, timer can also be an integer which specifies the frequency (in Hz)
to sample at. In this case Timer(6) will be automatically configured to run at the given frequency.
Example using a Timer object (preferred way):
This function does not allocate any heap memory. It has blocking behaviour: it does not return to the calling
program until the buffer is full.
ADC.read_timed_multi((adcx, adcy, ...), (bufx, bufy, ...), timer)
This is a static method. It can be used to extract relative timing or phase data from multiple ADC’s.
It reads analog values from multiple ADC’s into buffers at a rate set by the timer object. Each time the timer triggers
a sample is rapidly read from each ADC in turn.
ADC and buffer instances are passed in tuples with each ADC having an associated buffer. All buffers must be of
the same type and length and the number of buffers must equal the number of ADC’s.
Buffers can be bytearray or array.array for example. The ADC values have 12-bit resolution and are stored
directly into the buffer if its element size is 16 bits or greater. If buffers have only 8-bit elements (eg a bytearray)
then the sample resolution will be reduced to 8 bits.
timer must be a Timer object. The timer must already be initialised and running at the desired sampling frequency.
Example reading 3 ADC’s:
This function does not allocate any heap memory. It has blocking behaviour: it does not return to the calling
program until the buffers are full.
The function returns True if all samples were acquired with correct timing. At high sample rates the time taken to
acquire a set of samples can exceed the timer period. In this case the function returns False, indicating a loss of
precision in the sample interval. In extreme cases samples may be missed.
The maximum rate depends on factors including the data width and the number of ADC’s being read. In testing
two ADC’s were sampled at a timer rate of 210kHz without overrun. Samples were missed at 215kHz. For three
ADC’s the limit is around 140kHz, and for four it is around 110kHz. At high sample rates disabling interrupts for
the duration can reduce the risk of sporadic data loss.
Instantiating this changes all masked ADC pins to analog inputs. The preprocessed MCU temperature, VREF and VBAT
data can be accessed on ADC channels 16, 17 and 18 respectively. Appropriate scaling is handled according to reference
voltage used (usually 3.3V). The temperature sensor on the chip is factory calibrated and allows to read the die temperature
to +/- 1 degree centigrade. Although this sounds pretty accurate, don’t forget that the MCU’s internal temperature is
measured. Depending on processing loads and I/O subsystems active the die temperature may easily be tens of degrees
above ambient temperature. On the other hand a pyboard woken up after a long standby period will show correct ambient
temperature within limits mentioned above.
The ADCAll read_core_vbat(), read_vref() and read_core_vref() methods read the backup battery voltage,
reference voltage and the (1.21V nominal) reference voltage using the actual supply as a reference. All results are floating
point numbers giving direct voltage values.
read_core_vbat() returns the voltage of the backup battery. This voltage is also adjusted according to the actual
supply voltage. To avoid analog input overload the battery voltage is measured via a voltage divider and scaled according
to the divider value. To prevent excessive loads to the backup battery, the voltage divider is only active during ADC
conversion.
read_vref() is evaluated by measuring the internal voltage reference and backscale it using factory calibration value
of the internal voltage reference. In most cases the reading would be close to 3.3V. If the pyboard is operated from a
battery, the supply voltage may drop to values below 3.3V. The pyboard will still operate fine as long as the operating
conditions are met. With proper settings of MCU clock, flash access speed and programming mode it is possible to run
the pyboard down to 2 V and still get useful ADC conversion.
It is very important to make sure analog input voltages never exceed actual supply voltage.
Other analog input channels (0..15) will return unscaled integer values according to the selected precision.
To avoid unwanted activation of analog inputs (channel 0..15) a second parameter can be specified. This parameter is
a binary pattern where each requested analog input has the corresponding bit set. The default value is 0xffffffff which
means all analog inputs are active. If just the internal channels (16..18) are required, the mask value should be 0x70000.
Example:
CAN implements support for classic CAN (available on F4, F7 MCUs) and CAN FD (H7 series) controllers. At the
physical level CAN bus consists of 2 lines: RX and TX. Note that to connect the pyboard to a CAN bus you must use a
CAN transceiver to convert the CAN logic signals from the pyboard to the correct voltage levels on the bus.
Example usage for classic CAN controller in Loopback (transceiver-less) mode:
Example usage for CAN FD controller with all of the possible options enabled:
# FD frame + BRS mode + Extended frame ID. 500 Kbit/s for arbitration phase, 1Mbit/s␣
,→for data phase.
The following CAN module functions and their arguments are available for both classic and FD CAN controllers, unless
otherwise stated.
Constructors
Methods
The remaining parameters are only present on boards with CAN FD support, and configure the optional CAN FD
Bit Rate Switch (BRS) feature:
• brs_prescaler is the value by which the CAN FD input clock is divided to generate the data bit time
quanta. The prescaler can be a value between 1 and 32 inclusive.
• brs_sjw is the resynchronisation jump width in units of time quanta for data bits; it can be a value
between 1 and 16 inclusive
• brs_bs1 defines the location of the sample point in units of the time quanta for data bits; it can be
a value between 1 and 32 inclusive
• brs_bs2 defines the location of the transmit point in units of the time quanta for data bits; it can be
a value between 1 and 16 inclusive
• brs_baudrate if a baudrate other than 0 is provided, this function will try to automatically calcu-
late the CAN data bit time (overriding brs_prescaler, brs_bs1 and brs_bs2) that satisfies both the
brs_baudrate (within .1%) and the desired brs_sample_point (to the nearest 1%). For more precise
control over the BRS timing, set the brs_prescaler, brs_bs1 and brs_bs2 parameters directly.
• brs_sample_point specifies the position of the bit sample with respect to the whole nominal bit time,
expressed as an integer percentage of the nominal bit time. The default brs_sample_point is 75%.
This parameter is ignored unless brs_baudrate is set.
The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN prescaler value divided by
PCLK1 (the frequency of internal peripheral bus 1); see pyb.freq() to determine PCLK1.
A single bit is made up of the synchronisation segment, which is always 1 tq. Then follows bit segment
1, then bit segment 2. The sample point is after bit segment 1 finishes. The transmit point is after bit
segment 2 finishes. The baud rate will be 1/bittime, where the bittime is 1 + BS1 + BS2 multiplied by
the time quanta tq.
For example, with PCLK1=42MHz, prescaler=100, sjw=1, bs1=6, bs2=8, the value of tq is 2.38 mi-
croseconds. The bittime is 35.7 microseconds, and the baudrate is 28kHz.
See page 680 of the STM32F405 datasheet for more details.
CAN.deinit()
Turn off the CAN bus.
CAN.restart()
Force a software restart of the CAN controller without resetting its configuration.
If the controller enters the bus-off state then it will no longer participate in bus activity. If the controller is not
configured to automatically restart (see init()) then this method can be used to trigger a restart, and the controller
will follow the CAN protocol to leave the bus-off state and go into the error active state.
CAN.state()
Return the state of the controller. The return value can be one of:
• CAN.STOPPED – the controller is completely off and reset;
• CAN.ERROR_ACTIVE – the controller is on and in the Error Active state (both TEC and REC are less than
96);
• CAN.ERROR_WARNING – the controller is on and in the Error Warning state (at least one of TEC or REC is
96 or greater);
• CAN.ERROR_PASSIVE – the controller is on and in the Error Passive state (at least one of TEC or REC is
128 or greater);
• CAN.BUS_OFF – the controller is on but not participating in bus activity (TEC overflowed beyond 255).
[ ]
CAN.info( list )
Get information about the controller’s error states and TX and RX buffers. If list is provided then it should be a list
object with at least 8 entries, which will be filled in with the information. Otherwise a new list will be created and
filled in. In both cases the return value of the method is the populated list.
The values in the list are:
• TEC value
• REC value
• number of times the controller enterted the Error Warning state (wrapped around to 0 after 65535)
• number of times the controller enterted the Error Passive state (wrapped around to 0 after 65535)
• number of times the controller enterted the Bus Off state (wrapped around to 0 after 65535)
• number of pending TX messages
• number of pending RX messages on fifo 0
• number of pending RX messages on fifo 1
CAN.setfilter(bank, mode, fifo, params, *, rtr, extframe=False)
Configure a filter bank:
• bank is the classic CAN controller filter bank, or CAN FD filter index, to configure.
• mode is the mode the filter should operate in, see the tables below.
• fifo is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter.
• params is an array of values the defines the filter. The contents of the array depends on the mode argument.
• rtr For classic CAN controllers, this is an array of booleans that states if a filter should accept a remote
transmission request message. If this argument is not given then it defaults to False for all entries. The
length of the array depends on the mode argument. For CAN FD, this argument is ignored.
• extframe If True the frame will have an extended identifier (29 bits), otherwise a standard identifier (11 bits)
is used.
CAN.clearfilter(bank, extframe=False)
Clear and disables a filter bank:
• bank is the classic CAN controller filter bank, or CAN FD filter index, to clear.
• extframe For CAN FD controllers, if True, clear an extended filter (configured with extframe=True), other-
wise the clear a standard identifier (configured with extframe=False).
CAN.any(fifo)
Return True if any message waiting on the FIFO, else False.
CAN.recv(fifo, list=None, *, timeout=5000)
Receive data on the bus:
• fifo is an integer, which is the FIFO to receive on
• list is an optional list object to be used as the return value
• timeout is the timeout in milliseconds to wait for the receive.
Return value: A tuple containing five values.
• The id of the message.
• A boolean that indicates if the message ID is standard or extended.
• A boolean that indicates if the message is an RTR message.
• The FMI (Filter Match Index) value.
• An array containing the data.
If list is None then a new tuple will be allocated, as well as a new bytes object to contain the data (as the fifth
element in the tuple).
If list is not None then it should be a list object with a least five elements. The fifth element should be a memoryview
object which is created from either a bytearray or an array of type ‘B’ or ‘b’, and this array must have enough room
for at least 8 bytes. The list object will then be populated with the first four return values above, and the memoryview
object will be resized inplace to the size of the data and filled in with that data. The same list and memoryview
objects can be reused in subsequent calls to this method, providing a way of receiving data without using the heap.
For example:
buf = bytearray(8)
lst = [0, 0, 0, 0, memoryview(buf)]
# No heap memory is allocated in the following call
can.recv(0, lst)
Reason
0 A message has been accepted into a empty FIFO.
1 The FIFO is full
2 A message has been lost due to a full FIFO
Constants
CAN.NORMAL
CAN.LOOPBACK
CAN.SILENT
CAN.SILENT_LOOPBACK
The mode of the CAN bus used in init().
CAN.STOPPED
CAN.ERROR_ACTIVE
CAN.ERROR_WARNING
CAN.ERROR_PASSIVE
CAN.BUS_OFF
Possible states of the CAN controller returned from state().
CAN.LIST16
CAN.MASK16
CAN.LIST32
CAN.MASK32
The operation mode of a filter used in setfilter() for classic CAN.
CAN.DUAL
CAN.RANGE
CAN.MASK
The operation mode of a filter used in setfilter() for CAN FD.
The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6. The voltage will be between 0 and
3.3V.
This module will undergo changes to the API.
Example usage:
import math
from pyb import DAC
import math
from array import array
from pyb import DAC
Constructors
bits is an integer specifying the resolution, and can be 8 or 12. The maximum value for the write and write_timed
methods will be 2**``bits``-1.
The buffering parameter selects the behaviour of the DAC op-amp output buffer, whose purpose is to reduce the
output impedance. It can be None to select the default (buffering enabled for DAC.noise(), DAC.triangle()
and DAC.write_timed(), and disabled for DAC.write()), False to disable buffering completely, or True to
enable output buffering.
When buffering is enabled the DAC pin can drive loads down to 5KΩ. Otherwise it has an output impedance of
15KΩ maximum: consequently to achieve a 1% accuracy without buffering requires the applied load to be less than
1.5MΩ. Using the buffer incurs a penalty in accuracy, especially near the extremes of range.
Methods
DAC.init(bits=8, *, buffering=None)
Reinitialise the DAC. bits can be 8 or 12. buffering can be None, False or True; see above constructor for the
meaning of this parameter.
DAC.deinit()
De-initialise the DAC making its pin available for other uses.
DAC.noise(freq)
Generate a pseudo-random noise signal. A new random sample is written to the DAC output at the given frequency.
DAC.triangle(freq)
Generate a triangle wave. The value on the DAC output changes at the given frequency and ramps through the full
12-bit range (up and down). Therefore the frequency of the repeating triangle wave itself is 8192 times smaller.
DAC.write(value)
Direct access to the DAC output. The minimum value is 0. The maximum value is 2**``bits``-1, where bits is
set when creating the DAC object or by using the init method.
DAC.write_timed(data, freq, *, mode=DAC.NORMAL)
Initiates a burst of RAM to DAC using a DMA transfer. The input data is treated as an array of bytes in 8-bit
mode, and an array of unsigned half-words (array typecode ‘H’) in 12-bit mode.
freq can be an integer specifying the frequency to write the DAC samples at, using Timer(6). Or it can be an
already-initialised Timer object which is used to trigger the DAC sample. Valid timers are 2, 4, 5, 6, 7 and 8.
mode can be DAC.NORMAL or DAC.CIRCULAR.
dac1 = DAC(1)
dac2 = DAC(2)
dac1.write_timed(buf1, pyb.Timer(6, freq=100), mode=DAC.CIRCULAR)
dac2.write_timed(buf2, pyb.Timer(7, freq=200), mode=DAC.CIRCULAR)
Constants
DAC.NORMAL
NORMAL mode does a single transmission of the waveform in the data buffer,
DAC.CIRCULAR
CIRCULAR mode does a transmission of the waveform in the data buffer, and wraps around to the start of the
data buffer every time it reaches the end of the table.
There are a total of 22 interrupt lines. 16 of these can come from GPIO pins and the remaining 6 are from internal
sources.
For lines 0 through 15, a given line can map to the corresponding line from an arbitrary port. So line 0 can map to Px0
where x is A, B, C, … and line 1 can map to Px1 where x is A, B, C, …
def callback(line):
print("line =", line)
Now every time a falling edge is seen on the X1 pin, the callback will be called. Caution: mechanical pushbuttons have
“bounce” and pushing or releasing a switch will often generate multiple edges. See: http://www.eng.utah.edu/~cs5780/
debouncing.pdf for a detailed explanation, along with various techniques for debouncing.
Trying to register 2 callbacks onto the same pin will throw an exception.
If pin is passed as an integer, then it is assumed to map to one of the internal interrupt sources, and must be in the range
16 through 22.
All other pin objects go through the pin mapper to come up with one of the gpio pins.
Constructors
Class methods
classmethod ExtInt.regs()
Dump the values of the EXTI registers.
Methods
ExtInt.disable()
Disable the interrupt associated with the ExtInt object. This could be useful for debouncing.
ExtInt.enable()
Enable a disabled interrupt.
ExtInt.line()
Return the line number that the pin is mapped to.
ExtInt.swint()
Trigger the callback from software.
Constants
ExtInt.IRQ_FALLING
interrupt on a falling edge
ExtInt.IRQ_RISING
interrupt on a rising edge
ExtInt.IRQ_RISING_FALLING
interrupt on a rising or falling edge
The Flash class allows direct access to the primary flash device on the pyboard.
In most cases, to store persistent data on the device, you’ll want to use a higher-level abstraction, for example the filesystem
via Python’s standard file API, but this interface is useful to customise the filesystem configuration or implement a low-level
storage system for your application.
Constructors
class pyb.Flash
Create and return a block device that represents the flash device presented to the USB mass storage interface.
It includes a virtual partition table at the start, and the actual flash starts at block 0x100.
This constructor is deprecated and will be removed in a future version of MicroPython.
class pyb.Flash(*, start=-1, len=-1)
Create and return a block device that accesses the flash at the specified offset. The length defaults to the remaining
size of the device.
The start and len offsets are in bytes, and must be a multiple of the block size (typically 512 for internal flash).
Methods
Flash.readblocks(block_num, buf )
Flash.readblocks(block_num, buf, offset )
Flash.writeblocks(block_num, buf )
Flash.writeblocks(block_num, buf, offset )
Flash.ioctl(cmd, arg)
These methods implement the simple and extended block protocol defined by vfs.AbstractBlockDev .
Hardware Note
On boards with external spiflash (e.g. Pyboard D), the MicroPython firmware will be configured to use that as the primary
flash storage. On all other boards, the internal flash inside the MCU will be used.
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.
I2C objects are created attached to a specific bus. They can be initialised when created, or initialised later on.
Example:
Printing the i2c object gives you information about its configuration.
The basic methods are send and recv:
i2c.init(I2C.CONTROLLER)
i2c.send('123', 0x42) # send 3 bytes to peripheral with address 0x42
i2c.send(b'456', addr=0x42) # keyword for address
Constructors
Methods
I2C.deinit()
Turn off the I2C bus.
I2C.init(mode, *, addr=0x12, baudrate=400000, gencall=False, dma=False)
Initialise the I2C bus with the given parameters:
• mode must be either I2C.CONTROLLER or I2C.PERIPHERAL
• addr is the 7-bit address (only sensible for a peripheral)
• baudrate is the SCL clock rate (only sensible for a controller)
• gencall is whether to support general call mode
• dma is whether to allow the use of DMA for the I2C transfers (note that DMA transfers have more
precise timing but currently do not handle bus errors properly)
The actual clock frequency may be lower than the requested frequency. This is dependent on the plat-
form hardware. The actual rate may be determined by printing the I2C object.
I2C.is_ready(addr)
Check if an I2C device responds to the given address. Only valid when in controller mode.
I2C.mem_read(data, addr, memaddr, *, timeout=5000, addr_size=8)
Read from the memory of an I2C device:
• data can be an integer (number of bytes to read) or a buffer to read into
• addr is the I2C device address
• memaddr is the memory location within the I2C device
• timeout is the timeout in milliseconds to wait for the read
• addr_size selects width of memaddr: 8 or 16 bits
Returns the read data. This is only valid in controller mode.
I2C.mem_write(data, addr, memaddr, *, timeout=5000, addr_size=8)
Write to the memory of an I2C device:
• data can be an integer or a buffer to write from
• addr is the I2C device address
• memaddr is the memory location within the I2C device
• timeout is the timeout in milliseconds to wait for the write
• addr_size selects width of memaddr: 8 or 16 bits
Returns None. This is only valid in controller mode.
I2C.recv(recv, addr=0x00, *, timeout=5000)
Receive data on the bus:
• recv can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with
received bytes
• addr is the address to receive from (only required in controller mode)
• timeout is the timeout in milliseconds to wait for the receive
Return value: if recv is an integer then a new buffer of the bytes received, otherwise the same buffer that was
passed in to recv.
I2C.send(send, addr=0x00, *, timeout=5000)
Send data on the bus:
• send is the data to send (an integer to send, or a buffer object)
• addr is the address to send to (only required in controller mode)
• timeout is the timeout in milliseconds to wait for the send
Return value: None.
I2C.scan()
Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. Only valid when in controller
mode.
Constants
I2C.CONTROLLER
for initialising the bus to controller mode
I2C.PERIPHERAL
for initialising the bus to peripheral mode
The LCD class is used to control the LCD on the LCD touch-sensor pyskin, LCD32MKv1.0. The LCD is a 128x32 pixel
monochrome screen, part NHD-C12832A1Z.
The pyskin must be connected in either the X or Y positions, and then an LCD object is made using:
This driver implements a double buffer for setting/getting pixels. For example, to make a bouncing dot, try:
x = y = 0
dx = dy = 1
while True:
# update the dot's position
x += dx
y += dy
Constructors
class pyb.LCD(skin_position)
Construct an LCD object in the given skin position. skin_position can be ‘X’ or ‘Y’, and should match the
position where the LCD pyskin is plugged in.
Methods
LCD.command(instr_data, buf )
Send an arbitrary command to the LCD. Pass 0 for instr_data to send an instruction, otherwise pass 1 to send
data. buf is a buffer with the instructions/data to send.
LCD.contrast(value)
Set the contrast of the LCD. Valid values are between 0 and 47.
LCD.fill(colour)
Fill the screen with the given colour (0 or 1 for white or black).
This method writes to the hidden buffer. Use show() to show the buffer.
LCD.get(x, y)
Get the pixel at the position (x, y). Returns 0 or 1.
This method reads from the visible buffer.
LCD.light(value)
Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off.
LCD.pixel(x, y, colour)
Set the pixel at (x, y) to the given colour (0 or 1).
This method writes to the hidden buffer. Use show() to show the buffer.
LCD.show()
Show the hidden buffer on the screen.
LCD.text(str, x, y, colour)
Draw the given text to the position (x, y) using the given colour (0 or 1).
This method writes to the hidden buffer. Use show() to show the buffer.
LCD.write(str)
Write the string str to the screen. It will appear immediately.
Constructors
class pyb.LED(id )
Create an LED object associated with the given LED:
• id is the LED number, 1-4.
Methods
[
LED.intensity( value ) ]
Get or set the LED intensity. Intensity ranges between 0 (off) and 255 (full on). If no argument is given, return the
LED intensity. If an argument is given, set the LED intensity and return None.
Note: Only LED(3) and LED(4) can have a smoothly varying intensity, and they use timer PWM to implement it.
LED(3) uses Timer(2) and LED(4) uses Timer(3). These timers are only configured for PWM if the intensity of
the relevant LED is set to a value between 1 and 254. Otherwise the timers are free for general purpose use.
LED.off()
Turn the LED off.
LED.on()
Turn the LED on, to maximum intensity.
LED.toggle()
Toggle the LED between on (maximum intensity) and off. If the LED is at non-zero intensity then it is considered
“on” and toggle will turn it off.
A pin is the basic object to control I/O pins. It has methods to set the mode of the pin (input, output, etc) and methods
to get and set the digital logic level. For analog control of a pin, see the ADC class.
Usage Model:
All Board Pins are predefined as pyb.Pin.board.Name:
x1_pin = pyb.Pin.board.X1
g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN)
CPU pins which correspond to the board pins are available as pyb.Pin.cpu.Name. For the CPU pins, the names are
the port letter followed by the pin number. On the PYBv1.0, pyb.Pin.board.X1 and pyb.Pin.cpu.A0 are the same
pin.
You can also use strings:
g = pyb.Pin('X1', pyb.Pin.OUT_PP)
pin = pyb.Pin("LeftMotorDir")
def MyMapper(pin_name):
if pin_name == "LeftMotorDir":
return pyb.Pin.cpu.A0
(continues on next page)
pyb.Pin.mapper(MyMapper)
So, if you were to call: pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP) then "LeftMotorDir" is passed directly
to the mapper function.
To summarise, the following order determines how things get mapped into an ordinal pin number:
1. Directly specify a pin object
2. User supplied mapping function
3. User supplied mapping (object must be usable as a dictionary key)
4. Supply a string which matches a board pin
5. Supply a string which matches a CPU port/pin
You can set pyb.Pin.debug(True) to get some debug information about how a particular object gets mapped to a pin.
All pin objects go through the pin mapper to come up with one of the gpio pins.
Constructors
Class methods
Methods
Constants
Pin.ALT
initialise the pin to alternate-function mode for input or output
Pin.AF_OD
initialise the pin to alternate-function mode with an open-drain drive
Pin.AF_PP
initialise the pin to alternate-function mode with a push-pull drive
Pin.ANALOG
initialise the pin to analog mode
Pin.IN
initialise the pin to input mode
Pin.OUT_OD
initialise the pin to output mode with an open-drain drive
Pin.OUT_PP
initialise the pin to output mode with a push-pull drive
Pin.PULL_DOWN
enable the pull-down resistor on the pin
Pin.PULL_NONE
don’t enable any pull up or down resistors on the pin
Pin.PULL_UP
enable the pull-up resistor on the pin
A Pin represents a physical pin on the microprocessor. Each pin can have a variety of functions (GPIO, I2C SDA, etc).
Each PinAF object represents a particular function for a pin.
Usage Model:
x3 = pyb.Pin.board.X3
x3_af = x3.af_list()
x3_af will now contain an array of PinAF objects which are available on pin X3.
For the pyboard, x3_af would contain:
[Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2]
Normally, each peripheral would configure the alternate function automatically, but sometimes the same function is avail-
able on multiple pins, and having more control is desired.
To configure X3 to expose TIM2_CH3, you could use:
or:
Methods
pinaf.__str__()
Return a string describing the alternate function.
pinaf.index()
Return the alternate function index.
pinaf.name()
Return the name of the alternate function.
pinaf.reg()
Return the base register associated with the peripheral assigned to this alternate function. For example, if the
alternate function were TIM2_CH3 this would return stm.TIM2
The RTC is an independent clock that keeps track of the date and time.
Example usage:
rtc = pyb.RTC()
rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
print(rtc.datetime())
Constructors
class pyb.RTC
Create an RTC object.
Methods
[
RTC.datetime( datetimetuple ) ]
Get or set the date and time of the RTC.
With no arguments, this method returns an 8-tuple with the current date and time. With 1 argument (being an
8-tuple) it sets the date and time (and subseconds is reset to 255).
The 8-tuple has the following format:
(year, month, day, weekday, hours, minutes, seconds, subseconds)
weekday is 1-7 for Monday through Sunday.
Servo objects control standard hobby servo motors with 3-wires (ground, power, signal). There are 4 positions on the
pyboard where these motors can be plugged in: pins X1 through X4 are the signal pins, and next to them are 4 sets of
power and ground pins.
Example usage:
import pyb
® Note
The Servo objects use Timer(5) to produce the PWM output. You can use Timer(5) for Servo control, or your own
purposes, but not both at the same time.
Constructors
class pyb.Servo(id )
Create a servo object. id is 1-4, and corresponds to pins X1 through X4.
Methods
[
Servo.angle( angle, time=0 ) ]
If no arguments are given, this function returns the current angle.
If arguments are given, this function sets the angle of the servo:
• angle is the angle to move to in degrees.
• time is the number of milliseconds to take to get to the specified angle. If omitted, then the servo moves as
quickly as possible to its new position.
[
Servo.speed( speed, time=0 ) ]
If no arguments are given, this function returns the current speed.
If arguments are given, this function sets the speed of the servo:
• speed is the speed to change to, between -100 and 100.
• time is the number of milliseconds to take to get to the specified speed. If omitted, then the servo accelerates
as quickly as possible.
[
Servo.pulse_width( value ) ]
If no arguments are given, this function returns the current raw pulse-width value.
If an argument is given, this function sets the raw pulse-width value.
[ [
Servo.calibration( pulse_min, pulse_max, pulse_centre , pulse_angle_90, pulse_speed_100 ]])
If no arguments are given, this function returns the current calibration data, as a 5-tuple.
If arguments are given, this function sets the timing calibration:
• pulse_min is the minimum allowed pulse width.
• pulse_max is the maximum allowed pulse width.
• pulse_centre is the pulse width corresponding to the centre/zero position.
• pulse_angle_90 is the pulse width corresponding to 90 degrees.
• pulse_speed_100 is the pulse width corresponding to a speed of 100.
SPI is a serial protocol that is driven by a controller. At the physical level there are 3 lines: SCK, MOSI, MISO.
See usage model of I2C; SPI is very similar. Main difference is parameters to init the SPI bus:
Only required parameter is mode, SPI.CONTROLLER or SPI.PERIPHERAL. Polarity can be 0 or 1, and is the level
the idle clock line sits at. Phase can be 0 or 1 to sample data on the first or second clock edge respectively. Crc can be
None for no CRC, or a polynomial specifier.
Additional methods for SPI:
Constructors
• SPI(2) is on the Y position: (NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13,
PB14, PB15)
At the moment, the NSS pin is not used by the SPI driver and is free for other use.
Methods
SPI.deinit()
Turn off the SPI bus.
SPI.init(mode, baudrate=328125, *, prescaler=-1, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False,
crc=None)
Initialise the SPI bus with the given parameters:
• mode must be either SPI.CONTROLLER or SPI.PERIPHERAL.
• baudrate is the SCK clock rate (only sensible for a controller).
• prescaler is the prescaler to use to derive SCK from the APB bus frequency; use of prescaler overrides
baudrate.
• polarity can be 0 or 1, and is the level the idle clock line sits at.
• phase can be 0 or 1 to sample data on the first or second clock edge respectively.
• bits can be 8 or 16, and is the number of bits in each transferred word.
• firstbit can be SPI.MSB or SPI.LSB.
• ti True indicates Texas Instruments, as opposed to Motorola, signal conventions.
• crc can be None for no CRC, or a polynomial specifier.
Note that the SPI clock frequency will not always be the requested baudrate. The hardware only supports baudrates
that are the APB bus frequency (see pyb.freq()) divided by a prescaler, which can be 2, 4, 8, 16, 32, 64, 128
or 256. SPI(1) is on AHB2, and SPI(2) is on AHB1. For precise control over the SPI clock frequency, specify
prescaler instead of baudrate.
Printing the SPI object will show you the computed baudrate and the chosen prescaler.
SPI.recv(recv, *, timeout=5000)
Receive data on the bus:
• recv can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with
received bytes.
• timeout is the timeout in milliseconds to wait for the receive.
Return value: if recv is an integer then a new buffer of the bytes received, otherwise the same buffer that was
passed in to recv.
SPI.send(send, *, timeout=5000)
Send data on the bus:
• send is the data to send (an integer to send, or a buffer object).
• timeout is the timeout in milliseconds to wait for the send.
Return value: None.
SPI.send_recv(send, recv=None, *, timeout=5000)
Send and receive data on the bus at the same time:
• send is the data to send (an integer to send, or a buffer object).
• recv is a mutable buffer which will be filled with received bytes. It can be the same as send, or omitted. If
omitted, a new buffer will be created.
• timeout is the timeout in milliseconds to wait for the receive.
Return value: the buffer with the received bytes.
Constants
SPI.CONTROLLER
SPI.PERIPHERAL
for initialising the SPI bus to controller or peripheral mode
SPI.LSB
SPI.MSB
set the first bit to be the least or most significant bit
Example:
pyb.Switch().callback(lambda: pyb.LED(1).toggle())
Constructors
class pyb.Switch
Create and return a switch object.
Methods
Switch.__call__()
Call switch object directly to get its state: True if pressed down, False otherwise.
Switch.value()
Get the switch state. Returns True if pressed down, otherwise False.
Switch.callback(fun)
Register the given function to be called when the switch is pressed down. If fun is None, then it disables the
callback.
Timers can be used for a great variety of tasks. At the moment, only the simplest case is implemented: that of calling a
function periodically.
Each timer consists of a counter that counts up at a certain rate. The rate at which it counts is the peripheral clock
frequency (in Hz) divided by the timer prescaler. When the counter reaches the timer period it triggers an event, and the
counter resets back to zero. By using the callback method, the timer event can call a Python function.
Example usage to toggle an LED at a fixed frequency:
def tick(timer): # we will receive the timer object when being called
print(timer.counter()) # show current timer's counter value
tim = pyb.Timer(4, freq=1) # create a timer object using timer 4 - trigger at 1Hz
tim.callback(tick) # set the callback to our tick function
Further examples:
Note: Timer(2) and Timer(3) are used for PWM to set the intensity of LED(3) and LED(4) respectively. But these timers
are only configured for PWM if the intensity of the relevant LED is set to a value between 1 and 254. If the intensity
feature of the LEDs is not used then these timers are free for general purpose use. Similarly, Timer(5) controls the servo
driver, and Timer(6) is used for timed ADC/DAC reading/writing. It is recommended to use the other timers in your
programs.
Note: Memory can’t be allocated during a callback (an interrupt) and so exceptions raised within a callback don’t give
much information. See micropython.alloc_emergency_exception_buf() for how to get around this limitation.
Constructors
Methods
Keyword arguments:
• freq — specifies the periodic frequency of the timer. You might also view this as the frequency
with which the timer goes through one complete cycle.
• prescaler [0-0xffff] - specifies the value to be loaded into the timer’s Prescaler Register (PSC).
The timer clock source is divided by (prescaler + 1) to arrive at the timer clock. Timers 2-7
and 12-14 have a clock source of 84 MHz (pyb.freq()[2] * 2), and Timers 1, and 8-11 have a clock
source of 168 MHz (pyb.freq()[3] * 2).
• period [0-0xffff] for timers 1, 3, 4, and 6-15. [0-0x3fffffff] for timers 2 & 5. Specifies the value
to be loaded into the timer’s AutoReload Register (ARR). This determines the period of the timer
(i.e. when the counter cycles). The timer counter will roll-over after period + 1 timer clock
cycles.
• mode can be one of:
– Timer.UP - configures the timer to count from 0 to ARR (default)
– Timer.DOWN - configures the timer to count from ARR down to 0.
– Timer.CENTER - configures the timer to count from 0 to ARR and then back down to 0.
• div can be one of 1, 2, or 4. Divides the timer clock to determine the sampling clock used by the
digital filters.
• callback - as per Timer.callback()
• deadtime - specifies the amount of “dead” or inactive time between transitions on complimentary
channels (both channels will be inactive) for this time). deadtime may be an integer between 0
and 1008, with the following restrictions: 0-128 in steps of 1. 128-256 in steps of 2, 256-512 in
steps of 8, and 512-1008 in steps of 16. deadtime measures ticks of source_freq divided by
div clock ticks. deadtime is only available on timers 1 and 8.
• brk - specifies if the break mode is used to kill the output of the PWM when the BRK_IN input is
asserted. The value of this argument determines if break is enabled and what the polarity is, and
can be one of Timer.BRK_OFF, Timer.BRK_LOW or Timer.BRK_HIGH. To select the BRK_IN
pin construct a Pin object with mode=Pin.ALT, alt=Pin.AFn_TIMx. The pin’s GPIO input
features are available in alt mode - pull= , value() and irq().
You must either specify freq or both of period and prescaler.
Timer.deinit()
Deinitialises the timer.
Disables the callback (and the associated irq).
Disables any channel callbacks (and the associated irq). Stops the timer, and disables the timer peripheral.
Timer.callback(fun)
Set the function to be called when the timer triggers. fun is passed 1 argument, the timer object. If fun is None
then the callback will be disabled.
Timer.channel(channel, mode, ...)
If only a channel number is passed, then a previously initialized channel object is returned (or None if there is no
previous channel).
Otherwise, a TimerChannel object is initialized and returned.
Each channel can be configured to perform pwm, output compare, or input capture. All channels share the same
underlying timer, which means that they share the same timer clock.
Keyword arguments:
• mode can be one of:
PWM Example:
PWM Motor Example with complementary outputs, dead time, break input and break callback:
Timer.counter( value ) [ ]
Get or set the timer counter.
[
Timer.freq( value ) ]
Get or set the frequency for the timer (changes prescaler and period if set).
[
Timer.period( value ) ]
Get or set the period of the timer.
Timer.prescaler( value ) [ ]
Get or set the prescaler for the timer.
Timer.source_freq()
Get the frequency of the source of the timer.
Methods
timerchannel.callback(fun)
Set the function to be called when the timer channel triggers. fun is passed 1 argument, the timer object. If fun
is None then the callback will be disabled.
timerchannel.capture( value ) [ ]
Get or set the capture value associated with a channel. capture, compare, and pulse_width are all aliases for the
same function. capture is the logical name to use when the channel is in input capture mode.
timerchannel.compare( value ) [ ]
Get or set the compare value associated with a channel. capture, compare, and pulse_width are all aliases for the
same function. compare is the logical name to use when the channel is in output compare mode.
timerchannel.pulse_width( value ) [ ]
Get or set the pulse width value associated with a channel. capture, compare, and pulse_width are all aliases for
the same function. pulse_width is the logical name to use when the channel is in PWM mode.
In edge aligned mode, a pulse_width of period + 1 corresponds to a duty cycle of 100% In center aligned mode,
a pulse width of period corresponds to a duty cycle of 100%
timerchannel.pulse_width_percent( value ) [ ]
Get or set the pulse width percentage associated with a channel. The value is a number between 0 and 100 and
sets the percentage of the timer period for which the pulse is active. The value can be an integer or floating-point
number for more accuracy. For example, a value of 25 gives a duty cycle of 25%.
Constants
Timer.UP
Timer.DOWN
Timer.CENTER
Configures the timer to count Up, Down, or from 0 to ARR and then back down to 0.
Timer.BRK_OFF
Timer.BRK_LOW
Timer.BRK_HIGH
Configures the break mode when passed to the brk keyword argument.
UART implements the standard UART/USART duplex serial communications protocol. At the physical level it consists
of 2 lines: RX and TX. The unit of communication is a character (not to be confused with a string character) which can
be 8 or 9 bits wide.
UART objects can be created and initialised using:
Note: The stream functions read, write, etc. are new in MicroPython v1.3.4. Earlier versions use uart.send and
uart.recv.
Constructors
Methods
Note: with parity=None, only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits are supported.
UART.deinit()
Turn off the UART bus.
UART.any()
Returns the number of bytes waiting (may be 0).
[
UART.read( nbytes ) ]
Read characters. If nbytes is specified then read at most that many bytes. If nbytes are available in the buffer,
returns immediately, otherwise returns when sufficient characters arrive or the timeout elapses.
If nbytes is not given then the method reads as much data as possible. It returns after the timeout has elapsed.
Note: for 9 bit characters each character takes two bytes, nbytes must be even, and the number of characters is
nbytes/2.
Return value: a bytes object containing the bytes read in. Returns None on timeout.
UART.readchar()
Receive a single character on the bus.
Return value: The character read, as an integer. Returns -1 on timeout.
[
UART.readinto(buf , nbytes ) ]
Read bytes into the buf. If nbytes is specified then read at most that many bytes. Otherwise, read at most
len(buf) bytes.
Return value: number of bytes read and stored into buf or None on timeout.
UART.readline()
Read a line, ending in a newline character. If such a line exists, return is immediate. If the timeout elapses, all
available data is returned regardless of whether a newline exists.
Return value: the line read or None on timeout if no data is available.
UART.write(buf )
Write the buffer of bytes to the bus. If characters are 7 or 8 bits wide then each byte is one character. If characters
are 9 bits wide then two bytes are used for each character (little endian), and buf must contain an even number of
bytes.
Return value: number of bytes written. If a timeout occurs and no bytes were written returns None.
UART.writechar(char)
Write a single character on the bus. char is an integer to write. Return value: None. See note below if CTS flow
control is used.
UART.sendbreak()
Send a break condition on the bus. This drives the bus low for a duration of 13 bits. Return value: None.
Constants
UART.RTS
UART.CTS
to select the flow control type.
Flow Control
On Pyboards V1 and V1.1 UART(2) and UART(3) support RTS/CTS hardware flow control using the following pins:
• UART(2) is on: (TX, RX, nRTS, nCTS) = (X3, X4, X2, X1) = (PA2, PA3, PA1, PA0)
• UART(3) is on :(TX, RX, nRTS, nCTS) = (Y9, Y10, Y7, Y6) = (PB10, PB11, PB14, PB13)
On the Pyboard Lite only UART(2) supports flow control on these pins:
(TX, RX, nRTS, nCTS) = (X1, X2, X4, X3) = (PA2, PA3, PA1, PA0)
In the following paragraphs the term “target” refers to the device connected to the UART.
When the UART’s init() method is called with flow set to one or both of UART.RTS and UART.CTS the relevant flow
control pins are configured. nRTS is an active low output, nCTS is an active low input with pullup enabled. To achieve
flow control the Pyboard’s nCTS signal should be connected to the target’s nRTS and the Pyboard’s nRTS to the target’s
nCTS.
The USB_HID class allows creation of an object representing the USB Human Interface Device (HID) interface. It can
be used to emulate a peripheral such as a mouse or keyboard.
Before you can use this class, you need to use pyb.usb_mode() to set the USB mode to include the HID interface.
Constructors
class pyb.USB_HID
Create a new USB_HID object.
Methods
USB_HID.recv(data, *, timeout=5000)
Receive data on the bus:
• data can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with
received bytes.
• timeout is the timeout in milliseconds to wait for the receive.
Return value: if data is an integer then a new buffer of the bytes received, otherwise the number of bytes read
into data is returned.
USB_HID.send(data)
Send data over the USB HID interface:
• data is the data to send (a tuple/list of integers, or a bytearray).
The USB_VCP class allows creation of a stream-like object representing the USB virtual comm port. It can be used to
read and write data over USB to the connected host.
Constructors
class pyb.USB_VCP(id=0)
Create a new USB_VCP object. The id argument specifies which USB VCP port to use.
Methods
USB_VCP.init(*, flow=-1)
Configure the USB VCP port. If the flow argument is not -1 then the value sets the flow control, which can be a
bitwise-or of USB_VCP.RTS and USB_VCP.CTS. RTS is used to control read behaviour and CTS, to control write
behaviour.
USB_VCP.setinterrupt(chr)
Set the character which interrupts running Python code. This is set to 3 (CTRL-C) by default, and when a CTRL-C
character is received over the USB VCP port, a KeyboardInterrupt exception is raised.
Set to -1 to disable this interrupt feature. This is useful when you want to send raw bytes over the USB VCP port.
USB_VCP.isconnected()
Return True if USB is connected as a serial device, else False.
USB_VCP.any()
Return True if any characters waiting, else False.
USB_VCP.close()
This method does nothing. It exists so the USB_VCP object can act as a file.
[
USB_VCP.read( nbytes ) ]
Read at most nbytes from the serial device and return them as a bytes object. If nbytes is not specified then
the method reads all available bytes from the serial device. USB_VCP stream implicitly works in non-blocking
mode, so if no pending data available, this method will return immediately with None value.
[
USB_VCP.readinto(buf , maxlen ) ]
Read bytes from the serial device and store them into buf, which should be a buffer-like object. At most len(buf)
bytes are read. If maxlen is given and then at most min(maxlen, len(buf)) bytes are read.
Returns the number of bytes read and stored into buf or None if no pending data available.
USB_VCP.readline()
Read a whole line from the serial device.
Returns a bytes object containing the data, including the trailing newline character or None if no pending data
available.
USB_VCP.readlines()
Read as much data as possible from the serial device, breaking it into lines.
Returns a list of bytes objects, each object being one of the lines. Each line will include the newline character.
USB_VCP.write(buf )
Write the bytes from buf to the serial device.
Returns the number of bytes written.
USB_VCP.recv(data, *, timeout=5000)
Receive data on the bus:
• data can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with
received bytes.
• timeout is the timeout in milliseconds to wait for the receive.
Return value: if data is an integer then a new buffer of the bytes received, otherwise the number of bytes read
into data is returned.
USB_VCP.send(data, *, timeout=5000)
Send data over the USB VCP:
• data is the data to send (an integer to send, or a buffer object).
• timeout is the timeout in milliseconds to wait for the send.
Return value: number of bytes sent.
USB_VCP.irq(handler=None, trigger=IRQ_RX, hard=False)
Register handler to be called whenever an event specified by trigger occurs. The handler function must take exactly
one argument, which will be the USB VCP object. Pass in None to disable the callback.
Valid values for trigger are:
• USB_VCP.IRQ_RX: new data is available for reading from the USB VCP object.
Constants
USB_VCP.RTS
USB_VCP.CTS
to select the flow control type.
USB_VCP.IRQ_RX
IRQ trigger values for USB_VCP.irq().
This module provides functionality specific to STM32 microcontrollers, including direct access to peripheral registers.
Memory access
The module exposes three objects used for raw memory access.
stm.mem8
Read/write 8 bits of memory.
stm.mem16
Read/write 16 bits of memory.
stm.mem32
Read/write 32 bits of memory.
Use subscript notation [...] to index these objects with the address of interest.
These memory objects can be used in combination with the peripheral register constants to read and write registers of the
MCU hardware peripherals, as well as all other areas of address space.
The module defines constants for registers which are generated from CMSIS header files, and the constants available
depend on the microcontroller series that is being compiled for. Examples of some constants include:
stm.GPIOA
Base address of the GPIOA peripheral.
stm.GPIOB
Base address of the GPIOB peripheral.
stm.GPIO_BSRR
Offset of the GPIO bit set/reset register.
stm.GPIO_IDR
Offset of the GPIO input data register.
stm.GPIO_ODR
Offset of the GPIO output data register.
Constants that are named after a peripheral, like GPIOA, are the absolute address of that peripheral. Constants that have
a prefix which is the name of a peripheral, like GPIO_BSRR, are relative offsets of the register. Accessing peripheral
registers requires adding the absolute base address of the peripheral and the relative register offset. For example GPIOA
+ GPIO_BSRR is the full, absolute address of the GPIOA->BSRR register.
Example use:
# read PA3
value = (stm.mem32[stm.GPIOA + stm.GPIO_IDR] >> 3) & 1
These functions are available on STM32WBxx microcontrollers, and interact with the second CPU, the RF core.
stm.rfcore_status()
Returns the status of the second CPU as an integer (the first word of device info table).
stm.rfcore_fw_version(id )
Get the version of the firmware running on the second CPU. Pass in 0 for id to get the FUS version, and 1 to get
the WS version.
Returns a 5-tuple with the full version number.
stm.rfcore_sys_hci(ogf, ocf, data, timeout_ms=0)
Execute a HCI command on the SYS channel. The execution is synchronous.
Returns a bytes object with the result of the SYS command.
These functions are available on STM32WLxx microcontrollers, and interact with the integrated “SUBGHZ” radio mo-
dem peripheral.
stm.subghz_cs(level)
Sets the internal SPI CS pin attached to the radio peripheral. The level argument is active-low: a truthy value
means “CS pin high” and de-asserts the signal, a falsey value means “CS pin low” and asserts the signal.
The internal-only SPI bus corresponding to this CS signal can be instantiated using machine.SPI() id value "SUB-
GHZ".
stm.subghz_irq(handler)
Sets the internal SUBGHZ radio interrupt handler to the provided function. The handler function is called as a
“hard” interrupt in response to radio peripheral interrupts. See Writing interrupt handlers for more information
about interrupt handlers in MicroPython.
Calling this function with the handler argument set to None disables the IRQ.
Due to a hardware limitation, each time this IRQ fires MicroPython disables it before calling the handler. In order
to receive another interrupt, Python code should call subghz_irq() to set the handler again. This has the side
effect of re-enabling the IRQ.
stm.subghz_is_busy()
Return a bool corresponding to the internal “RFBUSYS” signal from the radio peripheral. Before sending a new
command to the radio over SPI then this function should be polled until it returns False, to confirm the busy signal
is de-asserted.
class LCD160CR
The LCD160CR class provides an interface to the display. Create an instance of this class and use its methods to draw
to the LCD and get the status of the touch panel.
For example:
import lcd160cr
lcd = lcd160cr.LCD160CR('X')
lcd.set_orient(lcd160cr.PORTRAIT)
lcd.set_pos(0, 0)
lcd.set_text_color(lcd.rgb(255, 0, 0), lcd.rgb(0, 0, 0))
lcd.set_font(1)
lcd.write('Hello MicroPython!')
print('touch:', lcd.get_touch())
Constructors
Static methods
static LCD160CR.rgb(r, g, b)
Return a 16-bit integer representing the given rgb color values. The 16-bit value can be used to set the font color
(see LCD160CR.set_text_color()) pen color (see LCD160CR.set_pen()) and draw individual pixels.
LCD160CR.clip_line(data, w, h):
Clip the given line data. This is for internal use.
Instance members
LCD160CR.h
The width and height of the display, respectively, in pixels. These members are updated when calling LCD160CR.
set_orient() and should be considered read-only.
Setup commands
LCD160CR.set_power(on)
Turn the display on or off, depending on the given value of on: 0 or False will turn the display off, and 1 or True
will turn it on.
LCD160CR.set_orient(orient )
Set the orientation of the display. The orient parameter can be one of PORTRAIT , LANDSCAPE, POR-
TRAIT_UPSIDEDOWN , LANDSCAPE_UPSIDEDOWN .
LCD160CR.set_brightness(value)
Set the brightness of the display, between 0 and 31.
LCD160CR.set_i2c_addr(addr)
Set the I2C address of the display. The addr value must have the lower 2 bits cleared.
LCD160CR.set_uart_baudrate(baudrate)
Set the baudrate of the UART interface.
LCD160CR.set_startup_deco(value)
Set the start-up decoration of the display. The value parameter can be a logical or of STARTUP_DECO_NONE,
STARTUP_DECO_MLOGO, STARTUP_DECO_INFO.
LCD160CR.save_to_flash()
Save the following parameters to flash so they persist on restart and power up: initial decoration, orientation,
brightness, UART baud rate, I2C address.
LCD160CR.get_pixel(x, y)
Get the 16-bit value of the specified pixel.
LCD160CR.get_line(x, y, buf )
Low-level method to get a line of pixels into the given buffer. To read n pixels buf should be 2*n+1 bytes in length.
The first byte is a dummy byte and should be ignored, and subsequent bytes represent the pixels in the line starting
at coordinate (x, y).
LCD160CR.screen_dump(buf, x=0, y=0, w=None, h=None)
Dump the contents of the screen to the given buffer. The parameters x and y specify the starting coordinate, and w
and h the size of the region. If w or h are None then they will take on their maximum values, set by the size of the
screen minus the given x and y values. buf should be large enough to hold 2*w*h bytes. If it’s smaller then only
the initial horizontal lines will be stored.
LCD160CR.screen_load(buf )
Load the entire screen from the given buffer.
Drawing text
To draw text one sets the position, color and font, and then uses LCD160CR.write to draw the text.
LCD160CR.set_pos(x, y)
Set the position for text output using LCD160CR.write(). The position is the upper-left corner of the text.
LCD160CR.set_text_color(fg, bg)
Set the foreground and background color of the text.
Primitive drawing commands use a foreground and background color set by the set_pen method.
LCD160CR.set_pen(line, fill)
Set the line and fill color for primitive shapes.
LCD160CR.erase()
Erase the entire display to the pen fill color.
LCD160CR.dot(x, y)
Draw a single pixel at the given location using the pen line color.
LCD160CR.rect(x, y, w, h)
LCD160CR.rect_outline(x, y, w, h)
LCD160CR.rect_interior(x, y, w, h)
Draw a rectangle at the given location and size using the pen line color for the outline, and the pen fill color for the
interior. The rect method draws the outline and interior, while the other methods just draw one or the other.
LCD160CR.line(x1, y1, x2, y2)
Draw a line between the given coordinates using the pen line color.
LCD160CR.dot_no_clip(x, y)
LCD160CR.rect_no_clip(x, y, w, h)
LCD160CR.rect_outline_no_clip(x, y, w, h)
LCD160CR.rect_interior_no_clip(x, y, w, h)
LCD160CR.poly_line(data)
Similar to LCD160CR.poly_dot() but draws lines between the dots.
Advanced commands
LCD160CR.set_spi_win(x, y, w, h)
Set the window that SPI data is written to.
LCD160CR.fast_spi(flush=True)
Ready the display to accept RGB pixel data on the SPI bus, resetting the location of the first byte to go to the top-left
corner of the window set by LCD160CR.set_spi_win(). The method returns an SPI object which can be used
to write the pixel data.
Pixels should be sent as 16-bit RGB values in the 5-6-5 format. The destination counter will increase as data is
sent, and data can be sent in arbitrary sized chunks. Once the destination counter reaches the end of the window
specified by LCD160CR.set_spi_win() it will wrap around to the top-left corner of that window.
LCD160CR.show_framebuf(buf )
Show the given buffer on the display. buf should be an array of bytes containing the 16-bit RGB values for the
pixels, and they will be written to the area specified by LCD160CR.set_spi_win(), starting from the top-left
corner.
The framebuf module can be used to construct frame buffers and provides drawing primitives. Using a frame buffer
will improve performance of animations when compared to drawing directly to the screen.
LCD160CR.set_scroll(on)
Turn scrolling on or off. This controls globally whether any window regions will scroll.
LCD160CR.set_scroll_win(win, x=-1, y=0, w=0, h=0, vec=0, pat=0, fill=0x07e0, color=0)
Configure a window region for scrolling:
• win is the window id to configure. There are 0..7 standard windows for general purpose use. Window 8 is the
text scroll window (the ticker).
• x, y, w, h specify the location of the window in the display.
• vec specifies the direction and speed of scroll: it is a 16-bit value of the form 0bF.ddSSSSSSSSSSSS. dd is
0, 1, 2, 3 for +x, +y, -x, -y scrolling. F sets the speed format, with 0 meaning that the window is shifted S %
256 pixel every frame, and 1 meaning that the window is shifted 1 pixel every S frames.
• pat is a 16-bit pattern mask for the background.
• fill is the fill color.
• color is the extra color, either of the text or pattern foreground.
LCD160CR.set_scroll_win_param(win, param, value)
Set a single parameter of a scrolling window region:
• win is the window id, 0..8.
• param is the parameter number to configure, 0..7, and corresponds to the parameters in the
set_scroll_win method.
• value is the value to set.
LCD160CR.set_scroll_buf(s)
Set the string for scrolling in window 8. The parameter s must be a string with length 32 or less.
LCD160CR.jpeg(buf )
Display a JPEG. buf should contain the entire JPEG data. JPEG data should not include EXIF information.
The following encodings are supported: Baseline DCT, Huffman coding, 8 bits per sample, 3 color components,
YCbCr4:2:2. The origin of the JPEG is set by LCD160CR.set_pos().
LCD160CR.jpeg_start(total_len)
LCD160CR.jpeg_data(buf )
Display a JPEG with the data split across multiple buffers. There must be a single call to jpeg_start to begin
with, specifying the total number of bytes in the JPEG. Then this number of bytes must be transferred to the display
using one or more calls to the jpeg_data command.
LCD160CR.feed_wdt()
The first call to this method will start the display’s internal watchdog timer. Subsequent calls will feed the watchdog.
The timeout is roughly 30 seconds.
LCD160CR.reset()
Reset the display.
Constants
lcd160cr.PORTRAIT
lcd160cr.LANDSCAPE
lcd160cr.PORTRAIT_UPSIDEDOWN
lcd160cr.LANDSCAPE_UPSIDEDOWN
Orientations of the display, used by LCD160CR.set_orient().
lcd160cr.STARTUP_DECO_NONE
lcd160cr.STARTUP_DECO_MLOGO
lcd160cr.STARTUP_DECO_INFO
Types of start-up decoration, can be OR’ed together, used by LCD160CR.set_startup_deco().
The wipy module contains functions to control specific features of the WiPy, such as the heartbeat LED.
Functions
[
wipy.heartbeat( enable ) ]
Get or set the state (enabled or disabled) of the heartbeat LED. Accepts and returns boolean values (True or
False).
® Note
This class is a non-standard ADC implementation for the WiPy. It is available simply as machine.ADC on the WiPy
but is named in the documentation below as machine.ADCWiPy to distinguish it from the more general machine.ADC
class.
Usage:
import machine
Constructors
Á Warning
ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it can withstand). When GP2, GP3,
GP4 or GP5 are remapped to the ADC block, 1.8 V is the maximum. If these pins are used in digital mode,
then the maximum allowed input is 3.6V.
Methods
ADCWiPy.channel(id, *, pin)
Create an analog pin. If only channel ID is given, the correct pin will be selected. Alternatively, only the pin can
be passed and the correct channel will be selected. Examples:
ADCWiPy.init()
Enable the ADC block.
ADCWiPy.deinit()
Disable the ADC block.
® Note
This class is a non-standard Timer implementation for the WiPy. It is available simply as machine.Timer on the
WiPy but is named in the documentation below as machine.TimerWiPy to distinguish it from the more general
machine.Timer class.
Hardware timers deal with timing of periods and events. Timers are perhaps the most flexible and heterogeneous kind of
hardware in MCUs and SoCs, differently greatly from a model to a model. MicroPython’s Timer class defines a baseline
operation of executing a callback with a given period (or once after some delay), and allow specific boards to define more
non-standard behaviour (which thus won’t be portable to other boards).
See discussion of important constraints on Timer callbacks.
® Note
Memory can’t be allocated inside irq handlers (an interrupt) and so exceptions raised within a handler don’t give much
information. See micropython.alloc_emergency_exception_buf() for how to get around this limitation.
Constructors
Methods
TimerWiPy.init(mode, *, width=16)
Initialise the timer. Example:
Keyword arguments:
• mode can be one of:
– TimerWiPy.ONE_SHOT - The timer runs once until the configured period of the channel expires.
– TimerWiPy.PERIODIC - The timer runs periodically at the configured frequency of the channel.
– TimerWiPy.PWM - Output a PWM signal on a pin.
• width must be either 16 or 32 (bits). For really low frequencies < 5Hz (or large periods), 32-bit timers should
be used. 32-bit mode is only available for ONE_SHOT AND PERIODIC modes.
TimerWiPy.deinit()
Deinitialises the timer. Stops the timer, and disables the timer peripheral.
TimerWiPy.channel(channel, **, freq, period, polarity=TimerWiPy.POSITIVE, duty_cycle=0)
If only a channel identifier passed, then a previously initialized channel object is returned (or None if there is no
previous channel).
Otherwise, a TimerChannel object is initialized and returned.
The operating mode is the one configured to the Timer object that was used to create the channel.
• channel if the width of the timer is 16-bit, then must be either TIMER.A, TIMER.B. If the width is 32-bit
then it must be TIMER.A | TIMER.B.
Keyword only arguments:
• freq sets the frequency in Hz.
• period sets the period in microseconds.
® Note
• polarity this is applicable for PWM, and defines the polarity of the duty cycle
• duty_cycle only applicable to PWM. It’s a percentage (0.00-100.00). Since the WiPy doesn’t
support floating point numbers the duty cycle must be specified in the range 0-10000, where 10000
would represent 100.00, 5050 represents 50.50, and so on.
® Note
When the channel is in PWM mode, the corresponding pin is assigned automatically, therefore there’s no need
to assign the alternate function of the pin via the Pin class. The pins which support PWM functionality are the
following:
• GP24 on Timer 0 channel A.
Methods
Constants
TimerWiPy.ONE_SHOT
TimerWiPy.PERIODIC
Timer operating mode.
The esp module contains specific functions related to both the ESP8266 and ESP32 modules. Some functions are only
available on one or the other of these ports.
Functions
[
esp.sleep_type( sleep_type ) ]
Note: ESP8266 only
Get or set the sleep type.
If the sleep_type parameter is provided, sets the sleep type to its value. If the function is called without parameters,
returns the current sleep type.
The possible sleep types are defined as constants:
• SLEEP_NONE – all functions enabled,
• SLEEP_MODEM – modem sleep, shuts down the WiFi Modem circuit.
• SLEEP_LIGHT – light sleep, shuts down the WiFi Modem circuit and suspends the processor periodically.
The system enters the set sleep mode automatically when possible.
esp.deepsleep(time_us=0, / )
Note: ESP8266 only - use machine.deepsleep() on ESP32
Enter deep sleep.
The whole module powers down, except for the RTC clock circuit, which can be used to restart the module after
the specified time if the pin 16 is connected to the reset pin. Otherwise the module will sleep until manually reset.
esp.flash_id()
Note: ESP8266 only
Read the device ID of the flash memory.
esp.flash_size()
Read the total size of the flash memory.
esp.flash_user_start()
Read the memory offset at which the user flash space begins.
esp.flash_read(byte_offset, length_or_buffer)
esp.flash_write(byte_offset, bytes)
esp.flash_erase(sector_no)
esp.osdebug(uart_no)
® Note
Change the level of OS serial debug log messages. On boot, OS serial debug log messages are disabled.
uart_no is the number of the UART peripheral which should receive OS-level output, or None to disable OS
serial debug log messages.
[
esp.osdebug(uart_no , level ) ]
® Note
Change the level of OS serial debug log messages. On boot, OS serial debug log messages are limited to Error
output only.
The behaviour of this function depends on the arguments passed to it. The following combinations are supported:
osdebug(None) restores the default OS debug log message level (LOG_ERROR).
osdebug(0) enables all available OS debug log messages (in the default build configuration this is LOG_INFO).
® Note
LOG_DEBUG and LOG_VERBOSE are not compiled into the MicroPython binary by default, to save size. A
custom build with a modified “sdkconfig” source file is needed to see any output at these log levels.
® Note
Log output on ESP32 is automatically suspended in “Raw REPL” mode, to prevent communications issues.
This means OS level logging is never seen when using mpremote run and similar tools.
esp.set_native_code_location(start, length)
Note: ESP8266 only
Set the location that native code will be placed for execution after it is compiled. Native code is emitted when the
@micropython.native, @micropython.viper and @micropython.asm_xtensa decorators are applied to
a function. The ESP8266 must execute code from either iRAM or the lower 1MByte of flash (which is memory
mapped), and this function controls the location.
If start and length are both None then the native code location is set to the unused portion of memory at the end of
the iRAM1 region. The size of this unused portion depends on the firmware and is typically quite small (around
500 bytes), and is enough to store a few very small functions. The advantage of using this iRAM1 region is that it
does not get worn out by writing to it.
If neither start nor length are None then they should be integers. start should specify the byte offset from the
beginning of the flash at which native code should be stored. length specifies how many bytes of flash from start
can be used to store native code. start and length should be multiples of the sector size (being 4096 bytes). The
flash will be automatically erased before writing to it so be sure to use a region of flash that is not otherwise used,
for example by the firmware or the filesystem.
When using the flash to store native code start+length must be less than or equal to 1MByte. Note that the flash
can be worn out if repeated erasures (and writes) are made so use this feature sparingly. In particular, native code
needs to be recompiled and rewritten to flash on each boot (including wake from deepsleep).
In both cases above, using iRAM1 or flash, if there is no more room left in the specified region then the use
of a native decorator on a function will lead to MemoryError exception being raised during compilation of that
function.
The esp32 module contains functions and classes specifically aimed at controlling ESP32 modules.
Functions
esp32.wake_on_touch(wake)
Configure whether or not a touch will wake the device from sleep. wake should be a boolean value.
esp32.wake_on_ulp(wake)
Configure whether or not the Ultra-Low-Power co-processor can wake the device from sleep. wake should be a
boolean value.
esp32.wake_on_ext0(pin, level)
Configure how EXT0 wakes the device from sleep. pin can be None or a valid Pin object. level should be esp32.
WAKEUP_ALL_LOW or esp32.WAKEUP_ANY_HIGH.
esp32.wake_on_ext1(pins, level)
Configure how EXT1 wakes the device from sleep. pins can be None or a tuple/list of valid Pin objects. level should
be esp32.WAKEUP_ALL_LOW or esp32.WAKEUP_ANY_HIGH.
esp32.gpio_deep_sleep_hold(enable)
Configure whether non-RTC GPIO pin configuration is retained during deep-sleep mode for held pads. enable
should be a boolean value.
esp32.raw_temperature()
Read the raw value of the internal temperature sensor, returning an integer.
esp32.idf_heap_info(capabilities)
Returns information about the ESP-IDF heap memory regions. One of them contains the MicroPython heap and
the others are used by ESP-IDF, e.g., for network buffers and other data. This data is useful to get a sense of how
much memory is available to ESP-IDF and the networking stack in particular. It may shed some light on situations
where ESP-IDF operations fail due to allocation failures.
The capabilities parameter corresponds to ESP-IDF’s MALLOC_CAP_XXX values but the two most useful ones are
predefined as esp32.HEAP_DATA for data heap regions and esp32.HEAP_EXEC for executable regions as used
by the native code emitter.
The return value is a list of 4-tuples, where each 4-tuple corresponds to one heap and contains: the total bytes, the
free bytes, the largest free block, and the minimum free seen over time.
Example after booting:
® Note
Free IDF heap memory in the esp32.HEAP_DATA region is available to be automatically added to the MicroPy-
thon heap to prevent a MicroPython allocation from failing. However, the information returned here is other-
wise not useful to troubleshoot Python allocation failures. micropython.mem_info() and gc.mem_free()
should be used instead:
The “max new split” value in micropython.mem_info() output corresponds to the largest free block of
ESP-IDF heap that could be automatically added on demand to the MicroPython heap.
The result of gc.mem_free() is the total of the current “free” and “max new split” values printed by
micropython.mem_info().
Flash partitions
This class gives access to the partitions in the device’s flash memory and includes methods to enable over-the-air (OTA)
updates.
class esp32.Partition(id, block_size=4096, / )
Create an object representing a partition. id can be a string which is the label of the partition to retrieve, or one of
the constants: BOOT or RUNNING. block_size specifies the byte size of an individual block.
classmethod Partition.find(type=TYPE_APP, subtype=0xff, label=None, block_size=4096)
Find a partition specified by type, subtype and label. Returns a (possibly empty) list of Partition objects. Note:
subtype=0xff matches any subtype and label=None matches any label.
block_size specifies the byte size of an individual block used by the returned objects.
Partition.info()
Returns a 6-tuple (type, subtype, addr, size, label, encrypted).
Partition.readblocks(block_num, buf )
Partition.readblocks(block_num, buf, offset )
Partition.writeblocks(block_num, buf )
Partition.writeblocks(block_num, buf, offset )
Partition.ioctl(cmd, arg)
These methods implement the simple and extended block protocol defined by vfs.AbstractBlockDev .
Partition.set_boot()
Sets the partition as the boot partition.
® Note
Do not enter deepsleep after changing the OTA boot partition, without first performing a hard reset or
power cycle. This ensures the bootloader will validate the new image before booting.
Partition.get_next_update()
Gets the next update partition after this one, and returns a new Partition object. Typical usage is
Partition(Partition.RUNNING).get_next_update() which returns the next partition to update given
the current running one.
classmethod Partition.mark_app_valid_cancel_rollback()
Signals that the current boot is considered successful. Calling mark_app_valid_cancel_rollback is re-
quired on the first boot of a new partition to avoid an automatic rollback at the next boot. This uses
the ESP-IDF “app rollback” feature with “CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE” and an
OSError(-261) is raised if called on firmware that doesn’t have the feature enabled. It is OK to call
mark_app_valid_cancel_rollback on every boot and it is not necessary when booting firmware that was
loaded using esptool.
Constants
Partition.BOOT
Partition.RUNNING
Used in the Partition constructor to fetch various partitions: BOOT is the partition that will be booted at the next
reset and RUNNING is the currently running partition.
Partition.TYPE_APP
Partition.TYPE_DATA
Used in Partition.find to specify the partition type: APP is for bootable firmware partitions (typically labelled
factory, ota_0, ota_1), and DATA is for other partitions, e.g. nvs, otadata, phy_init, vfs.
esp32.HEAP_DATA
esp32.HEAP_EXEC
Used in idf_heap_info.
RMT
The RMT (Remote Control) module, specific to the ESP32, was originally designed to send and receive infrared remote
control signals. However, due to a flexible design and very accurate (as low as 12.5ns) pulse generation, it can also be
used to transmit or receive many other types of digital signals:
import esp32
from machine import Pin
The input to the RMT module is an 80MHz clock (in the future it may be able to configure the input clock but, for now, it’s
fixed). clock_div divides the clock input which determines the resolution of the RMT channel. The numbers specified
in write_pulses are multiplied by the resolution to define the pulses.
clock_div is an 8-bit divider (0-255) and each pulse can be defined by multiplying the resolution by a 15-bit (1-
PULSE_MAX) number. There are eight channels (0-7) and each can have a different clock divider.
So, in the example above, the 80MHz clock is divided by 8. Thus the resolution is (1/(80Mhz/8)) 100ns. Since the start
level is 0 and toggles with each number, the bitstream is 0101 with durations of [100ns, 2000ns, 100ns, 4000ns].
For more details see Espressif’s ESP-IDF RMT documentation..
Á Warning
The current MicroPython RMT implementation lacks some features, most notably receiving pulses. RMT should be
considered a beta feature and the interface may change in the future.
Constants
RMT.PULSE_MAX
Maximum integer that can be set for a pulse duration.
Ultra-Low-Power co-processor
This class gives access to the Ultra Low Power (ULP) co-processor on the ESP32, ESP32-S2 and ESP32-S3 chips.
Á Warning
This class does not provide access to the RISCV ULP co-processor available on the ESP32-S2 and ESP32-S3 chips.
class esp32.ULP
This class provides access to the Ultra-Low-Power co-processor.
ULP.set_wakeup_period(period_index, period_us)
Set the wake-up period.
ULP.load_binary(load_addr, program_binary)
Load a program_binary into the ULP at the given load_addr.
ULP.run(entry_point )
Start the ULP running at the given entry_point.
Constants
esp32.WAKEUP_ALL_LOW
esp32.WAKEUP_ANY_HIGH
Selects the wake level for pins.
Non-Volatile Storage
This class gives access to the Non-Volatile storage managed by ESP-IDF. The NVS is partitioned into namespaces and
each namespace contains typed key-value pairs. The keys are strings and the values may be various integer types, strings,
and binary blobs. The driver currently only supports 32-bit signed integers and blobs.
Á Warning
Changes to NVS need to be committed to flash by calling the commit method. Failure to call commit results in
changes being lost at the next reset.
class esp32.NVS(namespace)
Create an object providing access to a namespace (which is automatically created if not present).
NVS.set_i32(key, value)
Sets a 32-bit signed integer value for the specified key. Remember to call commit!
NVS.get_i32(key)
Returns the signed integer value for the specified key. Raises an OSError if the key does not exist or has a different
type.
NVS.set_blob(key, value)
Sets a binary blob value for the specified key. The value passed in must support the buffer protocol, e.g. bytes,
bytearray, str. (Note that esp-idf distinguishes blobs and strings, this method always writes a blob even if a string
is passed in as value.) Remember to call commit!
NVS.get_blob(key, buffer)
Reads the value of the blob for the specified key into the buffer, which must be a bytearray. Returns the actual
length read. Raises an OSError if the key does not exist, has a different type, or if the buffer is too small.
NVS.erase_key(key)
Erases a key-value pair.
NVS.commit()
Commits changes made by set_xxx methods to flash.
This module provides an interface to the ESP-NOW protocol provided by Espressif on ESP32 and ESP8266 devices (API
docs).
Table of Contents:
• Introduction
• Configuration
• Sending and Receiving Data
• Peer Management
• Callback Methods
• Exceptions
• Constants
• Wifi Signal Strength (RSSI) - (ESP32 Only)
• Supporting asyncio
• Broadcast and Multicast
• ESPNow and Wifi Operation
• ESPNow and Sleep Modes
Introduction
import network
import espnow
e = espnow.ESPNow()
e.active(True)
peer = b'\xbb\xbb\xbb\xbb\xbb\xbb' # MAC address of peer's wifi interface
e.add_peer(peer) # Must add_peer() before send()
e.send(peer, "Starting...")
for i in range(100):
e.send(peer, str(i)*20, True)
e.send(peer, b'end')
Receiver:
import network
import espnow
e = espnow.ESPNow()
e.active(True)
while True:
host, msg = e.recv()
if msg: # msg == None if timeout in recv()
print(host, msg)
if msg == b'end':
break
class ESPNow
Constructor
class espnow.ESPNow
Returns the singleton ESPNow object. As this is a singleton, all calls to espnow.ESPNow() return a reference to
the same object.
® Note
Some methods are available only on the ESP32 due to code size restrictions on the ESP8266 and differences
in the Espressif API.
Configuration
[
ESPNow.active( flag ) ]
Initialise or de-initialise the ESP-NOW communication protocol depending on the value of the flag optional
argument.
Arguments:
ESPNow.config(param=value, ...)
ESPNow.config('param') (ESP32 only)
Set or get configuration values of the ESPNow interface. To set values, use the keyword syntax, and one or more
parameters can be set at a time. To get a value the parameter name should be quoted as a string, and just one
parameter is queried at a time.
Note: Getting parameters is not supported on the ESP8266.
Options:
rxbuf: (default=526) Get/set the size in bytes of the internal buffer used to store incoming ESPNow
packet data. The default size is selected to fit two max-sized ESPNow packets (250 bytes) with associated
mac_address (6 bytes), a message byte count (1 byte) and RSSI data plus buffer overhead. Increase this if
you expect to receive a lot of large packets or expect bursty incoming traffic.
Note: The recv buffer is allocated by ESPNow.active(). Changing this value will have no effect until the
next call of ESPNow.active(True).
timeout_ms: (default=300,000) Default timeout (in milliseconds) for receiving ESPNow messages. If
timeout_ms is less than zero, then wait forever. The timeout can also be provided as arg to
recv()/irecv()/recvinto().
rate: (ESP32 only) Set the transmission speed for ESPNow packets. Must be set to a number from the allowed
numeric values in enum wifi_phy_rate_t. This parameter is actually write-only due to ESP-IDF not providing
any means for querying the radio interface’s rate parameter.
Returns:
None or the value of the parameter being queried.
Raises:
A wifi interface (network.WLAN.IF_STA or network.WLAN.IF_AP) must be active() before messages can be sent
or received, but it is not necessary to connect or configure the WLAN interface. For example:
import network
sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
sta.disconnect() # For ESP8266
Note: The ESP8266 has a feature that causes it to automatically reconnect to the last wifi Access Point when set ac-
tive(True) (even after reboot/reset). This reduces the reliability of receiving ESP-NOW messages (see ESPNow and
Wifi Operation). You can avoid this by calling disconnect() after active(True).
[
ESPNow.send(mac, msg , sync ) ]
ESPNow.send(msg) (ESP32 only)
Send the data contained in msg to the peer with given network mac address. In the second form, mac=None and
sync=True. The peer must be registered with ESPNow.add_peer() before the message can be sent.
Arguments:
• mac: byte string exactly espnow.ADDR_LEN (6 bytes) long or None. If mac is None (ESP32 only) the
message will be sent to all registered peers, except any broadcast or multicast MAC addresses.
• msg: string or byte-string up to espnow.MAX_DATA_LEN (250) bytes long.
• sync:
– True: (default) send msg to the peer(s) and wait for a response (or not).
– False send msg and return immediately. Responses from the peers will be discarded.
Returns:
True if sync=False or if sync=True and all peers respond, else False.
Raises:
• As for ESPNow.recv(), except that msg is a bytearray, instead of a bytestring. On the ESP8266, mac
will also be a bytearray.
Raises:
• See ESPNow.recv().
Note: You may also read messages by iterating over the ESPNow object, which will use the irecv() method for
alloc-free reads, eg:
import espnow
e = espnow.ESPNow(); e.active(True)
for mac, msg in e:
print(mac, msg)
if mac is None: # mac, msg will equal (None, None) on timeout
break
[
ESPNow.recvinto(data , timeout_ms ) ]
Wait for an incoming message and return the length of the message in bytes. This is the low-level method used by
both recv() and irecv() to read messages.
Arguments:
data: A list of at least two elements, [peer, msg]. msg must be a bytearray large enough to hold the
message (250 bytes). On the ESP8266, peer should be a bytearray of 6 bytes. The MAC address of the
sender and the message will be stored in these bytearrays (see Note on ESP32 below).
timeout_ms: (Optional) Timeout in milliseconds (see ESPNow.recv()).
Returns:
• See ESPNow.recv().
Note: On the ESP32:
• It is unnecessary to provide a bytearray in the first element of the data list because it will be replaced by a
reference to a unique peer address in the peer device table (see ESPNow.peers_table).
• If the list is at least 4 elements long, the rssi and timestamp values will be saved as the 3rd and 4th elements.
ESPNow.any()
Check if data is available to be read with ESPNow.recv().
For more sophisticated querying of available characters use select.poll():
import select
import espnow
e = espnow.ESPNow()
poll = select.poll()
poll.register(e, select.POLLIN)
poll.poll(timeout)
Returns:
True if data is available to be read, else False.
Returns:
A 5-tuple containing the number of packets sent/received/lost:
(tx_pkts, tx_responses, tx_failures, rx_packets, rx_dropped_packets)
Incoming packets are dropped when the recv buffers are full. To reduce packet loss, increase the rxbuf config
parameters and ensure you are reading messages as quickly as possible.
Note: Dropped packets will still be acknowledged to the sender as received.
Peer Management
On ESP32 devices, the Espressif ESP-NOW software requires that other devices (peers) must be registered using
add_peer() before we can send() them messages (this is not enforced on ESP8266 devices). It is not necessary
to register a peer to receive an un-encrypted message from that peer.
Encrypted messages: To receive an encrypted message, the receiving device must first register the sender and use the
same encryption keys as the sender (PMK and LMK) (see set_pmk() and add_peer().
ESPNow.set_pmk(pmk)
Set the Primary Master Key (PMK) which is used to encrypt the Local Master Keys (LMK) for encrypting messages.
If this is not set, a default PMK is used by the underlying Espressif ESP-NOW software stack.
Note: messages will only be encrypted if lmk is also set in ESPNow.add_peer() (see Security in the Espressif
API docs).
Arguments:
pmk: Must be a byte string, bytearray or string of length espnow.KEY_LEN (16 bytes).
Returns:
None
Raises:
ValueError() on invalid pmk values.
ESPNow.add_peer(mac , lmk[ ][, channel ][, ifidx ][, encrypt ])
ESPNow.add_peer(mac, param=value, ...) (ESP32 only)
Add/register the provided mac address as a peer. Additional parameters may also be specified as positional or
keyword arguments (any parameter set to None will be set to it’s default value):
Arguments:
Raises:
Raises:
Callback Methods
def recv_cb(e):
while True: # Read out all messages waiting in the buffer
mac, msg = e.irecv(0) # Don't wait if no messages left
if mac is None:
return
print(mac, msg)
e.irq(recv_cb)
The irq() callback method is an alternative method for processing incoming messages, especially if the data rate
is moderate and the device is not too busy but there are some caveats:
• The scheduler stack can overflow and callbacks will be missed if packets are arriving at a sufficient rate or if
other MicroPython components (eg, bluetooth, machine.Pin.irq(), machine.timer, i2s, …) are exercising the
scheduler stack. This method may be less reliable for dealing with bursts of messages, or high throughput or
on a device which is busy dealing with other hardware operations.
• For more information on scheduled function callbacks see: micropython.schedule().
Constants
espnow.MAX_DATA_LEN(=250)
espnow.KEY_LEN(=16)
espnow.ADDR_LEN(=6)
espnow.MAX_TOTAL_PEER_NUM(=20)
espnow.MAX_ENCRYPT_PEER_NUM(=6)
Exceptions
If the underlying Espressif ESP-NOW software stack returns an error code, the MicroPython espnow module will raise
an OSError(errnum, errstring) exception where errstring is set to the name of one of the error codes identified
in the Espressif ESP-NOW docs. For example:
try:
e.send(peer, 'Hello')
except OSError as err:
if len(err.args) < 2:
raise err
if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT':
e.active(True)
elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
e.add_peer(peer)
elif err.args[1] == 'ESP_ERR_ESPNOW_IF':
network.WLAN(network.WLAN.IF_STA).active(True)
else:
raise err
The ESPNow object maintains a peer device table which contains the signal strength and timestamp of the last received
message from all hosts. The peer device table can be accessed using ESPNow.peers_table and can be used to track
device proximity and identify nearest neighbours in a network of peer devices. This feature is not available on ESP8266
devices.
ESPNow.peers_table
A reference to the peer device table: a dict of known peer devices and rssi values:
where:
• peer is the peer MAC address (as bytes);
• rssi is the wifi signal strength in dBm (-127 to 0) of the last message received from the peer; and
• time_ms is the time the message was received (in milliseconds since system boot - wraps every 12 days).
Example:
>>> e.peers_table
{b'\xaa\xaa\xaa\xaa\xaa\xaa': [-31, 18372],
b'\xbb\xbb\xbb\xbb\xbb\xbb': [-43, 12541]}
Note: the mac addresses returned by recv() are references to the peer key values in the peer device table.
Note: RSSI and timestamp values in the device table are updated only when the message is read by the application.
Supporting asyncio
import network
import aioespnow
import asyncio
class aioespnow.AIOESPNow
The AIOESPNow class inherits all the methods of ESPNow and extends the interface with the following async
methods.
async AIOESPNow.arecv()
Asyncio support for ESPNow.recv(). Note that this method does not take a timeout value as argument.
async AIOESPNow.airecv()
Asyncio support for ESPNow.irecv(). Note that this method does not take a timeout value as argument.
async AIOESPNow.asend(mac, msg, sync=True)
async AIOESPNow.asend(msg)
Asyncio support for ESPNow.send().
AIOESPNow._aiter__() / async AIOESPNow.__anext__()
AIOESPNow also supports reading incoming messages by asynchronous iteration using async for; eg:
e = AIOESPNow()
e.active(True)
async def recv_till_halt(e):
async for mac, msg in e:
print(mac, msg)
if msg == b'halt':
break
asyncio.run(recv_till_halt(e))
All active ESPNow clients will receive messages sent to their MAC address and all devices (except ESP8266 devices)
will also receive messages sent to the broadcast MAC address (b'\xff\xff\xff\xff\xff\xff') or any multicast
MAC address.
All ESPNow devices (including ESP8266 devices) can also send messages to the broadcast MAC address or any multicast
MAC address.
To send() a broadcast message, the broadcast (or multicast) MAC address must first be registered using add_peer().
send() will always return True for broadcasts, regardless of whether any devices receive the message. It is not permitted
to encrypt messages sent to the broadcast address or any multicast address.
Note: ESPNow.send(None, msg) will send to all registered peers except the broadcast address. To send a broadcast
or multicast message, you must specify the broadcast (or multicast) MAC address as the peer. For example:
bcast = b'\xff' * 6
e.add_peer(bcast)
e.send(bcast, "Hello World!")
ESPNow messages may be sent and received on any active() WLAN interface (network.WLAN.IF_STA or network.
WLAN.IF_AP), even if that interface is also connected to a wifi network or configured as an access point. When an
ESP32 or ESP8266 device connects to a Wifi Access Point (see ESP32 Quickref) the following things happen which
affect ESPNow communications:
1. Wifi Power-saving Mode (network.WLAN.PM_PERFORMANCE) is automatically activated and
2. The radio on the esp device changes wifi channel to match the channel used by the Access Point.
Wifi Power-saving Mode: (see Espressif Docs) The power saving mode causes the device to turn off the radio periodi-
cally (typically for hundreds of milliseconds), making it unreliable in receiving ESPNow messages. This can be resolved
by either of:
1. Disabling the power-saving mode on the STA_IF interface;
• Use sta.config(pm=sta.PM_NONE)
2. Turning on the AP_IF interface, which will disable the power saving mode. However, the device will then be
advertising an active wifi access point.
• You may also choose to send your messages via the AP_IF interface, but this is not necessary.
• ESP8266 peers must send messages to this AP_IF interface (see below).
3. Configuring ESPNow clients to retry sending messages.
Receiving messages from an ESP8266 device: Strangely, an ESP32 device connected to a wifi network using method 1
or 2 above, will receive ESPNow messages sent to the STA_IF MAC address from another ESP32 device, but will reject
messages from an ESP8266 device!!!. To receive messages from an ESP8266 device, the AP_IF interface must be set to
active(True) and messages must be sent to the AP_IF MAC address.
Managing wifi channels: Any other ESPNow devices wishing to communicate with a device which is also connected
to a Wifi Access Point MUST use the same channel. A common scenario is where one ESPNow device is connected to
a wifi router and acts as a proxy for messages from a group of sensors connected via ESPNow:
Proxy:
# Print the wifi channel used AFTER finished connecting to access point
(continues on next page)
Sensor:
Other issues to take care with when using ESPNow with wifi are:
• Set WIFI to known state on startup: MicroPython does not reset the wifi peripheral after a soft reset. This
can lead to unexpected behaviour. To guarantee the wifi is reset to a known state after a soft reset make sure you
deactivate the STA_IF and AP_IF before setting them to the desired state at startup, eg.:
sta, ap = wifi_reset()
Remember that a soft reset occurs every time you connect to the device REPL and when you type ctrl-D.
• STA_IF and AP_IF always operate on the same channel: the AP_IF will change channel when you connect to
a wifi network; regardless of the channel you set for the AP_IF (see Attention Note 3 ). After all, there is really
only one wifi radio on the device, which is shared by the STA_IF and AP_IF virtual devices.
• Disable automatic channel assignment on your wifi router: If the wifi router for your wifi network is configured
to automatically assign the wifi channel, it may change the channel for the network if it detects interference from
other wifi routers. When this occurs, the ESP devices connected to the wifi network will also change channels to
match the router, but other ESPNow-only devices will remain on the previous channel and communication will be
lost. To mitigate this, either set your wifi router to use a fixed wifi channel or configure your devices to re-scan the
wifi channels if they are unable to find their expected peers on the current channel.
• MicroPython re-scans wifi channels when trying to reconnect: If the esp device is connected to a Wifi Access
Point that goes down, MicroPython will automatically start scanning channels in an attempt to reconnect to the
Access Point. This means ESPNow messages will be lost while scanning for the AP. This can be disabled by
sta.config(reconnects=0), which will also disable the automatic reconnection after losing connection.
• Some versions of the ESP IDF only permit sending ESPNow packets from the STA_IF interface to peers which
have been registered on the same wifi channel as the STA_IF:
ESPNOW: Peer channel is not equal to the home channel, send fail!
print('Sending ping...')
if not e.send(peer, b'ping'):
print('Ping failed!')
e.active(False)
sta.active(False) # Disable the wifi before sleep
print('Going to sleep...')
machine.deepsleep(10000) # Sleep for 10 seconds then reboot
while True:
print('Sending ping...')
if not e.send(peer, b'ping'):
print('Ping failed!')
sta.active(False) # Disable the wifi before sleep
print('Going to sleep...')
machine.lightsleep(10000) # Sleep for 10 seconds
sta.active(True)
sta.config(channel=6) # Wifi loses config after lightsleep()
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, and pico-micropython-examples for example code.
rp2.bootsel_button()
Temporarily turns the QSPI_SS pin into an input and reads its value, returning 1 for low and 0 for high. On a
typical RP2040 board with a BOOTSEL button, a return value of 1 indicates that the button is pressed.
Since this function temporarily disables access to the external flash memory, it also temporarily disables interrupts
and the other core to prevent them from trying to execute code from flash.
class rp2.PIOASMError
This exception is raised from asm_pio() or asm_pio_encode() if there is an error assembling a PIO program.
PIO state machines are programmed in a custom assembly language with nine core PIO-machine instructions. In Mi-
croPython, PIO assembly routines are written as a Python function with the decorator @rp2.asm_pio(), and they use
Python syntax. Such routines support standard Python variables and arithmetic, as well as the following custom functions
that encode PIO instructions and direct the assembler. See sec 3.4 of the RP2040 datasheet for further details.
wrap_target()
Specify the location where execution continues after program wrapping. By default this is the start of the PIO
routine.
wrap()
Specify the location where the program finishes and wraps around. If this directive is not used then it is added
automatically at the end of the PIO routine. Wrapping does not cost any execution cycles.
label(label)
Define a label called label at the current location. label can be a string or integer.
word(instr, label=None)
Insert an arbitrary 16-bit word in the assembled output.
• instr: the 16-bit value
• label: if given, look up the label and logical-or the label’s value with instr
jmp(…)
This instruction takes two forms:
jmp(label)
• label: label to jump to unconditionally
jmp(cond, label)
• cond: the condition to check, one of:
– not_x, not_y: true if register is zero
– x_dec, y_dec: true if register is non-zero, and do post decrement
– x_not_y: true if X is not equal to Y
– pin: true if the input pin is set
– not_osre: true if OSR is not empty (hasn’t reached its threshold)
• label: label to jump to if condition is true
wait(polarity, src, index)
Block, waiting for high/low on a pin or IRQ line.
• polarity: 0 or 1, whether to wait for a low or high value
• src: one of: gpio (absolute pin), pin (pin relative to StateMachine’s in_base argument), irq
• index: 0-31, the index for src
in_(src, bit_count)
Shift data in from src to ISR.
If block is used then the instruction stalls until the flag is cleared by another entity. If clear is used then the
flag is cleared instead of being set. Relative IRQ indices add the state machine ID to the IRQ index with modulo-4
addition. IRQs 0-3 are visible from to the processor, 4-7 are internal to the state machines.
set(dest, data)
Set dest with the value data.
• dest: pins, x, y, pindirs
• data: value (0-31)
nop()
This is a pseudoinstruction that assembles to mov(y, y) and has no side effect.
.side(value)
This is a modifier which can be applied to any instruction, and is used to control side-set pin values.
• value: the value (bits) to output on the side-set pins
.delay(value)
This is a modifier which can be applied to any instruction, and specifies how many cycles to delay for after the
instruction executes.
• value: cycles to delay, 0-31 (maximum value reduced if side-set pins are used)
[value]
This is a modifier and is equivalent to .delay(value).
Classes
The DMA class offers access to the RP2040’s Direct Memory Access (DMA) controller, providing the ability move data
between memory blocks and/or IO registers. The DMA controller has its own, separate read and write bus master con-
nections onto the bus fabric and each DMA channel can independently read data from one address and write it back to
another address, optionally incrementing one or both pointers, allowing it to perform transfers on behalf of the processor
while the processor carries out other tasks or enters a low power state. The RP2040’s DMA controller has 12 independent
DMA channels that can run concurrently. For full details of the RP2040’s DMA system see section 2.5 of the RP2040
Datasheet.
Examples
The simplest use of the DMA controller is to move data from one block of memory to another. This can be accomplished
with the following code:
a = bytearray(32*1024)
b = bytearray(32*1024)
d = rp2.DMA()
c = d.pack_ctrl() # Just use the default control value.
# The count is in 'transfers', which defaults to four-byte words, so divide length by␣
,→4
Note that while this example sits in an idle loop while it waits for the transfer to complete, the program could just as well
do some useful work in this time instead.
Another, perhaps more common use of the DMA controller is to transfer between memory and an IO peripheral. In this
situation the address of the IO register does not change for each transfer but the memory address needs to be incremented.
It is also necessary to control the pace of the transfer so as to not write data before it can be accepted by a peripheral or
read it before the data is ready, and this can be controlled with the treq_sel field of the DMA channel’s control register.
The various fields of the control register for each DMA channel can be packed using the DMA.pack_ctrl() method
and unpacked using the DMA.unpack_ctrl() static method. Code to transfer data from a byte array to the TX FIFO
of a PIO state machine, one byte at a time, looks like this:
# pio_num is index of the PIO block being used, sm_num is the state machine in that␣
,→block.
src_data = bytearray(1024)
d = rp2.DMA()
# Transfer bytes, rather than words, don't increment the write address and pace the␣
,→transfer.
d.config(
read=src_data,
write=my_state_machine,
count=len(src_data),
ctrl=c,
trigger=True
)
Note that in this example the value given for the write address is just the PIO state machine to which we are sending
the data. This works because PIO state machines present the buffer protocol, allowing direct access to their data FIFO
registers.
Constructor
class rp2.DMA
Claim one of the DMA controller channels for exclusive use.
Methods
DMA.irq(handler=None, hard=False)
Returns the IRQ object for this DMA channel and optionally configures it.
DMA.close()
Release the claim on the underlying DMA channel and free the interrupt handler. The DMA object can not be used
after this operation.
DMA.pack_ctrl(default=None, **kwargs)
Pack the values provided in the keyword arguments into the named fields of a new control register value. Any field
that is not provided will be set to a default value. The default will either be taken from the provided default value,
or if that is not given, a default suitable for the current channel; setting this to the current value of the DMA.ctrl
attribute provides an easy way to override a subset of the fields.
The keys for the keyword arguments can be any key returned by the DMA.unpack_ctrl() method. The writable
values are:
• enable: bool Set to enable the channel (default: True).
• high_pri: bool Make this channel’s bus traffic high priority (default: False).
• size: int Transfer size: 0=byte, 1=half word, 2=word (default: 2).
• inc_read: bool Increment the read address after each transfer (default: True).
• inc_write: bool Increment the write address after each transfer (default: True).
• ring_size: int If non-zero, only the bottom ring_size bits of one address register will change when an
address is incremented, causing the address to wrap at the next 1 << ring_size byte boundary. Which
address is wrapped is controlled by the ring_sel flag. A zero value disables address wrapping.
• ring_sel: bool Set to False to have the ring_size apply to the read address or True to apply to the write
address.
• chain_to: int The channel number for a channel to trigger after this transfer completes. Setting this value to
this DMA object’s own channel number disables chaining (this is the default).
• treq_sel: int Select a Transfer Request signal. See section 2.5.3 in the RP2040 datasheet for details.
• irq_quiet: bool Do not generate interrupt at the end of each transfer. Interrupts will instead be generated
when a zero value is written to the trigger register, which will halt a sequence of chained transfers (default:
True).
• bswap: bool If set to true, bytes in words or half-words will be reversed before writing (default: True).
• sniff_en: bool Set to True to allow data to be accessed by the chips sniff hardware (default: False).
• write_err: bool Setting this to True will clear a previously reported write error.
• read_err: bool Setting this to True will clear a previously reported read error.
See the description of the CH0_CTRL_TRIG register in section 2.5.7 of the RP2040 datasheet for details of all of
these fields.
DMA.unpack_ctrl(value)
Unpack a value for a DMA channel control register into a dictionary with key/value pairs for each of the fields in
the control register. value is the ctrl register value to unpack.
This method will return values for all the keys that can be passed to DMA.pack_ctrl. In addition, it will also
return the read-only flags in the control register: busy, which goes high when a transfer starts and low when it
ends, and ahb_err, which is the logical OR of the read_err and write_err flags. These values will be ignored
when packing, so that the dictionary created by unpacking a control register can be used directly as the keyword
arguments for packing.
[
DMA.active( value ) ]
Gets or sets whether the DMA channel is currently running.
>>> sm.active()
0
>>> sm.active(1)
>>> while sm.active():
... pass
Attributes
DMA.read
This attribute reflects the address from which the next bus transfer will read. It may be written with either an integer
or an object that supports the buffer protocol and doing so has immediate effect.
DMA.write
This attribute reflects the address to which the next bus transfer will write. It may be written with either an integer
or an object that supports the buffer protocol and doing so has immediate effect.
DMA.count
Reading this attribute will return the number of remaining bus transfers in the current transfer sequence. Writing
this attribute sets the total number of transfers to be the next transfer sequence.
DMA.ctrl
This attribute reflects DMA channel control register. It is typically written with an integer packed using the DMA.
pack_ctrl() method. The returned register value can be unpacked using the DMA.unpack_ctrl() method.
DMA.channel
The channel number of the DMA channel. This can be passed in the chain_to argument of DMA.pack_ctrl()
on another channel to allow DMA chaining.
DMA.registers
This attribute is an array-like object that allows direct access to the DMA channel’s registers. The index is by word,
rather than by byte, so the register indices are the register address offsets divided by 4. See the RP2040 data sheet
for register details.
The DMA controller in the RP2040 offers a couple advanced features to allow one DMA channel to initiate a transfer on
another channel. One is the use of the chain_to value in the control register and the other is writing to one of the DMA
channel’s registers that has a trigger effect. When coupled with the ability to have one DMA channel write directly to the
DMA.registers of another channel, this allows for complex transactions to be performed without any CPU intervention.
Below is an example of using both chaining and register triggering to implement gathering of multiple blocks of data into
a single destination. Full details of these features can be found in section 2.5 of the RP2040 data sheet and the code below
is a Pythonic version of the example in sub-section 2.5.6.2.
for s in string_list:
gather_list.append(len(s))
gather_list.append(addressof(s))
gather_list.append(0)
gather_list.append(0)
# When writing to the registers of the second DMA channel, we need to wrap the
# write address on an 8-byte (1<<3 bytes) boundary. We write to the ``TRANS_
,→COUNT``
# When copying the data, the transfer size is single bytes, and when completed we␣
,→ need
# to chain back to the start another gather DMA transaction.
buffer_ctrl = buffer_dma.pack_ctrl(size=0, chain_to=gather_dma.channel)
# The read and count values will be set by the other DMA channel.
buffer_dma.config(write=buf, ctrl=buffer_ctrl)
input = ["This is ", "a ", "test", " of the scatter", " gather", " process"]
output = bytearray(64)
print(output)
gather_strings(input, output)
print(output)
This example idles while waiting for the transfer to complete; alternatively it could set an interrupt handler and return
immediately.
Constructors
class rp2.Flash
Gets the singleton object for accessing the SPI flash memory.
Methods
Flash.readblocks(block_num, buf )
Flash.readblocks(block_num, buf, offset )
Flash.writeblocks(block_num, buf )
Flash.writeblocks(block_num, buf, offset )
Flash.ioctl(cmd, arg)
These methods implement the simple and extended block protocol defined by vfs.AbstractBlockDev .
The PIO class gives access to an instance of the RP2040’s PIO (programmable I/O) interface.
The preferred way to interact with PIO is using rp2.StateMachine, the PIO class is for advanced use.
For assembling PIO programs, see rp2.asm_pio().
Constructors
class rp2.PIO(id )
Gets the PIO instance numbered id. The RP2040 has two PIO instances, numbered 0 and 1.
Raises a ValueError if any other argument is provided.
Methods
[
PIO.gpio_base( base ) ]
Query and optionally set the current GPIO base for this PIO instance.
If an argument is given then it must be a pin (or integer corresponding to a pin number), restricted to either GPIO0
or GPIO16. The GPIO base will then be set to that pin. Setting the GPIO base must be done before any programs
are added or state machines created.
Returns the current GPIO base pin.
PIO.add_program(program)
Add the program to the instruction memory of this PIO instance.
The amount of memory available for programs on each PIO instance is limited. If there isn’t enough space left in
the PIO’s program memory this method will raise OSError(ENOMEM).
[
PIO.remove_program( program ) ]
Remove program from the instruction memory of this PIO instance.
If no program is provided, it removes all programs.
It is not an error to remove a program which has already been removed.
[
PIO.state_machine(id , program, ... ) ]
Gets the state machine numbered id. On the RP2040, each PIO instance has four state machines, numbered 0 to
3.
Optionally initialize it with a program: see StateMachine.init.
>>> rp2.PIO(1).state_machine(3)
StateMachine(7)
Constants
PIO.IN_LOW
PIO.IN_HIGH
PIO.OUT_LOW
PIO.OUT_HIGH
These constants are used for the out_init, set_init, and sideset_init arguments to asm_pio.
PIO.SHIFT_LEFT
PIO.SHIFT_RIGHT
These constants are used for the in_shiftdir and out_shiftdir arguments to asm_pio or StateMachine.init.
PIO.JOIN_NONE
PIO.JOIN_TX
PIO.JOIN_RX
These constants are used for the fifo_join argument to asm_pio.
PIO.IRQ_SM0
PIO.IRQ_SM1
PIO.IRQ_SM2
PIO.IRQ_SM3
These constants are used for the trigger argument to PIO.irq .
The StateMachine class gives access to the RP2040’s PIO (programmable I/O) interface.
For assembling PIO programs, see rp2.asm_pio().
Constructors
[
class rp2.StateMachine(id , program, ... ) ]
Get the state machine numbered id. The RP2040 has two identical PIO instances, each with 4 state machines: so
there are 8 state machines in total, numbered 0 to 7.
Optionally initialize it with the given program program: see StateMachine.init.
Methods
>>> sm.active()
True
>>> sm.active(0)
False
StateMachine.restart()
Restarts the state machine and jumps to the beginning of the program.
This method clears the state machine’s internal state using the RP2040’s SM_RESTART register. This includes:
• input and output shift counters
• the contents of the input shift register
• the delay counter
If instr is an integer then it is treated as an already encoded PIO machine code instruction to be executed.
StateMachine.get(buf=None, shift=0)
Pull a word from the state machine’s RX FIFO.
If the FIFO is empty, it blocks until data arrives (i.e. the state machine pushes a word).
The value is shifted right by shift bits before returning, i.e. the return value is word >> shift.
StateMachine.put(value, shift=0)
Push words onto the state machine’s TX FIFO.
value can be an integer, an array of type B, H or I, or a bytearray .
This method will block until all words have been written to the FIFO. If the FIFO is, or becomes, full, the method
will block until the state machine pulls enough words to complete the write.
Each word is first shifted left by shift bits, i.e. the state machine receives word << shift.
StateMachine.rx_fifo()
Returns the number of words in the state machine’s RX FIFO. A value of 0 indicates the FIFO is empty.
Useful for checking if data is waiting to be read, before calling StateMachine.get().
StateMachine.tx_fifo()
Returns the number of words in the state machine’s TX FIFO. A value of 0 indicates the FIFO is empty.
Useful for checking if there is space to push another word using StateMachine.put().
StateMachine.irq(handler=None, trigger=0 | 1, hard=False)
Returns the IRQ object for the given StateMachine.
Optionally configure it.
Buffer protocol
The StateMachine class supports the buffer protocol, allowing direct access to the transmit and receive FIFOs for
each state machine. This is primarily in order to allow StateMachine objects to be passed directly as the read or write
parameters when configuring a rp2.DMA() channel.
The zephyr module contains functions and classes specific to the Zephyr port.
Functions
zephyr.is_preempt_thread()
Returns true if the current thread is a preemptible thread.
Zephyr preemptible threads are those with non-negative priority values (low priority levels), which therefore, can
be supplanted as soon as a higher or equal priority thread becomes ready.
zephyr.current_tid()
Returns the thread id of the current thread, which is used to reference the thread.
zephyr.thread_analyze()
Runs the Zephyr debug thread analyzer on the current thread and prints stack size statistics in the format:
“thread_name-20s: STACK: unused available_stack_space usage stack_space_used /
stack_size (percent_stack_space_used %); CPU: cpu_utilization %”
• CPU utilization is only printed if runtime statistics are configured via the ``CON-
FIG_THREAD_RUNTIME_STATS`` kconfig
This function can only be accessed if CONFIG_THREAD_ANALYZER is configured for the port in zephyr/prj.
conf. For more information, see documentation for Zephyr thread analyzer.
zephyr.shell_exec(cmd_in)
Executes the given command on an UART backend. This function can only be accessed if CON-
FIG_SHELL_BACKEND_SERIAL is configured for the port in zephyr/prj.conf.
A list of possible commands can be found in the documentation for Zephyr shell commands.
Classes
Constructors
class zephyr.DiskAccess(disk_name)
Gets an object for accessing disk memory of the specific disk. For accessing an SD card on the mimxrt1050_evk,
disk_name would be SDHC. See board documentation and devicetree for usable disk names for your board (ex.
RT boards use style USDHC#).
Methods
DiskAccess.readblocks(block_num, buf )
DiskAccess.writeblocks(block_num, buf )
DiskAccess.writeblocks(block_num, buf, offset )
DiskAccess.ioctl(cmd, arg)
These methods implement the simple and extended block protocol defined by vfs.AbstractBlockDev .
Constructors
Methods
FlashArea.readblocks(block_num, buf )
FlashArea.readblocks(block_num, buf, offset )
FlashArea.writeblocks(block_num, buf )
FlashArea.writeblocks(block_num, buf, offset )
FlashArea.ioctl(cmd, arg)
These methods implement the simple and extended block protocol defined by vfs.AbstractBlockDev .
Additional Modules
The zsensor module contains a class for using sensors with Zephyr.
Use this class to access data from sensors on your board. See Zephyr documentation for sensor usage here: Sensors.
Sensors are defined in the Zephyr devicetree for each board. The quantities that a given sensor can measure are called a
sensor channels. Sensors can have multiple channels to represent different axes of one property or different properties a
sensor can measure. See Channels below for defined sensor channels.
Constructor
class zsensor.Sensor(device_name)
Device names are defined in the devicetree for your board. For example, the device name for the accelerometer in
the FRDM-k64f board is “FXOS8700”.
Methods
Sensor.measure()
Obtains a measurement sample from the sensor device using Zephyr sensor_sample_fetch and stores it in an internal
driver buffer as a useful value, a pair of (integer part of value, fractional part of value in 1-millionths). Returns
none if successful or OSError value if failure.
Sensor.get_float(sensor_channel)
Returns the value of the sensor measurement sample as a float.
Sensor.get_micros(sensor_channel)
Returns the value of the sensor measurement sample in millionths. (Ex. value of (1, 500000) returns as
1500000)
Sensor.get_millis(sensor_channel)
Returns the value of sensor measurement sample in thousandths. (Ex. value of (1, 500000) returns as 1500)
Sensor.get_int(sensor_channel)
Returns only the integer value of the measurement sample. (Ex. value of (1, 500000) returns as 1)
Channels
zsensor.ACCEL_X
Acceleration on the X axis, in m/s^2.
zsensor.ACCEL_Y
Acceleration on the Y axis, in m/s^2.
zsensor.ACCEL_Z
Acceleration on the Z axis, in m/s^2.
zsensor.GYRO_X
Angular velocity around the X axis, in radians/s.
zsensor.GYRO_Y
Angular velocity around the Y axis, in radians/s.
zsensor.GYRO_Z
Angular velocity around the Z axis, in radians/s.
zsensor.MAGN_X
Magnetic field on the X axis, in Gauss.
zsensor.MAGN_Y
Magnetic field on the Y axis, in Gauss.
zsensor.MAGN_Z
Magnetic field on the Z axis, in Gauss.
zsensor.DIE_TEMP
Device die temperature in degrees Celsius.
zsensor.PRESS
Pressure in kilopascal.
zsensor.PROX
Proximity. Dimensionless. A value of 1 indicates that an object is close.
zsensor.HUMIDITY
Humidity, in percent.
zsensor.LIGHT
Illuminance in visible spectrum, in lux.
zsensor.ALTITUDE
Altitude, in meters.
_path = sys.path
sys.path = ()
try:
from time import *
finally:
sys.path = _path
del _path
def extra_method():
pass
The result is that time.py contains all the globals of the built-in time module, but adds extra_method.
In earlier versions of MicroPython, you can force an import of a built-in module by appending a u to the start of its name.
For example, import utime instead of import time. For example, time.py on the filesystem could look like:
def extra_method():
pass
This way is still supported, but the sys.path method described above is now preferred as the u-prefix will be removed
from the names of built-in modules in a future version of MicroPython.
Other than when it specifically needs to force the use of the built-in module, code should always use import module
rather than import umodule.
TWO
MicroPython aims to implement the Python 3.4 standard (with selected features from later versions) with respect to
language syntax, and most of the features of MicroPython are identical to those described by the “Language Reference”
documentation at docs.python.org.
The MicroPython standard library is described in the corresponding chapter. The MicroPython differences from CPython
chapter describes differences between MicroPython and CPython (which mostly concern standard library and types, but
also some language-level features).
This chapter describes features and peculiarities of MicroPython implementation and the best practices to use them.
2.1 Glossary
baremetal
A system without a (full-fledged) operating system, for example an MCU-based system. When running on a
baremetal system, MicroPython effectively functions like a small operating system, running user programs and
providing a command interpreter (REPL).
buffer protocol
Any Python object that can be automatically converted into bytes, such as bytes, bytearray, memoryview and
str objects, which all implement the “buffer protocol”.
board
Typically this refers to a printed circuit board (PCB) containing a microcontroller and supporting components.
MicroPython firmware is typically provided per-board, as the firmware contains both MCU-specific functionality
but also board-level functionality such as drivers or pin names.
bytecode
A compact representation of a Python program that generated by compiling the Python source code. This is what
the VM actually executes. Bytecode is typically generated automatically at runtime and is invisible to the user.
Note that while CPython and MicroPython both use bytecode, the format is different. You can also pre-compile
source code offline using the cross-compiler.
callee-owned tuple
This is a MicroPython-specific construct where, for efficiency reasons, some built-in functions or methods may
reuse the same underlying tuple object to return data. This avoids having to allocate a new tuple for every call, and
reduces heap fragmentation. Programs should not hold references to callee-owned tuples and instead only extract
data from them (or make a copy).
CircuitPython
A variant of MicroPython developed by Adafruit Industries.
CPython
CPython is the reference implementation of the Python programming language, and the most well-known one.
It is, however, one of many implementations (including Jython, IronPython, PyPy, and MicroPython). While
225
MicroPython Documentation, Release latest
MicroPython’s implementation differs substantially from CPython, it aims to maintain as much compatibility as
possible.
cross-compiler
Also known as mpy-cross. This tool runs on your PC and converts a .py file containing MicroPython code into a
.mpy file containing MicroPython bytecode. This means it loads faster (the board doesn’t have to compile the code),
and uses less space on flash (the bytecode is more space efficient).
driver
A MicroPython library that implements support for a particular component, such as a sensor or display.
FFI
Acronym for Foreign Function Interface. A mechanism used by the MicroPython Unix port to access operating
system functionality. This is not available on baremetal ports.
filesystem
Most MicroPython ports and boards provide a filesystem stored in flash that is available to user code via the standard
Python file APIs such as open(). Some boards also make this internal filesystem accessible to the host via USB
mass-storage.
frozen module
A Python module that has been cross compiled and bundled into the firmware image. This reduces RAM require-
ments as the code is executed directly from flash.
Garbage Collector
A background process that runs in Python (and MicroPython) to reclaim unused memory in the heap.
GPIO
General-purpose input/output. The simplest means to control electrical signals (commonly referred to as “pins”)
on a microcontroller. GPIO typically allows pins to be either input or output, and to set or get their digital value
(logical “0” or “1”). MicroPython abstracts GPIO access using the machine.Pin and machine.Signal classes.
GPIO port
A group of GPIO pins, usually based on hardware properties of these pins (e.g. controllable by the same register).
heap
A region of RAM where MicroPython stores dynamic data. It is managed automatically by the Garbage Collector.
Different MCUs and boards have vastly different amounts of RAM available for the heap, so this will affect how
complex your program can be.
interned string
An optimisation used by MicroPython to improve the efficiency of working with strings. An interned string is
referenced by its (unique) identity rather than its address and can therefore be quickly compared just by its identifier.
It also means that identical strings can be de-duplicated in memory. String interning is almost always invisible to
the user.
MCU
Microcontroller. Microcontrollers usually have much less resources than a desktop, laptop, or phone, but are
smaller, cheaper and require much less power. MicroPython is designed to be small and optimized enough to run
on an average modern microcontroller.
micropython-lib
MicroPython is (usually) distributed as a single executable/binary file with just few builtin modules. There is no
extensive standard library comparable with CPython’s. Instead, there is a related, but separate project micropython-
lib which provides implementations for many modules from CPython’s standard library.
Some of the modules are implemented in pure Python, and are able to be used on all ports. However, the majority
of these modules use FFI to access operating system functionality, and as such can only be used on the MicroPython
Unix port (with limited support for Windows).
Unlike the CPython stdlib, micropython-lib modules are intended to be installed individually - either using manual
copying or using mip.
MicroPython port
MicroPython supports different boards, RTOSes, and OSes, and can be relatively easily adapted to new systems.
MicroPython with support for a particular system is called a “port” to that system. Different ports may have widely
different functionality. This documentation is intended to be a reference of the generic APIs available across differ-
ent ports (“MicroPython core”). Note that some ports may still omit some APIs described here (e.g. due to resource
constraints). Any such differences, and port-specific extensions beyond the MicroPython core functionality, would
be described in the separate port-specific documentation.
MicroPython Unix port
The unix port is one of the major MicroPython ports. It is intended to run on POSIX-compatible operating systems,
like Linux, MacOS, FreeBSD, Solaris, etc. It also serves as the basis of Windows port. The Unix port is very
useful for quick development and testing of the MicroPython language and machine-independent features. It can
also function in a similar way to CPython’s python executable.
mip
A package installer for MicroPython (mip - “mip installs packages”). It installs MicroPython packages either from
micropython-lib, GitHub, or arbitrary URLs. mip can be used on-device on network-capable boards, and internally
by tools such as mpremote.
See Package management for more information on using mip.
mpremote
A tool for interacting with a MicroPython device. See MicroPython remote control: mpremote.
.mpy file
The output of the cross-compiler. A compiled form of a .py file that contains MicroPython bytecode instead of
Python source code.
native
Usually refers to “native code”, i.e. machine code for the target microcontroller (such as ARM Thumb, Xtensa,
x86/x64). The @native decorator can be applied to a MicroPython function to generate native code instead of
bytecode for that function, which will likely be faster but use more RAM.
port
Usually short for MicroPython port, but could also refer to GPIO port.
.py file
A file containing Python source code.
REPL
An acronym for “Read, Eval, Print, Loop”. This is the interactive Python prompt, useful for debugging or testing
short snippets of code. Most MicroPython boards make a REPL available over a UART, and this is typically
accessible on a host PC via USB.
stream
Also known as a “file-like object”. A Python object which provides sequential read-write access to the underlying
data. A stream object implements a corresponding interface, which consists of methods like read(), write(),
readinto(), seek(), flush(), close(), etc. A stream is an important concept in MicroPython; many I/O
objects implement the stream interface, and thus can be used consistently and interchangeably in different contexts.
For more information on streams in MicroPython, see the io module.
UART
Acronym for “Universal Asynchronous Receiver/Transmitter”. This is a peripheral that sends data over a pair of
pins (TX & RX). Many boards include a way to make at least one of the UARTs available to a host PC as a serial
port over USB.
upip
A now-obsolete package manager for MicroPython, inspired by CPython’s pip, but much smaller and with reduced
functionality. See its replacement, mip.
webrepl
A way of connecting to the REPL (and transferring files) on a device over the internet from a browser. See https:
//micropython.org/webrepl
2.2.1 Auto-indent
When typing python statements which end in a colon (for example if, for, while) then the prompt will change to three
dots (…) and the cursor will be indented by 4 spaces. When you press return, the next line will continue at the same level
of indentation for regular statements or an additional level of indentation where appropriate. If you press the backspace
key then it will undo one level of indentation.
If your cursor is all the way back at the beginning, pressing RETURN will then execute the code that you’ve entered. The
following shows what you’d see after entering a for statement (the underscore shows where the cursor winds up):
Finally type print(i), press RETURN, press BACKSPACE and press RETURN again:
Auto-indent won’t be applied if the previous two lines were all spaces. This means that you can finish entering a compound
statement by pressing RETURN twice, and then a third press will finish and execute.
2.2.2 Auto-completion
While typing a command at the REPL, if the line typed so far corresponds to the beginning of the name of something, then
pressing TAB will show possible things that could be entered. For example, first import the machine module by entering
import machine and pressing RETURN. Then type m and press TAB and it should expand to machine. Enter a dot
. and press TAB again. You should see something like:
>>> machine.
__name__ info unique_id reset
bootloader freq rng idle
sleep deepsleep disable_irq enable_irq
Pin
The word will be expanded as much as possible until multiple possibilities exist. For example, type machine.Pin.
AF3 and press TAB and it will expand to machine.Pin.AF3_TIM. Pressing TAB a second time will show the possible
expansions:
>>> machine.Pin.AF3_TIM
AF3_TIM10 AF3_TIM11 AF3_TIM8 AF3_TIM9
>>> machine.Pin.AF3_TIM
def foo():
print('This is a test to show paste mode')
print('Here is a second line')
foo()
and you try to paste this into the normal REPL, then you will see something like this:
If you press Ctrl-E, then you will enter paste mode, which essentially turns off the auto-indent feature, and changes the
prompt from >>> to ===. For example:
>>>
paste mode; Ctrl-C to cancel, Ctrl-D to finish
=== def foo():
=== print('This is a test to show paste mode')
=== print('Here is a second line')
=== foo()
===
This is a test to show paste mode
Here is a second line
>>>
Paste Mode allows blank lines to be pasted. The pasted text is compiled as if it were a file. Pressing Ctrl-D exits paste
mode and initiates the compilation.
machine.soft_reset()
For example, if you reset your MicroPython board, and you execute a dir() command, you’d see something like this:
>>> dir()
['__name__', 'pyb']
>>> i = 1
>>> j = 23
>>> x = 'abc'
>>> dir()
['j', 'x', '__name__', 'pyb', 'i']
>>>
Now if you enter Ctrl-D, and repeat the dir() command, you’ll see that your variables no longer exist:
For more information about reset types and the startup process, see Reset and Boot Sequence.
>>> 1 + 2 + 3 + 4 + 5
15
>>> x = _
>>> x
15
>>>
4. If the device is in raw-paste mode then continue, otherwise fallback to standard raw mode.
5. Read 2 bytes, this is the flow control window-size-increment (in bytes) stored as a 16-bit unsigned little endian
integer. The initial value for the remaining-window-size variable should be set to this number.
6. Write out the code to the device:
• While there are bytes to send, write up to the remaining-window-size worth of bytes, and decrease the
remaining-window-size by the number of bytes written.
• If the remaining-window-size is 0, or there is a byte waiting to read, read 1 byte. If this byte is b"\x01" then
increase the remaining-window-size by the window-size-increment from step 5. If this byte is b"\x04" then
the device wants to end the data reception, and b"\x04" should be written to the device and no more code sent
after that. (Note: if there is a byte waiting to be read from the device then it does not need to be read and acted
upon immediately, the device will continue to consume incoming bytes as long as reamining-window-size is
greater than 0.)
7. When all code has been written to the device, write b"\x04" to indicate end-of-data.
8. Read from the device until b"\x04" is received. At this point the device has received and compiled all of the code
that was sent and is executing it.
9. The device outputs any characters produced by the executing code. When (if) the code finishes b"\x04" will be
output, followed by any exception that was uncaught, followed again by b"\x04". It then goes back to the standard
raw REPL and outputs b">".
For example, starting at a new line at the normal (friendly) REPL, if you write:
b"\x01\x05A\x01print(123)\x04"
In this case the flow control window-size-increment is 128 and there are two windows worth of data immediately available
at the start, one from the initial window-size-increment value and one from the explicit b"\x01" value that is sent. So this
means up to 256 bytes can be written to begin with before waiting or checking for more incoming flow-control characters.
The tools/pyboard.py program uses the raw REPL, including raw-paste mode, to execute Python code on a
MicroPython-enabled board.
A soft reset clears the Python interpreter, frees all Python memory, and starts the MicroPython environment again.
State which is cleared by a soft reset includes:
• All Python variables, objects, imported modules, etc.
• Most peripherals configured using the machine module. There are very limited exceptions, for example machine.Pin
modes (i.e. if a pin is input or output, high or low) are not reset on most ports. More advanced configuration such
as Pin.irq() is always reset.
• Bluetooth.
• Network sockets. Open TCP sockets are closed cleanly with respect to the other party.
• Open files. The filesystem is left in a valid state.
Some system state remains the same after a soft reset, including:
• Any existing network connections (Ethernet, Wi-Fi, etc) remain active at the IP Network layer. Querying the
network interface from code may indicate the network interface is still active with a configured IP address, etc.
• An active REPL appears continuous before and after soft reset, except in some unusual cases:
– If the machine.USBDevice class has been used to create a custom USB interface then any built-in USB serial
device will appear to disconnect and reconnect as the custom USB interface must be cleared during reset.
– A serial UART REPL will restore its default hardware configuration (baud rate, etc).
• CPU clock speed is usually not changed by a soft reset.
• RTC configuration (i.e. setting of the current time) is not changed by soft reset.
_boot.py
This is an internal script frozen into the MicroPython firmware. It is provided by MicroPython on many ports to do
essential initialisation.
For example, on most ports _boot.py will detect the first boot of a new device and format the internal flash filesystem
ready for use.
Unless you’re creating a custom MicroPython build or adding a new port then you probably don’t need to worry about
_boot.py. It’s best not to change the contents unless you really know what you’re doing.
boot.py
A file named boot.py can be copied to the board’s internal filesystem using mpremote.
If boot.py is found then it is executed. You can add code in boot.py to perform custom one-off initialisation (for
example, to configure the board’s hardware).
A common practice is to configure a board’s network connection in boot.py so that it’s always available after reset for
use with the REPL, mpremote, etc.
Á Warning
® Note
It is sometimes simpler to not have a boot.py file and place any initialisation code at the top of main.py instead.
main.py
Similar to boot.py, a file named main.py can be copied to the board’s internal filesystem. If found then it is executed
next in the startup process.
main.py is for any Python code that you want to run each time your device starts.
Some tips for main.py usage:
• main.py doesn’t have to exit, feel free to put an infinite while True loop in there.
• For complex Python applications then you don’t need to put all your code in main.py. main.py can be a simple
entry point that imports your application and starts execution:
import my_app
my_app.main()
This can help keep the structure of your application clear. It also makes it easy to install multiple applications on a
board and switch among them.
• It’s good practice when writing robust apps to wrap code in main.py with an exception handler to take appropriate
action if the code crashes. For example:
Otherwise MicroPython will drop to the REPL following any crash or if main exits (see below).
• Any global variables that were set in boot.py will still be set in the global context of main.py.
• To fully optimise flash usage and memory consumption, you can copy pre-compiled main.mpy and/or boot.mpy
files to the filesystem, or even freeze them into the firmware build instead.
• main.py execution is skipped when a soft reset is initiated from raw REPL mode (for example, when mpremote or
another program is interacting directly with MicroPython).
® Note
Even if main.py contains an infinite loop, typing Ctrl-C on the REPL serial port will inject a KeyboardInterrupt.
If no exception handler catches it then main.py will exit and the REPL will start.
Any global variables that were set in boot.py and main.py will still be set in the global context of the REPL.
The REPL continues executing until Python code triggers a hard or soft reset.
KeyboardInterrupt
In many cases, opening the REPL serial port and typing Ctrl-C will inject KeyboardInterrupt and may cause the
running script to exit and a REPL to start. From the REPL, you can use os.remove() to remove the misbehaving
Python file:
import os
os.remove('main.py')
import os
os.listdir()
Á Warning
Re-flashing the MicroPython firmware without erasing the entire flash first will usually not recover from soft bricking,
as a firmware update usually preserves the contents of the filesystem.
Or via pipx:
The simplest way to use this tool is just by invoking it without any arguments:
$ mpremote
This command automatically detects and connects to the first available USB serial device and provides an interactive
terminal that you can use to access the REPL and your program’s output. Serial ports are opened in exclusive mode, so
running a second (or third, etc) instance of mpremote will connect to subsequent serial devices, if any are available.
Additionally pipx also allows you to directly run mpremote without installing first:
2.4.1 Commands
mpremote supports being given a series of commands given at the command line which will perform various actions in
sequence on a remote MicroPython device. See the examples section below to get an idea of how this works and for some
common combinations of commands.
Each command is of the form <command name> [--options] [args...]. For commands that support multiple
arguments (e.g. a list of files), the argument list can be terminated with +.
If no command is specified, the default command is repl. Additionally, if any command needs to access the device, and
no earlier connect has been specified, then an implicit connect auto is added.
In order to get the device into a known state for any action command (except repl), once connected mpremote will stop
any running program and soft-reset the device before running the first command. You can control this behavior using the
resume and soft-reset commands. See auto-connection and auto-soft-reset for more details.
• bootloader
• connect – connect to specified device via name:
$ mpremote disconnect
$ mpremote resume
This disables auto-soft-reset. This is useful if you want to run a subsequent command on a board without first
soft-resetting it.
• soft-reset – perform a soft-reset of the device:
$ mpremote soft-reset
This will clear out the Python heap and restart the interpreter. It also prevents the subsequent command from
triggering auto-soft-reset.
• repl – enter the REPL on the connected device:
Options are:
– --escape-non-printable, to print non-printable bytes/characters as their hex code
– --capture <file>, to capture output of the REPL session to the given file
– --inject-code <string>, to specify characters to inject at the REPL when Ctrl-J is pressed. This
allows you to automate a common command.
– --inject-file <file>, to specify a file to inject at the REPL when Ctrl-K is pressed. This allows you
to run a file (e.g. containing some useful setup code, or even the program you are currently working on).
While the repl command running, you can use Ctrl-] or Ctrl-x to exit.
Note: The name “REPL” here reflects that the common usage of this command to access the Read Eval Print Loop
that is running on the MicroPython device. Strictly, the repl command is just functioning as a terminal (or “serial
monitor”) to access the device. Because this command does not trigger the auto-reset behavior, this means that if
a program is currently running, you will first need to interrupt it with Ctrl-C to get to the REPL, which will then
allow you to access program state. You can also use mpremote soft-reset repl to get a “clean” REPL with
all program state cleared.
• eval – evaluate and print the result of a Python expression:
By default, mpremote exec will display any output from the expression until it terminates. The --no-follow
flag can be specified to return immediately and leave the device running the expression in the background.
• run – run a script from the local filesystem:
This will execute the file directly from RAM on the device without copying it to the filesystem. This is a very
useful way to iterate on the development of a single piece of code without having to worry about deploying it to the
filesystem.
By default, mpremote run will display any output from the script until it terminates. The --no-follow flag can
be specified to return immediately and leave the device running the script in the background.
• fs – execute filesystem commands on the device:
$ mpremote fs <sub-command>
So for example, mpremote fs cp main.py :main.py copies main.py from the current local directory to the
remote filesystem, whereas mpremote fs cp :main.py main.py copies main.py from the device back to
the current directory.
All of the filesystem sub-commands take multiple path arguments, so if there is another command in the sequence,
you must use + to terminate the arguments, e.g.
This will copy the file to the device then enter the REPL. The + prevents "repl" being interpreted as a path.
The cp command supports the -r option to make a recursive copy. By default cp will skip copying files to the
remote device if the SHA256 hash of the source and destination file matches. To force a copy regardless of the
hash use the -f option.
Note: For convenience, all of the filesystem sub-commands are also aliased as regular commands, i.e. you can
write mpremote cp ... instead of mpremote fs cp ....
• df – query device free/used space
$ mpremote df
The df command will print size/used/free statistics for the device filesystem, similar to the Unix df command.
• edit – edit a file on the device:
The edit command will copy each file from the device to a local temporary directory and then launch your editor
for each file (defined by the environment variable $EDITOR). If the editor exits successfully, the updated file will
be copied back to the device.
• mip – install packages from micropython-lib (or GitHub) using the mip tool:
This allows the remote device to see the local host directory as if it were its own filesystem. This is useful for
development, and avoids the need to copy files to the device while you are working on them.
The device installs a filesystem driver, which is then mounted in the device VFS as /remote, which uses the serial
connection to mpremote as a side-channel to access files. The device will have its current working directory (via
os.chdir) set to /remote so that imports and file access will occur there instead of the default filesystem path
while the mount is active.
Note: If the mount command is not followed by another action in the sequence, a repl command will be implicitly
added to the end of the sequence.
During usage, Ctrl-D will trigger a soft-reset as normal, but the mount will automatically be re-connected. If the
unit has a main.py running at startup however the remount cannot occur. In this case a raw mode soft reboot can
be used: Ctrl-A Ctrl-D to reboot, then Ctrl-B to get back to normal repl at which point the mount will be ready.
Options are:
– -l, --unsafe-links: By default an error will be raised if the device accesses a file or directory which is
outside (up one or more directory levels) the local directory that is mounted. This option disables this check
for symbolic links, allowing the device to follow symbolic links outside of the local directory.
• unmount – unmount the local directory from the remote device:
$ mpremote umount
This happens automatically when mpremote terminates, but it can be used in a sequence to unmount an earlier
mount before subsequent command are run.
• rtc – set/get the device clock (RTC):
$ mpremote rtc
This will query the device RTC for the current time and print it as a datetime tuple.
This will set the device RTC to the host PC’s current time.
• sleep – sleep (delay) before executing the next command
This will pause execution of the command sequence for the specified duration in seconds, e.g. to wait for the device
to do something.
• reset – hard reset the device
$ mpremote reset
$ mpremote bootloader
This will make the device enter its bootloader. The bootloader is port- and board-specific (e.g. DFU on stm32,
UF2 on rp2040/Pico).
2.4.3 Shortcuts
Shortcuts can be defined using the macro system. Built-in shortcuts are:
• devs: Alias for connect list
• a0, a1, a2, a3: Aliases for connect /dev/ttyACMn
• u0, u1, u2, u3: Aliases for connect /dev/ttyUSBn
• c0, c1, c2, c3: Aliases for connect COMn
• cat, edit, ls, cp, rm, mkdir, rmdir, touch: Aliases for fs <sub-command>
Additional shortcuts can be defined by in user-configuration files, which is located at .config/mpremote/config.py.
This file should define a dictionary named commands. The keys of this dictionary are the shortcuts and the values are
either a string or a list-of-strings:
Running mpremote times 3 7 will set x and y as variables on the device, then evaluate the expression x*y.
An example config.py might look like:
commands = {
"c33": "connect id:334D335C3138", # Connect to a specific device by ID.
"bl": "bootloader", # Shorter alias for bootloader.
"double x=4": "eval x*2", # x is an argument, with default 4
"wl_scan": ["exec", """
import network
wl = network.WLAN()
wl.active(1)
for ap in wl.scan():
print(ap)
""",], # Print out nearby WiFi networks.
"wl_ipconfig": [
"exec",
"import network; sta_if = network.WLAN(network.WLAN.IF_STA); print(sta_if.ipconfig(
,→'addr4'))",
2.4.4 Examples
mpremote
Connect to the first available device and implicitly run the repl command.
mpremote a1
Connect to the device at /dev/ttyACM1 (Linux) and implicitly run the repl command. See shortcuts above.
mpremote c1
Connect to the device at COM1 (Windows) and implicitly run the repl command. See shortcuts above.
Explicitly specify which device to connect to, and as above, implicitly run the repl command.
mpremote a1 ls
Run the specified Python command and display any output. This is equivalent to typing the command at the REPL
prompt.
Evaluate 1/2 on the device at /dev/ttyACM0, then 3/4 on the device at /dev/ttyACM1, printing each result.
Connect to the device without triggering a soft reset and execute the print_state_info() function (e.g. to find out
information about the current program state), then trigger a soft reset.
Hard-reset the device, wait 500ms for it to become available, then enter the bootloader.
Update the copy of utils/driver.py on the device, then execute the local test.py script on the device. test.py is never
copied to the device filesystem, rather it is run from RAM.
Update the copy of utils/driver.py on the device, then execute app.py on the device.
This is a common development workflow to update a single file and then re-start your program. In this scenario, your
main.py on the device would also do import app.
Update the copy of utils/driver.py on the device, then trigger a soft-reset to restart your program, and then monitor the
output via the repl command.
mpremote mount .
Mount the current local directory at /remote on the device and starts a repl session which will use /remote as the
working directory.
After mounting the current local directory, executes demo.py from the mounted directory.
After mounting the local directory app as /remote on the device, executes the local test.py from the host’s current
directory without copying it to the filesystem.
After mounting the current local directory, executes demo.py from the mounted directory each time Ctrl-J is pressed.
You will first need to press Ctrl-D to reset the interpreter state (which will preserve the mount) before pressing Ctrl-J
to re-import demo.py.
Same as above, but executes the contents of the local file demo.py at the REPL every time Ctrl-K is pressed. As above,
use Ctrl-D to reset the interpreter state first.
mpremote cp :main.py .
mpremote cp main.py :
mpremote cp -r dir/ :
Copy a.py and b.py from the local directory to the device, then run the repl command.
Install the aioble package from micropython-lib to the device. See Package management.
Install the package from the specified branch at org/repo on GitHub to the device. See Package management.
Install the package from the specified branch at org/repo on GitLab to the device. See Package management.
Install the functools package from micropython-lib to the /flash/third-party directory on the device. See Package
management.
These .mpy files can contain bytecode which is usually generated from Python source files (.py files) via the mpy-cross
program. For some architectures an .mpy file can also contain native machine code, which can be generated in a variety
of ways, most notably from C source code.
Trying to import an .mpy file that fails one of the first four tests will raise ValueError('incompatible .mpy file').
Trying to import an .mpy file that fails the native architecture test (if it contains native machine code) will raise Val-
ueError('incompatible .mpy arch').
import sys
sys_mpy = sys.implementation._mpy
arch = [None, 'x86', 'x64',
'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp',
'xtensa', 'xtensawin', 'rv32imc'][sys_mpy >> 10]
print('mpy version:', sys_mpy & 0xff)
print('mpy sub-version:', sys_mpy >> 8 & 3)
print('mpy flags:', end='')
if arch:
print(' -march=' + arch, end='')
print()
• Check the validity of the .mpy file by inspecting the first two bytes of the file. The first byte should be an uppercase
‘M’ and the second byte will be the version number, which should match the system version from above. If it doesn’t
match then rebuild the .mpy file.
• Check if the system .mpy version matches the version emitted by mpy-cross that was used to build the .mpy
file, found by mpy-cross --version. If it doesn’t match then recompile mpy-cross from the Git repository
checked out at the tag (or hash) reported by mpy-cross --version.
• Make sure you are using the correct mpy-cross flags, found by the code above, or by inspecting the
MPY_CROSS_FLAGS Makefile variable for the port that you are using.
The following table shows the correspondence between MicroPython release and .mpy version.
For completeness, the next table shows the Git commit of the main MicroPython repository at which the .mpy version
was changed.
The header
The .mpy header is:
size field
byte value 0x4d (ASCII ‘M’)
byte .mpy major version number
byte native arch and minor version number (was feature flags in older versions)
byte number of bits in a small int
size field
vuint number of qstrs
vuint number of constant objects
… qstr data
… encoded constant objects
size field
vuint type, size and whether there are sub-raw-code elements
… code (bytecode or machine code)
vuint number of sub-raw-code elements (only if non-zero)
… sub-raw-code elements
The first vuint in a raw-code element encodes the type of code stored in this element (the two least-significant bits),
whether this raw-code has any children (the third least-significant bit), and the length of the code that follows (the amount
of RAM to allocate for it).
Following the vuint comes the code itself. Unless the code type is viper code with relocations, this code is constant data
and does not need to be modified.
If this raw-code has any children (as indicated by a bit in the first vuint), following the code comes a vuint counting the
number of sub-raw-code elements.
Finally any sub-raw-code elements are stored, recursively.
• Where data is shared between the main program and an ISR, consider disabling interrupts prior to accessing the
data in the main program and re-enabling them immediately afterwards (see Critical Sections).
• Allocate an emergency exception buffer (see below).
import micropython
micropython.alloc_emergency_exception_buf(100)
The emergency exception buffer can only hold one exception stack trace. This means that if a second exception is thrown
during the handling of an exception while the heap is locked, that second exception’s stack trace will replace the original
one - even if the second exception is cleanly handled. This can lead to confusing exception messages if the buffer is later
printed.
Simplicity
For a variety of reasons it is important to keep ISR code as short and simple as possible. It should do only what has to
be done immediately after the event which caused it: operations which can be deferred should be delegated to the main
program loop. Typically an ISR will deal with the hardware device which caused the interrupt, making it ready for the
next interrupt to occur. It will communicate with the main loop by updating shared data to indicate that the interrupt has
occurred, and it will return. An ISR should return control to the main loop as quickly as possible. This is not a specific
MicroPython issue so is covered in more detail below.
In this example the red instance associates timer 4 with LED 1: when a timer 4 interrupt occurs red.cb() is called
causing LED 1 to change state. The green instance operates similarly: a timer 2 interrupt results in the execution of
green.cb() and toggles LED 2. The use of instance methods confers two benefits. Firstly a single class enables code
to be shared between multiple hardware instances. Secondly, as a bound method the callback function’s first argument is
self. This enables the callback to access instance data and to save state between successive calls. For example, if the
class above had a variable self.count set to zero in the constructor, cb() could increment the counter. The red and
green instances would then maintain independent counts of the number of times each LED had changed state.
The compiler instantiates the default buf argument when the function is loaded for the first time (usually when the module
it’s in is imported).
An instance of object creation occurs when a reference to a bound method is created. This means that an ISR cannot pass
a bound method to a function. One solution is to create a reference to the bound method in the class constructor and to
pass that reference in the ISR. For example:
class Foo():
def __init__(self):
self.bar_ref = self.bar # Allocation occurs here
self.x = 0.1
tim = pyb.Timer(4)
tim.init(freq=2)
tim.callback(self.cb)
Other techniques are to define and instantiate the method in the constructor or to pass Foo.bar() with the argument
self.
Using micropython.schedule
This function enables an ISR to schedule a callback for execution “very soon”. The callback is queued for execution which
will take place at a time when the heap is not locked. Hence it can create Python objects and use floats. The callback is
also guaranteed to run at a time when the main program has completed any update of Python objects, so the callback will
not encounter partially updated objects.
Typical usage is to handle sensor hardware. The ISR acquires data from the hardware and enables it to issue a further
interrupt. It then schedules a callback to process the data.
Scheduled callbacks should comply with the principles of interrupt handler design outlined below. This is to avoid prob-
lems resulting from I/O activity and the modification of shared data which can arise in any code which pre-empts the
main program loop.
Execution time needs to be considered in relation to the frequency with which interrupts can occur. If an interrupt occurs
while the previous callback is executing, a further instance of the callback will be queued for execution; this will run after
the current instance has completed. A sustained high interrupt repetition rate therefore carries a risk of unconstrained
queue growth and eventual failure with a RuntimeError.
If the callback to be passed to schedule() is a bound method, consider the note in “Creation of Python objects”.
2.6.3 Exceptions
If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the exception is
handled by the ISR code.
tsf = asyncio.ThreadSafeFlag()
In this example there will be a variable amount of latency between the execution of the ISR and the execution of foo().
This is inherent to cooperative scheduling. The maximum latency is application and platform dependent but may typically
be measured in tens of ms.
I2C or SPI may be necessary but the time taken for such accesses should be calculated or measured and its impact on the
application assessed.
There is usually a need to share data between the ISR and the main loop. This may be done either through global variables
or via class or instance variables. Variables are typically integer or boolean types, or integer or byte arrays (a pre-allocated
integer array offers faster access than a list). Where multiple values are modified by the ISR it is necessary to consider
the case where the interrupt occurs at a time when the main program has accessed some, but not all, of the values. This
can lead to inconsistencies.
Consider the following design. An ISR stores incoming data in a bytearray, then adds the number of bytes received to an
integer representing total bytes ready for processing. The main program reads the number of bytes, processes the bytes,
then clears down the number of bytes ready. This will work until an interrupt occurs just after the main program has read
the number of bytes. The ISR puts the added data into the buffer and updates the number received, but the main program
has already read the number, so processes the data originally received. The newly arrived bytes are lost.
There are various ways of avoiding this hazard, the simplest being to use a circular buffer. If it is not possible to use a
structure with inherent thread safety other ways are described below.
Reentrancy
A potential hazard may occur if a function or method is shared between the main program and one or more ISR’s or
between multiple ISR’s. The issue here is that the function may itself be interrupted and a further instance of that function
run. If this is to occur, the function must be designed to be reentrant. How this is done is an advanced topic beyond the
scope of this tutorial.
Critical sections
An example of a critical section of code is one which accesses more than one variable which can be affected by an ISR.
If the interrupt happens to occur between accesses to the individual variables, their values will be inconsistent. This is
an instance of a hazard known as a race condition: the ISR and the main program loop race to alter the variables. To
avoid inconsistency a means must be employed to ensure that the ISR does not alter the values for the duration of the
critical section. One way to achieve this is to issue pyb.disable_irq() before the start of the section, and pyb.
enable_irq() at the end. Here is an example of this approach:
class BoundsException(Exception):
pass
ARRAYSIZE = const(20)
index = 0
data = array.array('i', 0 for x in range(ARRAYSIZE))
def callback1(t):
global data, index
for x in range(5):
data[index] = pyb.rng() # simulate input
index += 1
if index >= ARRAYSIZE:
raise BoundsException('Array bounds exceeded')
tim4.callback(None)
A critical section can comprise a single line of code and a single variable. Consider the following code fragment.
count = 0
def cb(): # An interrupt callback
count +=1
def main():
# Code to set up the interrupt callback omitted
while True:
count += 1
This example illustrates a subtle source of bugs. The line count += 1 in the main loop carries a specific race condition
hazard known as a read-modify-write. This is a classic cause of bugs in real time systems. In the main loop MicroPython
reads the value of count, adds 1 to it, and writes it back. On rare occasions the interrupt occurs after the read and before
the write. The interrupt modifies count but its change is overwritten by the main loop when the ISR returns. In a real
system this could lead to rare, unpredictable failures.
As mentioned above, care should be taken if an instance of a Python built in type is modified in the main code and that
instance is accessed in an ISR. The code performing the modification should be regarded as a critical section to ensure
that the instance is in a valid state when the ISR runs.
Particular care needs to be taken if a dataset is shared between different ISR’s. The hazard here is that the higher priority
interrupt may occur when the lower priority one has partially updated the shared data. Dealing with this situation is an
advanced topic beyond the scope of this introduction other than to note that mutex objects described below can sometimes
be used.
Disabling interrupts for the duration of a critical section is the usual and simplest way to proceed, but it disables all
interrupts rather than merely the one with the potential to cause problems. It is generally undesirable to disable an
interrupt for long. In the case of timer interrupts it introduces variability to the time when a callback occurs. In the case
of device interrupts, it can lead to the device being serviced too late with possible loss of data or overrun errors in the
device hardware. Like ISR’s, a critical section in the main code should have a short, predictable duration.
An approach to dealing with critical sections which radically reduces the time for which interrupts are disabled is to use
an object termed a mutex (name derived from the notion of mutual exclusion). The main program locks the mutex before
running the critical section and unlocks it at the end. The ISR tests whether the mutex is locked. If it is, it avoids the
critical section and returns. The design challenge is defining what the ISR should do in the event that access to the critical
variables is denied. A simple example of a mutex may be found here. Note that the mutex code does disable interrupts,
but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are virtually
unaffected.
def bar():
foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end=''))
bar()
This continues to run until the timer is explicitly disabled or the board is reset with ctrl D.
Contents
This tutorial describes ways of improving the performance of MicroPython code. Optimisations involving other languages
are covered elsewhere, namely the use of modules written in C and the MicroPython inline assembler.
The process of developing high performance code comprises the following stages which should be performed in the order
listed.
• Design for speed.
• Code and debug.
Optimisation steps:
Algorithms
The most important aspect of designing any routine for performance is ensuring that the best algorithm is employed. This
is a topic for textbooks rather than for a MicroPython guide but spectacular performance gains can sometimes be achieved
by adopting algorithms known for their efficiency.
RAM allocation
To design efficient MicroPython code it is necessary to have an understanding of the way the interpreter allocates RAM.
When an object is created or grows in size (for example where an item is appended to a list) the necessary RAM is
allocated from a block known as the heap. This takes a significant amount of time; further it will on occasion trigger a
process known as garbage collection which can take several milliseconds.
Consequently the performance of a function or method can be improved if an object is created once only and not permitted
to grow in size. This implies that the object persists for the duration of its use: typically it will be instantiated in a class
constructor and used in various methods.
This is covered in further detail Controlling garbage collection below.
Buffers
An example of the above is the common case where a buffer is required, such as one used for communication with a device.
A typical driver will create the buffer in the constructor and use it in its I/O methods which will be called repeatedly.
The MicroPython libraries typically provide support for pre-allocated buffers. For example, objects which support stream
interface (e.g., file or UART) provide read() method which allocates new buffer for read data, but also a readinto()
method to read data into an existing buffer.
Some useful classes for creating reusable buffer objects:
• bytearray
• array (discussed below)
• io.StringIO and io.BytesIO
• micropython.RingIO
Floating point
Some MicroPython ports allocate floating point numbers on heap. Some other ports may lack dedicated floating-point
coprocessor, and perform arithmetic operations on them in “software” at considerably lower speed than on integers.
Where performance is important, use integer operations and restrict the use of floating point to sections of the code
where performance is not paramount. For example, capture ADC readings as integers values to an array in one quick go,
and only then convert them to floating-point numbers for signal processing.
Arrays
Consider the use of the various types of array classes as an alternative to lists. The array module supports various
element types with 8-bit elements supported by Python’s built in bytes and bytearray classes. These data structures
all store elements in contiguous memory locations. Once again to avoid memory allocation in critical code these should
be pre-allocated and passed as arguments or as bound objects.
Memoryviews
When passing slices of objects such as bytearray instances, Python creates a copy which involves allocation of the size
proportional to the size of slice. This can be alleviated using a memoryview object. The memoryview itself is allocated
on the heap, but is a small, fixed-size object, regardless of the size of slice it points too. Slicing a memoryview creates
a new memoryview , so this cannot be done in an interrupt service routine. Further, the slice syntax a:b causes further
allocation by instantiating a slice(a, b) object.
A memoryview can only be applied to objects supporting the buffer protocol - this includes arrays but not lists. Small
caveat is that while memoryview object is live, it also keeps alive the original buffer object. So, a memoryview isn’t a
universal panacea. For instance, in the example above, if you are done with 10K buffer and just need those bytes 30:2000
from it, it may be better to make a slice, and let the 10K buffer go (be ready for garbage collection), instead of making a
long-living memoryview and keeping 10K blocked for GC.
Nonetheless, memoryview is indispensable for advanced preallocated buffer management. readinto() method dis-
cussed above puts data at the beginning of buffer and fills in entire buffer. What if you need to put data in the middle of
existing buffer? Just create a memoryview into the needed section of buffer and pass it to readinto().
Strings vs Bytes
MicroPython uses string interning to save space when there are multiple identical strings. Each time a new string is
allocated at runtime (for example, when two other strings are concatenated), MicroPython checks whether the new string
can be interned to save RAM.
If you have code which performs performance-critical string operations then consider using bytes objects and literals
(i.e. b"abc"). This skips the interning check, and can be several times faster than performing the same operations with
string objects.
® Note
The fastest performance will always be achieved by avoiding new object creation entirely, for example with a reusable
buffer as described above.
class foo(object):
def __init__(self):
self.ba = bytearray(100)
def bar(self, obj_display):
ba_ref = self.ba
fb = obj_display.framebuffer
# iterative code using these two objects
This avoids the need repeatedly to look up self.ba and obj_display.framebuffer in the body of the method
bar().
@micropython.native
def foo(self, arg):
buf = self.linebuf # Cached object
# code
There are certain limitations in the current implementation of the native code emitter.
• Context managers are not supported (the with statement).
• Generators are not supported.
• If raise is used an argument must be supplied.
The trade-off for the improved performance (roughly twice as fast as bytecode) is an increase in compiled code size.
@micropython.viper
def foo(self, arg: int) -> int:
# code
As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser. Type hints provide
information on the data types of arguments and of the return value; these are a standard Python language feature formally
defined here PEP0484. Viper supports its own set of types namely int, uint (unsigned integer), ptr, ptr8, ptr16
and ptr32. The ptrX types are discussed below. Currently the uint type serves a single purpose: as a type hint for a
function return value. If such a function returns 0xffffffff Python will interpret the result as 2**32 -1 rather than as
-1.
In addition to the restrictions imposed by the native emitter the following constraints apply:
• Default argument values are not permitted.
• Floating point may be used but is not optimised.
Viper provides pointer types to assist the optimiser. These comprise
• ptr Pointer to an object.
• ptr8 Points to a byte.
• ptr16 Points to a 16 bit half-word.
• ptr32 Points to a 32 bit machine word.
The concept of a pointer may be unfamiliar to Python programmers. It has similarities to a Python memoryview object
in that it provides direct access to data stored in memory. Items are accessed using subscript notation, but slices are not
supported: a pointer can return a single item only. Its purpose is to provide fast random access to data stored in contiguous
memory locations - such as data stored in objects which support the buffer protocol, and memory-mapped peripheral
registers in a microcontroller. It should be noted that programming using pointers is hazardous: bounds checking is not
performed and the compiler does nothing to prevent buffer overrun errors.
Typical usage is to cache variables:
@micropython.viper
def foo(self, arg: int) -> int:
buf = ptr8(self.linebuf) # self.linebuf is a bytearray or bytes object
for x in range(20, 30):
bar = buf[x] # Access a data item through the pointer
# code omitted
In this instance the compiler “knows” that buf is the address of an array of bytes; it can emit code to rapidly compute the
address of buf[x] at runtime. Where casts are used to convert objects to Viper native types these should be performed
at the start of the function rather than in critical timing loops as the cast operation can take several microseconds. The
rules for casting are as follows:
• Casting operators are currently: int, bool, uint, ptr, ptr8, ptr16 and ptr32.
• The result of a cast will be a native Viper variable.
• Arguments to a cast can be a Python object or a native Viper variable.
• If argument is a native Viper variable, then cast is a no-op (i.e. costs nothing at runtime) that just changes the type
(e.g. from uint to ptr8) so that you can then store/load using this pointer.
• If the argument is a Python object and the cast is int or uint, then the Python object must be of integral type and
the value of that integral object is returned.
• The argument to a bool cast must be integral type (boolean or integer); when used as a return type the viper function
will return True or False objects.
• If the argument is a Python object and the cast is ptr, ptr, ptr16 or ptr32, then the Python object must either
have the buffer protocol (in which case a pointer to the start of the buffer is returned) or it must be of integral type
(in which case the value of that integral object is returned).
Writing to a pointer which points to a read-only object will lead to undefined behaviour.
The following example illustrates the use of a ptr16 cast to toggle pin X1 n times:
BIT0 = const(1)
@micropython.viper
def toggle_n(n: int):
odr = ptr16(stm.GPIOA + stm.GPIO_ODR)
for _ in range(n):
odr[0] ^= BIT0
A detailed technical description of the three code emitters may be found on Kickstarter here Note 1 and here Note 2
® Note
Code examples in this section are given for the Pyboard. The techniques described however may be applied to other
MicroPython ports too.
This comes into the category of more advanced programming and involves some knowledge of the target MCU. Consider
the example of toggling an output pin on the Pyboard. The standard approach would be to write
This involves the overhead of two calls to the Pin instance’s value() method. This overhead can be eliminated by
performing a read/write to the relevant bit of the chip’s GPIO port output data register (odr). To facilitate this the stm
module provides a set of constants providing the addresses of the relevant registers. A fast toggle of pin P4 (CPU pin
A14) - corresponding to the green LED - can be performed as follows:
import machine
import stm
import mymodule
The procedure for producing frozen modules and bytecode is platform dependent; instructions for building the firmware
can be found in the README files in the relevant part of the source tree.
In general terms the steps are as follows:
• Clone the MicroPython repository.
• Acquire the (platform specific) toolchain to build the firmware.
• Build the cross compiler.
• Place the modules to be frozen in a specified directory (dependent on whether the module is to be frozen as source
or as bytecode).
• Build the firmware. A specific command may be required to build frozen code of either type - see the platform
documentation.
• Flash the firmware to the device.
2.8.2 RAM
When reducing RAM usage there are two phases to consider: compilation and execution. In addition to memory con-
sumption, there is also an issue known as heap fragmentation. In general terms it is best to minimise the repeated creation
and destruction of objects. The reason for this is covered in the section covering the heap.
Compilation phase
When a module is imported, MicroPython compiles the code to bytecode which is then executed by the MicroPython
virtual machine (VM). The bytecode is stored in RAM. The compiler itself requires RAM, but this becomes available for
use when the compilation has completed.
If a number of modules have already been imported the situation can arise where there is insufficient RAM to run the
compiler. In this case the import statement will produce a memory exception.
If a module instantiates global objects on import it will consume RAM at the time of import, which is then unavailable
for the compiler to use on subsequent imports. In general it is best to avoid code which runs on import; a better approach
is to have initialisation code which is run by the application after all modules have been imported. This maximises the
RAM available to the compiler.
If RAM is still insufficient to compile all modules one solution is to precompile modules. MicroPython has a cross
compiler capable of compiling Python modules to bytecode (see the README in the mpy-cross directory). The resulting
bytecode file has a .mpy extension; it may be copied to the filesystem and imported in the usual way. Alternatively some
or all modules may be implemented as frozen bytecode: on most platforms this saves even more RAM as the bytecode is
run directly from flash rather than being stored in RAM.
Execution phase
There are a number of coding techniques for reducing RAM usage.
Constants
MicroPython provides a const keyword which may be used as follows:
In both instances where the constant is assigned to a variable the compiler will avoid coding a lookup to the name of
the constant by substituting its literal value. This saves bytecode and hence RAM. However the ROWS value will occupy
at least two machine words, one each for the key and value in the globals dictionary. The presence in the dictionary is
necessary because another module might import or use it. This RAM can be saved by prepending the name with an
underscore as in _COLS: this symbol is not visible outside the module so will not occupy RAM.
The argument to const() may be anything which, at compile time, evaluates to a constant e.g. 0x100, 1 << 8 or
(True, "string", b"bytes") (see section below for details). It can even include other const symbols that have
already been defined, e.g. 1 << BIT.
Constant data structures
Where there is a substantial volume of constant data and the platform supports execution from Flash, RAM may be saved
as follows. The data should be located in Python modules and frozen as bytecode. The data must be defined as bytes
objects. The compiler ‘knows’ that bytes objects are immutable and ensures that the objects remain in flash memory
rather than being copied to RAM. The struct module can assist in converting between bytes types and other Python
built-in types.
When considering the implications of frozen bytecode, note that in Python strings, floats, bytes, integers, complex numbers
and tuples are immutable. Accordingly these will be frozen into flash (for tuples, only if all their elements are immutable).
Thus, in the line
the actual string “The quick brown fox” will reside in flash. At runtime a reference to the string is assigned to the variable
mystring. The reference occupies a single machine word. In principle a long integer could be used to store constant
data:
bar = 0xDEADBEEF0000DEADBEEF
As in the string example, at runtime a reference to the arbitrarily large integer is assigned to the variable bar. That
reference occupies a single machine word.
Tuples of constant objects are themselves constant. Such constant tuples are optimised by the compiler so they do not
need to be created at runtime each time they are used. For example:
This entire tuple will exist as a single object (potentially in flash if the code is frozen) and referenced each time it is needed.
Needless object creation
There are a number of situations where objects may unwittingly be created and destroyed. This can reduce the usability
of RAM through fragmentation. The following sections discuss instances of this.
String concatenation
Consider the following code fragments which aim to produce constant strings:
Each produces the same outcome, however the first needlessly creates two string objects at runtime, allocates more RAM
for concatenation before producing the third. The others perform the concatenation at compile time which is more
efficient, reducing fragmentation.
Where strings must be dynamically created before being fed to a stream such as a file it will save RAM if this is done in
a piecemeal fashion. Rather than creating a large string object, create a substring and feed it to the stream before dealing
with the next.
The best way to create dynamic strings is by means of the string format() method:
Buffers
When accessing devices such as instances of UART, I2C and SPI interfaces, using pre-allocated buffers avoids the creation
of needless objects. Consider these two loops:
while True:
var = spi.read(100)
# process data
The first creates a buffer on each pass whereas the second reuses a pre-allocated buffer; this is both faster and more
efficient in terms of memory fragmentation.
Bytes are smaller than ints
On most platforms an integer consumes four bytes. Consider the three calls to the function foo():
def foo(bar):
for x in bar:
print(x)
foo([1, 2, 0xff])
foo((1, 2, 0xff))
foo(b'\1\2\xff')
In the first call a list of integers is created in RAM each time the code is executed. The second call creates a constant
tuple object (a tuple containing only constant objects) as part of the compilation phase, so it is only created once and is
more efficient than the list. The third call efficiently creates a bytes object consuming the minimum amount of RAM.
If the module were frozen as bytecode, both the tuple and bytes object would reside in flash.
Strings Versus Bytes
Python3 introduced Unicode support. This introduced a distinction between a string and an array of bytes. MicroPython
ensures that Unicode strings take no additional space so long as all characters in the string are ASCII (i.e. have a value <
126). If values in the full 8-bit range are required bytes and bytearray objects can be used to ensure that no additional
space will be required. Note that most string methods (e.g. str.strip()) apply also to bytes instances so the process
of eliminating Unicode can be painless.
Where it is necessary to convert between strings and bytes the str.encode() and the bytes.decode() methods can
be used. Note that both strings and bytes are immutable. Any operation which takes as input such an object and produces
another implies at least one RAM allocation to produce the result. In the second line below a new bytes object is allocated.
This would also occur if foo were a string.
micropython.qstr_info(1)
Then copy and paste all the Q(xxx) lines into a text editor. Check for and remove lines which are obviously invalid. Open
the file qstrdefsport.h which will be found in ports/stm32 (or the equivalent directory for the architecture in use). Copy
and paste the corrected lines at the end of the file. Save the file, rebuild and flash the firmware. The outcome can be
checked by importing the modules and again issuing:
micropython.qstr_info(1)
gc.collect()
gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
Fragmentation
Say a program creates an object foo, then an object bar. Subsequently foo goes out of scope but bar remains. The
RAM used by foo will be reclaimed by GC. However if bar was allocated to a higher address, the RAM reclaimed from
foo will only be of use for objects no bigger than foo. In a complex or long running program the heap can become
fragmented: despite there being a substantial amount of RAM available, there is insufficient contiguous space to allocate
a particular object, and the program fails with a memory error.
The techniques outlined above aim to minimise this. Where large permanent buffers or other objects are required it is
best to instantiate these early in the process of program execution before fragmentation can occur. Further improvements
may be made by monitoring the state of the heap and by controlling GC; these are outlined below.
Reporting
A number of library functions are available to report on memory allocation and to control GC. These are to be found in
the gc and micropython modules. The following example may be pasted at the REPL (ctrl e to enter paste mode,
ctrl d to run it).
import gc
import micropython
gc.collect()
micropython.mem_info()
print('-----------------------------')
print('Initial free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
def func():
a = bytearray(10000)
gc.collect()
print('Func definition: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
func()
print('Func run free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
gc.collect()
(continues on next page)
Symbol Meaning
. free block
h head block
= tail block
m marked head block
T tuple
L list
D dict
F float
B byte code
M module
S string or bytes
A bytearray
Each letter represents a single block of memory, a block being 16 bytes. So each line of the heap dump represents 0x400
bytes or 1KiB of RAM.
gc.collect()
gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
This will provoke a GC when more than 25% of the currently free heap becomes occupied.
In general modules should instantiate data objects at runtime using constructors or other initialisation functions. The
reason is that if this occurs on initialisation the compiler may be starved of RAM when subsequent modules are imported.
If modules do instantiate data on import then gc.collect() issued after the import will ameliorate the problem.
2.8.5 Postscript
MicroPython passes, returns and (by default) copies objects by reference. A reference occupies a single machine word so
these processes are efficient in RAM usage and speed.
Where variables are required whose size is neither a byte nor a machine word there are standard libraries which can assist
in storing these efficiently and in performing conversions. See the array , struct and uctypes modules.
This applies to all ports, including CMake-based ones (e.g. esp32, rp2), as the Makefile wrapper that will pass this into
the CMake build.
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
High-level functions
Note: The opt keyword argument can be set on the various functions, this controls the optimisation level used by the
cross-compiler. See micropython.opt_level().
add_library(library, library_path, prepend=False)
Register the path to an external named library.
The path library_path will be automatically searched when using require. By default the added library is added
to the end of the list of libraries to search. Pass True to prepend to add it to the start of the list.
Additionally, the added library can be explicitly requested by using require("name", library="library").
package(package_path, files=None, base_path='.', opt=None)
This is equivalent to copying the “package_path” directory to the device (except as frozen code).
In the simplest case, to freeze a package “foo” in the current directory:
package("foo")
will recursively include all .py files in foo, and will be frozen as foo/**/*.py.
If the package isn’t in the same directory as the manifest file, use base_path:
package("foo", base_path="path/to/libraries")
module("foo.py")
module("foo.py", base_path="src/drivers")
include(manifest_path)
Include another manifest.
Typically a manifest used for compiling firmware will need to include the port manifest, which might include frozen
modules that are required for the board to function.
The manifest argument can be a string (filename) or an iterable of strings.
Relative paths are resolved with respect to the current manifest file.
If the path is to a directory, then it implicitly includes the manifest.py file inside that directory.
You can use the variables above, such as $(PORT_DIR) in manifest_path.
metadata(description=None, version=None, license=None, author=None)
Define metadata for this manifest file. This is useful for manifests for micropython-lib packages.
Low-level functions
These functions are documented for completeness, but with the exception of freeze_as_str all functionality can be
accessed via the high-level functions.
freeze(path, script=None, opt=0)
Freeze the input specified by path, automatically determining its type. A .py script will be compiled to a .mpy
first then frozen, and a .mpy file will be frozen directly.
path must be a directory, which is the base directory to begin searching for files. When importing the resulting
frozen modules, the name of the module will start after path, i.e. path is excluded from the module name.
If path is relative, it is resolved to the current manifest.py.
If script is None, all files in path will be frozen.
If script is an iterable then freeze() is called on all items of the iterable (with the same path and opt passed
through).
If script is a string then it specifies the file or directory to freeze, and can include extra directories before the file or
last directory. The file or directory will be searched for in path. If script is a directory then all files in that directory
will be frozen.
opt is the optimisation level to pass to mpy-cross when compiling .py to .mpy. These levels are described in
micropython.opt_level().
freeze_as_str(path)
Freeze the given path and all .py scripts within it as a string, which will be compiled upon import.
freeze_as_mpy(path, script=None, opt=0)
Freeze the input by first compiling the .py scripts to .mpy files, then freezing the resulting .mpy files. See
freeze() for further details on the arguments.
2.9.3 Examples
To freeze a single file from the current directory which will be available as import mydriver, use:
module("mydriver.py")
To freeze a directory of files in a subdirectory “mydriver” of the current directory which will be available as import
mydriver, use:
package("mydriver")
require("hmac")
A more complete example of a custom manifest.py file for the PYBD_SF2 board is:
$ cd ports/stm32
$ make BOARD=PYBD_SF2 FROZEN_MANIFEST=~/src/myproject/manifest.py
Note that most boards do not have their own manifest.py, rather they use the port one directly, in which case your
manifest should just include("$(PORT_DIR)/boards/manifest.py") instead.
mip will detect an appropriate location on the filesystem by searching sys.path for the first entry ending in /lib. You
can override the destination using target, but note that this path must be in sys.path to be able to subsequently import
it.:
As well as downloading packages from the micropython-lib index, mip can also install third-party libraries. The simplest
way is to download a file directly:
>>> mip.install("http://example.com/x/y/foo.py")
>>> mip.install("http://example.com/x/y/foo.mpy")
When installing a file directly, the target argument is still supported to set the destination path, but mpy and version
are ignored.
The URL can also start with github: or gitlab: as a simple way of pointing to content hosted on GitHub or GitLab:
More sophisticated packages (i.e. with more than one file, or with dependencies) can be downloaded by specifying the
path to their package.json.
>>> mip.install("http://example.com/x/package.json")
>>> mip.install("github:org/user/path/package.json")
>>> mip.install("gitlab:org/user/path/package.json")
>>> mip.install("http://example.com/x/")
>>> mip.install("github:org/repo") # Uses default branch of that repo
(continues on next page)
{
"urls": [
["mlx90640/__init__.py", "github:org/micropython-mlx90640/mlx90640/__init__.py"],
["mlx90640/utils.py", "github:org/micropython-mlx90640/mlx90640/utils.py"]
],
"deps": [
["collections-defaultdict", "latest"],
["os-path", "latest"],
["github:org/micropython-additions", "main"],
["gitlab:org/micropython-otheradditions", "main"]
],
"version": "0.2"
}
This includes two files, hosted at a GitHub repo named org/micropython-mlx90640, which install into the mlx90640
directory on the device. It depends on collections-defaultdict and os-path which will be installed automatically
from the micropython-lib. The third dependency installs the content as defined by the package.json file of the main
branch of the GitHub repo org/micropython-additions.
Notation: Rd, Rn denote ARM registers R0-R15. immN denotes an immediate value having a width of N bits. These
instructions affect the condition flags.
Register moves
Where immediate values are used, these are zero-extended to 32 bits. Thus mov(R0, 0xff) will set R0 to 255.
• mov(Rd, imm8) Rd = imm8
• mov(Rd, Rn) Rd = Rn
• movw(Rd, imm16) Rd = imm16
• movt(Rd, imm16) Rd = (Rd & 0xffff) | (imm16 << 16)
movt writes an immediate value to the top halfword of the destination register. It does not affect the contents of the
bottom halfword.
• movwt(Rd, imm32) Rd = imm32
movwt is a pseudo-instruction: the MicroPython assembler emits a movw followed by a movt to move a 32-bit value into
Rd.
Notation: Rt, Rn denote ARM registers R0-R7 except where stated. immN represents an immediate value having a width
of N bits hence imm5 is constrained to the range 0-31. [Rn + immN] is the contents of the memory address obtained
by adding Rn and the offset immN. Offsets are measured in bytes. These instructions affect the condition flags.
Register Load
Notation: Rt, Rn denote ARM registers R0-R7 except where stated. immN represents an immediate value having a width
of N bits hence imm5 is constrained to the range 0-31. [Rn + imm5] is the contents of the memory address obtained
by adding Rn and the offset imm5. Offsets are measured in bytes. These instructions do not affect the condition flags.
Register Store
Notation: Rd, Rn denote ARM registers R0-R7 except in the case of the special instructions where R0-R15 may be
used. Rn<a-b> denotes an ARM register whose contents must lie in range a <= contents <= b. In the case of
instructions with two register arguments, it is permissible for them to be identical. For example the following will zero
R0 (Python R0 ^= R0) regardless of its initial contents.
• eor(r0, r0)
These instructions affect the condition flags except where stated.
Logical instructions
Special instructions
bit_reverse(Rn) returns the bit-reversed contents of Rn. If Rn contains bits b31 b30..b0 Rd will be set to b0 b1
b2..b31
Trailing zeros may be counted by performing a bit reverse prior to executing clz.
Arithmetic instructions
Document conventions
Notation: Rd, Rm, Rn denote ARM registers R0-R7. immN denotes an immediate value having a width of N bits e.g.
imm8, imm3. carry denotes the carry condition flag, not(carry) denotes its complement. In the case of instructions
with more than one register argument, it is permissible for some to be identical. For example the following will add the
contents of R0 to itself, placing the result in R0:
• add(r0, r0, r0)
Arithmetic instructions affect the condition flags except where stated.
Addition
Subtraction
Negation
• mul(Rd, Rn) Rd = Rd * Rn
This produces a 32 bit result with overflow lost. The result may be treated as signed or unsigned according to the definition
of the operands.
• sdiv(Rd, Rn, Rm) Rd = Rn / Rm
• udiv(Rd, Rn, Rm) Rd = Rn / Rm
These functions perform signed and unsigned division respectively. Condition flags are not affected.
Comparison instructions
These perform an arithmetic or logical instruction on two arguments, discarding the result but setting the condition flags.
Typically these are used to test data values without changing them prior to executing a conditional branch.
Document conventions
Notation: Rd, Rm, Rn denote ARM registers R0-R7. imm8 denotes an immediate value having a width of 8 bits.
This contains four bits which are tested by the conditional branch instructions. Typically a conditional branch will test
multiple bits, for example bge(LABEL). The meaning of condition codes can depend on whether the operands of an
arithmetic instruction are viewed as signed or unsigned integers. Thus bhi(LABEL) assumes unsigned numbers were
processed while bgt(LABEL) assumes signed operands.
APSR Bits
• Z (zero)
This is set if the result of an operation is zero or the operands of a comparison are equal.
• N (negative)
Set if the result is negative.
• C (carry)
An addition sets the carry flag when the result overflows out of the MSB, for example adding 0x80000000 and
0x80000000. By the nature of two’s complement arithmetic this behaviour is reversed on subtraction, with a borrow
indicated by the carry bit being clear. Thus 0x10 - 0x01 is executed as 0x10 + 0xffffffff which will set the carry bit.
• V (overflow)
The overflow flag is set if the result, viewed as a two’s compliment number, has the “wrong” sign in relation to the operands.
For example adding 1 to 0x7fffffff will set the overflow bit because the result (0x8000000), viewed as a two’s complement
integer, is negative. Note that in this instance the carry bit is not set.
Comparison instructions
These set the APSR (Application Program Status Register) N (negative), Z (zero), C (carry) and V (overflow) flags.
• cmp(Rn, imm8) Rn - imm8
• cmp(Rn, Rm) Rn - Rm
• cmn(Rn, Rm) Rn + Rm
• tst(Rn, Rm) Rn & Rm
Conditional execution
The it and ite instructions provide a means of conditionally executing from one to four subsequent instructions without
the need for a label.
• it(<condition>) If then
Execute the next instruction if <condition> is true:
cmp(r0, r1)
it(eq)
mov(r0, 100) # runs if r0 == r1
# execution continues here
If <condition> is true, execute the next instruction, otherwise execute the subsequent one. Thus:
cmp(r0, r1)
ite(eq)
mov(r0, 100) # runs if r0 == r1
mov(r0, 200) # runs if r0 != r1
# execution continues here
This may be extended to control the execution of up to four subsequent instructions: it[x[y[z]]] where x,y,z=t/e; e.g. itt,
itee, itete, ittte, itttt, iteee, etc.
Branch instructions
These cause execution to jump to a target location usually specified by a label (see the label assembler directive).
Conditional branches and the it and ite instructions test the Application Program Status Register (APSR) N (negative),
Z (zero), C (carry) and V (overflow) flags to determine whether the branch should be executed.
Most of the exposed assembler instructions (including move operations) set the flags but there are explicit comparison
instructions to enable values to be tested.
Further detail on the meaning of the condition flags is provided in the section describing comparison functions.
Document conventions
Notation: Rm denotes ARM registers R0-R15. LABEL denotes a label defined with the label() assembler directive.
<condition> indicates one of the following condition specifiers:
Branch to label
Long branches
The code produced by the branch instructions listed above uses a fixed bit width to specify the branch destination, which
is PC relative. Consequently in long programs where the branch instruction is remote from its destination the assembler
will produce a “branch not in range” error. This can be overcome with the “wide” variants such as
• beq_w(LABEL) long branch if equal
Wide branches use 4 bytes to encode the instruction (compared with 2 bytes for standard branch instructions).
Subroutines (functions)
When entering a subroutine the processor stores the return address in register r14, also known as the link register (lr).
Return to the instruction after the subroutine call is performed by updating the program counter (r15 or pc) from the link
register, This process is handled by the following instructions.
• bl(LABEL)
Transfer execution to the instruction after LABEL storing the return address in the link register (r14).
• bx(Rm) Branch to address specified by Rm.
Typically bx(lr) is issued to return from a subroutine. For nested subroutines the link register of outer scopes must be
saved (usually on the stack) before performing inner subroutine calls.
The push() and pop() instructions accept as their argument a register set containing a subset, or possibly all, of the
general-purpose registers R0-R12 and the link register (lr or R14). As with any Python set the order in which the registers
are specified is immaterial. Thus the in the following example the pop() instruction would restore R1, R7 and R8 to their
contents prior to the push():
• push({r1, r8, r7}) Save three registers on the stack.
• pop({r7, r1, r8}) Restore them
Stack operations
Miscellaneous instructions
• nop() pass no operation.
• wfi() Suspend execution in a low power state until an interrupt occurs.
• cpsid(flags) set the Priority Mask Register - disable interrupts.
• cpsie(flags) clear the Priority Mask Register - enable interrupts.
• mrs(Rd, special_reg) Rd = special_reg copy a special register to a general register. The special register may be
IPSR (Interrupt Status Register) or BASEPRI (Base Priority Register). The IPSR provides a means of determining
the exception number of an interrupt being processed. It contains zero if no interrupt is being processed.
Currently the cpsie() and cpsid() functions are partially implemented. They require but ignore the flags argument
and serve as a means of enabling and disabling interrupts.
Document conventions
Notation: Sd, Sm, Sn denote FPU registers, Rd, Rm, Rn denote ARM core registers. The latter can be any ARM
core register although registers R13-R15 are unlikely to be appropriate in this context.
Arithmetic
• vmov(Sd, Rm) Sd = Rm
• vmov(Rd, Sm) Rd = Sm
The FPU has a register known as FPSCR, similar to the ARM core’s APSR, which stores condition codes plus other data.
The following instructions provide access to this.
• vmrs(APSR_nzcv, FPSCR)
Move the floating-point N, Z, C, and V flags to the APSR N, Z, C, and V flags.
This is done after an instruction such as an FPU comparison to enable the condition codes to be tested by the assembler
code. The following is a more general form of the instruction.
• vmrs(Rd, FPSCR) Rd = FPSCR
Data comparison
• vcmp(Sd, Sm)
Compare the values in Sd and Sm and set the FPU N, Z, C, and V flags. This would normally be followed by
vmrs(APSR_nzcv, FPSCR) to enable the results to be tested.
Assembler directives
Labels
• label(INNER1)
This defines a label for use in a branch instruction. Thus elsewhere in the code a b(INNER1) will cause execution to
continue with the instruction after the label directive.
The following assembler directives facilitate embedding data in an assembler code block.
• data(size, d0, d1 .. dn)
The data directive creates n array of data values in memory. The first argument specifies the size in bytes of the subsequent
arguments. Hence the first statement below will cause the assembler to put three bytes (with values 2, 3 and 4) into
consecutive memory locations while the second will cause it to emit two four byte words.
data(1, 2, 3, 4)
data(4, 2, 100000)
Data values longer than a single byte are stored in memory in little-endian format.
• align(nBytes)
Align the following instruction to an nBytes value. ARM Thumb-2 instructions must be two byte aligned, hence it’s
advisable to issue align(2) after data directives and prior to any subsequent code. This ensures that the code will run
irrespective of the size of the data array.
It is important to appreciate that labels are local to an assembler function. There is currently no way for a subroutine
defined in one function to be called from another.
To call a subroutine the instruction bl(LABEL) is issued. This transfers control to the instruction following the la-
bel(LABEL) directive and stores the return address in the link register (lr or r14). To return the instruction bx(lr)
is issued which causes execution to continue with the instruction following the subroutine call. This mechanism implies
that, if a subroutine is to call another, it must save the link register prior to the call and restore it before terminating.
The following rather contrived example illustrates a function call. Note that it’s necessary at the start to branch around all
subroutine calls: subroutines end execution with bx(lr) while the outer function simply “drops off the end” in the style
of Python functions.
@micropython.asm_thumb
def quad(r0):
b(START)
label(DOUBLE)
add(r0, r0, r0)
bx(lr)
label(START)
bl(DOUBLE)
bl(DOUBLE)
print(quad(10))
The following code example demonstrates a nested (recursive) call: the classic Fibonacci sequence. Here, prior to a
recursive call, the link register is saved along with other registers which the program logic requires to be preserved.
@micropython.asm_thumb
def fib(r0):
b(START)
label(DOFIB)
push({r1, r2, lr})
cmp(r0, 1)
ble(FIBDONE)
sub(r0, 1)
mov(r2, r0) # r2 = n -1
bl(DOFIB)
mov(r1, r0) # r1 = fib(n -1)
sub(r0, r2, 1)
bl(DOFIB) # r0 = fib(n -2)
add(r0, r0, r1)
label(FIBDONE)
pop({r1, r2, lr})
(continues on next page)
for n in range(10):
print(fib(n))
The tutorial details the fact that assembler functions can support from zero to three arguments, which must (if used) be
named r0, r1 and r2. When the code executes the registers will be initialised to those values.
The data types which can be passed in this way are integers and memory addresses. With current firmware all possible
32 bit values may be passed and returned. If the return value may have the most significant bit set a Python type hint
should be employed to enable MicroPython to determine whether the value should be interpreted as a signed or unsigned
integer: types are int or uint.
@micropython.asm_thumb
def uadd(r0, r1) -> uint:
add(r0, r0, r1)
hex(uadd(0x40000000,0x40000000)) will return 0x80000000, demonstrating the passing and return of integers
where bits 30 and 31 differ.
The limitations on the number of arguments and return values can be overcome by means of the array module which
enables any number of values of any type to be accessed.
Multiple arguments
If a Python array of integers is passed as an argument to an assembler function, the function will receive the address of
a contiguous set of integers. Thus multiple arguments can be passed as elements of a single array. Similarly a function
can return multiple values by assigning them to array elements. Assembler functions have no means of determining the
length of an array: this will need to be passed to the function.
This use of arrays can be extended to enable more than three arrays to be used. This is done using indirection: the
uctypes module supports addressof() which will return the address of an array passed as its argument. Thus you
can populate an integer array with the addresses of other arrays:
def testindirect():
a = array.array('i',[23, 24])
b = array.array('i',[0,0])
b[0] = addressof(a)
print(getindirect(b))
These may be handled by means of arrays of the appropriate data type. For example, single precision floating point data
may be processed as follows. This code example takes an array of floats and replaces its contents with their squares.
@micropython.asm_thumb
def square(r0, r1):
label(LOOP)
vldr(s0, [r0, 0])
vmul(s0, s0, s0)
vstr(s0, [r0, 0])
add(r0, 4)
sub(r1, 1)
bgt(LOOP)
The uctypes module supports the use of data structures beyond simple arrays. It enables a Python data structure to be
mapped onto a bytearray instance which may then be passed to the assembler function.
Named constants
Assembler code may be made more readable and maintainable by using named constants rather than littering code with
numbers. This may be achieved thus:
MYDATA = const(33)
@micropython.asm_thumb
def foo():
mov(r0, MYDATA)
The const() construct causes MicroPython to replace the variable name with its value at compile time. If constants are
declared in an outer Python scope they can be shared between multiple assembler functions and with Python code.
MicroPython passes the address of the object instance as the first argument to class methods. This is normally of little
use to an assembler function. It can be avoided by declaring the function as a static method thus:
class foo:
@staticmethod
@micropython.asm_thumb
def bar(r0):
add(r0, r0, r0)
These can be coded using the data statement as shown below. While push() and pop() are supported the example below
illustrates the principle. The necessary machine code may be found in the ARM v7-M Architecture Reference Manual.
Note that the first argument of data calls such as
The Pyboard chip includes a CRC generator. Its use presents a problem in MicroPython because the returned values
cover the full gamut of 32 bit quantities whereas small integers in MicroPython cannot have differing values in bits 30 and
31. This limitation is overcome with the following code, which uses assembler to put the result into an array and Python
code to coerce the result into an arbitrary precision unsigned integer.
def enable_crc():
stm.mem32[stm.RCC + stm.RCC_AHB1ENR] |= 0x1000
def reset_crc():
stm.mem32[stm.CRC+stm.CRC_CR] = 1
@micropython.asm_thumb
def getval(r0, r1):
movwt(r3, stm.CRC + stm.CRC_DR)
str(r1, [r3, 0])
ldr(r2, [r3, 0])
str(r2, [r0, 0])
def getcrc(value):
a = array('i', [0])
getval(a, value)
return a[0] & 0xffffffff # coerce to arbitrary precision
enable_crc()
reset_crc()
for x in range(20):
print(hex(getcrc(0)))
2.11.4 References
• Assembler Tutorial
• Wiki hints and tips
• uPy Inline Assembler source-code, emitinlinethumb.c
• ARM Thumb2 Instruction Set Quick Reference Card
• RM0090 Reference Manual
• ARM v7-M Architecture Reference Manual (Available on the ARM site after a simple registration procedure. Also
available on academic sites but beware of out of date versions.)
Contents
This tutorial describes how MicroPython provides an on-device filesystem, allowing standard Python file I/O methods to
be used with persistent storage.
MicroPython automatically creates a default configuration and auto-detects the primary filesystem, so this tutorial will be
mostly useful if you want to modify the partitioning, filesystem type, or use custom block devices.
The filesystem is typically backed by internal flash memory on the device, but can also use external flash, RAM, or a
custom block device.
On some ports (e.g. STM32), the filesystem may also be available over USB MSC to a host PC. The pyboard.py tool also
provides a way for the host PC to access to the filesystem on all ports.
Note: This is mainly for use on bare-metal ports like STM32 and ESP32. On ports with an operating system (e.g. the
Unix port) the filesystem is provided by the host OS.
2.12.1 VFS
MicroPython implements a Unix-like Virtual File System (VFS) layer. All mounted filesystems are combined into a
single virtual filesystem, starting at the root /. Filesystems are mounted into directories in this structure, and at startup
the working directory is changed to where the primary filesystem is mounted.
On STM32 / Pyboard, the internal flash is mounted at /flash, and optionally the SDCard at /sd. On ESP8266/ESP32,
the primary filesystem is mounted at /.
STM32 / Pyboard
The pyb.Flash class provides access to the internal flash. On some boards which have larger external flash (e.g. Pyboard
D), it will use that instead. The start kwarg should always be specified, i.e. pyb.Flash(start=0).
Note: For backwards compatibility, when constructed with no arguments (i.e. pyb.Flash()), it only implements the
simple block interface and reflects the virtual device presented to USB MSC (i.e. it includes a virtual partition table at
the start).
ESP8266
The internal flash is exposed as a block device object which is created in the flashbdev module on start up. This object
is by default added as a global variable so it can usually be accessed simply as bdev. This implements the extended
interface.
ESP32
The esp32.Partition class implements a block device for partitions defined for the board. Like ESP8266, there is a
global variable bdev which points to the default partition. This implements the extended interface.
class RAMBlockDev:
def __init__(self, block_size, num_blocks):
self.block_size = block_size
self.data = bytearray(block_size * num_blocks)
import vfs
An example of a block device that supports both the simple and extended interface (i.e. both signatures and behaviours
of the vfs.AbstractBlockDev.readblocks() and vfs.AbstractBlockDev.writeblocks() methods) is:
class RAMBlockDev:
def __init__(self, block_size, num_blocks):
self.block_size = block_size
self.data = bytearray(block_size * num_blocks)
import vfs
Once mounted, the filesystem (regardless of its type) can be used as it normally would be used from Python code, for
example:
2.12.3 Filesystems
MicroPython ports can provide implementations of FAT , littlefs v1 and littlefs v2.
The following table shows which filesystems are included in the firmware by default for given port/board combinations,
however they can be optionally enabled in a custom firmware build.
FAT
The main advantage of the FAT filesystem is that it can be accessed over USB MSC on supported boards (e.g. STM32)
without any additional drivers required on the host PC.
However, FAT is not tolerant to power failure during writes and this can lead to filesystem corruption. For applications
that do not require USB MSC, it is recommended to use littlefs instead.
To format the entire flash using FAT:
# STM32
import os, vfs, pyb
vfs.umount('/flash')
vfs.VfsFat.mkfs(pyb.Flash(start=0))
vfs.mount(pyb.Flash(start=0), '/flash')
os.chdir('/flash')
Littlefs
Littlefs is a filesystem designed for flash-based devices, and is much more resistant to filesystem corruption.
® Note
There are reports of littlefs v1 and v2 failing in certain situations, for details see littlefs issue 347 and littlefs issue 295.
A littlefs filesystem can be still be accessed on a PC over USB MSC using the littlefs FUSE driver. Note that you must
specify both the --block_size and --block_count options to override the defaults. For example (after building the
littlefs-fuse executable):
This will allow the board’s littlefs filesystem to be accessed at the mnt directory. To get the correct values of block_size
and block_count use:
import pyb
f = pyb.Flash(start=0)
f.ioctl(1, 1) # initialise flash in littlefs raw-block mode
block_count = f.ioctl(4, 0)
block_size = f.ioctl(5, 0)
Hybrid (STM32)
By using the start and len kwargs to pyb.Flash, you can create block devices spanning a subset of the flash device.
For example, to configure the first 256kiB as FAT (and available over USB MSC), and the remainder as littlefs:
This might be useful to make your Python files, configuration and other rarely-modified content available over USB MSC,
but allowing for frequently changing application data to reside on littlefs with better resilience to power failure, etc.
The partition at offset 0 will be mounted automatically (and the filesystem type automatically detected), but you can add:
Hybrid (ESP32)
On ESP32, if you build custom firmware, you can modify partitions.csv to define an arbitrary partition layout.
At boot, the partition named “vfs” will be mounted at / by default, but any additional partitions can be mounted in your
boot.py using:
usage: pyboard [-h] [-d DEVICE] [-b BAUDRATE] [-u USER] [-p PASSWORD]
[-c COMMAND] [-w WAIT] [--follow | --no-follow] [-f]
[files [files ...]]
positional arguments:
files input files
optional arguments:
-h, --help show this help message and exit
-d DEVICE, --device DEVICE
the serial device or the IP address of the pyboard
-b BAUDRATE, --baudrate BAUDRATE
the baud rate of the serial device
-u USER, --user USER the telnet login username
-p PASSWORD, --password PASSWORD
the telnet login password
-c COMMAND, --command COMMAND
program passed in as string
-w WAIT, --wait WAIT seconds to wait for USB connected board to become
available
--follow follow the output after running the scripts
[default if no scripts given]
-f, --filesystem perform a filesystem action: cp local :device | cp
:device local | cat path | ls [path] | rm path | mkdir
path | rmdir path
If you are often interacting with the same device, you can set the environment variable PYBOARD_DEVICE as an alternative
to using the --device command line option. For example, the following is equivalent to the previous example:
$ export PYBOARD_DEVICE=/dev/ttyACM0
$ pyboard.py -c 'print(1+1)'
Similarly, the PYBOARD_BAUDRATE environment variable can be used to set the default for the --baudrate option.
Note that this doesn’t actually copy app.py to the device’s filesystem, it just loads the code into RAM and executes it. Any
output generated by the program will be displayed.
If the program app.py does not finish then you’ll need to stop pyboard.py, eg with Ctrl-C. The program app.py will
still continue to run on the MicroPython device.
will copy main.py from the current directory on the PC to a file named main.py on the device. The filename can be
omitted, e.g.:
import pyboard
pyb = pyboard.Pyboard('/dev/ttyACM0', 115200)
pyb.enter_raw_repl()
ret = pyb.exec('print(1+1)')
print(ret)
pyb.exit_raw_repl()
Changes
None yet
Changes
None yet
Changes
Introduction of a new module vfs. The following functions and classes have moved out of os to vfs: - os.mount -
os.umount - os.VfsFat - os.VfsLfs1 - os.VfsLfs2 - os.VfsPosix
THREE
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.
Added the namereplace error handlers. The backslashreplace error handlers now work with decoding and
translating.
Property docstrings are now writable. This is especially useful for collections.namedtuple() docstrings
Circular imports involving relative imports are now supported.
New Modules:
• typing
• zipzap
1 The MicroPython parser correct ignores all type hints. However, the typing module is not built-in.
295
MicroPython Documentation, Release latest
collections
The OrderedDict class is now implemented in C, which makes it 4 to 100 times faster.
OrderedDict.items() , OrderedDict.keys() , OrderedDict.values() views now support reversed() iteration.
The deque class now defines index(), insert(), and copy(), and supports the + and * operators.
Docstrings produced by namedtuple() can now be updated.
The UserString class now implements the __getnewargs__(), __rmod__(), casefold(), format_map(), is-
printable(), and maketrans() methods to match the corresponding methods of str.
heapq
Element comparison in merge() can now be customized by passing a key function in a new optional key
keyword argument, and a new optional reverse keyword argument can be used to reverse element compar-
ison
io
A new BufferedIOBase.readinto1() method, that uses at most one call to the underlying raw stream’s Raw-
IOBase.read() or RawIOBase.readinto() methods
json
JSON decoder now raises JSONDecodeError instead of ValueError to provide better context information
about the error.
math
Two new constants have been added to the math module: inf and nan. Com-
plete
A new function isclose() provides a way to test for approximate equality.
A new gcd() function has been added. The fractions.gcd() function is now deprecated.
os
The new scandir() function returning an iterator of DirEntry objects has been added.
The urandom() function now uses the getrandom() syscall on Linux 3.17 or newer, and getentropy() on
OpenBSD 5.6 and newer, removing the need to use /dev/urandom and avoiding failures due to potential
file descriptor exhaustion.
New get_blocking() and set_blocking() functions allow getting and setting a file descriptor’s blocking mode
(O_NONBLOCK.)
There is a new os.path.commonpath() function returning the longest common sub-path of each passed
pathname
re
References and conditional references to groups with fixed length are now allowed in lookbehind assertions
The number of capturing groups in regular expressions is no longer limited to 100.
The sub() and subn() functions now replace unmatched groups with empty strings instead of raising an
exception.
The re.error exceptions have new attributes, msg, pattern, pos, lineno, and colno, that provide better context
information about the error
socket
Functions with timeouts now use a monotonic clock, instead of a system clock.
A new socket.sendfile() method allows sending a file over a socket by using the high-performance
os.sendfile() function on UNIX, resulting in uploads being from 2 to 3 times faster than when using plain
socket.send()
The socket.sendall() method no longer resets the socket timeout every time bytes are received or sent. The
socket timeout is now the maximum total duration to send all data.
The backlog argument of the socket.listen() method is now optional. By default it is set to SOMAXCONN Com-
or to 128, whichever is less. plete
ssl
Memory BIO Support
Application-Layer Protocol Negotiation Support
continues on next page
Notes
A global or nonlocal statement must now textually appear before the first use of the affected name in the
same scope. Previously this was a SyntaxWarning.
It is now possible to set a special method to None to indicate that the corresponding operation is not
available. For example, if a class sets __iter__() to None , the class is not iterable.
Long sequences of repeated traceback lines are now abbreviated as [Previous line repeated {count} more
times]
Import now raises the new exception ModuleNotFoundError when it cannot find a module. Code that
currently checks for ImportError (in try-except) will still work.
Class methods relying on zero-argument super() will now work correctly when called from metaclass meth-
ods during class creation.
array
Exhausted iterators of array.array will now stay exhausted even if the iterated array is extended.
binascii
The b2a_base64() function now accepts an optional newline keyword argument to control whether the Com-
newline character is appended to the return value plete
cmath
The new cmath.tau (τ) constant has been added
New constants: cmath.inf and cmath.nan to match math.inf and math.nan , and also cmath.infj and
cmath.nanj to match the format used by complex repr
collections
The new Collection abstract base class has been added to represent sized iterable container classes
The new Reversible abstract base class represents iterable classes that also provide the __reversed__()
method.
The new AsyncGenerator abstract base class represents asynchronous generators.
The namedtuple() function now accepts an optional keyword argument module, which, when specified, is
used for the __module__ attribute of the returned named tuple class.
The verbose and rename arguments for namedtuple() are now keyword-only.
Recursive collections.deque instances can now be pickled.
hashlib
BLAKE2 hash functions were added to the module. blake2b() and blake2s() are always available and
support the full feature set of BLAKE2.
The SHA-3 hash functions sha3_224(), sha3_256(), sha3_384(), sha3_512(), and SHAKE hash functions
shake_128() and shake_256() were added.
The password-based key derivation function scrypt() is now available with OpenSSL 1.1.0 and newer.
json
json.load() and json.loads() now support binary input. Encoded JSON should be represented using either
UTF-8, UTF-16, or UTF-32.
math
The new math.tau (τ) constant has been added Com-
plete
os
A new close() method allows explicitly closing a scandir() iterator. The scandir() iterator now supports the
context manager protocol.
On Linux, os.urandom() now blocks until the system urandom entropy pool is initialized to increase the
security.
The Linux getrandom() syscall (get random bytes) is now exposed as the new os.getrandom() function.
re
continues on next page
Feature Status
PEP 538 Coercing the legacy C locale to a UTF-8 based locale
PEP 539 A New C-API for Thread-Local Storage in CPython
PEP 540 UTF-8 mode
PEP 552 Deterministic pyc
PEP 553 Built-in breakpoint()
PEP 557 Data Classes
PEP 560 Core support for typing module and generic types
PEP 562 Module __getattr__ and __dir__ Partial
PEP 563 Postponed Evaluation of Annotations
PEP 564 Time functions with nanosecond resolution Partial1
PEP 565 Show DeprecationWarning in __main__
PEP 567 Context Variables
asyncio
Too many to list
gc
New features include gc.freeze(), gc.unfreeze(), gc-get_freeze_count
math
math.remainder() added to implement IEEE 754-style remainder
re
A number of tidy up features including better support for splitting on empty strings and copy support for
compiled expressions and match objects
sys
sys.breakpointhook() added. sys.get(/set)_coroutine_origin_tracking_depth() added
time
Mostly updates to support nanosecond resolution in PEP564, see above
Notes
Features Status
PEP 570 Positional-only arguments
PEP 572 Assignment Expressions Complete
PEP 574 Pickle protocol 5 with out-of-band data
PEP 578 Runtime audit hooks
PEP 587 Python Initialization Configuration
PEP 590 Vectorcall: a fast calling protocol for CPython
Miscellaneous
f-strings support = for self-documenting expressions and debugging Complete
A continue statement was illegal in the finally clause due to a problem with the implementation. In Python Com-
3.8 this restriction was lifted plete
The bool, int , and fractions.Fraction types now have an as_integer_ratio() method like that found in float
and decimal.Decimal
Constructors of int, float and complex will now use the __index__() special method, if available and the
corresponding method __int__(), __float__() or __complex__() is not available
Added support of N{name} escapes in regular expressions
Dict and dictviews are now iterable in reversed insertion order using reversed()
The syntax allowed for keyword names in function calls was further restricted. In particular,
f((keyword)=arg) is no longer allowed
Generalized iterable unpacking in yield and return statements no longer requires enclosing parentheses
When a comma is missed in code such as [(10, 20) (30, 40)], the compiler displays a SyntaxWarning with
a helpful suggestion
Arithmetic operations between subclasses of datetime.date or datetime.datetime and datetime.timedelta ob-
jects now return an instance of the subclass, rather than the base class
When the Python interpreter is interrupted by Ctrl-C (SIGINT) and the resulting KeyboardInterrupt excep-
tion is not caught, the Python process now exits via a SIGINT signal or with the correct exit code such that
the calling process can detect that it died due to a Ctrl-C
Some advanced styles of programming require updating the types.CodeType object for an existing function
For integers, the three-argument form of the pow() function now permits the exponent to be negative in
the case where the base is relatively prime to the modulus
Dict comprehensions have been synced-up with dict literals so that the key is computed first and the value
second
The object.__reduce__() method can now return a tuple from two to six elements long
asyncio
asyncio.run() has graduated from the provisional to stable API Com-
plete
Running python -m asyncio launches a natively async REPL
The exception asyncio.CancelledError now inherits from BaseException rather than Exception and no longer Com-
inherits from concurrent.futures.CancelledError plete
Added asyncio.Task.get_coro() for getting the wrapped coroutine within an asyncio.Task
Asyncio tasks can now be named, either by passing the name keyword argument to asyncio.create_task()
or the create_task() event loop method, or by calling the set_name() method on the task object
Added support for Happy Eyeballs to asyncio.loop.create_connection(). To specify the behavior, two new
parameters have been added: happy_eyeballs_delay and interleave.
gc
get_objects() can now receive an optional generation parameter indicating a generation to get objects from.
(Note, though, that while gc is a built-in, get_objects() is not implemented for MicroPython)
math
Added new function math.dist() for computing Euclidean distance between two points
Expanded the math.hypot() function to handle multiple dimensions
Added new function, math.prod(), as analogous function to sum() that returns the product of a “start” value
(default: 1) times an iterable of numbers
Added two new combinatoric functions math.perm() and math.comb()
Added a new function math.isqrt() for computing accurate integer square roots without conversion to float-
ing point
The function math.factorial() no longer accepts arguments that are not int-like Com-
plete
sys
Add new sys.unraisablehook() function which can be overridden to control how “unraisable exceptions”
are handled
Features Status
PEP 573 Fast access to module state from methods of C extension types Not relevant
PEP 584 Union operators added to dict Complete1
PEP 585 Type hinting generics in standard collections
PEP 593 Flexible function and variable annotations
PEP 602 CPython adopts an annual release cycle. Instead of annual, aiming for Not relevant
two month release cycle
PEP 614 Relaxed grammar restrictions on decorators
PEP 615 The IANA Time Zone Database is now present in the standard library
in the zoneinfo module
PEP 616 String methods to remove prefixes and suffixes
PEP 617 CPython now uses a new parser based on PEG Not relevant
asyncio
Due to significant security concerns, the reuse_address parameter of asyn-
cio.loop.create_datagram_endpoint() is no longer supported
Added a new coroutine shutdown_default_executor() that schedules a shutdown for the default executor
that waits on the ThreadPoolExecutor to finish closing. Also, asyncio.run() has been updated to use the
new coroutine.
Added asyncio.PidfdChildWatcher, a Linux-specific child watcher implementation that polls process file
descriptors
added a new coroutine asyncio.to_thread()
When cancelling the task due to a timeout, asyncio.wait_for() will now wait until the cancellation is com-
plete also in the case when timeout is <= 0, like it does with positive timeouts
asyncio now raises TyperError when calling incompatible methods with an ssl.SSLSocket socket
gc
Garbage collection does not block on resurrected objects
Added a new function gc.is_finalized() to check if an object has been finalized by the garbage collector
math
Expanded the math.gcd() function to handle multiple arguments. Formerly, it only supported two argu-
ments
Added math.lcm(): return the least common multiple of specified arguments
Added math.nextafter(): return the next floating-point value after x towards y
Added math.ulp(): return the value of the least significant bit of a float
os
Exposed the Linux-specific os.pidfd_open() and os.P_PIDFD
The os.unsetenv() function is now also available on Windows Com-
plete
The os.putenv() and os.unsetenv() functions are now always available Com-
plete
Added os.waitstatus_to_exitcode() function: convert a wait status to an exit code
random
Added a new random.Random.randbytes method: generate random bytes
sys
Added a new sys.platlibdir attribute: name of the platform-specific library directory
Previously, sys.stderr was block-buffered when non-interactive. Now stderr defaults to always being line-
buffered
Notes
The int type has a new method int.bit_count(), returning the number of ones in the binary expansion
of a given integer, also known as the population count.
The views returned by dict.keys(), dict.values() and dict.items() now all have a mapping
attribute that gives a types.MappingProxyType object wrapping the original dictionary.
PEP 618: The zip() function now has an optional strict flag, used to require that all the iterables have
an equal length.
Builtin and extension functions that take integer arguments no longer accept Decimals, Fractions and
other objects that can be converted to integers only with a loss (e.g. that have the __int__() method but
do not have the __index__() method).
If object.__ipow__() returns NotImplemented, the operator will correctly fall back to object.
__pow__() and object.__rpow__() as expected.
Assignment expressions can now be used unparenthesized within set literals and set comprehensions, as
well as in sequence indexes (but not slices).
Functions have a new __builtins__ attribute which is used to look for builtin symbols when a function
is executed, instead of looking into __globals__['__builtins__']. The attribute is initialized from
__globals__["__builtins__"] if it exists, else from the current builtins.
Two new builtin functions – aiter() and anext() have been added to provide asynchronous counter-
parts to iter() and next(), respectively.
Static methods (@staticmethod) and class methods (@classmethod) now inherit the method at-
tributes (__module__, __name__, __qualname__, __doc__, __annotations__) and have a new
__wrapped__ attribute. Moreover, static methods are now callable as regular functions.
Annotations for complex targets (everything beside simple name targets defined by PEP 526) no longer
cause any runtime effects with from __future__ import annotations.
Class and module objects now lazy-create empty annotations dicts on demand. The annotations dicts are
stored in the object’s __dict__ for backwards compatibility. This improves the best practices for working
with __annotations__.
Annotations consist of yield, yield from, await or named expressions are now forbidden under from
__future__ import annotations due to their side effects.
Usage of unbound variables, super() and other expressions that might alter the processing of symbol
table as annotations are now rendered effectless under from __future__ import annotations.
Hashes of NaN values of both float type and decimal.Decimal type now depend on object identity.
Formerly, they always hashed to 0 even though NaN values are not equal to one another. This caused
potentially quadratic runtime behavior due to excessive hash collisions when creating dictionaries and sets
containing multiple NaNs.
A SyntaxError (instead of a NameError) will be raised when deleting the __debug__ constant.
SyntaxError exceptions now have end_lineno and end_offset attributes. They will be None if not
determined.
asyncio
Add missing connect_accepted_socket() method.
array
The index() method of array.array now has optional start and stop parameters.
gc
Add audit hooks for gc.get_objects(), gc.get_referrers() and gc.get_referents().
hashlib
The hashlib module requires OpenSSL 1.1.1 or newer.
The hashlib module has preliminary support for OpenSSL 3.0.0.
The pure-Python fallback of pbkdf2_hmac() is deprecated. In the future PBKDF2-HMAC will only be
available when Python has been built with OpenSSL support.
continues on next page
Notes
For the features of Python that are implemented by MicroPython, there are sometimes differences in their behaviour
compared to standard Python. The operations listed in the sections below produce conflicting results in MicroPython
when compared to standard Python.
3.7 Syntax
Generated Wed 19 Feb 2025 18:48:30 UTC
3.7.1 Argument unpacking does not work if the argument being unpacked is the
nth or greater argument where n is the number of bits in an MP_SMALL_INT.
Cause: The implementation uses an MP_SMALL_INT to flag args that need to be unpacked.
Workaround: Use fewer arguments.
Sample code:
def example(*args):
print(len(args))
example(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
*MORE,
)
Operators
Spaces
3.7.3 uPy requires spaces between literal numbers and keywords, CPy doesn’t
Sample code:
try:
print(eval("1and 0"))
except SyntaxError:
print("Should have worked")
try:
print(eval("1or 0"))
except SyntaxError:
print("Should have worked")
try:
print(eval("1if 1else 0"))
except SyntaxError:
print("Should have worked")
Unicode
3.8.1 f-strings don’t support concatenation with adjacent literals if the adjacent
literals contain braces
Cause: MicroPython is optimised for code space.
Workaround: Use the + operator between literal strings when they are not both f-strings
Sample code:
x, y = 1, 2
print("aa" f"{x}") # works
print(f"{x}" "ab") # works
print("a{}a" f"{x}") # fails
print(f"{x}" "a{}b") # fails
aa1 aa1
1ab 1ab
a{}a1 Traceback (most recent call last):
1a{}b File "<stdin>", line 11, in <module>
IndexError: tuple index out of range
3.8.2 f-strings cannot support expressions that require parsing to resolve unbal-
anced nested braces and brackets
Cause: MicroPython is optimised for code space.
Workaround: Always use balanced braces and brackets in expressions inside f-strings
Sample code:
print(f'{"hello { world"}')
print(f'{"hello ] world"}')
f"{'unicode text'!a}"
Classes
import gc
class Foo:
def __del__(self):
print("__del__")
f = Foo()
del f
gc.collect()
__del__
class Foo:
def __str__(self):
return "Foo"
t = C((1, 2, 3))
print(t)
Foo (1, 2, 3)
def __print_string(string):
print(string)
class Foo:
def __init__(self, string):
self.string = string
def do_print(self):
__print_string(self.string)
class_item = Foo(example_string)
print(class_item.string)
class_item.do_print()
,→string'?
class L1(list):
def __init__(self, a):
self.append(a)
try:
L1(1)
print("OK")
except AttributeError:
print("AttributeError")
class L2(list):
def __init__(self, a):
super().__init__()
self.append(a)
try:
L2(1)
print("OK")
except AttributeError:
print("AttributeError")
OK AttributeError
OK OK
3.8.8 When inheriting from multiple classes super() only calls one class
Cause: See Method Resolution Order (MRO) is not compliant with CPython
Workaround: See Method Resolution Order (MRO) is not compliant with CPython
Sample code:
class A:
def __init__(self):
print("A.__init__")
class B(A):
def __init__(self):
print("B.__init__")
super().__init__()
class C(A):
def __init__(self):
print("C.__init__")
super().__init__()
(continues on next page)
D()
D.__init__ D.__init__
B.__init__ B.__init__
C.__init__ A.__init__
A.__init__
3.8.9 Calling super() getter property in subclass will return a property object, not
the value
Sample code:
class A:
@property
def p(self):
return {"a": 10}
class AA(A):
@property
def p(self):
return super().p
a = AA()
print(a.p)
Functions
3.8.10 Error messages for methods may display unexpected argument counts
Cause: MicroPython counts “self” as an argument.
Workaround: Interpret error messages with the information above in mind.
Sample code:
try:
[].append()
except Exception as e:
print(e)
def f():
pass
print(f.__module__)
def f():
pass
f.x = 0
print(f.x)
Generator
3.8.13 Context manager __exit__() not called in a generator which does not run to
completion
Sample code:
class foo(object):
def __enter__(self):
print("Enter")
def bar(x):
with foo():
while True:
x += 1
yield x
def func():
g = bar(0)
for _ in range(3):
print(next(g))
func()
Enter Enter
1 1
2 2
3 3
Exit
Runtime
Sample code:
def test():
val = 2
print(locals())
test()
3.8.15 Code running in eval() function doesn’t have access to local variables
Cause: MicroPython doesn’t maintain symbolic local environment, it is optimized to an array of slots. Thus, local vari-
ables can’t be accessed by a name. Effectively, eval(expr) in MicroPython is equivalent to eval(expr, globals(),
globals()).
Sample code:
val = 1
def test():
val = 2
print(val)
eval("print(val)")
test()
2 2
2 1
import
foo.hello()
3.8.17 __path__ attribute of a package has a different type (single string instead of
list of strings) in MicroPython
Cause: MicroPython doesn’t support namespace packages split across filesystem. Beyond that, MicroPython’s import
system is highly optimized for minimal memory usage.
Workaround: Details of import handling is inherently implementation dependent. Don’t rely on such details in portable
applications.
Sample code:
import modules
print(modules.__path__)
['/home/micropython/micropython-autodocs/ ../tests/cpydiff/modules
,→tests/cpydiff/modules']
import sys
sys.path.append(sys.path[1] + "/modules")
sys.path.append(sys.path[1] + "/modules2")
import subpkg.foo
import subpkg.bar
Two modules of a split namespace package␣ Traceback (most recent call last):
,→imported
File "<stdin>", line 13, in <module>
ImportError: no module named 'subpkg.bar'
3.9.1 Exception
All exceptions have readable value and errno attributes, not just StopIteration and OSError.
Cause: MicroPython is optimised to reduce code size.
Workaround: Only use value on StopIteration exceptions, and errno on OSError exceptions. Do not use or rely
on these attributes on other exceptions.
Sample code:
e = Exception(1)
print(e.value)
print(e.errno)
try:
raise TypeError
except TypeError:
raise ValueError
Traceback (most recent call last): Traceback (most recent call last):
File "<stdin>", line 8, in <module> File "<stdin>", line 10, in <module>
TypeError ValueError:
e = Exception()
e.x = 0
print(e.x)
l = ["-foo", "-bar"]
i = 0
while l[i][0] == "-":
print("iter")
i += 1
iter iter
iter iter
Traceback (most recent call last): Traceback (most recent call last):
File "<stdin>", line 10, in <module> File "<stdin>", line 12, in <module>
IndexError: list index out of range IndexError: list index out of range
class A(Exception):
def __init__(self):
super().__init__()
Sample code:
class A(Exception):
def __init__(self):
Exception.__init__(self)
a = A()
3.9.2 bytearray
Array slice assignment with unsupported RHS
Sample code:
b = bytearray(4)
b[0:1] = [1, 2]
print(b)
3.9.3 bytes
bytes objects support .format() method
Cause: MicroPython strives to be a more regular implementation, so if both str and bytes support __mod__() (the
% operator), it makes sense to support format() for both too. Support for __mod__ can also be compiled out, which
leaves only format() for bytes formatting.
Workaround: If you are interested in CPython compatibility, don’t use .format() on bytes objects.
Sample code:
print(b"{}".format(1))
print(bytes("abc", encoding="utf8"))
,→instead
print(b"123"[0:3:2])
3.9.4 dict
Dictionary keys view does not behave as a set.
Cause: Not implemented.
Workaround: Explicitly convert keys to a set before using set operations.
Sample code:
3.9.5 float
uPy allows implicit conversion of objects in maths operations while CPython does not.
Workaround: Objects should be wrapped in float(obj) for compatibility with CPython.
Sample code:
class Test:
def __float__(self):
return 0.5
print(2.0 * Test())
print("%.1g" % -9.9)
-1e+01 -10
3.9.6 int
bit_length method doesn’t exist.
x = 255
print("{} is {} bits long.".format(x, x.bit_length()))
class A(int):
__add__ = lambda self, other: A(int(self) + other)
a = A(42)
print(a + a)
x = -1
print(x.to_bytes(1, "big"))
3.9.7 list
List delete with step != 1 not implemented
Workaround: Use explicit loop for this rare operation.
Sample code:
l = [1, 2, 3, 4]
del l[0:4:2]
print(l)
l = [10, 20]
l[0:1] = range(4)
print(l)
l = [1, 2, 3, 4]
l[0:4:2] = [5, 6]
print(l)
3.9.8 memoryview
memoryview can become invalid if its target is resized
Cause: CPython prevents a bytearray or io.bytesIO object from changing size while there is a memoryview object
that references it. MicroPython requires the programmer to manually ensure that an object is not resized while any
memoryview references it.
In the worst case scenario, resizing an object which is the target of a memoryview can cause the memoryview(s) to
reference invalid freed memory (a use-after-free bug) and corrupt the MicroPython runtime.
Workaround: Do not change the size of any bytearray or io.bytesIO object that has a memoryview assigned to it.
Sample code:
b = bytearray(b"abcdefg")
m = memoryview(b)
b.extend(b"hijklmnop")
print(b, bytes(m))
3.9.9 str
Start/end indices such as str.endswith(s, start) not implemented
Sample code:
print("abc".endswith("c", 1))
print("{a[0]}".format(a=[1, 2]))
print(str(b"abc", encoding="utf8"))
,→instead
Sample code:
print("abc".ljust(10))
print("abcdefghi"[0:9:2])
3.9.10 tuple
Tuple load with step != 1 not implemented
Sample code:
print((1, 2, 3, 4)[0:4:2])
3.10 Modules
Generated Wed 19 Feb 2025 18:48:30 UTC
Example
For example, in CPython 3.4 this is the signature of the constructor socket.socket:
The / at the end of the parameters indicates that they are all positional-only in MicroPython. The following code works
in CPython but not in most MicroPython ports:
import socket
s = socket.socket(type=socket.SOCK_DGRAM)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
3.10.2 array
Comparison between different typecodes not supported
Cause: Code size
Workaround: Compare individual elements
Sample code:
import array
import array
a = array.array("b", [257])
print(a)
import array
import array
import array
3.10.3 builtins
Second argument to next() is not implemented
Cause: MicroPython is optimised for code space.
Workaround: Instead of val = next(it, deflt) use:
try:
val = next(it)
except StopIteration:
val = deflt
Sample code:
print(next(iter(range(0)), 42))
3.10.4 json
JSON module does not throw exception when object is not serialisable
Sample code:
import json
try:
print(json.dumps(b"shouldn't be able to serialise bytes"))
except TypeError:
print("TypeError")
3.10.5 os
environ attribute is not implemented
import os
import os
print(os.getenv("NEW_VARIABLE"))
os.putenv("NEW_VARIABLE", "VALUE")
print(os.getenv("NEW_VARIABLE"))
None None
None VALUE
3.10.6 random
getrandbits method can only return a maximum of 32 bits at a time.
Cause: PRNG’s internal state is only 32bits so it can only return a maximum of 32 bits of data at a time.
Workaround: If you need a number that has more than 32 bits then utilize the random module from micropython-lib.
Sample code:
import random
x = random.getrandbits(64)
print("{}".format(x))
randint method can only return an integer that is at most the native word size.
Cause: PRNG is only able to generate 32 bits of state at a time. The result is then cast into a native sized int instead of
a full int object.
Workaround: If you need integers larger than native wordsize use the random module from micropython-lib.
Sample code:
import random
x = random.randint(2**128 - 1, 2**128)
print("x={}".format(x))
3.10.7 struct
Struct pack with too few args, not checked by uPy
Sample code:
import struct
try:
print(struct.pack("bb", 1))
print("Should not get here")
except:
print("struct.error")
struct.error b'\x01\x00'
Should not get here
import struct
try:
print(struct.pack("bb", 1, 2, 3))
print("Should not get here")
except:
print("struct.error")
struct.error b'\x01\x02'
Should not get here
Struct pack with whitespace in format, whitespace ignored by CPython, error on uPy
Cause: MicroPython is optimised for code size.
Workaround: Don’t use spaces in format strings.
Sample code:
import struct
try:
print(struct.pack("b b", 1, 2))
print("Should have worked")
except:
print("struct.error")
b'\x01\x02' struct.error
Should have worked
3.10.8 sys
Overriding sys.stdin, sys.stdout and sys.stderr not possible
Cause: They are stored in read-only memory.
Sample code:
import sys
sys.stdin = None
print(sys.stdin)
FOUR
MICROPYTHON INTERNALS
This chapter covers a tour of MicroPython from the perspective of a developer, contributing to MicroPython. It acts as
a comprehensive resource on the implementation details of MicroPython for both novice and expert contributors.
Development around MicroPython usually involves modifying the core runtime, porting or maintaining a new library.
This guide describes at great depth, the implementation details of MicroPython including a getting started guide, compiler
internals, porting MicroPython to a new platform and implementing a core MicroPython library.
® Note
For a reference on the installation instructions, please refer to the Git installation instructions. Learn about the basic
git commands in this Git Handbook or any other sources on the internet.
® Note
A .git-blame-ignore-revs file is included which avoids the output of git blame getting cluttered by commits which are
only for formatting code but have no functional changes. See git blame documentation on how to use this.
337
MicroPython Documentation, Release latest
Then, configure the remote repositories to be able to collaborate on the MicroPython project.
Configure remote upstream:
$ cd micropython
$ git remote add upstream https://github.com/micropython/micropython
It is common to configure upstream and origin on a forked repository to assist with sharing code changes. You
can maintain your own mapping but it is recommended that origin maps to your fork and upstream to the main
MicroPython repository.
After the above configuration, your setup should be similar to this:
$ git remote -v
origin https://github.com/<your-user-name>/micropython (fetch)
origin https://github.com/<your-user-name>/micropython (push)
upstream https://github.com/micropython/micropython (fetch)
upstream https://github.com/micropython/micropython (push)
You should now have a copy of the source code. By default, you are pointing to the master branch. To prepare for further
development, it is recommended to work on a development branch.
You can give it any name. You will have to compile MicroPython whenever you change to a different branch.
Required dependencies
Install the required dependencies for Linux:
$ python3
Python 3.5.0 (default, Jul 17 2020, 14:04:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
All supported ports have different dependency requirements, see their respective readme files.
$ cd mpy-cross
$ make
® Note
Note that, mpy-cross must be built for the host architecture and not the target architecture.
LINK mpy-cross
text data bss dec hex filename
279328 776 880 280984 44998 mpy-cross
® Note
Use make -C mpy-cross to build the cross-compiler in one statement without moving to the mpy-cross directory
otherwise, you will need to do cd .. for the next steps.
$ gcc --version
gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.then build:
$ cd ports/unix
$ make submodules
$ make
LINK micropython
text data bss dec hex filename
412033 5680 2496 420209 66971 micropython
$ ./micropython
MicroPython v1.13-38-gc67012d-dirty on 2020-09-13; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> print("hello world")
hello world
>>>
$ cd ports/stm32
$ make submodules
$ make
Please refer to the stm32 documentation for more details on flashing the firmware.
® Note
See the Required dependencies to make sure that all dependencies are installed for this port. The cross-compiler is
needed. arm-none-eabi-gcc should also be in the $PATH or specified manually via CROSS_COMPILE, either
by setting the environment variable or in the make command line arguments.
$ cd ports/stm32
$ make BOARD=<board> submodules
$ make BOARD=<board>
$ cd docs
$ make html
Open docs/build/html/index.html in your browser to view the docs locally. Refer to the documentation on im-
porting your documentation to use Read the Docs.
$ cd ports/unix
$ make test
$ cd tests
$ ./run-tests.py -t /dev/ttyACM0
.
├── basics
├── extmod
├── float
├── micropython
├── run-tests.py
...
There are subfolders maintained to categorize the tests. Add a test by creating a new file in one of the existing folders
or in a new folder. It’s also possible to make custom tests outside this tests folder, which would be recommended for a
custom port.
For example, add the following code in a file print.py in the tests/unix/ subdirectory:
def print_one():
print(1)
print_one()
If you run your tests, this test should appear in the test output:
$ cd ports/unix
$ make tests
skip unix/extra_coverage.py
pass unix/ffi_callback.py
pass unix/ffi_float.py
pass unix/ffi_float2.py
pass unix/print.py
pass unix/time.py
pass unix/time2.py
Tests are run by comparing the output from the test target against the output from CPython. So any test should use print
statements to indicate test results.
For tests that can’t be compared to CPython (i.e. micropython-specific functionality), you can provide a .py.exp file
which will be used as the truth for comparison.
The other way to run tests, which is useful when running on targets other than the Unix port, is:
$ cd tests
$ ./run-tests.py
$ ./run-tests.py -t /dev/ttyACM0
$ ./run-tests.py -d basics
$ ./run-tests.py float/builtin*.py
>>> add1 3
4
>>>
The second argument c(add1_stmt) is the corresponding compile function that should be implemented in py/
compile.c to turn this rule into executable code.
The third required argument can be or or and. This specifies the number of nodes associated with a statement. For
example, in this case, our add1 statement is similar to ADD1 in assembly language. It takes one numeric argument.
Therefore, the add1_stmt has two nodes associated with it. One node is for the statement itself, i.e the literal add1
corresponding to KW_ADD1, and the other for its argument, a testlist rule which is the top-level expression rule.
® Note
The add1 rule here is just an example and not part of the standard MicroPython grammar.
The fourth argument in this example is the token associated with the rule, KW_ADD1. This token should be defined in the
lexer by editing py/lexer.h.
Defining the same rule without a compile function is achieved by using the DEF_RULE_NC macro and omitting the compile
function argument:
The remaining arguments take on the same meaning. A rule without a compile function must be handled explicitly by all
rules that may have this rule as a node. Such NC-rules are usually used to express sub-parts of a complicated grammar
structure that cannot be expressed in a single rule.
® Note
The macros DEF_RULE and DEF_RULE_NC take other arguments. For an in-depth understanding of supported pa-
rameters, see py/grammar.h.
Then also edit py/lexer.c to add the new keyword literal text:
Notice the keyword is named depending on what you want it to be. For consistency, maintain the naming standard
accordingly.
® Note
The order of these keywords in py/lexer.c must match the order of tokens in the enum defined in py/lexer.h.
4.3.3 Parsing
In the parsing stage the parser takes the tokens produced by the lexer and converts them to an abstract syntax tree (AST)
or parse tree. The implementation for the parser is defined in py/parse.c.
The parser also maintains a table of constants for use in different aspects of parsing, similar to what a symbol table does.
Several optimizations like constant folding on integers for most operations e.g. logical, binary, unary, etc, and optimizing
enhancements on parenthesis around expressions are performed during this phase, along with some optimizations on
strings.
It’s worth noting that docstrings are discarded and not accessible to the compiler. Even optimizations like string interning
are not applied to docstrings.
// Create and return a function object that executes the outer module.
return mp_make_function_from_proto_fun(cm.rc, cm.context, NULL);
}
The compiler compiles the code in four passes: scope, stack size, code size and emit. Each pass runs the same C code
over the same AST data structure, with different things being computed each time based on the results of the previous
pass.
First pass
In the first pass, the compiler learns about the known identifiers (variables) and their scope, being global, local, closed
over, etc. In the same pass the emitter (bytecode or native code) also computes the number of labels needed for the
emitted code.
// Compile pass 1.
comp->emit = emit_bc;
comp->emit_method_table = &emit_bc_method_table;
uint max_num_labels = 0;
for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL;␣
,→s = s->next) {
if (s->emit_options == MP_EMIT_OPT_ASM) {
compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);
} else {
compile_scope(comp, s, MP_PASS_SCOPE);
...
...
}
Just before pass two there is a selection for the type of code to be emitted, which can either be native or bytecode.
}
comp->emit_method_table = NATIVE_EMITTER_TABLE;
comp->emit = emit_native;
break;
default:
comp->emit = emit_bc;
comp->emit_method_table = &emit_bc_method_table;
break;
}
The bytecode option is the default but something unique to note for the native code option is that there is another option
via VIPER. See the Emitting native code section for more details on viper annotations.
There is also support for inline assembly code, where assembly instructions are written as Python function calls but are
emitted directly as the corresponding machine code. This assembler has only three passes (scope, code size, emit) and
uses a different implementation, not the compile_scope function. See the inline assembler tutorial for more details.
Fourth pass
The fourth pass emits the final code that can be executed, either bytecode in the virtual machine, or native code directly
by the CPU.
...
We use the unary operator expressions for an example here but the implementation details are similar for other
statements/expressions. The method emit_write_bytecode_byte() is a wrapper around the main function
emit_get_cur_to_write_bytecode() that all functions must call to emit bytecode.
}
}
The difference here is that we have to handle viper typing. Viper annotations allow us to handle more than one type of
variable. By default all variables are Python objects, but with viper a variable can also be declared as a machine-typed
variable like a native integer or pointer. Viper can be thought of as a superset of Python, where normal Python objects
are handled as usual, while native machine variables are handled in an optimised way by using direct machine instructions
for the operations. Viper typing may break Python equivalence because, for example, integers become native integers
and can overflow (unlike Python integers which extend automatically to arbitrary precision).
>>> x = 5
>>> x
5
>>> import gc
>>> gc.enable()
>>> gc.mem_alloc()
1312
>>> gc.mem_free()
2071392
>>> gc.collect()
19
>>> gc.disable()
>>>
Pointer tagging
Because pointers are word-aligned, when they are stored in an mp_obj_t the lower bits of this object handle will be zero.
For example on a 32-bit architecture the lower 2 bits will be zero:
********|********|********|******00
These bits are reserved for purposes of storing a tag. The tag stores extra information as opposed to introducing a new
field to store that information in the object, which may be inefficient. In MicroPython the tag tells if we are dealing with
a small integer, interned (small) string or a concrete object, and different semantics apply to each of these.
For small integers the mapping is this:
********|********|********|*******1
Where the asterisks hold the actual integer value. For an interned string or an immediate object (e.g. True) the layout of
the mp_obj_t value is, respectively:
********|********|********|*****010
********|********|********|*****110
While a concrete object that is none of the above takes the form:
********|********|********|******00
The stars here correspond to the address of the concrete object in memory.
+++++++++++
+ +
+ type + object header
+ +
+++++++++++
+ + object items
+ +
+ +
+++++++++++
The heap’s smallest unit of allocation is a block, which is four machine words in size (16 bytes on a 32-bit machine, 32
bytes on a 64-bit machine). Another structure also allocated on the heap tracks the allocation of objects in each block.
This structure is called a bitmap.
The bitmap tracks whether a block is “free” or “in use” and use two bits to track this state for each block.
The mark-sweep garbage collector manages the objects allocated on the heap, and also utilises the bitmap to mark objects
that are still in use. See py/gc.c for the full implementation of these details.
Allocation: heap layout
The heap is arranged such that it consists of blocks in pools. A block can have different properties:
• ATB(allocation table byte): If set, then the block is a normal block
• FREE: Free block
• HEAD: Head of a chain of blocks
• TAIL: In the tail of a chain of blocks
• MARK : Marked head block
• FTB(finaliser table byte): If set, then the block has a finaliser
® Note
This chapter describes modules implemented in py/ or core modules. See Extending MicroPython in C for details on
implementing an external module. For details on port-specific modules, see Porting MicroPython.
>>> import gc
>>> gc.enable()
>>>
MicroPython has several other builtin standard/core modules like io, array etc. Adding a new core module involves
several modifications.
First, create the C file in the py/ directory. In this example we are adding a hypothetical new module subsystem in the
file modsubsystem.c:
#include "py/builtin.h"
#include "py/runtime.h"
#if MICROPY_PY_SUBSYSTEM
// info()
static mp_obj_t py_subsystem_info(void) {
return MP_OBJ_NEW_SMALL_INT(42);
}
MP_DEFINE_CONST_FUN_OBJ_0(subsystem_info_obj, py_subsystem_info);
MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem);
#endif
The implementation includes a definition of all functions related to the module and adds the functions to the module’s global
table in mp_module_subsystem_globals_table. It also creates the module object with mp_module_subsystem.
The module is then registered with the wider system via the MP_REGISTER_MODULE macro.
After building and running the modified MicroPython, the module should now be importable:
Our info() function currently returns just a single number but can be extended to do anything. Similarly, more functions
can be added to this new module.
4.6 Optimizations
MicroPython uses several optimizations to save RAM but also ensure the efficient execution of programs. This chapter
discusses some of these optimizations.
® Note
MicroPython string interning and Maps and Dictionaries details other optimizations on strings and dictionaries.
4.6.2 Variables
MicroPython processes local and global variables differently. Global variables are stored and looked up from a global
dictionary that is allocated on the heap (note that each module has its own separate dict, so separate namespace). Local
variables on the other hand are stored on the Python value stack, which may live on the C stack or on the heap. They are
accessed directly by their offset within the Python stack, which is more efficient than a global lookup in a dict.
The length of global variable names also affects how much RAM is used as identifiers are stored in RAM. The shorter
the identifier, the less memory is used.
The other aspect is that const variables that start with an underscore are treated as proper constants and are not allocated
or added in a dictionary, hence saving some memory. These variables use const() from the MicroPython library.
Therefore:
X = const(1)
_Y = const(2)
foo(X, _Y)
Compiles to:
X = 1
foo(1, 2)
1. All files referenced in $(SRC_QSTR). This is all C code (i.e. py, extmod, ports/stm32) but not including
third-party code such as lib.
2. Additional $(QSTR_GLOBAL_DEPENDENCIES) (which includes mpconfig*.h).
Note: frozen_mpy.c (generated by mpy-tool.py) has its own QSTR generation and pool.
Some additional strings that can’t be expressed using the MP_QSTR_Foo syntax (e.g. they contain non-alphanumeric
characters) are explicitly provided in qstrdefs.h and qstrdefsport.h via the $(QSTR_DEFS) variable.
Processing happens in the following stages:
1. qstr.i.last is the concatenation of putting every single input file through the C pre-processor. This means
that any conditionally disabled code will be removed, and macros expanded. This means we don’t add strings to
the pool that won’t be used in the final firmware. Because at this stage (thanks to the NO_QSTR macro added by
QSTR_GEN_CFLAGS) there is no definition for MP_QSTR_Foo it passes through this stage unaffected. This file also
includes comments from the preprocessor that include line number information. Note that this step only uses files
that have changed, which means that qstr.i.last will only contain data from files that have changed since the
last compile.
2. qstr.split is an empty file created after running makeqstrdefs.py split on qstr.i.last. It’s just used as a
dependency to indicate that the step ran. This script outputs one file per input C file, genhdr/qstr/...file.
c.qstr, which contains only the matched QSTRs. Each QSTR is printed as Q(Foo). This step is necessary to
combine the existing files with the new data generated from the incremental update in qstr.i.last.
3. qstrdefs.collected.h is the output of concatenating genhdr/qstr/* using makeqstrdefs.py cat. This
is now the full set of MP_QSTR_Foo’s found in the code, now formatted as Q(Foo), one-per-line, with dupli-
cates. This file is only updated if the set of qstrs has changed. A hash of the QSTR data is written to another file
(qstrdefs.collected.h.hash) which allows it to track changes across builds.
4. Generate an enumeration, each entry of which maps a MP_QSTR_Foo to it’s corresponding index. It concatenates
qstrdefs.collected.h with qstrdefs*.h, then it transforms each line from Q(Foo) to "Q(Foo)" so they
pass through the preprocessor unchanged. Then the preprocessor is used to deal with any conditional compilation in
qstrdefs*.h. Then the transformation is undone back to Q(Foo), and saved as qstrdefs.preprocessed.h.
5. qstrdefs.generated.h is the output of makeqstrdata.py. For each Q(Foo) in qstrdefs.preprocessed.h
(plus some extra hard-coded ones), it outputs QDEF(MP_QSTR_Foo, (const byte*)"hash" "Foo").
Then in the main compile, two things happen with qstrdefs.generated.h:
1. In qstr.h, each QDEF becomes an entry in an enum, which makes MP_QSTR_Foo available to code and equal to
the index of that string in the QSTR table.
2. In qstr.c, the actual QSTR data table is generated as elements of the mp_qstr_const_pool->qstrs.
foo[x] = 3
Will need to create a QSTR for the value of x so it can be used by the “load attr” bytecode.
Also, when compiling Python code, identifiers and literals need to have QSTRs created. Note: only literals shorter than
10 characters become QSTRs. This is because a regular string on the heap always takes up a minimum of 16 bytes (one
GC block), whereas QSTRs allow them to be packed more efficiently into the pool.
QSTR pools (and the underlying “chunks” that store the string data) are allocated on-demand on the heap with a minimum
size.
If there is a request to fill slot 0 with 70, since the slot 0 is not empty, open addressing finds the next available slot in
the dictionary to service this request. This sequential search for an alternate location is called probing. There are several
sequence probing algorithms but MicroPython uses linear probing that is described in the next section.
The same methods i.e open addressing and linear probing are used to search for an item in a dictionary. Assume we want
to search for the data item 33. The computed hash value will be 2. Looking at slot 2 reveals 33, at this point, we return
True. Searching for 70 is quite different as there was a collision at the time of insertion. Therefore computing the hash
value is 0 which is currently holding 44. Instead of simply returning False, we perform a sequential search starting at
point 1 until the item 70 is found or we encounter a free slot. This is the general way of performing look-ups in hashes:
if (pos == start_pos) {
// search got back to starting position, so index is not in table
if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
if (avail_slot != NULL) {
// there was an available slot, so use that
set->used++;
*avail_slot = index;
return index;
} else {
// not enough room in table, rehash it
mp_set_rehash(set);
// restart the search for the new element
start_pos = pos = hash % set->alloc;
}
}
} else {
(continues on next page)
At its core, any functions and macros in header files make up the public API and can be used to access very low-level
details of MicroPython. Static inline functions in header files are fine too, such functions will be inlined in the code when
used.
Header files in the ports directory are only exposed to the functionality specific to a given port.
Your micropython.mk must add your modules source files to the SRC_USERMOD_C or SRC_USERMOD_LIB_C
variables. The former will be processed for MP_QSTR_ and MP_REGISTER_MODULE definitions, the latter will not
(e.g. helpers and library code that isn’t MicroPython-specific). These paths should include your expanded copy of
$(USERMOD_DIR), e.g.:
SRC_USERMOD_C += $(EXAMPLE_MOD_DIR)/modexample.c
SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c
Similarly, use SRC_USERMOD_CXX and SRC_USERMOD_LIB_CXX for C++ source files. If you want to include
assembly files use SRC_USERMOD_LIB_ASM.
If you have custom compiler options (like -I to add directories to search for header files), these should be added
to CFLAGS_USERMOD for C code and to CXXFLAGS_USERMOD for C++ code.
• micropython.cmake contains the CMake configuration for this module.
In micropython.cmake, you may use ${CMAKE_CURRENT_LIST_DIR} as the path to the current module.
Your micropython.cmake should define an INTERFACE library and associate your source files, compile defini-
tions and include directories with it. The library should then be linked to the usermod target.
add_library(usermod_cexample INTERFACE)
target_sources(usermod_cexample INTERFACE
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
)
target_include_directories(usermod_cexample INTERFACE
${CMAKE_CURRENT_LIST_DIR}
)
Basic example
The cexample module provides examples for a function and a class. The cexample.add_ints(a, b) function adds
two integer args together and returns the result. The cexample.Timer() type creates timers that can be used to measure
the elapsed time since the object is instantiated.
The module can be found in the MicroPython source tree in the examples directory and has a source file and a Makefile
fragment with content as described above:
micropython/
└──examples/
└──usercmodule/
└──cexample/
├── examplemodule.c
├── micropython.mk
└── micropython.cmake
Refer to the comments in these files for additional explanation. Next to the cexample module there’s also cppexample
which works in the same way but shows one way of mixing C and C++ code in MicroPython.
For example, here’s how the to build the unix port with the example modules:
cd micropython/ports/unix
make USER_C_MODULES=../../examples/usercmodule
You may need to run make clean once at the start when including new user modules in the build. The build output will
show the modules found:
...
Including User C Module from ../../examples/usercmodule/cexample
Including User C Module from ../../examples/usercmodule/cppexample
...
For a CMake-based port such as rp2, this will look a little different (note that CMake is actually invoked by make):
cd micropython/ports/rp2
make USER_C_MODULES=../../examples/usercmodule/micropython.cmake
Again, you may need to run make clean first for CMake to pick up the user modules. The CMake build output lists the
modules by name:
...
Including User C Module(s) from ../../examples/usercmodule/micropython.cmake
Found User C Module(s): usermod_cexample, usermod_cppexample
...
The contents of the top-level micropython.cmake can be used to control which modules are enabled.
For your own projects it’s more convenient to keep custom code out of the main MicroPython source tree, so a typical
project directory structure will look like this:
my_project/
├── modules/
│ ├── example1/
│ │ ├── example1.c
│ │ ├── micropython.mk
│ │ └── micropython.cmake
│ ├── example2/
│ │ ├── example2.c
│ │ ├── micropython.mk
│ │ └── micropython.cmake
│ └── micropython.cmake
└── micropython/
├──ports/
... ├──stm32/
...
When building with Make set USER_C_MODULES to the my_project/modules directory. For example, building the
stm32 port:
cd my_project/micropython/ports/stm32
make USER_C_MODULES=../../../modules
When building with CMake the top level micropython.cmake – found directly in the my_project/modules directory
– should include all of the modules you want to have available:
include(${CMAKE_CURRENT_LIST_DIR}/example1/micropython.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/example2/micropython.cmake)
cd my_project/micropython/ports/esp32
make USER_C_MODULES=../../../../modules/micropython.cmake
Note that the esp32 port needs the extra .. for relative paths due to the location of its main CMakeLists.txt file. You
can also specify absolute paths to USER_C_MODULES.
All modules specified by the USER_C_MODULES variable (either found in this directory when using Make, or added via
include when using CMake) will be compiled, but only those which are enabled will be available for importing. User
modules are usually enabled by default (this is decided by the developer of the module), in which case there is nothing
more to do than set USER_C_MODULES as described above.
If a module is not enabled by default then the corresponding C preprocessor macro must be enabled. This macro name
can be found by searching for the MP_REGISTER_MODULE line in the module’s source code (it usually appears at the end
of the main source file). This macro should be surrounded by a #if X / #endif pair, and the configuration option X must
be set to 1 using CFLAGS_EXTRA to make the module available. If there is no #if X / #endif pair then the module is
enabled by default.
For example, the examples/usercmodule/cexample module is enabled by default so has the following line in its
source code:
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule);
Alternatively, to make this module disabled by default but selectable through a preprocessor configuration option, it would
be:
#if MODULE_CEXAMPLE_ENABLED
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule);
#endif
In this case the module is enabled by adding CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1 to the make com-
mand, or editing mpconfigport.h or mpconfigboard.h to add
Note that the exact method depends on the port as they have different structures. If not done correctly it will compile but
importing will fail to find the module.
import cexample
print(cexample.add_ints(1, 3))
# should display 4
watch = Timer()
sleep_ms(1000)
print(watch.time())
# should display approximately 1000
• The Makefile contains the build configuration for the module and list the source files used to build the .mpy
module. It should define MPY_DIR as the location of the MicroPython repository (to find header files, the relevant
Makefile fragment, and the mpy_ld.py tool), MOD as the name of the module, SRC as the list of source files,
optionally specify the machine architecture via ARCH, and then include py/dynruntime.mk.
Minimal example
This section provides a fully working example of a simple module named factorial. This module provides a single
function factorial.factorial(x) which computes the factorial of the input and returns the result.
Directory layout:
factorial/
├── factorial.c
└── Makefile
// This is the entry point and is called when the module is imported
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
// This must be first, it sets up the globals dict and other things
MP_DYNRUNTIME_INIT_ENTRY
# Name of module
MOD = factorial
# Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin, rv32imc)
ARCH = x64
# Include to get the rules for compiling and linking the module
include $(MPY_DIR)/py/dynruntime.mk
$ make
Without modifying the Makefile you can specify the target architecture via:
$ make ARCH=armv7m
import factorial
print(factorial.factorial(10))
# should display 3628800
Further examples
See examples/natmod/ for further examples which show many of the available features of native .mpy modules. Such
features include:
• using multiple C source files
• including Python code alongside C code
• rodata and BSS data
• memory allocation
• use of floating point
• exception handling
• including external C libraries
$ cd ports
$ mkdir example_port
The basic MicroPython firmware is implemented in the main port file, e.g main.c:
#include "py/builtin.h"
#include "py/compile.h"
#include "py/gc.h"
#include "py/mperrno.h"
#include "py/stackctrl.h"
#include "shared/runtime/gchelper.h"
#include "shared/runtime/pyexec.h"
This configuration file contains machine-specific configurations including aspects like if different MicroPython features
should be enabled e.g. #define MICROPY_ENABLE_GC (1). Making this Setting (0) disables the feature.
Other configurations include type definitions, root pointers, board name, microcontroller name etc.
Similarly, an minimal example mphalport.h file looks like this:
#include <unistd.h>
#include "py/mpconfig.h"
These input and output functions have to be modified depending on the specific board API. This example uses the standard
input/output stream.
ports/example_port/
├── main.c
├── Makefile
├── mpconfigport.h
├── mphalport.c
└── mphalport.h
The port can now be built by running make (or otherwise, depending on your system).
If you are using the default compiler settings in the Makefile given above then this will create an executable called build/
firmware.elf which can be executed directly. To get a functional REPL you may need to first configure the terminal
to raw mode:
That should give a MicroPython REPL. You can then run commands like:
Use Ctrl-D to exit, and then run reset to reset the terminal.
#include "py/runtime.h"
MP_REGISTER_MODULE(MP_QSTR_myport, myport_module);
You will also need to edit the Makefile to add modmyport.c to the SRC_C list, and a new line adding the same file to
SRC_QSTR (so qstrs are searched for in this new file), like this:
SRC_C = \
main.c \
modmyport.c \
mphalport.c \
...
SRC_QSTR += modmyport.c
If all went correctly then, after rebuilding, you should be able to import the new module:
FIVE
371
MicroPython Documentation, Release latest
SIX
The below pinout is for PYBv1.1. You can also view pinouts for other versions of the pyboard: PYBv1.0 or
PYBLITEv1.0-AC or PYBLITEv1.0.
Below is a quick reference for the pyboard. If it is your first time working with this board please consider reading the
following sections first:
373
MicroPython Documentation, Release latest
Contents
If your filesystem becomes corrupt, boot into mode 3 to fix it. If resetting the filesystem while plugged into your compute
doesn’t work, you can try doing the same procedure while the board is plugged into a USB charger, or other USB power
supply without data connection.
When the pyboard is connected to your PC it will power on and enter the start up process (the boot process). The green
LED should light up for half a second or less, and when it turns off it means the boot process has completed.
Editing main.py
Now we are going to write our Python program, so open the main.py file in a text editor. On Windows you can use
notepad, or any other editor. On Mac and Linux, use your favourite text editor. With the file open you will see it contains
1 line:
This line starts with a # character, which means that it is a comment. Such lines will not do anything, and are there for
you to write notes about your program.
Let’s add 2 lines to this main.py file, to make it look like this:
The first line we wrote says that we want to use the pyb module. This module contains all the functions and classes to
control the features of the pyboard.
The second line that we wrote turns the blue LED on: it first gets the LED class from the pyb module, creates LED number
4 (the blue LED), and then turns it on.
Windows
You need to install the pyboard driver to use the serial USB device. The driver is on the pyboard’s USB flash drive, and
is called pybcdc.inf.
To install this driver you need to go to Device Manager for your computer, find the pyboard in the list of devices (it should
have a warning sign next to it because it’s not working yet), right click on the pyboard device, select Properties, then Install
Driver. You need to then select the option to find the driver manually (don’t use Windows auto update), navigate to the
pyboard’s USB drive, and select that. It should then install. After installing, go back to the Device Manager to find the
installed pyboard, and see which COM port it is (eg COM4). More comprehensive instructions can be found in the Guide
for pyboard on Windows (PDF). Please consult this guide if you are having problems installing the driver.
You now need to run your terminal program. You can use HyperTerminal if you have it installed, or download the free
program PuTTY: putty.exe. Using your serial program you must connect to the COM port that you found in the previous
step. With PuTTY, click on “Session” in the left-hand panel, then click the “Serial” radio button on the right, then enter
you COM port (eg COM4) in the “Serial Line” box. Finally, click the “Open” button.
Mac OS X
Open a terminal and run:
screen /dev/tty.usbmodem*
When you are finished and want to exit screen, type CTRL-A CTRL-\.
Linux
Open a terminal and run:
screen /dev/ttyACM0
You can also try picocom or minicom instead of screen. You may have to use /dev/ttyACM1 or a higher number for
ttyACM. And, you may need to give yourself the correct permissions to access this devices (eg group uucp or dialout,
or use sudo).
In the above, you should not type in the >>> characters. They are there to indicate that you should type the text after it at
the prompt. In the end, once you have entered the text print("hello pyboard!") and pressed Enter, the output on
your screen should look like it does above.
If you already know some python you can now try some basic commands here.
If any of this is not working you can try either a hard reset or a soft reset; see below.
Go ahead and try typing in some other commands. For example:
>>> pyb.LED(1).on()
>>> pyb.LED(2).on()
>>> 1 + 2
3
>>> 1 / 2
0.5
>>> 20 * 'py'
'pypypypypypypypypypypypypypypypypypypypy'
>>>
MPY: sync filesystems
MPY: soft reboot
Micro Python v1.0 on 2014-05-03; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>>
If that isn’t working you can perform a hard reset (turn-it-off-and-on-again) by pressing the RST switch (the small black
button closest to the micro-USB socket on the board). This will end your session, disconnecting whatever program
(PuTTY, screen, etc) that you used to connect to the pyboard.
If you are going to do a hard-reset, it’s recommended to first close your serial program and eject/unmount the pyboard
drive.
led = pyb.LED(2)
while True:
led.toggle()
pyb.delay(1000)
When you save, the red light on the pyboard should turn on for about a second. To run the script, do a soft reset (CTRL-
D). The pyboard will then restart and you should see a green light continuously flashing on and off. Success, the first step
on your path to building an army of evil robots! When you are bored of the annoying flashing light then press CTRL-C
at your terminal to stop it running.
So what does this code do? First we need some terminology. Python is an object-oriented language, almost everything in
python is a class and when you create an instance of a class you get an object. Classes have methods associated to them.
A method (also called a member function) is used to interact with or control the object.
The first line of code creates an LED object which we have then called led. When we create the object, it takes a single
parameter which must be between 1 and 4, corresponding to the 4 LEDs on the board. The pyb.LED class has three
important member functions that we will use: on(), off() and toggle(). The other function that we use is pyb.delay() this
simply waits for a given time in milliseconds. Once we have created the LED object, the statement while True: creates
an infinite loop which toggles the led between on and off and waits for 1 second.
Exercise: Try changing the time between toggling the led and turning on a different LED.
Exercise: Connect to the pyboard directly, create a pyb.LED object and turn it on using the on() method.
If you call pyb.LED() with a number that isn’t 1,2,3,4 you will get an error message. Next we will set up an infinite loop
that cycles through each of the LEDs turning them on and off.
n = 0
while True:
n = (n + 1) % 4
leds[n].toggle()
pyb.delay(50)
Here, n keeps track of the current LED and every time the loop is executed we cycle to the next n (the % sign is a modulus
operator that keeps n between 0 and 3.) Then we access the nth LED and toggle it. If you run this you should see each of
the LEDs turning on then all turning off again in sequence.
One problem you might find is that if you stop the script and then start it again that the LEDs are stuck on from the
previous run, ruining our carefully choreographed disco. We can fix this by turning all the LEDs off when we initialise
the script and then using a try/finally block. When you press CTRL-C, MicroPython generates a VCPInterrupt exception.
Exceptions normally mean something has gone wrong and you can use a try: command to “catch” an exception. In this
case it is just the user interrupting the script, so we don’t need to catch the error but just tell MicroPython what to do
when we exit. The finally block does this, and we use it to make sure all the LEDs are off. The full code is:
n = 0
try:
while True:
n = (n + 1) % 4
leds[n].toggle()
pyb.delay(50)
finally:
for l in leds:
l.off()
led = pyb.LED(4)
intensity = 0
while True:
intensity = (intensity + 1) % 255
led.intensity(intensity)
pyb.delay(20)
You can call intensity() on LEDs 1 and 2 but they can only be off or on. 0 sets them off and any other number up to 255
turns them on.
>>> sw = pyb.Switch()
Remember that you may need to type import pyb if you get an error that the name pyb does not exist.
With the switch object you can get its status:
>>> sw.value()
False
This will print False if the switch is not held, or True if it is held. Try holding the USR switch down while running the
above command.
There is also a shorthand notation to get the switch status, by “calling” the switch object:
>>> sw()
False
Switch callbacks
The switch is a very simple object, but it does have one advanced feature: the sw.callback() function. The callback
function sets up something to run when the switch is pressed, and uses an interrupt. It’s probably best to start with an
example before understanding how interrupts work. Try running the following at the prompt:
>>> sw.callback(lambda:print('press!'))
This tells the switch to print press! each time the switch is pressed down. Go ahead and try it: press the USR switch and
watch the output on your PC. Note that this print will interrupt anything you are typing, and is an example of an interrupt
routine running asynchronously.
As another example try:
>>> sw.callback(lambda:pyb.LED(1).toggle())
This will toggle the red LED each time the switch is pressed. And it will even work while other code is running.
To disable the switch callback, pass None to the callback function:
>>> sw.callback(None)
You can pass any function (that takes zero arguments) to the switch callback. Above we used the lambda feature of
Python to create an anonymous function on the fly. But we could equally do:
This creates a function called f and assigns it to the switch callback. You can do things this way when your function is
more complicated than a lambda will allow.
Note that your callback functions must not allocate any memory (for example they cannot create a tuple or list). Callback
functions should be relatively simple. If you need to make a list, make it beforehand and store it in a global variable (or
make it local and close over it). If you need to do a long, complicated calculation, then use the callback to set a flag which
some other code then responds to.
The above sequence of events gets a bit more complicated when multiple interrupts occur at the same time. In that case,
the interrupt with the highest priority goes first, then the others in order of their priority. The switch interrupt is set at the
lowest priority.
Further reading
For further information about using hardware interrupts see writing interrupt handlers.
This returns a signed integer with a value between around -30 and 30. Note that the measurement is very noisy, this means
that even if you keep the board perfectly still there will be some variation in the number that you measure. Because of
this, you shouldn’t use the exact value of the x() method but see if it is in a certain range.
We will start by using the accelerometer to turn on a light if it is not flat.
accel = pyb.Accel()
light = pyb.LED(3)
SENSITIVITY = 3
while True:
x = accel.x()
if abs(x) > SENSITIVITY:
light.on()
else:
light.off()
pyb.delay(100)
We create Accel and LED objects, then get the value of the x direction of the accelerometer. If the magnitude of x is
bigger than a certain value SENSITIVITY, then the LED turns on, otherwise it turns off. The loop has a small pyb.
delay() otherwise the LED flashes annoyingly when the value of x is close to SENSITIVITY. Try running this on the
pyboard and tilt the board left and right to make the LED turn on and off.
Exercise: Change the above script so that the blue LED gets brighter the more you tilt the pyboard. HINT: You
will need to rescale the values, intensity goes from 0-255.
accel = pyb.Accel()
SENSITIVITY = 3
while True:
x = accel.x()
if x > SENSITIVITY:
xlights[0].on()
xlights[1].off()
elif x < -SENSITIVITY:
xlights[1].on()
xlights[0].off()
else:
xlights[0].off()
xlights[1].off()
y = accel.y()
if y > SENSITIVITY:
ylights[0].on()
ylights[1].off()
elif y < -SENSITIVITY:
ylights[1].on()
ylights[0].off()
else:
ylights[0].off()
ylights[1].off()
pyb.delay(100)
We start by creating a tuple of LED objects for the x and y directions. Tuples are immutable objects in python which
means they can’t be modified once they are created. We then proceed as before but turn on a different LED for positive
and negative x values. We then do the same for the y direction. This isn’t particularly sophisticated but it does the job.
Run this on your pyboard and you should see different LEDs turning on depending on how you tilt the board.
Safe mode
To enter safe mode, do the following steps:
1. Connect the pyboard to USB so it powers up.
2. Hold down the USR switch.
3. While still holding down USR, press and release the RST switch.
4. The LEDs will then cycle green to orange to green+orange and back again.
5. Keep holding down USR until only the orange LED is lit, and then let go of the USR switch.
6. The orange LED should flash quickly 4 times, and then turn off.
7. You are now in safe mode.
In safe mode, the boot.py and main.py files are not executed, and so the pyboard boots up with default settings. This
means you now have access to the filesystem (the USB drive should appear), and you can edit boot.py and main.py to
fix any problems.
Entering safe mode is temporary, and does not make any changes to the files on the pyboard.
Resetting the filesystem deletes all files on the internal pyboard storage (not the SD card), and restores the files boot.py,
main.py, README.txt and pybcdc.inf back to their original state.
To do a factory reset of the filesystem you follow a similar procedure as you did to enter safe mode, but release USR on
green+orange:
1. Connect the pyboard to USB so it powers up.
2. Hold down the USR switch.
3. While still holding down USR, press and release the RST switch.
4. The LEDs will then cycle green to orange to green+orange and back again.
5. Keep holding down USR until both the green and orange LEDs are lit, and then let go of the USR switch.
6. The green and orange LEDs should flash quickly 4 times.
7. The red LED will turn on (so red, green and orange are now on).
8. The pyboard is now resetting the filesystem (this takes a few seconds).
9. The LEDs all turn off.
10. You now have a reset filesystem, and are in safe mode.
11. Press and release the RST switch to boot normally.
import pyb
#pyb.main('main.py') # main script to run after this one
#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
To enable the mouse mode, uncomment the last line of the file, to make it look like:
If you already changed your boot.py file, then the minimum code it needs to work is:
import pyb
pyb.usb_mode('VCP+HID')
This tells the pyboard to configure itself as a VCP (Virtual COM Port, ie serial port) and HID (human interface device,
in our case a mouse) USB device when it boots up.
Eject/unmount the pyboard drive and reset it using the RST switch. Your PC should now detect the pyboard as a mouse!
Your mouse should move 100 pixels to the right! In the command above you are sending 4 pieces of information: button
status, x-direction, y-direction, and scroll. The number 100 is telling the PC that the mouse moved 100 pixels in the x
direction.
Let’s make the mouse oscillate left and right:
The first argument to the function osc is the number of mouse events to send, and the second argument is the delay (in
milliseconds) between events. Try playing around with different numbers.
Exercise: make the mouse go around in a circle.
4. Keep holding down USR until only the orange LED is lit, and then let go of the USR switch.
5. The orange LED should flash quickly 4 times, and then turn off.
6. You are now in safe mode.
In safe mode, the boot.py and main.py files are not executed, and so the pyboard boots up with default settings. This
means you now have access to the filesystem (the USB drive should appear), and you can edit main.py. (Leave boot.py
as-is, because we still want to go back to HID-mode after we finish editing main.py.)
In main.py put the following code:
import pyb
switch = pyb.Switch()
accel = pyb.Accel()
hid = pyb.USB_HID()
Save your file, eject/unmount your pyboard drive, and reset it using the RST switch. It should now act as a mouse, and
the angle of the board will move the mouse around. Try it out, and see if you can make the mouse stand still!
Press the USR switch to stop the mouse motion.
You’ll note that the y-axis is inverted. That’s easy to fix: just put a minus sign in front of the y-coordinate in the hid.
send() line above.
Save your file, eject/unmount the drive, and reset the pyboard. It is now back to normal operating mode.
>>> tim
Timer(4)
The pyboard is telling us that tim is attached to timer number 4, but it’s not yet initialised. So let’s initialise it to trigger
at 10 Hz (that’s 10 times per second):
>>> tim.init(freq=10)
Now that it’s initialised, we can see some information about the timer:
>>> tim
Timer(4, prescaler=624, period=13439, mode=UP, div=1)
The information means that this timer is set to run at the peripheral clock speed divided by 624+1, and it will count from
0 up to 13439, at which point it triggers an interrupt, and then starts counting again from 0. These numbers are set to
make the timer trigger at 10 Hz: the source frequency of the timer is 84MHz (found by running tim.source_freq())
so we get 84MHz / 625 / 13440 = 10Hz.
Timer counter
So what can we do with our timer? The most basic thing is to get the current value of its counter:
>>> tim.counter()
21504
Timer callbacks
The next thing we can do is register a callback function for the timer to execute when it triggers (see the switch tutorial
for an introduction to callback functions):
This should start the red LED flashing right away. It will be flashing at 5 Hz (2 toggle’s are needed for 1 flash, so toggling
at 10 Hz makes it flash at 5 Hz). You can change the frequency by re-initialising the timer:
>>> tim.init(freq=20)
>>> tim.callback(None)
The function that you pass to callback must take 1 argument, which is the timer object that triggered. This allows you to
control the timer from within the callback function.
We can create 2 timers and run them independently:
Because the callbacks are proper hardware interrupts, we can continue to use the pyboard for other things while these
timers are running.
The prescaler is set at 83, which makes this timer count at 1 MHz. This is because the CPU clock, running at 168 MHz,
is divided by 2 and then by prescaler+1, giving a frequency of 168 MHz/2/(83+1)=1 MHz for timer 2. The period is set
to a large number so that the timer can count up to a large number before wrapping back around to zero. In this case it
will take about 17 minutes before it cycles back to zero.
To use this timer, it’s best to first reset it to 0:
>>> micros.counter(0)
Returning a value
Inline assembler functions are denoted by a special function decorator. Let’s start with the simplest example:
@micropython.asm_thumb
def fun():
movw(r0, 42)
You can enter this in a script or at the REPL. This function takes no arguments and returns the number 42. r0 is a register,
and the value in this register when the function returns is the value that is returned. MicroPython always interprets the r0
as an integer, and converts it to an integer object for the caller.
If you run print(fun()) you will see it print out 42.
Accessing peripherals
For something a bit more complicated, let’s turn on an LED:
@micropython.asm_thumb
def led_on():
movwt(r0, stm.GPIOA)
movw(r1, 1 << 13)
strh(r1, [r0, stm.GPIO_BSRRL])
• stm.GPIOA is the address in memory of the GPIOA peripheral. On the pyboard, the red LED is on port A, pin
PA13.
• movwt moves a 32-bit number into a register. It is a convenience function that turns into 2 thumb instructions:
movw followed by movt. The movt also shifts the immediate value right by 16 bits.
• strh stores a half-word (16 bits). The instruction above stores the lower 16-bits of r1 into the memory location
r0 + stm.GPIO_BSRRL. This has the effect of setting high all those pins on port A for which the corresponding
bit in r0 is set. In our example above, the 13th bit in r0 is set, so PA13 is pulled high. This turns on the red LED.
Accepting arguments
Inline assembler functions can accept up to 4 arguments. If they are used, they must be named r0, r1, r2 and r3 to
reflect the registers and the calling conventions.
Here is a function that adds its arguments:
@micropython.asm_thumb
def asm_add(r0, r1):
add(r0, r0, r1)
This performs the computation r0 = r0 + r1. Since the result is put in r0, that is what is returned. Try asm_add(1,
2), it should return 3.
Loops
We can assign labels with label(my_label), and branch to them using b(my_label), or a conditional branch like
bgt(my_label).
@micropython.asm_thumb
def flash_led(r0):
# get the GPIOA address in r1
movwt(r1, stm.GPIOA)
# get the bit mask for PA14 (the pin LED #2 is on)
movw(r2, 1 << 14)
b(loop_entry)
label(loop1)
# turn LED on
strh(r2, [r1, stm.GPIO_BSRRL])
# loop r0 times
sub(r0, r0, 1)
label(loop_entry)
cmp(r0, 0)
bgt(loop1)
Further reading
For further information about supported instructions of the inline assembler, see the reference documentation.
while True:
do_some_processing()
pyb.wfi()
In this picture there are male-male double adaptors to connect the servos to the header pins on the pyboard.
The ground wire on a servo is usually the darkest coloured one, either black or dark brown. The power wire will most
likely be red.
The power pin for the servos (labelled VIN) is connected directly to the input power source of the pyboard. When powered
via USB, VIN is powered through a diode by the 5V USB power line. Connect to USB, the pyboard can power at least 4
small to medium sized servo motors.
If using a battery to power the pyboard and run servo motors, make sure it is not greater than 6V, since this is the maximum
voltage most servo motors can take. (Some motors take only up to 4.8V, so check what type you are using.)
Plug in a servo to position 1 (the one with pin X1) and create a servo object using:
>>> servo1.angle(45)
>>> servo1.angle(-60)
The angle here is measured in degrees, and ranges from about -90 to +90, depending on the motor. Calling angle without
parameters will return the current angle:
>>> servo1.angle()
-60
Note that for some angles, the returned angle is not exactly the same as the angle you set, due to rounding errors in setting
the pulse width.
You can pass a second parameter to the angle method, which specifies how long to take (in milliseconds) to reach the
desired angle. For example, to take 1 second (1000 milliseconds) to go from the current position to 50 degrees, use
This command will return straight away and the servo will continue to move to the desired angle, and stop when it gets
there. You can use this feature as a speed control, or to synchronise 2 or more servo motors. If we have another servo
motor (servo2 = pyb.Servo(2)) then we can do
This will move the servos together, making them both take 2 seconds to reach their final angles.
Note: the semicolon between the 2 expressions above is used so that they are executed one after the other when you press
enter at the REPL prompt. In a script you don’t need to do this, you can just write them one line after the other.
So far we have been using standard servos that move to a specific angle and stay at that angle. These servo motors are useful
to create joints of a robot, or things like pan-tilt mechanisms. Internally, the motor has a variable resistor (potentiometer)
which measures the current angle and applies power to the motor proportional to how far it is from the desired angle. The
desired angle is set by the width of a high-pulse on the servo signal wire. A pulse width of 1500 microsecond corresponds
to the centre position (0 degrees). The pulses are sent at 50 Hz, ie 50 pulses per second.
You can also get continuous rotation servo motors which turn continuously clockwise or counterclockwise. The direction
and speed of rotation is set by the pulse width on the signal wire. A pulse width of 1500 microseconds corresponds to a
stopped motor. A pulse width smaller or larger than this means rotate one way or the other, at a given speed.
On the pyboard, the servo object for a continuous rotation motor is the same as before. In fact, using angle you can set
the speed. But to make it easier to understand what is intended, there is another method called speed which sets the
speed:
>>> servo1.speed(30)
speed has the same functionality as angle: you can get the speed, set it, and set it with a time to reach the final speed.
>>> servo1.speed()
30
>>> servo1.speed(-20)
>>> servo1.speed(0, 2000)
The final command above will set the motor to stop, but take 2 seconds to do it. This is essentially a control over the
acceleration of the continuous servo.
A servo speed of 100 (or -100) is considered maximum speed, but actually you can go a bit faster than that, depending
on the particular motor.
The only difference between the angle and speed methods (apart from the name) is the way the input numbers (angle
or speed) are converted to a pulse width.
Calibration
The conversion from angle or speed to pulse width is done by the servo object using its calibration values. To get the
current calibration, use
>>> servo1.calibration()
(640, 2420, 1500, 2470, 2200)
Of course, you would change the above values to suit your particular servo motor.
Fading LEDs
In addition to turning LEDs on and off, it is also possible to control the brightness of an LED using Pulse-Width Modu-
lation (PWM), a common technique for obtaining variable output from a digital pin. This allows us to fade an LED:
Components
Connecting Things Up
For this tutorial, we will use the X1 pin. Connect one end of the resistor to X1, and the other end to the anode of the
LED, which is the longer leg. Connect the cathode of the LED to ground.
Code
By examining the Quick reference for the pyboard, we see that X1 is connected to channel 1 of timer 5 (TIM5 CH1).
Therefore we will first create a Timer object for timer 5, then create a TimerChannel object for channel 1:
Brightness of the LED in PWM is controlled by controlling the pulse-width, that is the amount of time the LED is on
every cycle. With a timer frequency of 100 Hz, each cycle takes 0.01 second, or 10 ms.
To achieve the fading effect shown at the beginning of this tutorial, we want to set the pulse-width to a small value, then
slowly increase the pulse-width to brighten the LED, and start over when we reach some maximum brightness:
while True:
tchannel.pulse_width(cur_width)
cur_width += wstep
Breathing Effect
If we want to have a breathing effect, where the LED fades from dim to bright then bright to dim, then we simply need to
reverse the sign of wstep when we reach maximum brightness, and reverse it again at minimum brightness. To do this
we modify the while loop to be:
while True:
tchannel.pulse_width(cur_width)
sleep(0.01)
cur_width += wstep
Advanced Exercise
You may have noticed that the LED brightness seems to fade slowly, but increases quickly. This is because our eyes
interprets brightness logarithmically (Weber’s Law ), while the LED’s brightness changes linearly, that is by the same
amount each time. How do you solve this problem? (Hint: what is the opposite of the logarithmic function?)
Addendum
We could have also used the digital-to-analog converter (DAC) to achieve the same effect. The PWM method has the
advantage that it drives the LED with the same current each time, but for different lengths of time. This allows better
control over the brightness, because LEDs do not necessarily exhibit a linear relationship between the driving current and
brightness.
The following video shows how to solder the headers onto the LCD skin. At the end of the video, it shows you how to
correctly connect the LCD skin to the pyboard.
For circuit schematics and datasheets for the components on the skin see The pyboard hardware.
To get started using the LCD, try the following at the MicroPython prompt. Make sure the LCD skin is attached to the
pyboard as pictured at the top of this page.
import pyb
lcd = pyb.LCD('X')
lcd.light(True)
(continues on next page)
To read the touch-sensor data you need to use the I2C bus. The MPR121 capacitive touch sensor has address 90.
To get started, try:
The first line above makes an I2C object, and the second line enables the 4 touch sensors. The third line reads the touch
status and the touch variable holds the state of the 4 touch buttons (A, B, X, Y).
There is a simple driver here which allows you to set the threshold and debounce parameters, and easily read the touch
status and electrode voltage levels. Copy this script to your pyboard (either flash or SD card, in the top directory or lib/
directory) and then try:
This will continuously print out the touch status of all electrodes. Try touching each one in turn.
Note that if you put the LCD skin in the Y-position, then you need to initialise the I2C bus using:
There is also a demo which uses the LCD and the touch sensors together, and can be found here.
The following video shows how to solder the headers, microphone and speaker onto the AMP skin.
For circuit schematics and datasheets for the components on the skin see The pyboard hardware.
Example code
The AMP skin has a speaker which is connected to DAC(1) via a small power amplifier. The volume of the amplifier is
controlled by a digital potentiometer, which is an I2C device with address 46 on the IC2(1) bus.
To set the volume, define the following function:
import pyb
def volume(val):
pyb.I2C(1, pyb.I2C.CONTROLLER).mem_write(val, 46, 0)
To play a sound, use the write_timed method of the DAC object. For example:
import math
from pyb import DAC
You can also play WAV files using the Python wave module. You can get the wave module here and you will also need
the chunk module available here. Put these on your pyboard (either on the flash or the SD card in the top-level directory).
You will need an 8-bit WAV file to play, such as this one, or to convert any file you have with the command:
This should play the WAV file. Note that this will read the whole file into RAM so it has to be small enough to fit in it.
To play larger wave files you will have to use the micro-SD card to store it. Also the file must be read and sent to the
DAC in small chunks that will fit the RAM limit of the microcontroller. Here is an example function that can play 8-bit
wave files with up to 16kHz sampling:
import wave
from pyb import DAC
from pyb import delay
dac = DAC(1)
def play(filename):
f = wave.open(filename, 'r')
total_frames = f.getnframes()
framerate = f.getframerate()
This function reads one second worth of data and sends it to DAC. It then waits one second and moves the file cursor to
the new position to read the next second of data in the next iteration of the for-loop. It plays one second of audio at a
time every one second.
For detailed documentation of the driver for the display see the lcd160cr module.
The display can be plugged directly into a pyboard (all pyboard versions are supported). You plug the display onto the
top of the pyboard either in the X or Y positions. The display should cover half of the pyboard. See the picture above for
how to achieve this; the left half of the picture shows the X position, and the right half shows the Y position.
You can control the display directly using a power/enable pin and an I2C bus, but it is much more convenient to use the
driver provided by the lcd160cr module. This driver is included in recent version of the pyboard firmware (see here).
You can also find the driver in the GitHub repository here, and to use this version you will need to copy the file to your
board, into a directory that is searched by import (usually the lib/ directory).
Once you have the driver installed you need to import it to use it:
import lcd160cr
There is a test program which you can use to test the features of the display, and which also serves as a basis to start
creating your own code that uses the LCD. This test program is available on GitHub here. Copy it to the board over USB
mass storage, or by using MicroPython remote control: mpremote.
It will then print some brief instructions. You will need to know which position your display is connected to (X or Y) and
then you can run (assuming you have the display on position X):
>>> test_all('X')
You must first create an LCD160CR object which will control the display. Do this using:
This assumes your display is connected in the X position. If it’s in the Y position then use lcd = lcd160cr.
LCD160CR('Y') instead.
The next example draws random rectangles on the screen. You can copy-and-paste it into the MicroPython prompt by
first pressing “Ctrl-E” at the prompt, then “Ctrl-D” once you have pasted the text.
The display includes a resistive touch sensor that can report the position (in pixels) of a single force-based touch on the
screen. To see if there is a touch on the screen use:
>>> lcd.is_touched()
This will return either False or True. Run the above command while touching the screen to see the result.
To get the location of the touch you can use the method:
>>> lcd.get_touch()
This will return a 3-tuple, with the first entry being 0 or 1 depending on whether there is currently anything touching the
screen (1 if there is), and the second and third entries in the tuple being the x and y coordinates of the current (or most
recent) touch.
The display supports input from a UART and implements basic VT100 commands, which means it can be used as a
simple, general purpose terminal. Let’s set up the pyboard to redirect its output to the display.
First you need to create a UART object:
This assumes your display is connected to position X. If it’s on position Y then use uart = pyb.UART('YA', 115200)
instead.
Now, connect the REPL output to this UART:
>>> pyb.repl_uart(uart)
From now on anything you type at the MicroPython prompt, and any output you receive, will appear on the display.
No set-up commands are required for this mode to work and you can use the display to monitor the output of any UART,
not just from the pyboard. All that is needed is for the display to have power, ground and the power/enable pin driven
high. Then any characters on the display’s UART input will be printed to the screen. You can adjust the UART baudrate
from the default of 115200 using the set_uart_baudrate method.
import pyb
def wait_pin_change(pin):
# wait for pin to change value
# it needs to be stable for a continuous 20ms
cur_value = pin.value()
active = 0
while active < 20:
if pin.value() != cur_value:
active += 1
else:
active = 0
pyb.delay(1)
import pyb
import pyb
import select
import pyb
import time
sw = Switch()
sw.value() # returns True or False
sw.callback(lambda: pyb.LED(1).toggle())
6.10 Timers
See pyb.Timer.
rtc = RTC()
rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
# time, eg. 2017/8/23 1:12:48
# the day-of-week value is ignored
rtc.datetime() # get date and time
dac = DAC(Pin('X5'))
dac.write(120) # output between 0 and 255
The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged.
Based on this feedback, the I2S class API and implementation may be changed.
PYBv1.0/v1.1 has one I2S bus with id=2. PYBD-SFxW has two I2S buses with id=1 and id=2. I2S is shared with SPI.
accel = Accel()
print(accel.x(), accel.y(), accel.z(), accel.tilt())
SEVEN
411
MicroPython Documentation, Release latest
• GPIO pin numbering is based on ESP8266 chip numbering, not some “logical” numbering of a particular board.
Please have the manual/pin diagram of your board at hand to find correspondence between your board pins and
actual ESP8266 pins. We also encourage users of various boards to share this mapping via MicroPython forum,
with the idea to collect community-maintained reference materials eventually.
• All pins which make sense to support, are supported by MicroPython (for example, pins which are used to connect
SPI flash are not exposed, as they’re unlikely useful for anything else, and operating on them will lead to board
lock-up). However, any particular board may expose only subset of pins. Consult your board reference manual.
• Some boards may lack external pins/internal connectivity to support ESP8266 deepsleep mode.
Real-time clock
RTC in ESP8266 has very bad accuracy, drift may be seconds per minute. As a workaround, to measure short enough
intervals you can use time.time(), etc. functions, and for wall clock time, synchronize from the net using included
ntptime.py module.
Due to limitations of the ESP8266 chip the internal real-time clock (RTC) will overflow every 7:45h. If a long-term
working RTC time is required then time() or localtime() must be called at least once within 7 hours. MicroPython
will then handle the overflow.
sock = socket(...)
try:
# Use sock
finally:
sock.close()
SSL/TLS limitations
ESP8266 uses axTLS library, which is one of the smallest TLS libraries with compatible licensing. However, it also has
some known issues/limitations:
1. No support for Diffie-Hellman (DH) key exchange and Elliptic-curve cryptography (ECC). This means it can’t
work with sites which require the use of these features (it works ok with the typical sites that use RSA certificates).
2. Half-duplex communication nature. axTLS uses a single buffer for both sending and receiving, which leads to
considerable memory saving and works well with protocols like HTTP. But there may be problems with protocols
which don’t follow classic request-response model.
Besides axTLS’s own limitations, the configuration used for MicroPython is highly optimized for code size, which leads
to additional limitations (these may be lifted in the future):
3. Optimized RSA algorithms are not enabled, which may lead to slow SSL handshakes.
4. Session Reuse is not enabled, which means every connection must undergo the full, expensive SSL handshake.
Besides axTLS specific limitations described above, there’s another generic limitation with usage of TLS on the low-
memory devices:
5. The TLS standard specifies the maximum length of the TLS record (unit of TLS communication, the entire record
must be buffered before it can be processed) as 16KB. That’s almost half of the available ESP8266 memory, and
inside a more or less advanced application would be hard to allocate due to memory fragmentation issues. As a
compromise, a smaller buffer is used, with the idea that the most interesting usage for SSL would be accessing
various REST APIs, which usually require much smaller messages. The buffers size is on the order of 5KB, and
is adjusted from time to time, taking as a reference being able to access https://google.com . The smaller buffer
however means that some sites can’t be accessed using it, and it’s not possible to stream large amounts of data.
axTLS does have support for TLS’s Max Fragment Size extension, but no HTTPS website does, so use of the
extension is really only effective for local communication with other devices.
There are also some not implemented features specifically in MicroPython’s ssl module based on axTLS:
6. Certificates are not validated (this makes connections susceptible to man-in-the-middle attacks).
7. There is no support for client certificates (scheduled to be fixed in 1.9.4 release).
Requirements
The first thing you need is a board with an ESP8266 chip. The MicroPython software supports the ESP8266 chip itself
and any board should work. The main characteristic of a board is how much flash it has, how the GPIO pins are connected
to the outside world, and whether it includes a built-in USB-serial converter to make the UART available to your PC.
The minimum requirement for flash size is 1Mbyte. There is also a special build for boards with 512KB, but it is highly
limited comparing to the normal build: there is no support for filesystem, and thus features which depend on it won’t work
(WebREPL, mip, etc.). As such, 512KB build will be more interesting for users who build from source and fine-tune
parameters for their particular application.
Names of pins will be given in this tutorial using the chip names (eg GPIO0) and it should be straightforward to find
which pin this corresponds to on your particular board.
Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer). An older version (at least 1.2.1 is needed)
works fine but will require Python 2.7.
Any other flashing program should work, so feel free to try them out or refer to the documentation for your board to see
its recommendations.
Using esptool.py you can erase the flash with the command:
You might need to change the “port” setting to something else relevant for your PC. You may also need to reduce the
baudrate if you get errors when flashing (eg down to 115200). The filename of the firmware should also match the file
that you have.
For some boards with a particular FlashROM configuration (e.g. some variants of a NodeMCU board) you may need to
manually set a compatible SPI Flash Mode. You’d usually pick the fastest option that is compatible with your device, but
the -fm dout option (the slowest option) should have the best compatibility:
If the above commands run without error then MicroPython should be installed on your board!
If you pulled GPIO0 manually to ground to enter programming mode, release it now and reset the device by again pulling
the reset pin to ground for a short duration.
Serial prompt
Once you have the firmware on the device you can access the REPL (Python prompt) over UART0 (GPIO1=TX,
GPIO3=RX), which might be connected to a USB-serial converter, depending on your board. The baudrate is 115200.
The next part of the tutorial will discuss the prompt in more detail.
WiFi
After a fresh install and boot the device configures itself as a WiFi access point (AP) that you can connect to. The ESSID
is of the form MicroPython-xxxxxx where the x’s are replaced with part of the MAC address of your device (so will
be the same every time, and most likely different for all ESP8266 chips). The password for the WiFi is micropythoN
(note the upper-case N). Its IP address will be 192.168.4.1 once you connect to its network. WiFi configuration will be
discussed in more detail later in the tutorial.
This version doesn’t support --flash_size=detect option, so you will need to specify FlashROM size explicitly
(in megabits). It also requires Python 2.7, so you may need to use pip2 instead of pip in the command above.
• The --flash_size option in the commands above is mandatory. Omitting it will lead to a corrupted firmware.
• To catch incorrect flash content (e.g. from a defective sector on a chip), add --verify switch to the commands
above.
• Additionally, you can check the firmware integrity from a MicroPython REPL prompt (assuming you were able to
flash it and --verify option doesn’t report errors):
import esp
esp.check_fw()
If the last output value is True, the firmware is OK. Otherwise, it’s corrupted and need to be reflashed correctly.
• If you experience any issues with another flashing application (not esptool.py), try esptool.py, it is a generally
accepted flashing application in the ESP8266 community.
• If you still experience problems with even flashing the firmware, please refer to esptool.py project page, https:
//github.com/espressif/esptool for additional documentation and bug tracker where you can report problems.
• If you are able to flash firmware, but --verify option or esp.check_fw() return errors even after multiple
retries, you may have a defective FlashROM chip, as explained above.
Once you have made the connection over the serial port you can test if it is working by hitting enter a few times. You
should see the Python REPL prompt, indicated by >>>.
import webrepl_setup
Follow the on-screen instructions and prompts. To make any changes active, you will need to reboot your device.
To use WebREPL connect your computer to the ESP8266’s access point (MicroPython-xxxxxx, see the previous section
about this). If you have already reconfigured your ESP8266 to connect to a router then you can skip this part.
Once you are on the same network as the ESP8266 you click the “Connect” button (if you are connecting via a router
then you may need to change the IP address, by default the IP address is correct when connected to the ESP8266’s access
point). If the connection succeeds then you should see a password prompt.
Once you type the password configured at the setup step above, press Enter once more and you should get a prompt
looking like >>>. You can now start typing Python commands!
Note that you shouldn’t type the >>> arrows, they are there to indicate that you should type the text after it at the
prompt. And then the line following is what the device should respond with. In the end, once you have entered the
text print("hello esp8266!") and pressed the Enter key, the output on your screen should look exactly like it does
above.
If you already know some python you can now try some basic commands here. For example:
>>> 1 + 2
3
>>> 1 / 2
0.5
>>> 12**34
4922235242952026704037113243122008064
If your board has an LED attached to GPIO2 (the ESP-12 modules do) then you can turn it on and off using the following
code:
Note that on method of a Pin might turn the LED off and off might turn it on (or vice versa), depending on how the
LED is wired on your board. To resolve this, machine.Signal class is provided.
Line editing
You can edit the current line that you are entering using the left and right arrow keys to move the cursor, as well as the
delete and backspace keys. Also, pressing Home or ctrl-A moves the cursor to the start of the line, and pressing End or
ctrl-E moves to the end of the line.
Input history
The REPL remembers a certain number of previous lines of text that you entered (up to 8 on the ESP8266). To recall
previous lines use the up and down arrow keys.
Tab completion
Pressing the Tab key will do an auto-completion of the current word that you are entering. This can be very useful to
find out functions and methods that a module or object has. Try it out by typing “ma” and then pressing Tab. It should
complete to “machine” (assuming you imported machine in the above example). Then type “.” and press Tab again to
see a list of all the functions that the machine module has.
Certain things that you type will need “continuing”, that is, will need more lines of text to make a proper Python statement.
In this case the prompt will change to ... and the cursor will auto-indent the correct amount so you can start typing the
next line straight away. Try this by defining the following function:
In the above, you needed to press the Enter key three times in a row to finish the compound statement (that’s the three
lines with just dots on them). The other way to finish a compound statement is to press backspace to get to the start of the
line, then press the Enter key. (If you did something wrong and want to escape the continuation mode then press ctrl-C;
all lines will be ignored.)
The function you just defined allows you to toggle a pin. The pin object you created earlier should still exist (recreate it
if it doesn’t) and you can toggle the LED using:
>>> toggle(pin)
Let’s now toggle the LED in a loop (if you don’t have an LED then you can just print some text instead of calling toggle,
to see the effect):
This will toggle the LED at 1Hz (half a second on, half a second off). To stop the toggling press ctrl-C, which will raise
a KeyboardInterrupt exception and break out of the loop.
The time module provides some useful functions for making delays and doing timing. Use tab completion to find out what
they are and play around with them!
Paste mode
Pressing ctrl-E will enter a special paste mode. This allows you to copy and paste a chunk of text into the REPL. If you
press ctrl-E you will see the paste-mode prompt:
You can then paste (or type) your text in. Note that none of the special keys or commands work in paste mode (eg Tab
or backspace), they are just accepted as-is. Press ctrl-D to finish entering the text and execute it.
The “9” is the number of bytes that were written with the write() method. Then you can read back the contents of this
new file using:
>>> f = open('data.txt')
>>> f.read()
'some data'
>>> f.close()
Note that the default mode when opening a file is to open it in read-only mode, and as a text file. Specify 'wb' as the
second argument to open() to open for writing in binary mode, and 'rb' to open for reading in binary mode.
>>> import os
>>> os.listdir()
['boot.py', 'port_config.py', 'data.txt']
>>> os.mkdir('dir')
>>> os.remove('data.txt')
Start up scripts
There are two files that are treated specially by the ESP8266 when it starts up: boot.py and main.py. The boot.py script
is executed first (if it exists) and then once it completes the main.py script is executed. You can create these files yourself
and populate them with the code that you want to run when the device starts up.
>>> sta_if.active()
False
>>> ap_if.active()
True
You can also check the network settings of the interface by:
>>> ap_if.ipconfig('addr4')
('192.168.4.1', '255.255.255.0')
>>> sta_if.active(True)
>>> sta_if.isconnected()
>>> sta_if.ipconfig('addr4')
('192.168.0.2', '255.255.255.0')
You can then disable the access-point interface if you no longer need it:
>>> ap_if.active(False)
Here is a function you can run (or put in your boot.py file) to automatically connect to your WiFi network:
def do_connect():
import network
sta_if = network.WLAN(network.WLAN.IF_STA)
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect('<ssid>', '<key>')
while not sta_if.isconnected():
pass
print('network config:', sta_if.ipconfig('addr4'))
Sockets
Once the WiFi is set up the way to access the network is by using sockets. A socket represents an endpoint on a network
device, and when two sockets are connected together communication can proceed. Internet protocols are built on top of
sockets, such as email (SMTP), the web (HTTP), telnet, ssh, among many others. Each of these protocols is assigned a
specific port, which is just an integer. Given an IP address and a port number you can connect to a remote device and
start talking with it.
The next part of the tutorial discusses how to use sockets to do some common and useful network tasks.
The getaddrinfo function actually returns a list of addresses, and each address has more information than we need.
We want to get just the first valid address, and then just the IP address and port of the server. To do this use:
If you type addr_info and addr at the prompt you will see exactly what information they hold.
Using the IP address we can make a socket and connect to the server:
>>> s = socket.socket()
>>> s.connect(addr)
Now that we are connected we can download and display the data:
When this loop executes it should start showing the animation (use ctrl-C to interrupt it).
You should also be able to run this same code on your PC using normal Python if you want to try it out there.
def http_get(url):
import socket
_, _, host, path = url.split('/', 3)
addr = socket.getaddrinfo(host, 80)[0][-1]
s = socket.socket()
s.connect(addr)
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
(continues on next page)
>>> http_get('http://micropython.org/ks/test.html')
This should retrieve the webpage and print the HTML to the console.
import machine
pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)]
import socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
while True:
cl, addr = s.accept()
print('client connected from', addr)
cl_file = cl.makefile('rwb', 0)
while True:
line = cl_file.readline()
if not line or line == b'\r\n':
break
rows = ['<tr><td>%s</td><td>%d</td></tr>' % (str(p), p.value()) for p in pins]
response = html % '\n'.join(rows)
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
cl.send(response)
cl.close()
Here, the “0” is the pin that you want to access. Usually you want to configure the pin to be input or output, and you do
this when constructing it. To make an input pin use:
You can either use PULL_UP or None for the input pull-mode. If it’s not specified then it defaults to None, which is no
pull resistor. GPIO16 has no pull-up mode. You can read the value on the pin using:
>>> pin.value()
0
The pin on your board may return 0 or 1 here, depending on what it’s connected to. To make an output pin use:
>>> pin.value(0)
>>> pin.value(1)
Or:
>>> pin.off()
>>> pin.on()
External interrupts
All pins except number 16 can be configured to trigger a hard interrupt if their input changes. You can set code (a callback
function) to be executed on the trigger.
Let’s first define a callback function, which must take a single argument, being the pin that triggered the function. We will
make the function just print the pin:
An finally we need to tell the pins when to trigger, and the function to call when they detect an event:
We set pin 0 to trigger only on a falling edge of the input (when it goes from high to low), and set pin 2 to trigger on both
a rising and falling edge. After entering this code you can apply high and low voltages to pins 0 and 2 to see the interrupt
being executed.
A hard interrupt will trigger as soon as the event occurs and will interrupt any running code, including Python code. As
such your callback functions are limited in what they can do (they cannot allocate memory, for example) and should be
as short and simple as possible.
>>> pwm12.freq(500)
>>> pwm12.duty(512)
Note that the duty cycle is between 0 (all off) and 1023 (all on), with 512 being a 50% duty. Values beyond this min/max
will be clipped. If you print the PWM object then it will tell you its current configuration:
>>> pwm12
PWM(12, freq=500, duty=512)
You can also call the freq() and duty() methods with no arguments to get their current values.
The pin will continue to be in PWM mode until you deinitialise it using:
>>> pwm12.deinit()
Fading an LED
Let’s use the PWM feature to fade an LED. Assuming your board has an LED connected to pin 2 (ESP-12 modules do)
we can create an LED-PWM object using:
>>> adc.read()
58
The values returned from the read() function are between 0 (for 0.0 volts) and 1024 (for 1.0 volts). Please note that
this input can only tolerate a maximum of 1.0 volts and you must use a voltage divider circuit to measure larger voltages.
By default the CPU runs at 80MHz. It can be changed to 160MHz if you need more processing power, at the expense of
current consumption:
>>> machine.freq(160000000)
>>> machine.freq()
160000000
You can change to the higher frequency just while your code does the heavy processing and then change back when it’s
finished.
Deep-sleep mode
The deep-sleep mode will shut down the ESP8266 and all its peripherals, including the WiFi (but not including the real-
time-clock, which is used to wake the chip). This drastically reduces current consumption and is a good way to make
devices that can run for a while on a battery.
To be able to use the deep-sleep feature you must connect GPIO16 to the reset pin (RST on the Adafruit Feather HUZZAH
board). Then the following code can be used to sleep and wake the device:
import machine
Note that when the chip wakes from a deep-sleep it is completely reset, including all of the memory. The boot scripts
will run as usual and you can put code in them to check the reset cause to perhaps do something different if the device
just woke from a deep-sleep. For example, to print the reset cause you can use:
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
print('woke from a deep sleep')
else:
print('power on or hard reset')
import time
import machine
import onewire, ds18x20
Note that you must execute the convert_temp() function to initiate a temperature reading, then wait at least 750ms
before reading the value.
This configures a NeoPixel strip on GPIO4 with 8 pixels. You can adjust the “4” (pin number) and the “8” (number of
pixel) to suit your set up.
To set the colour of pixels use:
For LEDs with more than 3 colours, such as RGBW pixels or RGBY pixels, the NeoPixel class takes a bpp parameter.
To setup a NeoPixel object for an RGBW Pixel, do the following:
In a 4-bpp mode, remember to use 4-tuples instead of 3-tuples to set the colour. For example to set the first three pixels
use:
Then use the write() method to output the colours to the LEDs:
>>> np.write()
import time
def demo(np):
n = np.n
# cycle
for i in range(4 * n):
for j in range(n):
np[j] = (0, 0, 0)
np[i % n] = (255, 255, 255)
np.write()
time.sleep_ms(25)
# bounce
for i in range(4 * n):
for j in range(n):
np[j] = (0, 0, 128)
if (i // n) % 2 == 0:
np[i % n] = (0, 0, 0)
else:
np[n - 1 - (i % n)] = (0, 0, 0)
np.write()
time.sleep_ms(60)
# fade in/out
for i in range(0, 4 * 256, 8):
for j in range(n):
if (i // 256) % 2 == 0:
val = i & 0xff
else:
val = 255 - (i & 0xff)
np[j] = (val, 0, 0)
np.write()
# clear
for i in range(n):
np[i] = (0, 0, 0)
np.write()
Execute it using:
>>> demo(np)
This configures an 60 pixel APA102 strip with clock on GPIO5 and data on GPIO4. You can adjust the pin numbers and
the number of pixels to suit your needs.
The RGB colour data, as well as a brightness level, is sent to the APA102 in a certain order. Usually this is (Red,
Green, Blue, Brightness). If you are using one of the newer APA102C LEDs the green and blue are swapped,
so the order is (Red, Blue, Green, Brightness). The APA102 has more of a square lens while the APA102C
has more of a round one. If you are using a APA102C strip and would prefer to provide colours in RGB order instead of
RBG, you can customise the tuple colour order like so:
>>> strip[0] = (255, 255, 255, 31) # set to white, full brightness
>>> strip[1] = (255, 0, 0, 31) # set to red, full brightness
>>> strip[2] = (0, 255, 0, 15) # set to green, half brightness
>>> strip[3] = (0, 0, 255, 7) # set to blue, quarter brightness
>>> strip.write()
Demonstration:
import time
import machine, apa102
strip.write()
# Demo 3: Fade all pixels together through rainbow colours, offset each pixel
for r in range(5):
for n in range(256):
for i in range(strip.n):
strip[i] = wheel(((i * 256 // strip.n) + n) & 255, brightness)
strip.write()
time.sleep_ms(25)
>>> d.measure()
>>> d.temperature()
>>> d.humidity()
Values returned from temperature() are in degrees Celsius and values returned from humidity() are a percentage
of relative humidity.
The DHT11 can be called no more than once per second and the DHT22 once every two seconds for most accurate results.
Sensor accuracy will degrade over time. Each sensor supports a different operating range. Refer to the product datasheets
for specifics.
In 1-wire mode, only three of the four pins are used and in I2C mode, all four pins are used. Older sensors may still have
4 pins even though they do not support I2C. The 3rd pin is simply not connected.
Pin configurations:
Sensor without I2C in 1-wire mode (eg. DHT11, DHT22, AM2301, AM2302):
1=VDD, 2=Data, 3=NC, 4=GND
Sensor with I2C in 1-wire mode (eg. DHT12, AM2320, AM2321, AM2322):
1=VDD, 2=Data, 3=GND, 4=GND
Sensor with I2C in I2C mode (eg. DHT12, AM2320, AM2321, AM2322):
1=VDD, 2=SDA, 3=GND, 4=SCL
You should use pull-up resistors for the Data, SDA and SCL pins.
To make newer I2C sensors work in backwards compatible 1-wire mode, you must connect both pins 3 and 4 to GND.
This disables the I2C interface.
DHT22 sensors are now sold under the name AM2302 and are otherwise identical.
dc = Pin(4) # data/command
rst = Pin(5) # reset
cs = Pin(15) # chip select, some modules do not have a pin for this
dc = Pin(4) # data/command
rst = Pin(5) # reset
cs = Pin(15) # chip select, some modules do not have a pin for this
I2C interface:
display.text('Hello, World!', 0, 0, 1)
display.show()
Basic functions:
# draw another FrameBuffer on top of the current one at the given coordinates
import framebuf
fbuf = framebuf.FrameBuffer(bytearray(8 * 8 * 1), 8, 8, framebuf.MONO_VLSB)
(continues on next page)
display.fill(0)
display.fill_rect(0, 0, 32, 32, 1)
display.fill_rect(2, 2, 28, 28, 0)
display.vline(9, 8, 22, 1)
display.vline(16, 2, 22, 1)
display.vline(23, 8, 22, 1)
display.fill_rect(26, 24, 2, 4, 1)
display.text('MicroPython', 40, 0, 1)
display.text('SSD1306', 40, 12, 1)
display.text('OLED 128x64', 40, 24, 1)
display.show()
import machine
import esp
7.5 Networking
The network.WLAN class in the network module:
import network
def do_connect():
import network
wlan = network.WLAN(network.WLAN.IF_STA)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('ssid', 'key')
while not wlan.isconnected():
pass
print('network config:', wlan.ipconfig('addr4'))
Once the network is established the socket module can be used to create and use TCP/UDP sockets as usual.
import time
7.7 Timers
Virtual (RTOS-based) timers are supported. Use the machine.Timer class with timer ID of -1:
tim = Timer(-1)
(continues on next page)
Available pins are: 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, which correspond to the actual GPIO pin numbers of ESP8266
chip. Note that many end-user boards use their own adhoc pin numbering (marked e.g. D0, D1, …). As MicroPython
supports different boards and modules, physical pin numbering was chosen as the lowest common denominator. For
mapping between board logical pins and physical chip pins, consult your board documentation.
Note that Pin(1) and Pin(3) are REPL UART TX and RX respectively. Also note that Pin(16) is a special pin (used for
wakeup from deepsleep mode) and may be not available for use with higher-level classes like Neopixel.
There’s a higher-level abstraction machine.Signal which can be used to invert a pin. Useful for illuminating active-low
LEDs using on() or value(1).
Two UARTs are available. UART0 is on Pins 1 (TX) and 3 (RX). UART0 is bidirectional, and by default is used for the
REPL. UART1 is on Pins 2 (TX) and 8 (RX) however Pin 8 is used to connect the flash chip, so UART1 is TX only.
When UART0 is attached to the REPL, all incoming chars on UART(0) go straight to stdin so uart.read() will always
return None. Use sys.stdin.read() if it’s needed to read characters from the UART(0) while it’s also used for the REPL
(or detach, read, then reattach). When detached the UART(0) can be used for other purposes.
If there are no objects in any of the dupterm slots when the REPL is started (on hard or soft reset) then UART(0) is
automatically attached. Without this, the only way to recover a board without a REPL would be to completely erase and
reflash (which would install the default boot.py which attaches the REPL).
To detach the REPL from UART0, use:
import os
os.dupterm(None, 1)
The REPL is attached by default. If you have detached it, to reattach it use:
® Note
Not all methods are implemented: RTC.now(), RTC.irq(handler=*) (using a custom handler), RTC.init()
and RTC.deinit() are currently not supported.
import machine
Be sure to put a 4.7k pull-up resistor on the data line. Note that the convert_temp() method must be called each time
you want to sample the temperature.
Á Warning
By default NeoPixel is configured to control the more popular 800kHz units. It is possible to use alternative timing
to control other (typically 400kHz) devices by passing timing=0 when constructing the NeoPixel object.
apa[0] = (255, 255, 255, 31) # set the first pixel to white with a maximum brightness␣
,→of 31
import esp
esp.apa102_write(clock_pin, data_pin, rgbi_buf)
import dht
import machine
d = dht.DHT11(machine.Pin(4))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin(4))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)
display.text('Hello World', 0, 0, 1)
display.show()
import webrepl_setup
and following on-screen instructions. After reboot, it will be available for connection. If you disabled automatic start-up
on boot, you may run configured daemon on demand using:
import webrepl
webrepl.start()
The supported way to use WebREPL is by connecting to ESP8266 access point, but the daemon is also started on STA
interface if it is active, so if your router is set up and works correctly, you may also use WebREPL while connected to
your normal Internet access point (use the ESP8266 AP connection method if you face any issues).
Besides terminal/command prompt access, WebREPL also has provision for file transfer (both upload and download).
Web client has buttons for the corresponding functions, or you can use command-line client webrepl_cli.py from the
repository above.
See the MicroPython forum for other community-supported alternatives to transfer files to ESP8266.
EIGHT
445
MicroPython Documentation, Release latest
Requirements
The first thing you need is a board with an ESP32 chip. The MicroPython software supports the ESP32 chip itself and
any board should work. The main characteristic of a board is how the GPIO pins are connected to the outside world, and
whether it includes a built-in USB-serial converter to make the UART available to your PC.
Names of pins will be given in this tutorial using the chip names (eg GPIO2) and it should be straightforward to find
which pin this corresponds to on your particular board.
® Note
If you don’t see your specific board on the download page, then it’s very likely that one of the generic firmwares will
work. These are listed at the top of the download page and have names matching the onboard Espressif chip (i.e.
ESP32 / WROOM, ESP32-C3, ESP32-S3, etc).
However, you may need to double check with the vendor you purchased the board from.
Serial prompt
Once you have the firmware on the device you can access the REPL (Python prompt) over either UART0, which might be
connected to a USB-serial converter depending on your board, or the chip’s built-in USB device. The baudrate is 115200.
From here you can now follow the ESP8266 tutorial, because these two Espressif chips are very similar when it comes to
using MicroPython on them. The ESP8266 tutorial is found at MicroPython tutorial for ESP8266 (but skip the Introduction
section).
print(pwms[i])
finally:
for pwm in pwms:
try:
pwm.deinit()
except:
pass
Output is:
PWM(Pin(15), freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0)
PWM(Pin(2), freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0)
PWM(Pin(4), freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1)
PWM(Pin(16), freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1)
PWM(Pin(18), freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2)
PWM(Pin(19), freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2)
PWM(Pin(22), freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3)
PWM(Pin(23), freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3)
PWM(Pin(25), freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0)
PWM(Pin(26), freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0)
PWM(Pin(27), freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1)
PWM(Pin(14), freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1)
PWM(Pin(12), freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2)
PWM(Pin(13), freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2)
PWM(Pin(32), freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3)
PWM(Pin(33), freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3)
F_MIN = 500
F_MAX = 1000
f = F_MIN
delta_f = 1
(continues on next page)
p = PWM(Pin(5), f)
print(p)
while True:
p.freq(f)
sleep(10 / F_MIN)
f += delta_f
if f >= F_MAX or f <= F_MIN:
delta_f = -delta_f
DUTY_MAX = 2**16 - 1
duty_u16 = 0
delta_d = 16
while True:
p.duty_u16(duty_u16)
sleep(1 / 1000)
duty_u16 += delta_d
if duty_u16 >= DUTY_MAX:
duty_u16 = DUTY_MAX
delta_d = -delta_d
elif duty_u16 <= 0:
duty_u16 = 0
delta_d = -delta_d
The specific addresses will be different on different ESP32 models. For example, ESP32-S3 uses these values:
DR_REG_DPORT_BASE = const(0x600C_0000)
DPORT_PERIP_CLK_EN0_REG = const(DR_REG_DPORT_BASE + 0x0018)
DPORT_PERIP_RST_EN0_REG = const(DR_REG_DPORT_BASE + 0x0020)
DPORT_PWM0_CLK_EN = const(1 << 17)
MCPWM0 = const(0x6001_E000 + 0x0004)
...
Note that before a peripheral can be used its clock must be enabled and it must be taken out of reset. In the above example
the following registers are used for this:
• DPORT_PERI_CLK_EN_REG: used to enable a peripheral clock
• DPORT_PERI_RST_EN_REG: used to reset (or take out of reset) a peripheral
The MCPWM0 peripheral is in bit position 17 of the above two registers, hence the value of DPORT_PWM0_CLK_EN.
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG]))
while True:
# Set outputs to 1
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17
(continues on next page)
# Set outputs to 0
mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17)
mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33)
Output is:
0x0 0x0
0x30000 0x3
0x0 0x0
1. You will need the Espressif esptool installed on your system. This is the same tool that you may have used to
initially install MicroPython on your board (see installation instructions).
2. Find the serial port name of your board, and then use esptool to erase the entire flash contents:
3. Use esptool to flash the MicroPython file to your board again. If needed, this file and flashing instructions can be
found on the MicroPython downloads page.
Note that there are several varieties of ESP32 – ESP32, ESP32C3, ESP32C6, ESP32S2, ESP32S3 – supported by
MicroPython, with some differences in functionality between them.
import machine
import esp
import esp32
Note that the temperature sensor in the ESP32 will typically read higher than ambient due to the IC getting warm while
it runs. This effect can be minimised by reading the temperature sensor immediately after waking up from sleep.
ESP32C3, ESP32C6, ESP32S2, and ESP32S3 also have an internal temperature sensor available. It is implemented a
bit differently to the ESP32 and returns the temperature in Celsius:
8.5 Networking
8.5.1 WLAN
The network.WLAN class in the network module:
import network
def do_connect():
import network
wlan = network.WLAN(network.WLAN.IF_STA)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('ssid', 'key')
while not wlan.isconnected():
pass
print('network config:', wlan.ipconfig('addr4'))
Once the network is established the socket module can be used to create and use TCP/UDP sockets as usual, and the
requests module for convenient HTTP requests.
After a call to wlan.connect(), the device will by default retry to connect forever, even when the authentication failed
or no AP is in range. wlan.status() will return network.STAT_CONNECTING in this state until a connection succeeds
or the interface gets disabled. This can be changed by calling wlan.config(reconnects=n), where n are the number
of desired reconnect attempts (0 means it won’t retry, -1 will restore the default behaviour of trying to reconnect forever).
8.5.2 LAN
Built-in MAC (original ESP32)
The original ESP32 SoC has a built-in Ethernet MAC. Using this MAC requires an external Ethernet PHY to be wired
to the chip’s EMAC pins. Most of the EMAC pin assignments are fixed, consult the ESP32 datasheet for details.
If the PHY is connected, the internal Ethernet MAC can be configured via the network.LAN constructor:
import network
• phy_addr - The address number of the PHY device. Must be an integer in the range 0x00 to 0x1f, inclusive.
Common values are 0 and 1.
All of the above keyword arguments must be present to configure the interface.
Optional keyword arguments:
• reset - machine.Pin object (or integer) specifying the PHY reset pin.
• power - machine.Pin object (or integer) specifying a pin which switches the power of the PHY device.
• ref_clk - machine.Pin object (or integer) specifying the pin used for the EMAC ref_clk signal. If not
specified, the board default is used (typically GPIO 0, but may be different if a particular board has Ethernet.)
• ref_clk_mode - Defines whether the EMAC ref_clk pin of the ESP32 should be an input or an output. Suitable
values are machine.Pin.IN and machine.Pin.OUT. If not specified, the board default is used (typically input,
but may be different if a particular board has Ethernet.)
These are working configurations for LAN interfaces of some popular ESP32 boards:
# Wireless-Tag's WT32-ETH01
# Espressif ESP32-Ethernet-Kit_A_V1.2
® Note
The only exception is the ESP32 d2wd variant, where this feature is disabled to save code size.
SPI Ethernet uses the same network.LAN constructor, with a different set of keyword arguments:
• phy_addr - The address number of the PHY device. Must be an integer in the range 0x00 to 0x1f, inclusive. This
is usually 0 for SPI Ethernet devices.
All of the above keyword arguments must be present to configure the interface.
Optional keyword arguments for the constructor:
• reset - machine.Pin object (or integer) specifying the SPI Ethernet interface reset pin.
• power - machine.Pin object (or integer) specifying a pin which switches the power of the SPI Ethernet interface.
Here is a sample configuration for a WIZNet W5500 chip connected to pins on an ESP32-S3 development board:
® Note
WIZnet W5500 Ethernet is also supported on some other MicroPython ports, but using a different software interface.
import time
8.7 Timers
The ESP32 port has four hardware timers. Use the machine.Timer class with a timer ID from 0 to 3 (inclusive):
tim0 = Timer(0)
tim0.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(0))
tim1 = Timer(1)
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))
Available Pins are from the following ranges (inclusive): 0-19, 21-23, 25-27, 32-39. These correspond to the actual GPIO
pin numbers of ESP32 chip. Note that many end-user boards use their own adhoc pin numbering (marked e.g. D0, D1,
…). For mapping between board logical pins and physical chip pins consult your board documentation.
Four drive strengths are supported, using the drive keyword argument to the Pin() constructor or Pin.init() method,
with different corresponding safe maximum source/sink currents and approximate internal driver resistances:
• Pin.DRIVE_0: 5mA / 130 ohm
The ESP32 has three hardware UARTs: UART0, UART1 and UART2. They each have default GPIO assigned to them,
however depending on your ESP32 variant and board, these pins may conflict with embedded flash, onboard PSRAM or
peripherals.
Any GPIO can be used for hardware UARTs using the GPIO matrix, except for input-only pins 34-39 that can be used
as rx. To avoid conflicts simply provide tx and rx pins when constructing. The default pins listed below.
tx 1 10 17
rx 3 9 16
duty = pwm0.duty() # get current duty cycle, range 0-1023 (default 512, 50%)
pwm0.duty(256) # set duty cycle from 0 to 1023 as a ratio duty/1023, (now␣
,→25%)
A maximum number of PWM channels (Pins) are available on the ESP32 - 16 channels, but only 8 different PWM
frequencies are available, the remaining 8 channels must have the same frequency. On the other hand, 16 independent
PWM duty cycles are possible at the same frequency.
See more examples in the Pulse Width Modulation tutorial.
ADC block 2 is also used by WiFi and so attempting to read analog values from block 2 pins when WiFi is active will
raise an exception.
The internal ADC reference voltage is typically 1.1V, but varies slightly from package to package. The ADC is less
linear close to the reference voltage (particularly at higher attenuations) and has a minimum measurement voltage around
100mV, voltages at or below this will read as 0. To read voltages accurately, it is recommended to use the read_uv()
method (see below).
ESP32-specific ADC class method reference:
class ADC(pin, *, atten)
Return the ADC object for the specified pin. ESP32 does not support different timings for ADC sampling and so
the sample_ns keyword argument is not supported.
To read voltages above the reference voltage, apply input attenuation with the atten keyword argument. Valid
values (and approximate linear measurement ranges) are:
• ADC.ATTN_0DB: No attenuation (100mV - 950mV)
• ADC.ATTN_2_5DB: 2.5dB attenuation (100mV - 1250mV)
• ADC.ATTN_6DB: 6dB attenuation (150mV - 1750mV)
• ADC.ATTN_11DB: 11dB attenuation (150mV - 2450mV)
Á Warning
Note that the absolute maximum voltage rating for input pins is 3.6V. Going near to this boundary risks damage to
the IC!
ADC.read_uv()
This method uses the known characteristics of the ADC and per-package eFuse values - set during manufacture - to
return a calibrated input voltage (before attenuation) in microvolts. The returned value has only millivolt resolution
(i.e., will always be a multiple of 1000 microvolts).
The calibration is only valid across the linear range of the ADC. In particular, an input tied to ground will read as a
value above 0 microvolts. Within the linear range, however, more accurate and consistent results will be obtained
than using read_u16() and scaling the result with a constant.
The ESP32 port also supports the machine.ADC API:
class ADCBlock(id, *, bits)
Return the ADC block object with the given id (1 or 2) and initialize it to the specified resolution (9 to 12-bits
depending on the ESP32 series) or the highest supported resolution if not specified.
ADCBlock.connect(pin)
ADCBlock.connect(channel)
ADCBlock.connect(channel, pin)
Return the ADC object for the specified ADC pin or channel number. Arbitrary connection of ADC channels to
GPIO is not supported and so specifying a pin that is not connected to this block, or specifying a mismatched
channel and pin, will raise an exception.
Legacy methods:
ADC.read()
This method returns the raw ADC value ranged according to the resolution of the block, e.g., 0-4095 for 12-bit
resolution.
ADC.atten(atten)
Equivalent to ADC.init(atten=atten).
ADC.width(bits)
Equivalent to ADC.block().init(bits=bits).
For compatibility, the ADC object also provides constants matching the supported ADC resolutions:
• ADC.WIDTH_9BIT = 9
• ADC.WIDTH_10BIT = 10
• ADC.WIDTH_11BIT = 11
• ADC.WIDTH_12BIT = 12
Á Warning
Currently all of sck, mosi and miso must be specified when initialising Software SPI.
sck 14 18
mosi 13 23
miso 12 19
Hardware SPI is accessed via the machine.SPI class and has the same methods as software SPI above:
I2C(0) I2C(1)
scl 18 25
sda 19 26
The driver is accessed via the machine.I2C class and has the same methods as software I2C above:
i2c = I2C(0)
i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000)
The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged.
Based on this feedback, the I2S class API and implementation may be changed.
ESP32 has two I2S buses with id=0 and id=1
rtc = RTC()
rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
# time, eg. 2017/8/23 1:12:48
# the day-of-week value is ignored
rtc.datetime() # get date and time
import machine
Notes:
• Calling deepsleep() without an argument will put the device to sleep indefinitely
• A software reset does not change the reset cause
Some ESP32 pins (0, 2, 4, 12-15, 25-27, 32-39) are connected to the RTC during deep-sleep and can be used to wake
the device with the wake_on_ functions in the esp32 module. The output-capable RTC pins (all except 34-39) will also
retain their pull-up or pull-down resistor configuration when entering deep-sleep.
If the pull resistors are not actively required during deep-sleep and are likely to cause current leakage (for example a
pull-up resistor is connected to ground through a switch), then they should be disabled to save power before entering
deep-sleep mode:
Output-configured RTC pins will also retain their output direction and level in deep-sleep if pad hold is enabled with the
hold=True argument to Pin.init().
Non-RTC GPIO pins will be disconnected by default on entering deep-sleep. Configuration of non-RTC pins - including
output level - can be retained by enabling pad hold on the pin and enabling GPIO pad hold during deep-sleep:
The pin configuration - including the pad hold - will be retained on wake from sleep. See Pins and GPIO above for a
further discussion of pad holding.
8.21 SD card
See machine.SDCard.
vfs.umount('/sd') # eject
8.22 RMT
The RMT is ESP32-specific and allows generation of accurate digital pulses with 12.5ns resolution. See esp32.RMT for
details. Usage is:
import esp32
from machine import Pin
Be sure to put a 4.7k pull-up resistor on the data line. Note that the convert_temp() method must be called each time
you want to sample the temperature.
The APA106 driver extends NeoPixel, but internally uses a different colour order:
Á Warning
By default NeoPixel is configured to control the more popular 800kHz units. It is possible to use alternative timing
to control other (typically 400kHz) devices by passing timing=0 when constructing the NeoPixel object.
For low-level driving of a NeoPixel see machine.bitstream. This low-level driver uses an RMT channel by default.
To configure this see RMT.bitstream_channel.
APA102 (DotStar) uses a different driver as it has an additional clock pin.
t = TouchPad(Pin(14))
t.read() # Returns a smaller number when touched
TouchPad.read returns a value proportional to the capacitance between the pin and the board’s Ground connection. On
ESP32 the number becomes smaller when the pin (or connected touch pad) is touched, on ESP32-S2 and ESP32-S3 the
number becomes larger when the pin is touched.
In all cases, a touch causes a significant change in the return value. Note the returned values are relative and can vary
depending on the board and surrounding environment so some calibration (i.e. comparison to a baseline or rolling average)
may be required.
import machine
from machine import TouchPad, Pin
import esp32
t = TouchPad(Pin(14))
t.config(500) # configure the threshold at which the pin is considered␣
,→touched
esp32.wake_on_touch(True)
machine.lightsleep() # put the MCU to sleep until a touchpad is touched
import dht
import machine
d = dht.DHT11(machine.Pin(4))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin(4))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)
import webrepl_setup
and following on-screen instructions. After reboot, it will be available for connection. If you disabled automatic start-up
on boot, you may run configured daemon on demand using:
import webrepl
webrepl.start()
The WebREPL daemon listens on all active interfaces, which can be STA or AP. This allows you to connect to the ESP32
via a router (the STA interface) or directly when connected to its access point.
In addition to terminal/command prompt access, WebREPL also has provision for file transfer (both upload and down-
load). The web client has buttons for the corresponding functions, or you can use the command-line client webrepl_cli.
py from the repository above.
See the MicroPython forum for other community-supported alternatives to transfer files to an ESP32 board.
NINE
471
MicroPython Documentation, Release latest
9.2.2 Programmable IO
The RP2040 has hardware support for standard communication protocols like I2C, SPI and UART. For protocols where
there is no hardware support, or where there is a requirement of custom I/O behaviour, Programmable Input Output
(PIO) comes into play. Also, some MicroPython applications make use of a technique called bit banging in which pins
are rapidly turned on and off to transmit data. This can make the entire process slow as the processor concentrates on bit
banging rather than executing other logic. However, PIO allows bit banging to happen in the background while the CPU
is executing the main work.
Along with the two central Cortex-M0+ processing cores, the RP2040 has two PIO blocks each of which has four in-
dependent state machines. These state machines can transfer data to/from other entities using First-In-First-Out (FIFO)
buffers, which allow the state machine and main processor to work independently yet also synchronise their data. Each
FIFO has four words (each of 32 bits) which can be linked to the DMA to transfer larger amounts of data.
All PIO instructions follow a common pattern:
The side-set .side(...) and delay [...] parts are both optional, and if specified allow the instruction to perform more
than one operation. This keeps PIO programs small and efficient.
There are nine instructions which perform the following tasks:
• jmp() transfers control to a different part of the code
• wait() pauses until a particular action happens
• in_() shifts the bits from a source (scratch register or set of pins) to the input shift register
• out() shifts the bits from the output shift register to a destination
• push() sends data to the RX FIFO
• pull() receives data from the TX FIFO
• mov() moves data from a source to a destination
• irq() sets or clears an IRQ flag
• set() writes a literal value to a destination
The instruction modifiers are:
• .side() sets the side-set pins at the start of the instruction
• [] delays for a certain number of cycles after execution of the instruction
There are also directives:
• wrap_target() specifies where the program execution will get continued from
• wrap() specifies the instruction where the control flow of the program will get wrapped from
• label() sets a label for use with jmp() instructions
• word() emits a raw 16-bit value which acts as an instruction in the program
An example
Take the pio_1hz.py example for a simple understanding of how to use the PIO and state machines. Below is the code
for reference.
import time
from machine import Pin
import rp2
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_1hz():
# Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
(continues on next page)
This creates an instance of class rp2.StateMachine which runs the blink_1hz program at 2000Hz, and connects to
pin 25. The blink_1hz program uses the PIO to blink an LED connected to this pin at 1Hz, and also raises an IRQ as
the LED turns on. This IRQ then calls the lambda function which prints out a millisecond timestamp.
The blink_1hz program is a PIO assembler routine. It connects to a single pin which is configured as an output and
starts out low. The instructions do the following:
• irq(rel(0)) raises the IRQ associated with the state machine.
• The LED is turned on via the set(pins, 1) instruction.
• The value 31 is put into register X, and then there is a delay for 5 more cycles, specified by the [5].
• The nop() [29] instruction waits for 30 cycles.
• The jmp(x_dec, "delay_high") will keep looping to the delay_high label as long as the register X is non-
zero, and will also post-decrement X. Since X starts with the value 31 this jump will happen 31 times, so the nop()
[29] runs 32 times in total (note there is also one instruction cycle taken by the jmp for each of these 32 loops).
• The single nop() correlates with the cycle used for IRQ raise, and ensures the same number of cycles are used for
LED on and LED off.
• set(pins, 0) will turn the LED off by setting pin 25 low.
• Another 32 loops of nop() [29] and jmp(...) will execute.
• Because wrap_target() and wrap() are not specified, their default will be used and execution of the program
will wrap around from the bottom to the top. This wrapping does not cost any execution cycles.
The entire routine takes exactly 2000 cycles of the state machine. Setting the frequency of the state machine to 2000Hz
makes the LED blink at 1Hz.
machine.freq(MCU_frequency[, peripheral_frequency=48_000_000])
The MCU frequency can be set in a range from less than 48 MHz to about 250MHz. The default at boot time is 125
MHz. The peripheral frequency must be either 48 MHz or identical to the MCU frequency, with 48 MHz as the default.
If the peripheral frequency is changed, any already existing instance of UART and SPI will change it’s baud rate and may
have to be re-configured:
import machine
import rp2
import time
9.6 Timers
RP2040’s system timer peripheral provides a global microsecond timebase and generates interrupts for it. The software
timer is available currently, and there are unlimited number of them (memory permitting). There is no need to specify
the timer id (id=-1 is supported at the moment) as it will default to this.
Use the machine.Timer class:
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_1hz():
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
set(pins, 1)
set(x, 31) [6]
label("delay_high")
nop() [29]
jmp(x_dec, "delay_high")
® Note
REPL over UART is disabled by default. You can see the Getting started with MicroPython on the RP2xxx for details
on how to enable REPL over UART.
# create PWM object from a pin and set the frequency of slice 0
# and duty cycle for channel A
pwm0 = PWM(Pin(0), freq=2000, duty_u16=32768)
pwm0.freq() # get the current frequency of slice 0
pwm0.freq(1000) # set/change the frequency of slice 0
pwm0.duty_u16() # get the current duty cycle of channel A, range 0-65535
pwm0.duty_u16(200) # set the duty cycle of channel A, range 0-65535
pwm0.duty_u16(0) # stop the output at channel A
print(pwm0) # show the properties of the PWM object.
pwm0.deinit() # turn off PWM of slice 0, stopping channels A and B
The argument of the constructor ADC specifies either a Pin by number, name of as Pin object, or a channel number in
the range 0 - 3 or ADC.CORE_TEMP for the internal temperature sensor. If a pin is specified, the pin is initialized in
high-Z mode. If a channel number is used, the pin is not initialized and configuring is left to the user code. After hard
reset, RP2040 pins operate in current sink mode at about 60µA. If the pin is not otherwise configured, that may lead to
wrong ADC readings.
Á Warning
Currently all of sck, mosi and miso must be specified when initialising Software SPI.
The ws pin number must be one greater than the sck pin number.
The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged.
Based on this feedback, the I2S class API and implementation may be changed.
Two I2S buses are supported with id=0 and id=1.
rtc = RTC()
rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
# time, eg. 2017/8/23 1:12:48
# the day-of-week value is ignored
rtc.datetime() # get date and time
Be sure to put a 4.7k pull-up resistor on the data line. Note that the convert_temp() method must be called each time
you want to sample the temperature.
The APA106 driver extends NeoPixel, but internally uses a different colour order:
TEN
483
MicroPython Documentation, Release latest
• MIMXRT1020-EVK
• MIMXRT1050-EVK
• MIMXRT1060-EVK
• MIMXRT1064-EVK
• Teensy 4.0
• Teensy 4.1
Note: Most of the controllers do not have internal flash memory. Therefore their flash capacity is dependent on an external
flash chip.
To make a generic MIMXRT port and support as many boards as possible the following design and implementation
decision were made:
• GPIO pin numbering is based on the board numbering as well as on the MCU numbering. Please have the man-
ual/pin diagram of your board at hand to find correspondence between your board pins and actual i.MXRT pins.
• All MCU pins are supported by MicroPython but not all are usable on any given board.
10.2.1 Requirements
The first thing you need is a board with an i.MXRT chip. The MicroPython software supports the i.MXRT chip itself
and any board should work. The main characteristic of a board is how the GPIO pins are connected to the outside world,
and whether it includes a built-in USB-serial converter to make the UART available to your PC.
Names of pins will be given in this tutorial using the chip names (eg GPIO2) and it should be straightforward to find
which pin this corresponds to on your particular board.
IMXRT10xx-EVK boards
The IMXRT10xx-EVK boards have a second USB port connected to a support MCU. Connecting that USB port to your
PC will register a disk drive with the name of the board. Just copy the firmware.bin file to this drive, and that will start
the flashing procedure. You will know that the flash was complete, if that drive disappears and reappears. If you decided
to install the very useful Segger open-SDA firmware on that sidekick MCU, then you have to use the debugger software
to upload the i.MXRT firmware.
D1 • Q1/0 F1/1/A • • •
D7 • • F1/0/A Q3/3 • •
A0 • • F1/2/A • • •
A4 • • • Q3/1 • F1/2/X
A5 • • • Q3/0 • •
D31 • • • • F1/2/B •
D32 • • • • F1/2/A •
D33 F1/1/B
10.3. Pinout for the• i.MXRT machine
• modules • • • 489
D34 • • • • F1/1/A •
MicroPython Documentation, Release latest
Pins denoted with (*) are by default not wired at the board.
• • 37 F2/3/B
• • 49 F1/2/A
• • 50 F1/2/B
• • 51 F3/3/B
• • 52 F1/1/B
• • 53 F1/1/A
• • 54 F3/0/A
D1 F1/0/B
D2 F1/0/A
D3 F1/1/B
D4 F1/1/A
D5 F1/2/B
D6 F1/2/A
D7 F1/3/B
D8 F1/3/A
D9 •
D10 F1/0/B
D11 F1/0/A
D12 F1/1/B
D13 F1/1/A
D14 •
A0 •
A1 F1/2/B
A2 F1/2/A
A3 F1/3/B
A4 F1/3/A
SDI F1/3/X
SDO F1/2/X
CS0 F1/1/X
SCK F1/0/X
Legend:
• Qm/n: QTMR module m, channel n
• Fm/n/l: FLEXPWM module m, submodule n, channel l. The pulse at a X channel is always aligned to the period
start.
Pins without a PWM signal are not listed. A signal may be available at more than one Pin. FlexPWM pins may also be
pure CPU pin, not assigned to a board signal. In that case the PWM output is disabled. The PWM channel of a submodule
0 may still be used as synchronization source for other channels of the same module, unless used by another peripheral.
Submodule 0 pins for i.MX RT1011:
Pin Channel
Pin.cpu.GPIO_01 B
Pin.cpu.GPIO_02 A
Pin.cpu.GPIO_AD_12 X
Pin.cpu.GPIO_SD_01 B
Pin.cpu.GPIO_SD_02 A
Submodule 0 pins for i.MX RT1052, i.MX RT1062 and i.MX RT1064:
MIXMXRT1015-EVK D10/-/D11/D12/D13 • •
Pins denoted with (*) are by default not wired at the board. The CS0 and CS1 signals are enabled with the keyword option
cs=0 or cs=1 of the SPI object constructor.
Symbolic pin names are provided for the MIMXRT_10xx_DEV boards. These are provided for the other boards as well.
import machine
import time
10.7 Timers
The i.MXRT port supports virtual Timers. Example of usage:
tim0 = Timer(-1)
tim0.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(0))
tim1 = Timer(-1)
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))
Available Pins follow the ranges and labelling of the respective board, like:
• ‘D0-Dxx’, or ‘A0-Ann’ for Teensy 4.0, MIMXRT10xx-EVK ns Olimex board,
• ‘J3_xx’, ‘J4_xx’, ‘J5_xx’ for the Seeed ARCH MIX board,
or the pin names of the Pin.board or Pin.cpu classes.
Notes:
• The MIMXRT1xxx-EVK boards may have other on-board devices connected to these pins, limiting it’s use for
input or output.
• At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by default not connected to the
MCU. For details refer to the schematics.
• At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows:
– ‘D16’ - ‘D23’: J9, odd pin numbers; ‘D17’ is by default not connected.
– ‘D24’ - ‘D27’: J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
– ‘D29’ - ‘D36’: J25, odd pin numbers; ‘D29’ and ‘D30’ are by default not connected.
There’s a higher-level abstraction machine.Signal which can be used to invert a pin. Useful for illuminating active-low
LEDs using on() or value(1).
The i.MXRT has up to eight hardware UARTs, but not every board exposes all TX and RX pins for users. For the
assignment of Pins to UART signals, refer to the UART pinout.
# create PWM object from a pin and set the frequency and duty cycle
pwm2 = PWM(Pin('D2'), freq=2000, duty_u16=32768)
pwm2.freq() # get the current frequency
pwm2.freq(1000) # set/change the frequency
pwm2.duty_u16() # get the current duty cycle, range 0-65535
pwm2.duty_u16(200) # set the duty cycle, range 0-65535
pwm2.deinit() # turn off PWM on the pin
# create a complementary signal pair on Pin 2 and 3
pwm2 = PWM(('D2', 'D3'), freq=2000, duty_ns=20000)
Construct and return a new PWM object using the following parameters:
• dest is the entity on which the PWM is output, which is usually a machine.Pin object, but a port may
allow other values, like integers or strings, which designate a Pin in the machine.PIN class. dest is
either a single object or a two element object tuple. If the object tuple is specified, the two pins act
in complementary mode. These two pins must be the A/B channels of the same submodule.
PWM objects are either provided by a FLEXPWM module or a QTMR module. The i.MXRT de-
vices have either two or four FLEXPWM and QTMR modules. Each FLEXPWM module has four
submodules with three channels, each, called A, B and X. Each QTMR module has four channels. Each
FLEXPWM submodule or QTMR channel may be set to different parameters. Not every channel is
routed to a board pin. Details are listed below.
Setting freq affects the three channels of the same FLEXPWM submodule. Only one of duty_u16 and
duty_ns should be specified at a time.
Keyword arguments:
• freq should be an integer which sets the frequency in Hz for the PWM cycle. The valid frequency
range is 15 Hz resp. 18Hz resp. 24Hz up to > 1 MHz.
• duty_u16 sets the duty cycle as a ratio duty_u16 / 65535. The duty cycle of a X channel can
only be changed, if the A and B channel of the respective submodule is not used. Otherwise the
duty_16 value of the X channel is 32768 (50%).
• duty_ns sets the pulse width in nanoseconds. The limitation for X channels apply as well.
• center=value. An integer sets the center of the pulse within the pulse period. The range is 0-65535.
The resulting pulse will last from center - duty_u16/2 to center + duty_u16/2.
• align=value. Shortcuts for the pulse center setting, causing the pulse either at the center of the
frame (value=0), the leading edge at the begin (value=1) or the trailing edge at the end of a pulse
period (value=2).
• invert=value channel_mask. Setting a bit in the mask inverts the respective channel. Bit 0 inverts
the first specified channel, bit 1 the second. The default is 0. For a PWM object with a single
channel, True and False may be used as values.
• sync=True|False. If a channel of a module’s submodule 0 is already active, other submodules of
the same module can be forced to be synchronous to submodule 0. Their pulse period start then at
at same clock cycle. The default is False.
• xor=0|1|2. If set to 1 or 2, the channel will output the XOR’d signal from channels A or B. If set
to 1 on channel A or B, both A and B will show the same signal. If set to 2, A and B will show
alternating signals. For details and an illustration, please refer to the MCU’s reference manual,
chapter “Double Switching PWMs”.
• deadtime=time_ns. This setting affects complementary channels and defines a deadtime between
an edge of a first channel and the edge of the next channel, in which both channels are set to low.
That allows connected H-bridges to switch off one side of a push-pull driver before switching on
the other side.
f = pwm_clk / (2**n * m)
with n being in the range of 0..7, and m in the range of 2..65535. pmw_clk is 125Mhz for MIMXRT1010/1015/1020,
150 MHz for MIMXRT1050/1060/1064 and 160MHz for MIMXRT1170. The lowest frequency is pwm_clk/2**23 (15,
18, 20Hz). The highest frequency with U16 resolution is pwm_clk/2**16 (1907, 2288, 2441 Hz), the highest frequency
with 1 percent resolution is pwm_clk/100 (1.25, 1.5, 1.6 MHz). The highest achievable frequency is pwm_clk/3 for the
A/B channels, and pwm_clk/2 for the X channels and QTMR signal.
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the value returned by read_u16(). If you
need a higher resolution or better accuracy, use an external ADC.
For the assignment of Pins to SPI signals, refer to Hardware SPI pinout. The keyword option cs=n can be used to enable
the cs pin 0 or 1 for an automatic cs signal. The default is cs=-1. Using cs=-1 the automatic cs signal is not created. In
that case, cs has to be set by the script. Clearing that assignment requires a power cycle.
Notes:
1. Even if the highest reliable baud rate at the moment is about 30 Mhz, setting a baud rate will not always result in
exactly that frequency, especially at high baud rates.
2. Sending at higher baud rate is possible. In the tests receiving worked up to 60 MHz, sending up to 90 MHz.
i2c=I2C(0)
wm=wm8960.WM8960(i2c, sample_rate=SAMPLE_RATE_IN_HZ,
adc_sync=wm8960.sync_dac,
swap=wm8960.swap_input)
In this example, the input channels are swapped in the WM8960 driver, since the on-board microphone is connected to
the right channel, but mono audio is taken from the left channel. Note, that the sck and ws pins are connected to the TX
signals of the I2S bus. That is intentional, since at the MW8960 codec these signals are shared for RX and TX.
Example using the Teensy audio shield:
The SGTL5000 codec used by the Teensy Audio shield uses the RX signals for both RX and TX. Note that the codec is
initialized after the I2S device. That is essential since MCK is needed for its I2C operation and is provided by the I2S
controller.
MIMXRT boards may have 1 or 2 I2S buses available at the board connectors. On MIMXRT1010 devices the bus
numbers are 1 and 3. The I2S signals have fixed assignments to GPIO pins. For the assignment of Pins to I2S signals,
refer to I2S pinout.
rtc = RTC()
rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
# time, eg. 2017/8/23 1:12:48
# the day-of-week value is ignored
rtc.datetime() # get date and time
rtc.now() # return date and time in CPython format.
The i.MXRT MCU supports battery backup of the RTC. By connecting a battery of 1.5-3.6V, time and date are main-
tained in the absence of the main power. The current drawn from the battery is ~20µA, which is rather high. A CR2032
coin cell will last for about one year.
Note: In v1.23.0 the support for subseconds was removed. When reading the RTC, 0 will be returned as value for
subsecond, When setting the RTC time, the subsecond field is ignored. The RTC itself does not provide a microsecond
value.
10.18 SD card
See machine.SDCard:
sd = machine.SDCard()
fs = vfs.VfsFat(sd)
vfs.mount(fs, "/sd") # mount
os.listdir('/sd') # list directory contents
vfs.umount('/sd') # eject
Note: The i.mx-rt 1011 and 1015 based boards do not support the machine.SDCard class. For these, the SPI based
driver sdcard.py from the MicroPython drivers can be used. When using it, you have to overdrive the CS pin of the
SPI hardware module. Example:
cs_pin = "D10"
spi = machine.SPI(0) # SPI0 with cs at Pin "D10" used for SDCARD
cs = machine.Pin(cs_pin, machine.Pin.OUT, value=1)
sd = sdcard.SDCard(spi, cs)
fs = vfs.VfsFat(sd)
vfs.mount(fs, "/sdcard")
Be sure to put a 4.7k pull-up resistor on the data line. Note that the convert_temp() method must be called each time
you want to sample the temperature.
import dht
import machine
d = dht.DHT11(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)
Be sure to have a 4.7k pull-up resistor on the data line. Some DHT modules may already have one.
import network
lan = network.LAN(0)
lan.active(True)
If there is a DHCP server in the LAN, the IP address is supplied by that server. Otherwise, the IP address can be set with
lan.ipconfig(addr4=”…”). The default address is 192.168.0.1.
Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an adapter for self-assembly. The Seeed ARCH
MIX board has no PHY hardware on the board, however you can attach external PHY interfaces. By default, the firmware
for Seeed Arch Mix uses the driver for a LAN8720 PHY. The MIMXRT1170_EVK is equipped with two Ethernet ports,
which are addressed as LAN(0) for the 100M port and LAN(1) for the 1G port.
For details of the network interface refer to the class network.LAN.
ELEVEN
Below is a quick reference for CC3200/WiPy. If it is your first time working with this board please consider reading the
following sections first:
Á Warning
The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higher than 3.6V will cause irreparable
damage to the board. ADC pins, when configured in analog mode cannot withstand voltages above 1.8V. Keep these
considerations in mind when wiring your electronics.
507
MicroPython Documentation, Release latest
$ telnet 192.168.1.1
$ ftp 192.168.1.1
The FTP server on the WiPy doesn’t support active mode, only passive, therefore, if using the native unix ftp client, just
after logging in do:
ftp> passive
Besides that, the FTP server only supports one data connection at a time. Check out the Filezilla settings section below
for more info.
Software updates can be found in: https://github.com/wipy/wipy/releases (Binaries.zip). It’s always recommended to
update to the latest software, but make sure to read the release notes before.
® Note
The bootloader.bin found inside Binaries.zip is there only for reference, it’s not needed for the Over The Air
update.
>>> import os
>>> os.uname().release
If the version number is lower than the latest release found in the releases, go ahead and update your WiPy!
1st 3 secs window 2nd 3 secs window Final 1.5 secs window
Safe boot, latest Safe boot, previous Safe boot, the factory
firmware is selected user update selected firmware is selected
On all of the above 3 scenarios, safe boot mode is entered, meaning that the execution of both boot.py and main.py is
skipped. This is useful to recover from crash situations caused by the user scripts. The selection made during safe boot
is not persistent, therefore after the next normal reset the latest firmware will run again.
You can also configure the Pin to generate interrupts. For instance:
def pincb(pin):
print(pin.id())
Now every time a falling edge is seen on the gpio pin, the callback will be executed. Caution: mechanical push buttons have
“bounce” and pushing or releasing a switch will often generate multiple edges. See: http://www.eng.utah.edu/~cs5780/
debouncing.pdf for a detailed explanation, along with various techniques for debouncing.
All pin objects go through the pin mapper to come up with one of the gpio pins.
For the drive parameter the strengths are:
• Pin.LOW_POWER - 2mA drive capability.
• Pin.MED_POWER - 4mA drive capability.
• Pin.HIGH_POWER - 6mA drive capability.
For the alt parameter please refer to the pinout and alternate functions table at <https://raw.githubusercontent.com/
wipy/wipy/master/docs/PinOUT.png>`_ for the specific alternate functions that each pin supports.
For interrupts, the priority can take values in the range 1-7. And the wake parameter has the following properties:
• If wake_from=machine.Sleep.ACTIVE any pin can wake the board.
• If wake_from=machine.Sleep.SUSPENDED pins GP2, GP4, GP10, GP11, GP17`` or GP24 can wake the board.
Note that only 1 of this pins can be enabled as a wake source at the same time, so, only the last enabled pin as a
machine.Sleep.SUSPENDED wake source will have effect.
• If wake_from=machine.Sleep.SUSPENDED pins GP2, GP4, GP10, GP11, GP17 and GP24 can wake the board.
In this case all of the 6 pins can be enabled as a machine.Sleep.HIBERNATE wake source at the same time.
Additional Pin methods:
machine.Pin.alt_list()
Returns a list of the alternate functions supported by the pin. List items are a tuple of the form:
('ALT_FUN_NAME', ALT_FUN_INDEX)
i2c = machine.I2C()
Only certain pins can be used as SCL/SDA. Please refer to the pinout for further information.
import socket
import ssl
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s)
Certificates must be used in order to validate the other side of the connection, and also to authenticate ourselves with the
other end. Such certificates must be stored as files using the FTP server, and they must be placed in specific paths with
specific names.
• The certificate to validate the other side goes in: ‘/flash/cert/ca.pem’
• The certificate to authenticate ourselves goes in: ‘/flash/cert/cert.pem’
• The key for our own certificate goes in: ‘/flash/cert/private.key’
® Note
When these files are stored, they are placed inside the internal hidden file system (just like firmware updates), and
therefore they are never visible.
For instance to connect to the Blynk servers using certificates, take the file ca.pem located in the blynk examples folder.
and put it in ‘/flash/cert/’. Then do:
import socket
import ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
(continues on next page)
import network
server = network.Server()
server.deinit() # disable the server
# enable the server again with new settings
server.init(login=('user', 'password'), timeout=600)
server.isrunning()
Returns True if the server is running, False otherwise.
vfs.mount(sd, '/sd')
unmount(path)
Unmounts a previously mounted block device from the given path.
mkfs(block_device or path)
Formats the specified path, must be either /flash or /sd. A block device can also be passed like an SD object
before being mounted.
Place this piece of code inside your boot.py so that it’s done automatically after reset.
Windows
First you need to install the FTDI drivers for the expansion board’s USB to serial converter. Then you need a terminal
software. The best option is to download the free program PuTTY: putty.exe.
In order to get to the telnet REPL:
Using putty, select Telnet as connection type, leave the default port (23) and enter the IP address of your WiPy
(192.168.1.1 when in WLAN.AP mode), then click open.
In order to get to the REPL UART:
Using your serial program you must connect to the COM port that you found in the previous step. With PuTTY, click on
“Session” in the left-hand panel, then click the “Serial” radio button on the right, then enter you COM port (eg COM4)
in the “Serial Line” box. Finally, click the “Open” button.
Mac OS X
Open a terminal and run:
$ telnet 192.168.1.1
or:
When you are finished and want to exit screen, type CTRL-A CTRL-\. If your keyboard does not have a \-key (i.e. you
need an obscure combination for \ like ALT-SHIFT-7) you can remap the quit command:
• create ~/.screenrc
• add bind q quit
This will allow you to quit screen by hitting CTRL-A Q.
Linux
Open a terminal and run:
$ telnet 192.168.1.1
or:
You can also try picocom or minicom instead of screen. You may have to use /dev/ttyUSB01 or a higher number for
ttyUSB. And, you may need to give yourself the correct permissions to access this devices (eg group uucp or dialout,
or use sudo).
In the above, you should not type in the >>> characters. They are there to indicate that you should type the text after it at
the prompt. In the end, once you have entered the text print("hello WiPy!") and pressed Enter, the output on your
screen should look like it does above.
If you already know some Python you can now try some basic commands here.
If any of this is not working you can try either a hard reset or a soft reset; see below.
Go ahead and try typing in some other commands. For example:
>>>
MPY: soft reboot
MicroPython v1.4.6-146-g1d8b5e5 on 2015-10-21; WiPy with CC3200
Type "help()" for more information.
>>>
If that isn’t working you can perform a hard reset (turn-it-off-and-on-again) by pressing the RST switch (the small black
button next to the heartbeat LED). During telnet, this will end your session, disconnecting whatever program that you
used to connect to the WiPy.
>>> execfile('sync_virtual.py')
You can check the current mode (which is always WLAN.AP after power up):
>>> wlan.mode()
Á Warning
When you change the WLAN mode following the instructions below, your WLAN connection to the WiPy will be
broken. This means you will not be able to run these commands interactively over the WLAN.
There are two ways around this::
1. put this setup code into your boot.py file so that it gets executed automatically after reset.
2. duplicate the REPL on UART, so that you can run commands via USB.
nets = wlan.scan()
for net in nets:
if net.ssid == 'mywifi':
print('Network found!')
wlan.connect(net.ssid, auth=(net.sec, 'mywifikey'), timeout=5000)
while not wlan.isconnected():
machine.idle() # save power while waiting
print('WLAN connection succeeded!')
break
if machine.reset_cause() != machine.SOFT_RESET:
wlan.init(WLAN.STA)
# configuration below MUST match your home router settings!!
network.ipconfig(dns='8.8.8.8')
wlan.ipconfig(addr4='192.168.0.107/24', gw4='192.168.0.1')
if not wlan.isconnected():
# change the line below to match your network ssid, security and password
wlan.connect('mywifi', auth=(WLAN.WPA2, 'mywifikey'), timeout=5000)
while not wlan.isconnected():
machine.idle() # save power while waiting
® Note
Notice how we check for the reset cause and the connection status, this is crucial in order to be able to soft reset the
WiPy during a telnet session without breaking the connection.
def tick(timer): # we will receive the timer object when being called
global led
led.toggle() # toggle the LED
Further examples:
Timer.B
Selects the timer channel. Must be ORed (Timer.A | Timer.B) when using a 32-bit timer.
Timer.POSITIVE
Timer.NEGATIVE
Timer channel polarity selection (only relevant in PWM mode).
Timer.TIMEOUT
Timer.MATCH
Timer channel IRQ triggers.
import sys
sys.exit()
• A hard reset is the same as performing a power cycle to the board. In order to hard reset the WiPy, press the switch
on the board or:
import machine
machine.reset()
Safe boot
If something goes wrong with your WiPy, don’t panic! It is almost impossible for you to break the WiPy by programming
the wrong thing.
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 problems with the filesystem you can format the internal flash drive.
To boot in safe mode, follow the detailed instructions described here.
In safe mode, the boot.py and main.py files are not executed, and so the WiPy boots up with default settings. This
means you now have access to the filesystem, and you can edit boot.py and main.py to fix any problems.
Entering safe mode is temporary, and does not make any changes to the files on the WiPy.
>>> import os
>>> os.mkfs('/flash')
Resetting the filesystem deletes all files on the internal WiPy storage (not the SD card), and restores the files boot.py
and main.py back to their original state after the next reset.
import machine
11.5 Timers
See machine.TimerWiPy and machine.Pin. Timer id’s take values from 0 to 3.:
adc = ADC()
apin = adc.channel(pin='GP3')
apin() # read value, 0-4095
print(rtc.now())
# go into suspended mode waiting for the RTC alarm to expire and wake us up
machine.lightsleep()
11.13 SD card
See machine.SD.
import wipy
TWELVE
Invocation options:
-c <command>
Runs the code in <command>. The code can be one or more Python statements.
-m <module>
Runs the module <module>. The module must be in sys.path.
<script>
Runs the file <script>. The script must be a valid MicroPython source code file.
If none of the 3 options above are given, then MicroPython is run in an interactive REPL mode.
<args>
Any additional arguments after the module or script will be passed to sys.argv (not supported with the -c option).
General options:
-h
Prints a help message containing the command line usage and exits.
-i
Enables inspection. When this flag is set, MicroPython will enter the interactive REPL mode after the command,
module or script has finished. This can be useful for debugging the state after an unhandled exception. Also see
the MICROPYINSPECT environment variable.
-O | -O<level> | -OO...
Sets the optimization level. The O can be followed by a number or can be repeated multiple times to indicate the
level. E.g. -O3 is the same as -OOO.
-v
Increases the verbosity level. This option can be given multiple times. This option only has an effect if MI-
CROPY_DEBUG_PRINTERS was enabled when MicroPython itself was compiled.
-X <option>
Specifies additional implementation-specific options. Possible options are:
• -X compile-only compiles the command, module or script but does not run it.
525
MicroPython Documentation, Release latest
• -X emit={bytecode,native,viper} sets the default code emitter. Native emitters may not be available
depending on the settings when MicroPython itself was compiled.
• -X heapsize=<n>[w][K|M] sets the heap size for the garbage collector. The suffix w means words instead
of bytes. K means x1024 and M means x1024x1024.
• -X realtime sets thread priority to realtime. This can be used to improve timer precision. Only available
on macOS.
MICROPYINSPECT
Enables inspection. If MICROPYINSPECT is set to a non-empty string, it has the same effect as setting the -i
command line option.
526 Chapter 12. Quick reference for the UNIX and Windows ports
CHAPTER
THIRTEEN
Below is a quick reference for the Zephyr port. If it is your first time working with this port please consider reading the
following sections first:
Requirements
To use the MicroPython Zephyr port, you will need a Zephyr supported board (for a list of acceptable boards see General
information about the Zephyr port).
Powering up
If your board has a USB connector on it then most likely it is powered through this when connected to your PC. Otherwise
you will need to power it directly. Please refer to the documentation for your board for further details.
527
MicroPython Documentation, Release latest
You can also try picocom or minicom instead of screen. You may have to use /dev/ttyACM1 or a higher number for
ttyACM. Additional permissions may be necessary to access this device (eg group uucp or dialout, or use sudo). For
Windows, get a terminal software, such as puTTY and connect via a serial session using the proper COM port.
Now you can try running MicroPython code directly on your board.
Anything you type at the prompt, indicated by >>>, will be executed after you press the Enter key. If there is an error
with the text that you enter then an error message is printed.
Start by typing the following at the prompt to make sure it is working:
If you already know some python you can now try some basic commands here. For example:
>>> 1 + 2
3
>>> 1 / 2
0.5
(continues on next page)
If your board has an LED, you can blink it using the following code:
>>>import time
>>>from machine import Pin
The above code uses an LED location for a FRDM-K64F board (port B, pin 21; following Zephyr conventions ports are
identified by “GPIO_x”, where x starts from 0). You will need to adjust it for another board using the board’s reference
materials.
Disk Access
The zephyr.DiskAccess class can be used to access storage devices, such as SD cards. This class uses Zephyr Disk Access
API and implements the vfs.AbstractBlockDev protocol.
For use with SD card controllers, SD cards must be present at boot & not removed; they will be auto detected and
initialized by filesystem at boot. Use the disk driver interface and a file system to access SD cards via disk access (see
below).
Example usage of FatFS with an SD card on the mimxrt1050_evk board:
import vfs
from zephyr import DiskAccess
bdev = zephyr.DiskAccess('SDHC') # create block device object using DiskAccess
vfs.VfsFat.mkfs(bdev) # create FAT filesystem object using the disk␣
,→storage block
Flash Area
The zephyr.FlashArea class can be used to implement a low-level storage system or customize filesystem configurations.
To store persistent data on the device, using a higher-level filesystem API is recommended (see below).
This class uses Zephyr Flash map API and implements the vfs.AbstractBlockDev protocol.
Example usage with the internal flash on the reel_board or the rv32m1_vega_ri5cy board:
import vfs
from zephyr import FlashArea
bdev = FlashArea(FlashArea.STORAGE, 4096) # create block device object using␣
,→FlashArea
For boards such as the frdm_k64f in which the MicroPython application spills into the default flash storage partition, use
the scratch partition by replacing FlashArea.STORAGE with the integer value 4.
Reference your board’s datasheet or Zephyr documentation for pin numbers, see below for more examples.
Interrupts
The Zephyr port also supports interrupt handling for Pins using machine.Pin.irq(). To respond to Pin change IRQs
run:
import time
# equivalently, construct spi bus and set configuration at the same time
spi = SPI("spi0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB)
print(spi) # print device name and bus configuration
spi.readinto(buf, 0xF) # read into the buffer while writing 0xF on MOSI
import vfs
from zephyr import DiskAccess
import vfs
from zephyr import FlashArea
13.10 Sensor
Use the zsensor.Sensor class to access sensor data:
import zsensor
from zsensor import Sensor
FOURTEEN
535
MicroPython Documentation, Release latest
• RA4M1-CLICKER
For the manual and other references for the board and RA Family MCU, please refer to the web page: RA4M1 CLICKER
• EK-RA6M2
For the manual and other references for the board and RA Family MCU, please refer to the web page: EK-RA6M2
The following boards are unofficially supported.
• EK-RA4M1
For the manual and other references for the board and RA Family MCU, please refer to the web page: EK-RA4M1
• EK-RA4W1
For the manual and other references for the board and RA Family MCU, please refer to the web page: EK-RA4W1
• EK-RA6M1
For the manual and other references for the board and RA Family MCU, please refer to the web page: EK-RA6M1
For more information, please visit the web page: https://github.com/renesas/micropython/wiki
Requirements
You need a board. For the information of available boards, please refer to the general information about Renesas RA
port: General information about Renesas RA port.
You need a USB-Serial conversion cable to connect the board and your PC. Please get a type with separate signal pins so
that you can connect to the UART TX and RX pins on the board.
Board Device
EK-RA4M1 R7FA4M1AB
EK-RA4W1 R7FA4W1AD2CNG
EK-RA6M1 R7FA6M1AD
EK-RA6M2 R7FA6M2AF
RA4M1 CLICKER R7FA4M1AB
Select a firmware hex file in Data File of J-Link-Lite, and push Program Device button to flash the firmware.
Access the MicroPython REPL (the Python prompt) via USB serial or UART with 115200 baud rate, 1 stop bit and no
parity bit using your favorite terminal software, picocom on Linux or Tera Term on Windows. You can try on Linux:
$ picocom /dev/ttyACM0
help()
You can access RA MCU’s peripherals using MicroPython modules. To list supported modules, please enter:
help('modules')
Especially machine module and class machine.Pin are very important for using peripherals.
Using “from machine import Pin”, Pin name is available corresponding to the RA MCU’s pin name which are
Pin.cpu.P000 and ‘P000’. In addition, you can use ‘LED1’, ‘LED2’, ‘SW1’, and ‘SW2’ name if the board has these
LEDs and switches.
LED blinking
As simple example, you can enter following program to blink LED1. Please enter key 4 times after the input of last
time.sleep(1).
import time
from machine import Pin
led1 = Pin('LED1')
print(led1)
while True:
led1.on()
time.sleep(1)
led1.off()
time.sleep(1)
This message is displayed, and the program stops. The message means the program was interrupted at line 5 “while”
statement.
Using print(led1), you can confirm that LED1 is assigned to Pin.cpu.P106 on the board.:
So you can get the same result if Pin(Pin.cpu.P106) is specified instead of Pin(‘LED1’).
import time
from machine import Pin
led1 = Pin(Pin.cpu.P106)
print(led1)
while True:
led1.on()
time.sleep(1)
led1.off()
time.sleep(1)
As the factory setting, following 2 files are created in the file system:
• boot.py : executed first when the system starts
• main.py : executed after boot.py completes
See Reset and Boot Sequence for more information.
import os
os.getcwd()
f = open('main.py', 'rw+')
print(f.read())
f.write('import time\n')
f.write('from machine import Pin\n')
f.write('led1 = Pin(Pin.cpu.P106)\n')
f.write('while True:\n')
f.write(' led1.on()\n')
f.write(' time.sleep(1)\n')
f.write(' led1.off()\n')
f.write(' time.sleep(1)\n')
f.close()
f = open('main.py', 'r')
print(f.read())
f.close()
Entering CTRL-D for software reset, the MicroPython reboots, displays following messages:
and main.py is executed and LED1 blinks per 1 second. If you want to stop the program, please enter CTRL-C.
If that isn’t working you can perform a hard reset (turn-it-off-and-on-again) by pressing the RESET button. This will end
your session, disconnecting whatever program (PuTTY, screen, etc) that you used to connect to the board.
For more details, see Reset and Boot Sequence.
boot mode
There are 3 boot modes:
• normal boot mode
• safe boot mode
• factory filesystem boot mode
boot.py and main.py are executed on “normal boot mode”. See Boot Sequence.
The other modes can be used to recover from Soft Bricking (failure to boot):
boot.py and main.py are NOT executed on “safe boot mode”.
The file system of internal flash is initialized and all files are erased on “factory filesystem boot mode”.
For changing boot mode, please push the RESET button with pressing USER SW1 on the board:
• For normal boot mode, release the USER SW1 after LED1 flashes 4 times or more
• For safe boot mode, release the USER SW1 after LED1 flashes 2 times
• For factory file system boot mode, release the USER SW1 after LED1 flashes 3 times.
You have created the main.py which executes LED1 blinking in the previous part. If you change the boot mode to safe
boot mode, the MicroPython starts without the execution of main.py.
import machine
machine.freq()
machine.reset()
machine.soft_reset()
machine.unique_id()
machine.reset_cause()
machine.bootloader([value])
machine.disable_irq()
machine.enable_irq(state)
(continues on next page)
import time
14.6 Timers
The RA MCU’s system timer peripheral provides a global microsecond timebase and generates interrupts for it. The
software timer is available currently and there are unlimited number of them (memory permitting). There is no need to
specify the timer id (id=-1 is supported at the moment) as it will default to this.
Use the machine.Timer class:
tim = Timer(-1)
tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t: print(2))
Pin id is available corresponding to the RA MCU’s pin name which are Pin.cpu.P106 and ‘P106’. The RA MCU has many
feature’s pins. However, there are some cases that pin feature is fixed or not connected by the board. Please confirm the
board manual for the pin mapping.
The following drive keyword argument are available if the port drive capability of the Pin is supported by the MCU:
Pin.mode()
Pin.pull()
Pin.drive()
Available UARTs and pins on the board are fixed and follows. One of these UARTs is used for REPL.
rtc = RTC()
rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
# time, eg. 2017/8/23 1:12:48
# the day-of-week value is ignored
rtc.datetime() # get date and time
RTC.init(datetime)
RTC.now()
(continues on next page)
Pin id is available corresponding to the RA MCU’s pin name which are ‘P000’ as AN000 (analog channel 000). The RA
MCU has many analog channels. However, there are some cases that pin feature is fixed or not available by the board.
Please confirm the MCU and board manual for the pin mapping.
Following functions are not supported at the present:
ADC.init()
ADC(sample_ns)
ADC(atten)
ADC.read_uv()
ADC.block()
Available SPIs and pins on the board are fixed and follows.
EK-RA4M1 SPI0
sck P102
mosi P101
miso P100
cs P206
EK-RA4W1 SPI0
sck P102
mosi P101
miso P100
cs P103
EK-RA6M1 SPI0
sck P102
mosi P101
miso P100
cs P103
RA4M1-CLICKER SPI0
sck P102
mosi P101
miso P100
cs P103
i2c = I2C(0)
Available I2Cs and pins on the board are fixed and follows.
EK-RA4M1 •
EK-RA4W1 I2C0
scl P204
sda P407
EK-RA6M1 I2C0
scl P400
sda P401
EK-RA6M2 I2C2
scl P512
sda P511
RA4M1-CLICKER I2C1
scl P205
sda P206
14.15 SDCard
The frozen sdcard driver (drivers/sdcard/sdcard.py) is available by connecting microSD card device to hardware SPI0
pins.:
Be sure to put a 4.7k pull-up resistor on the data line. Note that the convert_temp() method must be called each time
you want to sample the temperature.
FIFTEEN
549
MicroPython Documentation, Release latest
15.2.1 Requirements
The first thing you need is a board with an SAMD chip. The MicroPython software supports the SAMD chip itself and
any board should work. The main characteristic of a board is how the GPIO pins are connected to the outside world, and
whether it includes a built-in USB-serial converter to make the UART available to your PC.
Names of pins will be given in this tutorial using the board names (“D0”) and it should be straightforward to find which
pin this corresponds to on your particular board.
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
2 PA02 A0 2 0 • • • •
35 PB03 FLASH_MISO
3 11 • 5/1 6/1 •
54 PB22 FLASH_MOSI
6 • • 5/2 7/0 •
3 PA03 3 1 • • • •
28 PA28 8 • • • • •
Pin GPIO Pin IRQ ADC ADC Serial Serial TC PWM PWM
name
2 PA02 A0 2 0 • • • • • •
3 PA03 • 3 10 • • • • • •
27 PA27 • 11 • • • • • • •
#. The pad # is the respective internal signal of that serial device. Details below.
• TC - These device are currently not assigned to Pin. the TC device pair 0/1 is used for ticks_us().
• PWM - Two columns with assignments of the TCC modules for PWM The cell content is device #/output #. Details
below.
Pin GPIO Pin IRQ ADC ADC Serial Serial TC PWM PWM
name
2 PA02 A0 2 0 • • • • • •
38 PB06 A5 6 • 8 • • • • •
3 PA03 AREF 3 10 • • • • • •
35 PB03 NEOPIXEL
9 15 • • 5/1 6/1 • •
27 PA27 • 11 • • • • • • •
36 PB04 • 4 • 6 • • • • •
37 PB05 • 5 • 7 • • • • •
39 PB07 • 7 • 9 • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M4 Express Adafruit ItsyBitsy
M4 Express pin assignment table.
The default devices at the board are:
• UART 5 at pins D0/D1, labelled RX/TX
• I2C 2 at pins PA12/PA13, labelled SDA/SCL
• SPI 1 at pins PA23/PA22/PA17, labelled MOSI, MISO and SCK
• DAC output on pins PA02 and PA05, labelled A0 and A1
Pin GPIO Pin IRQ ADC ADC Serial Serial TC PWM PWM
name
2 PA02 A0 2 0 • • • • • •
3 PA03 AREF 3 10 • • • • • •
33 PB01 ESP_GPIO0
1 13 • • 5/3 7/1 • •
37 PB05 ESP_RESET
5 • 7 • • • • •
43 PB11 FLASH_CS
12 • • • 4/3 5/1 0/5 1/1
11 PA11 FLASH_HOLD
11 11 • 0/3 2/3 1/1 0/3 1/7
9 PA09 FLASH_MISO
9 9 3 0/1 2/0 0/1 0/1 1/5
8 PA08 FLASH_MOSI• 8 2 0/0 2/1 0/0 0/0 1/4
42 PB10 FLASH_SCK
10 • • • 4/2 5/0 0/4 1/0
10 PA10 FLASH_WP
10 10 • 0/2 2/2 1/0 0/2 1/6
54 PB22 NEOPIXEL
22 • • 1/2 5/2 7/0 • •
38 PB06 RXLED 6 • 8 • • • • •
39 PB07 TXLED 7 • 9 • • • • •
17 PA17 USB_HOSTEN
1 • • 1/1 3/0 2/1 1/1 0/5
27 PA27 • 11 • • • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M4 Express Adafruit ItsyBitsy
M4 Express pin assignment table.
The default devices at the board are:
• UART 3 at pins PA23/PA22, labelled D0/D1 resp. RX/TX
• I2C 5 at pins PB02/PB03, labelled SDA/SCL
• SPI 4 at pins PA12/PA14/PA13, labelled MOSI, MISO and SCK
• DAC output on pins PA02 and PA05, labelled A0 and A1
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
2 PA02 A0_D0 2 0 • • • •
3 PA03 • 3 1 • • • •
27 PA27 • 15 • • • • •
28 PA28 • 8 • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M0 Express Adafruit ItsyBitsy
M0 Express pin assignment table.
The default devices at the board are:
• UART 4 at pins PB08/PB09, labelled A6_D6/A7_D7
• I2C 2 at pins PA08/PA09, labelled A4_D4/A5_D5
• SPI 0 at pins PA06/PA05/PA07, labelled A10_D10, A9_D9 and A8_D8
• DAC output on pin PA02, labelled A0_D0
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
2 PA02 A0 2 0 • • • •
27 PA27 LED_TX 15 • • • • •
3 PA03 • 3 1 • • • •
28 PA28 • 8 • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M0 Express Adafruit ItsyBitsy
M0 Express pin assignment table.
The default devices at the board are:
• UART 5 at pins PB23/PB22, labelled RX/TX
• I2C 3 at pins PA22/PA23, labelled SDA/SCL
• SPI 4 at pins PA10/PA12/PA11, labelled MOSI, MISO and SCK
• DAC output on pin PA02, labelled A0
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
8 PA08 D0 • 16 0/0 2/0 0/0 1/2
2 PA02 D1 2 0 • • • •
3 PA03 • 3 1 • • • •
570
23 PA23 7 Chapter 15. Quick3/1
reference 5/1
for the SAMD21/SAMD51
4/1 0/5 family
• •
27 PA27 • 15 • • • • •
MicroPython Documentation, Release latest
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M0 Express Adafruit ItsyBitsy
M0 Express pin assignment table.
The default devices at the board are:
• UART 0 at pins PA07/PA06, labelled D3/D4
• I2C 2 at pins PA08/PA09, labelled D0/D2
• SPI 0 at pins PA06/PA09/PA08, labelled D4, D2 and D0
• DAC output on pin PA02, labelled D1
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
2 PA02 A0 2 0 • • • •
3 PA03 A1 3 1 • • • •
19 PA19 FLASH_MISO
3 • 1/3 3/3 3/1 0/3
22 PA22 FLASH_MOSI
6 • 3/0 5/0 4/0 0/4
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M0 Express Adafruit ItsyBitsy
M0 Express pin assignment table.
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
15 PA15 NEOPIXEL 15 • 2/3 4/3 3/1 0/5
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M0 Express Adafruit ItsyBitsy
M0 Express pin assignment table.
The board does not provide access to UART, I2C, SPI or DAC.
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
32 PB00 EXT1_PIN3 0 8 • 5/2 7/0 •
38 PB06 EXT1_PIN5 6 14 • • • •
39 PB07 EXT1_PIN6 7 15 • • • •
36 PB04 EXT1_PIN9 4 12 • • • •
37 PB05 EXT1_PIN105 13 • • • •
2 PA02 EXT3_PIN3 2 0 • • • •
3 PA03 EXT3_PIN4 3 1 • • • •
28 PA28 EXT3_PIN9 8 • • • • •
27 PA27 EXT3_PIN1015 • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M0 Express Adafruit ItsyBitsy
M0 Express pin assignment table.
There are no pins labelled for default devices on this board. DAC output is on pin PA02, labelled EXT3_PIN3
Pin GPIO Pin IRQ ADC ADC Serial Serial TC PWM PWM
name
16 PA16 D0 0 • • 1/0 3/1 2/0 1/0 0/4
2 PA02 A0_D9 2 0 • • • • • •
3 PA03 AREF 3 10 • • • • • •
27 PA27 • 11 • • • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M4 Express Adafruit ItsyBitsy
M4 Express pin assignment table.
The default devices at the board are:
• UART 1 at pins PA16/PA17, labelled D0/D1
• I2C 2 at pins PA12/PA13, labelled SDA/SCL
• SPI 1 at pins PB22/PB23/PA01, labelled MOSI, MISO and SCK
• DAC output on pins PA02 and PA05, labelled A0_D9 and A4_D13
Pin GPIO Pin IRQ ADC ADC Serial Serial TC PWM PWM
name
33 PB01 CS 1 13 • • 5/3 7/1 • •
79 PC15 3V3_ENABLE
15 • • 7/3 6/3 • 0/5 1/1
78 PC14 5V_ENABLE
14 • • 7/2 6/2 • 0/4 1/0
36 PB04 A3_D3 4 • 6 • • • • •
37 PB05 A4_D4 5 • 7 • • • • •
39 PB07 A7_D7 7 • 9 • • • • •
90 PC26 BUT- 10 • • • • • • •
TON_1
91 PC27 BUT- 11 • • 1/0 • • • •
TON_2
92 PC28 BUT- 12 • • 1/1 • • • •
TON_3
107 PD11 BUZZER 6 • • 7/3 6/3 • 0/4 •
20 PA20 I2S_LRCLK
4 • • 5/2 3/2 7/0 1/4 0/0
22 PA22 I2S_SDOUT
6 • • 3/0 5/1 4/0 1/6 0/2
50 PB18 LCD_MISO
2 • • 5/2 7/2 • 1/0 •
51 PB19 LCD_MOSI
3 • • 5/3 7/3 • 1/1 •
15 PA15 LED_BLUE
15 • • 2/3 4/3 3/1 2/1 1/3
94 PC30 MIC 14 • 12 • • • • •
2 PA02 • 2 0 • • • • • •
3 PA03 • 3 10 • • • • • •
27 PA27 • 11 • • • • • • •
64 PC00 • 0 • 10 • • • • •
65 PC01 • 1 • 11 • • • • •
66 PC02 • 2 • 4 • • • • •
67 PC03 • 3 • 5 • • • • •
84 PC20 • 4 • • • • • 0/4 •
95 PC31 • 15 • 13 • • • • •
96 PD00 • 0 • 14 • • • • •
97 PD01 • 1 • 15 • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M4 Express Adafruit ItsyBitsy
M4 Express pin assignment table.
Default pin assignments: - UART 2 at pins PB27 and PB26, labelled RX and TX - I2C 4 at pins PA12 and PA13, labelled
SCL0 and SDA0 - I2C 3 at pins PA16 and PA17, labelled SCL1 and SDA1 - SPI 5 at pins PB00, PB02 and PB03, labelle
MISO, MOSI and SCK
There seems to be no default pin assignment for this board.
Pin GPIO Pin IRQ ADC ADC Serial Serial TC PWM PWM
name
2 PA02 A0 2 0 • • • • • •
10 PA10 FLASH_CS
10 10 • 0/2 2/2 1/0 0/2 1/6
11 PA11 FLASH_MISO
11 11 • 0/3 2/3 1/1 0/3 1/7
9 PA09 FLASH_SCK
9 9 3 0/1 2/0 0/1 0/1 1/5
43 PB11 MISO 12 • • • 4/3 5/1 0/5 1/1
27 PA27 TXLED 11 • • • • • • •
3 PA03 • 3 10 • • • • • •
36 PB04 • 4 • 6 • • • • •
37 PB05 • 5 • 7 • • • • •
38 PB06 • 6 • 8 • • • • •
39 PB07 • 7 • 9 • • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M4 Express Adafruit ItsyBitsy
M4 Express pin assignment table.
The default devices at the board are:
• UART 2 at pins PA13/PA12, labelled RXD/TXD
• I2C 5 at pins PA22/PA23, labelled SDA/SCL
• SPI 4 at pins PB12/PB11/PB13, labelled MOSI, MISO and SCK
• DAC output on pins PA02 and PA05, labelled A0 and A4
2 PA02 EGJ 2 0 • • • •
3 PA03 EGJ 3 1 • • • •
27 PA27 EGJ 15 • • • • •
28 PA28 EGJ 8 • • • • •
36 PB04 J 4 12 • • • •
37 PB05 J 5 13 • • • •
38 PB06 J 6 14 • • • •
39 PB07 J 7 15 • • • •
For the definition of the table columns see the explanation at the table for Adafruit ItsyBitsy M0 Express Adafruit ItsyBitsy
M0 Express pin assignment table.
The Package column indicates the package letter providing this pin. An entry EGJ tells for instance, that the pin is
available for SAMD21E18, SAMD21G18 and SAMD21J18.
2 PA02 GJP 2 0 • • • • • •
3 PA03 GJP 3 10 • • • • • •
27 PA27 GJP 11 • • • • • • •
36 PB04 JP 4 • 6 • • • • •
37 PB05 JP 5 • 7 • • • • •
38 PB06 JP 6 • 8 • • • • •
39 PB07 JP 7 • 9 • • • • •
65 PC01 P 1 • 11 • • • • •
66 PC02 P 2 • 4 • • • • •
67 PC03 P 3 • 5 • • • • •
69 PC05 P 5 • • 6/1 • • • •
70 PC06 P 6 • • 6/2 • • • •
71 PC07 P 9 • • 6/3 • • • •
84 PC20 P 4 • • • • • 0/4 •
85 PC21 P 5 • • • • • 0/5 •
90 PC26 P 10 • • • • • • •
91 PC27 P 11 • • 1/0 • • • •
92 PC28 P 12 • • 1/1 • • • •
94 PC30 P 14 • 12 • • • • •
95 PC31 P 15 • 13 • • • • •
96 PD00 P 0 • 14 • • • • •
97 PD01 P 1 • 15 • • • • •
The Package column indicates the package letter providing this pin. An entry GJP tells for instance, that the pin is available
for SAMD51G19, SAMD51J19/-J20 and SAMD51P19/-P20.
def tblkey(i):
name = i[1]
if name != "":
if len(name) < 3:
return " " + name
else:
return name
else:
return "zzzzzzz%03d" % i[0]
if sort:
pintbl.sort(key=tblkey)
for item in pintbl:
print_pininfo(item[0], item[1], item[2])
table()
import machine
The range accepted by the function call is 1_000_000 to 200_000_000 (1 MHz to 200 MHz) for SAMD51 and 1_000_000
to 54_000_000 (1 MHz to 54 MHz) for SAMD21. The safe range for SAMD51 according to the data sheet is up to 120
MHz, for the SAMD21 up to 48Mhz. Frequencies below 48Mhz are set by dividing 48Mhz by an integer, limiting the
number of discrete frequencies to 24Mhz, 16Mhz, 12MHz, and so on. At frequencies below 8 MHz USB will be disabled.
Changing the frequency below 48 MHz impacts the baud rates of UART, I2C and SPI. These have to be set again after
changing the CPU frequency. The ms and µs timers are not affected by the frequency change.
import time
Note that time.sleep_us() delays by busy waiting. During that time, other tasks are not scheduled.
import time
The format of the date_time tuple follows the standard. The µs value of the date_time tuple is ignored. On boards without
the RTC module, time.localtime(seconds) sets the system time. Use of the Use the RTC module:
The weekday value set will be ignored and calculated in the returned tuple from the actual date. rtc.now() is only provided
at SAMD51 boards. The value used in the rtc.calibration() call has a range from -127 - 127. It defines roughly a ppm
quantity, by which the clock can run faster or slower.
15.8 Timers
The SAMD21/SAMD51 uses software timers. Use the machine.Timer class:
tim0 = Timer()
tim0.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(0))
tim1 = Timer()
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))
Pins can be denoted by a string or a number. The string is either the pin label of the respective board, like “D0” or “SDA”,
or in the form “Pxnn”, where x is A,B,C or D, and nn a two digit number in the range 0-31. Examples: “PA03”, PD31”.
Pin numbers are the MCU port numbers in the range:
PA0..PA31: 0..31
PB0..PB31: 32..63
PC0..PC31: 64..95
PD0..PD31: 96..127
Note: On Adafruit Feather and ItsyBity boards, pin D5 is connected to an external gate output and can therefore only be
used as input.
The SAMD21/SAMD51 MCUs have up to eight hardware so called SERCOM devices, which can be used as UART,
SPI or I2C device, but not every MCU variant and board exposes all TX and RX pins for users. For the assignment of
Pins to devices and UART signals, refer to the SAMD pinout.
# create PWM object from a pin and set the frequency and duty cycle
pwm = PWM(Pin('D7'), freq=2000, duty_u16=32768)
pwm.freq() # get the current frequency
pwm.freq(1000) # set/change the frequency
pwm.duty_u16() # get the current duty cycle, range 0-65535
pwm.duty_u16(200) # set the duty cycle, range 0-65535
pwm.deinit() # turn off PWM on the pin
(continues on next page)
Construct and return a new PWM object using the following parameters:
• dest is the Pin object on which the PWM is output.
PWM objects are provided by TCC timer module. The TCC timer modules have up to six channels and
eight outputs. All channels of a module run at the same frequency, but allow for different duty cycles.
Outputs are assigned to channels in modulo-n fashion, where n is the number of channels. Outputs of
a channel have the same frequency and duty rate, but may have different polarity. So if for instance a
module has four channels, output 0 and 4, 1 and 5, 2 and 6, 3, and 7 share the same frequency and duty
rate.
Only one of duty_u16 and duty_ns should be specified at a time.
Keyword arguments:
• freq should be an integer which sets the frequency in Hz for the PWM cycle. The valid frequency
range is 1 Hz to 24 MHz.
• duty_u16 sets the duty cycle as a ratio duty_u16 / 65535.
• duty_ns sets the pulse width in nanoseconds. The limitation for X channels apply as well.
• invert=True|False. Setting a bit inverts the respective output.
• device=n Use TCC module n if available. At some pins two TCC modules could be used. If not
device is mentioned, the software tries to use a module which is not yet used for a PWM signal.
But if pins shall have the same frequency and/or duty cycle to be changed synchronously, they must
be driven by the same TCC module.
The resolution of the ADC is 12 bit with 12 bit accuracy, irrespective of the value returned by read_u16(). If you need a
higher resolution or better accuracy, use an external ADC.
Construct and return a new ADC object using the following parameters:
• dest is the Pin object on which the ADC is output.
Keyword arguments:
• average is used to reduce the noise. With a value of 16 the LSB noise is about 1 digit.
• vref sets the reference voltage for the ADC.
The default setting is for 3.3V. Other values are:
Read a single ADC value as unsigned 16 bit quantity. The voltage range is defined by the vref option of the constructor,
the resolutions by the bits option.
The resolution of the DAC is 12 bit for SAMD51 and 10 bit for SAMD21. SAMD21 devices have 1 DAC channel at
GPIO PA02, SAMD51 devices have 2 DAC channels at GPIO PA02 and PA05.
The vref arguments defines the output voltage range, the callback option is used for dac_timed(). Suitable values for vref
are:
Write a single value to the selected DAC output. The value range is 0-1023 for SAMD21 and 0-4095 for SAMD51. The
voltage range depends on the vref setting.
If miso is not specified, it is not used. For the assignment of Pins to SPI devices and signals, refer to SAMD pinout.
Note: Even if the highest reliable baud rate at the moment is about 24 Mhz, setting a baud rate will not always result in
exactly that frequency, especially at high baud rates.
Be sure to put a 4.7k pull-up resistor on the data line. Note that the convert_temp() method must be called each time
you want to sample the temperature.
import dht
import machine
d = dht.DHT11(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)
Be sure to have a 4.7k pull-up resistor on the data line. Some DHT modules may already have one.
Since SoftSPI does not allow miso to be undefined, miso has to be assigned to an otherwise unused pin.
import neopixel
import machine
machine.bitstream() is set up for a SAMD21 clock frequency of 48MHz and a SAMD51 clock frequency of 120 MHz.
At other clock frequencies, the timing will not fit.
_ j
_thread, 46 json, 19
a l
aioespnow, 204 lcd160cr, 176
array, 2
asyncio, 3 m
machine, 66
b marshal, 20
binascii, 7 math, 20
bluetooth, 46 micropython, 101
btree, 58
n
c neopixel, 104
cmath, 11 network, 105
collections, 12
cryptolib, 60 o
openamp, 118
d os, 22
deflate, 61
p
e platform, 25
errno, 13 pyb, 133
esp, 187
esp32, 189
r
espnow, 194 random, 25
re, 26
f rp2, 208
framebuf, 63 s
g select, 29
socket, 30
gc, 14
ssl, 35
gzip, 15
stm, 175
struct, 38
h
sys, 39
hashlib, 16
heapq, 17 t
time, 41
i
io, 18 u
uctypes, 120
605
MicroPython Documentation, Release latest
v
vfs, 125
w
wipy, 183
z
zephyr, 220
zlib, 45
zsensor, 221