(Source: MPIX.TURE/Shutterstock.com)
Computer programming languages are a fascinating study of technological evolution. From machine code and assembly language to the first high-level languages such as COBOL and FORTRAN, the march toward more powerful yet easier-to-comprehend languages has enabled faster development cycles and brought programming to an increasingly broader spectrum of creators, from professional to amateur.
Before the advent of Arduino and Raspberry Pis, many proto-makers got our start with PBASIC and microcontrollers such as the BASIC Stamp. In the professional embedded world, the C programming language has long reigned supreme. Indeed, the Arduino “programming language” consist of a set of C/C++ functions. This allows the complexity of programming for various embedded devices to be abstracted away to be more friendly to those who are just beginning their embedded electronics education. So while the C-language dominance is still reasonably secure, the winds of change are afoot. Enter the Python programming language.
According to a July 2020 IEEE study, Python is the most popular programming language of 2020. Its creator, Guido van Rossum, explained that Python was created for the following reasons:
“I had extensive experience with implementing an interpreted language in the ABC group at CWI, and from working with this group, I had learned a lot about language design. This is the origin of many Python features, including the use of indentation for statement grouping and the inclusion of very-high-level data types.”
Guido goes on to explain the impact of other languages on Python design choices:
“Modula-3 is the origin of the syntax and semantics used for exceptions and some other Python features.”
Also:
“My experience with error handling in Amoeba made me acutely aware of the importance of exceptions as a programming language feature.”
The Python programming language was first released over 30 years ago. Python code is first compiled to a byte-code and then fed to an interpreter, which is a large C program (see, you just can’t avoid C). A popular aspect of Python is the interactive interpreter mode or read-evaluate-print-loop (REPL), a way to interact with Python via a command-line interactive prompt to test out concepts before committing the code to a .py file. MicroPython firmware can also be built and ran without the compiler because the virtual machine can run pre-compiled (.mpy) programs.
.py
.mpy
Fast forward to 2014, and MicroPython is released. For those with experience with programming on the desktop, you are likely to use a particular implementation of Python known as CPython, which is the language’s reference implementation. MicroPython is simply another implementation, one that is optimized for memory and processing constrained hardware such as a microcontroller. MicroPython contains a full Python 3 compiler, runtime, and subset of the Python standard library. As an aside, MicroPython has since been forked itself into CircuitPython, which is more focused on the education and maker communities. Here are examples of MicroPython’s versatility and influence in embedded development.
The MicroPython interpreter is available on quite a few development boards with various hardware features. When acquiring a MicroPython-based development board, the first thing to do is update the interpreter firmware to the latest version. This is accomplished by visiting the MicroPython firmware website and downloading the latest device firmware update (.dfu) file for your particular board. Each board has a different physical methodology for entering an update mode. It will typically involve shorting a certain pin to a voltage or ground when applying power to the board. With the development board plugged into a computer and set to update mode, launch a utility called dfu-util (available at https://sourceforge.net/projects/dfu-util) to flash the new firmware to the development board.
.dfu
dfu-util
The exact mechanics of using dfu-util will vary depending on your host system operating system (Windows, Mac OS, Linux). Some additional steps might be required if using a Windows-based host computer.
Once complete, unplug the USB cable from the development board and plug it back in. The development board should enumerate as a removable medium such as a USB flash drive or disc. The drive should be listed as /flash, and it should contain the following four files:
/flash
boot.py
main.py
pybcdc.inf
readme.txt
It is possible to interact with the development board using a REPL via serial terminal on the host computer. Alternatively, we can use a code editor to edit the main.py file. A neat feature about MicroPython and associated development boards is that that source code remains as a user-accessible file. By simply plugging the development board into a computer, it enumerates as a removable storage device. The source code file can then be viewed and edited directly in the end-users code editor of choice. Then by ejecting the development board, unplugging and powering the board up, the new or modified source code is executed.
Several development tools are capable of handling MicroPython. Some of the more popular choices include:
MicroPython has been ported to many Arm® Cortex®-M4-based embedded platforms (including STM32, TI CC3200/WiPy, Teensy boards, Nordic nRF series, SAMD21, and SAMD51), Also, it has been ported to other architectures such as ESP8266, ESP32, 16bit PICs, RISC-V (RV32 and RV64), and even Lego Mindstorms EV3. MicroPython must contend with a significant variety of architectures and embedded system specifications versus the relatively more homogenous environment of CPython (mostly x86/x64 and ARM architecture). As such, there are a few not insignificant differences between CPython and MicroPython. A few key differences include:
sys.path
0:/
1:/
mymodule.py
import mymodule
module.py
mymodule
__init__.py
sys.path.append('1:/')
import array
import uarray
pyb
esp
pyb.delay(ms)
pyb.disable_irq()
:=
sys.stdin
sys.stdout
sys.stderr
The entirety of the differences between CPython and MicroPython are too many to enumerate here. For the most part, the differences should be fairly minimal to all but the most fastidious Python coders. If you encounter an error trying to implement a feature that you know works with CPython, check this site for a robust list of differences between CPython and MicroPython.
If speed is a priority, it is possible to write inline assembly code within MicroPython. The inline assembler supports a subset of the ARM Thumb-2 instruction set. The inline assembly is subsequently converted into Python function calls. Per the Architecture Reference Manual, “... [the assembly] instructions operate on 32-bit signed integer data except where stated otherwise. Most supported instructions operate on registers R0-R7 only: where R8-R15 is supported, this is stated. Registers R8-R12 must be restored to their initial value before return from a function. Registers R13-R15 constitute the Link Register, Stack Pointer, and Program Counter, respectively.”
MicroPython is an exciting new entry into the embedded development world. It offers tantalizing new possibilities for professionals and makers alike. Although it might not be ideal for certain edge use cases with extremely tight timing and performance requirements, it can be a worthy companion to the traditional C programming language. Coupled with Python language’s rise, MicroPython can serve as a bridge to desktop application developers looking to get started in embedded hardware development.
Michael Parks, P.E. is the co-founder of Green Shoe Garage, a custom electronics design studio and embedded security research firm located in Western Maryland. He produces the Gears of Resistance Podcast to help raise public awareness of technical and scientific matters. Michael is also a licensed Professional Engineer in the state of Maryland and holds a Master’s degree in systems engineering from Johns Hopkins University.