Designing Embedded Systems using MicroPython

The C/C++ programming languages have long dominated the embedded systems industry, with very few other languages being able to find a foothold. While languages such as Java and Ada have certainly tried, the popularity of Python has not only been on the rise but has been finding its way into Linux based applications for quite some time. Python for use on a microcontroller though never seemed like it would fit the bill until MicroPython, a Python 3 port designed to run on microcontrollers. With the project now in its sixth year, it’s been gaining popularity and momentum that could make it the programming language you use to design your next product. Let’s examine a few pros and cons for using MicroPython.


Python Language Programming Characteristics

The Python programming language has a shallow learning curve which makes it extremely easy for developers to get started with it. In fact, I’ve encountered elementary students who were learning Python! Python provides developers with a high-level programming language that they can use to build simple scripts or that can be used to develop complex object-oriented architectures that utilize all the best practices for a modern software project. When compared with C, Python also provides built in mechanisms for creating threads, handling errors and easily integrating into test harnesses.

What’s interesting about these language characteristics is that it makes it possible for every member of a development team to become a programmer! MicroPython provides a series of libraries that provide control to low-level microcontroller features that abstract out the complexity. For example, a hardware engineer could design their circuit board and with little to no knowledge about how the microcontroller works (or C), develop high-level scripts that could test their circuit board by controlling GPIO or even communicating with I2C devices. Developing an I2C driver can be fairly complicated in C, but with MicroPython it requires nothing more than the following lines of code to create an I2C object and send data to a slave device:


from pyb import I2C

i2c = I2C(1)                                                        # create on bus 1

i2c = I2C(1, I2C.MASTER)                                 # create and init as a master

i2c.init(I2C.MASTER, baudrate=400000)        # init as a master


# Set the proximity threshold that will enable GMODE

i2c.mem_write(40, DEVICE_SLAVE_ADDRESS, REGISTER_ADDRESS, timeout=1000)


That’s it! All the ground work for handling I2C is handled by the MicroPython libraries which dramatically simplifies development for a developer. (Looking at one of my I2C drivers in C revealed several thousand lines of code, granted it is a very robust implementation and provides a just a handful of functions to interact with the bus once the ground work is laid).


Production Design Considerations

When considering using MicroPython for product development, there are several key considerations that developers need to consider. First, developers need to consider how to protect their application code. MicroPython allows developers to either load code text based Python scripts or to compile those scripts into bytecode and placed into a .mpy module. The problem with these solutions is that the application code is readily available to anyone who can gain access to the MicroPython file system which is quite easy to do. The bytecode does make it a little bit harder but it’s not too difficult to convert the byte code back into readable code. Developers need to consider how secure they need their system to be and potentially take extra steps to protect the intellectual property.

Next, developers need to consider how they will recover their system if something goes wrong. Depending on the microcontroller selected they may have their application code internal on the MCU or externally on a memory device such as an SD card. I’ve found that the filesystem is not very robust when it comes to power cycles or brown out conditions. If the file system becomes corrupted, MicroPython will recover it by copying a default image back to the file system. Developers need to make sure that their default code is integrated into their kernel build so that if something does go wrong, they are at least returned to a factory default setting and then can restore any updates from other memory locations that may be present on the device.

Finally, developers may want to make sure that they have multiple memory devices on board to choose from. The new flagship MicroPython development board, the pyboard D-series, includes two separate SPI memory devices of 2 MB each. One is used to store application code while the other can store data or other information. A production system should do something similar or even keep a firmware backup copy so that if something goes wrong, the application could be restored without issues to the user.


MicroPython Based Products

While using MicroPython for product design sounds intriguing, has anyone actually used it to develop a commercial product? As far as I know, MicroPython has been used in several products and most likely more that I am not aware of. For example, MicroPython has been used in small satellites for electronic power supplies and data acquisition systems (some of which I have personally worked on). The European Space Agency has also been investigating using MicroPython on larger satellite systems.

MicroPython is also used on the popular OpenMV module which allows developers to create machine vision applications. The module runs MicroPython and allows developers to create their scripts through an interactive IDE that then downloads the developer’s scripts to the module. Developers can even train a machine learning model and convert it to run on the OpenMV module! This shows that MicroPython can be used to run more than just simple algorithms or toggle a few I/O.



Using MicroPython to build an embedded product will not meet every development teams needs like C/C++ but it provides developers with an intriguing solution for rapid prototyping or developing commercial products. There are certainly challenges that still exist such as securing a MicroPython based system and ensuring deterministic behavior. These are challenges that can be overcome with proper application design up front. MicroPython’s ease of use and Python’s popularity makes using MicroPython to build embedded systems an intriguing opportunity.

One thought on “Designing Embedded Systems using MicroPython”

  1. In my view a good target application for MicroPython is IoT and Building Automation sensors. Many of these are low sample rate and the speed with which you can get a system communicating and collecting data is surprising.

    I have also used it for debugging i2c busses. You can prove the h/w is working , as expected, pretty quickly resolving the question “is it my s/w or the h/w ?”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.