Embedded Hardware Development with MicroPythonDesign Trends and the Transformation of Everything
Read the full Design Trends eZine:
Interview with Limor "Ladyada" Fried - Founder, Adafruit
MicroPython and a variant, CircuitPython, are enjoying increasing popularity among microcontroller programmers. To learn more about why this is so and how to apply MicroPython, we reached out to Limor Fried—
a leader and innovator in this space. Here’s what she had to say.
MicroPython at a Glance
These days, people are paying a lot of attention to the Internet of Things (IoT) and how connected devices are changing just about everything. The engineering behind this phenomenon centers on embedded hardware development, which is creating smarter IoT devices and pushing more computing power to the network edge. Several factors are making this advance possible. One important advance is the growing popularity of MicroPython, a version of the Python programming language specifically designed as a simple language for quickly developing programs that run on microcontrollers that have limited processing speed and memory. MicroPython makes it possible to shorten the development cycle for embedded hardware solutions, which is an important consideration when designing IoT products.
Q. What are MicroPython and CircuitPython? How do they stack up to the Python installation you may find on a client or server machine?
A. Damien George created MicroPython in 2013, as an implementation of Python designed to run on microcontrollers— processors with limited speed, RAM, and flash memory relative to more sophisticated microprocessors. Damien implemented MicroPython from scratch, making design decisions that favored efficient use of the limited resources available on these chips. The core language of MicroPython is close to Python’s version 3.4, with some rarely used features omitted or slightly changed. Many of the “batteries included” libraries that ship with the standard implementation of Python are not included, largely for space reasons. In addition, MicroPython typically has either no underlying operating system or a simple, real-time operating system. Many operating system features, such as file system access, MicroPython or CircuitPython must provide directly or through specialized libraries. Both MicroPython and CircuitPython include natively implemented Python modules that enable “close-tothe-metal” access to the on-chip peripherals that microcontrollers provide.
Scott Shawcroft, working for Adafruit, started CircuitPython in 2016. The original idea was to port MicroPython to the SAMD21 series of microcontrollers, which Adafruit uses extensively in its products. Eventually, because the goals of MicroPython and Adafruit were different, Adafruit forked MicroPython and named the fork CircuitPython. Adafruit considers CircuitPython a “friendly” fork: CircuitPython incorporates updates from MicroPython regularly, and Adafruit keeps in touch with Damien about what both organizations are working on.
Why would someone use MicroPython/CircuitPython for an embedded project instead of traditional C/C++ tools?
As with Python, MicroPython and CircuitPython allow for a quick development cycle. You can write the code quickly and make changes and retest code quickly. The higher-level language features of Python, such as automatic storage management, easy string manipulation, and variablelength sequences, reduce program size and remove a lot of tedious code. Mapping and filtering a list, for example, require 20 to 30 lines of C/ C++ code but just a single line of readable Python code.
MicroPython and CircuitPython have no pointers or memory alignment issues to worry about, and string and file parsing are built into Python natively, which make it a great language for the Internet of Things and user interface products. Using Python for embedded applications is never going to be as fast or as memory efficient as using C/C++ or similar compiled languages, but an embedded application often doesn’t need to be that fast or small. When the underlying technology is more powerful and complicated, it’s important to be able to get something working quickly and to change it on the fly. For example, consider the user of embedded computers in a laboratory environment or a flexible manufacturing environment. Changes can be made and tested much more quickly with a language like Python.
Key Facts
- Gartner predicts that the market for “connected things” will continue to grow by more than 30 percent per year through 2020.
- Based on a Stack Overflow Trends report, Python is currently the fastest-growing computer language in the world.
- In a recent article at Electronic Design, William Wong explains how MicroPython provides advantages for embedded systems that require shorter development cycles and platform portability.
What’s the typical edit/debug cycle in a MicroPython/CircuitPython environment? Do you typically develop directly on the target hardware, or do you cross-develop using a separate workstation?
A big advantage of MicroPython is that it has a faster development cycle than C/C++. The MicroPython or CircuitPython board provides an onboard file system that appears as a USB flash drive. You can edit code on the board directly from the host computer. The main program— main.py (MicroPython) or code.py (CircuitPython)—executes when the board starts and contains a loop that runs forever, analogous to the loop() function in an Arduino program. You can store additional code files as Python source (.py) files or as precompiled bytecodes (.mpy) and data files in whatever format you like.
In addition to the disk drive, a serial USB connects to the Python interactive read-eval-print loop (REPL), so you can type Python code at the REPL prompt for testing. The onboard program can also print and read to and from that serial connection.
Being an interpreted language, Python runs code instantaneously: There’s no compile, link, convert, bootload, upload, like in C. Instead, you edit code directly on the device, and it executes the moment you save changes. When you’re working on projects that require a lot of calibration and tweaking, Python can save you hours.
Adafruit recommends the Mu editor (https://codewith.mu) for beginners. It contains a simple Python-aware editor and a serial connection to the MicroPython or CircuitPython board. It automatically detects the device when plugged in, has a REPL window, and even comes with a built-in plotter.
Does MicroPython/CircuitPython support direct hardware I/O access? What kind of TCP/IP networking support does it typically support? What about Bluetooth?
Both MicroPython and CircuitPython include natively implemented Python modules that enable direct access to on-chip peripherals, such as general-purpose I/O pins and analog conversion. In MicroPython, these modules can vary between ports. In CircuitPython, Adafruit has tried to make these libraries as uniform as possible across microcontrollers and microcomputers. For example, you can use our more than 100 CircuitPython drivers and libraries with Raspberry Pi or BeagleBone Linux running classic Python 3.
MicroPython/CircuitPython provide network stack access to boards that have Wi-Fi and Ethernet. There are MicroPython ports to both the ESP8266 and ESP32 models. CircuitPython has been ported to ESP8266. Simple wired Ethernet support was recently added to CircuitPython as well. MicroPython can use Bluetooth Low Energy or other radio-based protocols on boards that support them. CircuitPython is currently being ported to the nRF528xx series of microcontrollers; an alpha version of Bluetooth Low Energy is currently available.
What range of microcontrollers and embedded processors can run MicroPython/CircuitPython? What are typical RAM and flash minimum sizing requirements?
CircuitPython has ports to the Microchip/Atmel SAMD21 (M0) and SAMD51 (M4) microcontrollers and to the ESP8266 module. SAMD21 chips run at 48 MHz, with 32KB of RAM and 256KB of on-chip flash memory— the minimum for getting started with basic projects. SAMD51 chips are much faster, with a 120-MHz clock, up to 256KB of RAM, and 1MB of flash storage. A port to the nRF52832 and nRF52840 microcontrollers is underway and available in alpha versions. Because Python is interpreted and has a garbage collector, plenty of RAM is handy (we recommend 64KB or more).
Adafruit’s “Express” boards, which are designed for CircuitPython, also provide an onboard external SPI flash chip, typically 2 to 8MB, used as the file system for storing Python code and other files. MicroPython is not ported to SAMDx1 chips but includes many ports for STM32, ESP32, nRF51, nRF52, Kinetis, and several other processors.
Mouser Manufacturers Leading the Way
- Adafruit’s recent partnerships with Microsoft MakeCode and Cartoon Network will help inspire the next generation of engineers. And Ladyada’s recent awards from Inc. and Forbes further solidify Adafruit’s place in the future of electronics.
Does MicroPython/CircuitPython have any special features for supporting embedded development, such as multithreading, memory management, and the ability to differentiate read-only memory and read/write memory?
Many issues that come up in embedded programming are already solved in Python. Take memory management. Humans and pointers don’t mix very well, but in Python, you never have to worry about accidentally overwriting memory because all objects are checked during all instance accesses.
Also, many embedded engineers struggle to perform full error checking at all steps. In C, returns checking is particularly clunky and easy to mess up. In Python, exceptions are built in, so you can halt at any failure. If you make a “divide by zero” or a memory access mistake, your code doesn’t completely halt. Instead, it will bump out an exception that you can display to the user, communicate up the control queue, or handle immediately. Adafruit implements locking for peripherals, so you don’t have to worry about multiple objects talking to the SPI port, for example.
MicroPython has optional threading and interrupt callback support as well. In CircuitPython these features are not currently supported, but Adafruit is examining ways to provide concurrency and asynchronous execution that is simple to use and understand. Currently, we implement those operations that require concurrency and asynchronous handling in the native CircuitPython libraries.
We have built some nice features into CircuitPython that handle concurrency for you. Obviously, the USB parts are completely handled for you, separate from the runtime code. Timers are dynamically allocated to the first one available. Audio playback is built in: You can play .wav files right off the file system, completely asynchronously.
We also added direct memory access for all underlying peripheral transactions—with no effort required.
Does MicroPython/CircuitPython follow Python 2 or Python 3 syntax? What are the implications for embedded development?
MicroPython and CircuitPython are up to date with Python 3.4. Support for Python 2 is not a good idea because that version has been deprecated, and all new development is in Python 3 only.
Can I use any of the standard Python packages found in the Python Package Index (PyPI)? If not, what packages are typically compatible with MicroPython/ CircuitPython? How do I know which packages will work with MicroPython/CircuitPython?
Packages that depend on the built-in libraries and are not optimized may not fit in memory for the smaller microcontrollers. Many PyPI libraries are too large or not written with limited storage in mind. Some smaller libraries and a lot of example code will work just fine (just, not NumPy, for example).
For chips, actuators, and sensors, Adafruit has written well-supported and easy-to-use libraries that support various hardware devices available on PyPI, such as I2 C sensors and LED color management. Adafruit also wrote a wrapper library (adafruit-blinka) that enables those libraries to run using native, regular Python on the Raspberry Pi and other boards that support access to chip peripherals. More than 110 CircuitPython drivers and libraries are available, and we are adding more all the time. Just search for “adafruitcircuitpython” on pypi.org.
Are there any runtime royalties or licensing considerations for MicroPython/CircuitPython, particularly with regard to using it in product design?
Both MicroPython and CircuitPython use the permissive MIT open source license, which allows free use for any purpose as long as copyright notices and original license text are included in derived products. There are no license fees for production use.
For a product application, can my Python source code be read back out of the embedded hardware? If yes, are there ways to protect my code so that no one else can access it?
Yes. The Python source is stored in the onboard file system and can be accessed again. You can store the code as a compiled .mpy file (similar to a .pyc file), which stores bytecodes. This format obfuscates the code but doesn’t hide it.
It’s possible to further restrict the source to the onboard file system, but we have not implemented such a feature. At this time, MicroPython/ CircuitPython would not protect code against advanced hardware snooping. In contrast, most microcontroller chips can have firmware read out of them, and many devices are moving toward embedded Linux with Python, where a whole file system is available. If you have keys that you want to keep secret, Adafruit recommends a security chip to handle that encryption and privacy for you.
Massachusetts Institute of Technology-educated hacker and engineer Limor “Ladyada” Fried founded Adafruit in 2005 to be the best place online for learning electronics and designing products for makers of all ages and skill levels. Adafruit has grown to more than 100 employees in a 50,000- square-foot factory in New York City, New York. It has expanded to include tools, equipment, and electronics that Limor personally selects, tests, and approves before they go into the Adafruit store. Adafruit is a 100 percent woman-owned company.