Python is one of the fastest growing languages in the world. It’s accessible enough for schools to teach as a first programming language but powerful enough to handle the complexities of some of the most widely used web services, including Instagram, Spotify, and Netflix. And now Python’s star is rising in the world of physical computing too.
Languages like C and C++ and their cousin Arduino used to dominate hardware, from hobbyists in garages to engineers in industry. But these days, thousands of makers are switching to Python to control hardware, whether they’re programming microcontrollers or designing microprocessors. Today more than 130 microcontroller boards support Python, including the original Pyboard, the blazing Teensy 4.0, the tiny Serpente, a host of Adafruit boards, and even five Arduinos.
In this article, we’ll explore the reasons behind this shift, talk about why you might (or might not!) want to use Python in your next project, and take a look at some cool hardware projects and technologies that use Python.
Best for Beginners?
Beginner programmers often ask, “Which language is best to learn: Python or C++?” There’s no definitive answer, of course, but here are some reasons why many programmers might well respond with “Python.” Let’s start off with user friendliness. When you upload your code to an Arduino board, your computer compiles it into a machine-readable binary format. The semicolons and curly braces in your code help the compiler to identify where statements and function blocks begin and end. Python doesn’t require semicolons to end lines and instead relies on indentation to distinguish code blocks. This has the benefit of making Python code very human-readable and clean.
Python is also not as nosy about your variables because as an interpreted language it doesn’t require the programmer to manage memory — Python manages memory for you. Data types for variables in C languages (floats, integers, const signed long, etc.) have to be declared, but Python will happily interpret these for you. Because the language isn’t compiled but interpreted, you can also skip all those pesky considerations that have to do with memory management, like “Should I use a constant? Is this a long or a short? Do I need to use a pointer?”
Python is also a fantastic choice for rapid prototyping because of its readability and ability to run without needing to compile. When you upload your code to an Arduino, it has to compile and flash the hardware, which takes time. When you save your CircuitPython code to a board, it skips that step and executes the code as soon as you hit Save. But hold up! This doesn’t make Python code faster. Compiled languages like C++ are actually much faster, because they don’t have to be interpreted at runtime. For projects where speed is of the essence (for example, when using extra demanding sensors or actuators), this is something to consider, but for most beginner maker projects it won’t likely be an issue.
MicroPython and CircuitPython
Two Python implementations are heating up the microcontroller world. First up is MicroPython, created by Damien George for the STM32 chip but now popularly used by both the BBC micro:bit as well as the ESP32. MicroPython is a direct translation of Python with its own interpreter.
The other big player is CircuitPython, a fork of MicroPython maintained by Adafruit Industries. CircuitPython’s goal is to lower the barrier to entry for beginner programmers, so the Adafruit team have decided to sacrifice some functionality in exchange for simplicity. We’ll show off some of its features later in this article.
Community, Education, Creativity
The other big advantage of using Python on hardware is the people that come with it. Lots of new users are coming over from the Python community, many of whom have little or no experience with hardware. For developers who’ve never touched a microcontroller, something like the Circuit Playground Express (CPX) allows them to experiment with the joy of DIY sensing systems, blinky lights, and buzzy music without needing all the tools, electrical engineering knowledge, and fabrication skills to put together a circuit.
There’s also the cultural aspect: Python is well known as a language that has a comparatively diverse, welcoming user base. This is a tradition that Adafruit are continuing with their family-friendly, tightly moderated Discord channel which has over 17,000 members who you can ask for help troubleshooting your project.
Boards running Python are extremely popular learning devices in education, from schools and colleges to families who want to explore technology at home. The BBC micro:bit alone has deployed nearly 5 million devices into education, including 1 million in the UK, 45,000 to schools across Croatia, and one for every fourth grade child in Denmark. Microsoft’s MakeCode, a popular visual block-based programming environment for Minecraft, micro:bit, CPX, and other education-focused technologies, added Python support this year, so students can toggle back and forth between visual blocks and text-based Python while they learn the ropes.
Another significant group using Python on hardware are people who are looking to add technology into their existing practice — artists, designers, scientists, and cosplayers who use hardware as a tool to make their work easier, cooler, or more exciting. These people, like many Arduino users, don’t necessarily want to learn to code to become a programmer, they want to learn to code so they can make their ideas come to life.
This wide variety of users are exactly what the team behind CircuitPython — including Scott Shawcroft, Kattni Rembor, and Anne Barela — keep in mind when they make decisions about the direction they take their work in. Kattni explains that this is why every board they work on comes with a wide range of learning guides and ready-to-use examples that are designed around creative applications of the tech. Scott says their approach is to minimize the number of computing concepts people need to know to make useful and fun things when they’re starting out, saying that “If it ruins the beginner experience then we’re not interested.”
Bigger, Slower, Hungrier
Python on hardware is still a work in progress and won’t be the best option for every project. Some common complaints are that it requires a lot of memory and uses up a lot of power. For example, one badge hacking team wanted to use CircuitPython for a convention badge but weren’t able to, given that a badge needs to last for a weekend of hacking on two AA batteries.
As mentioned, Python is also slower than C++ so if you’re weighing up CircuitPython on the Circuit Playground Express versus C++ code on the eye-wateringly fast Teensy 4.0, then Python might not come out on top for your project.
There has always been room in our community for different languages that serve different purposes. It’s clear that Python on hardware has a great deal to contribute and that it’s here to stay.
Getting Started With CircuitPython
Let’s get started with Python on hardware. We’re going to use CircuitPython and Adafruit’s Circuit Playground Express board (Figure A).
The easiest way to start coding Python on hardware is using the Mu code editor, a free and open source piece of software. Go to codewith.mu and install the package that works best for your system. Then plug in your board with a USB cable that supports both data and charging. If you see a drive called CIRCUITPY appear on your computer then you’re good to go.
No CIRCUITPY? No worries! If you see a drive called CPLAYBOOT you’ll need to set up your board. Follow the instructions at the Adafruit Learn guide.
Go ahead and open Mu. If it doesn’t detect a board the program will prompt you to select your mode. For the Circuit Playground Express you need to select Adafruit CircuitPython, but you can also choose modes for the BBC micro:bit, PyGame Zero, or Python 3. You’re ready to code!
2. Blink! Your First CircuitPython Code
Blinking an LED is the hardware version of
Hello, World! Let’s test our Circuit Playground Express (“cpx” in code) by blinking an onboard LED. Here’s the blink code (Figure B) to turn an LED on and off every second. Make sure to indent the lines of code underneath
The first two lines of this code are importing libraries: one to manage time and another with all the settings for your board. The main body of your code lives underneath while True: — your board will loop through all the things that are indented underneath this line. In this case,
cpx.red_led = True tells our board to turn on the red LED,
time.sleep(0.5) tells it to pause for half a second,
cpx.red_led = False turns the red LED off, and one more
time.sleep(0.5) adds in another pause. These pauses control how long the LED stays on and off.
Once you’re ready to send the blink code to your board, save the file as code.py on your CIRCUITPY drive. Once it’s done saving, take a look at your Circuit Playground Express and
you should see a small red LED blinking away every second.
One of the cool things about coding hardware using CircuitPython is that if you want to change something in your code you can simply make the change and hit Save. Your new code will be automatically sent to the board and start running straight away. This makes for much faster coding cycles — great for trying out new things or quickly checking changes. Try it out by changing the timing of your blinking light. The Mu editor also has a code checker that will warn you if you have any obvious errors. Delete one of the tabs underneath
while True: and click on the Check button to see what happens.
Working? Amazing! You’re up and running. Problems? Don’t worry! Head over to the Adafruit Learn guide and you’ll find more detailed instructions and troubleshooting tips to get you going.
3. Reading Sensors
Like a lot of modern boards designed for education, the Circuit Playground Express has lots of cool sensors built into it. If you want to find out what they’re sensing, you’re going to want to get to know the Serial and Plotter features of Mu.
The serial console is how we receive information from our board, including sensor data and error messages that help us figure out what’s wrong. To connect to the serial console, click the Serial button on the Mu toolbar. The plotter displays data from your board, with data on the vertical y-axis and time on the horizontal x-axis. Here’s some code (Figure C) that shows us data from the accelerometer — a sensor onboard the Circuit Playground Express that detects motion in three different directions:
x, y, and z.
Again, we’re importing our libraries on lines 1 and 2, then setting up a
while True: loop for our main block of code. Inside the loop, the line
x, y, z = cpx.acceleration assigns accelerometer data values to the variables x, y, and z, while
print((x, y, z)) prints that data to our plotter (the wiggly lines on the bottom left) and to the serial monitor (the numbers on the bottom right). Finally,
time.sleep(1) pauses the board for one second before starting the loop again.
4. Super fast coding with REPL
One of the most exciting things about using Python on hardware is REPL, an interactive way of talking to your board that makes experimenting with code super speedy. REPL stands for Read, Evaluate, Print, Loop, which tells you how it works: It reads your Python commands, evaluates your code to figure out what you want, prints any results, then loops back to the start.
Let’s try it out. Click the Serial button to open a serial connection to the connected device, then hit Ctrl-C. Press any key to enter the REPL. Once you’re done, press Ctrl-D to exit the REPL.
Let’s take a look at the example in Figure D. I entered the REPL by typing Ctrl-C, then pressing a random key. The board told me a bit of information about itself, then prompted me to enter a command with >>>. I imported the usual libraries, then I tried to take a look at the readings of the light sensor using the command print(“light:”, cpz.light). However, I didn’t get a reading. I got an error, telling me it didn’t understand cpz. That’s because I had a typo! REPL is great for sniffing out errors like this. Next, I tried to get a light sensor reading again, this time without the typo. To save me typing the whole command again, I used the Up key to select my previous command, then edited it to remove the typo. Success! Next, I used the Up key again to print another light sensor reading, this time with my torch (flashlight, for those of you across the pond) on the sensor to see how it would change.
The last six lines of code are me playing with NeoPixels — smart LEDs that let you change colors, adjust brightness, or even make animations. There are ten NeoPixels on the Circuit Playground Express, numbered 0 through 9. In the line
cpx.pixels = (255, 0, 0) I am setting NeoPixel 0 to red. Changing the number in the square brackets changes which NeoPixel you’re addressing. Changing the values separated by commas in the brackets changes the color mix of red, green, and blue, from 0 through 255. The value
(255, 0, 0) maxes out the red value and zeros out the green and blue, giving me a pure red color. The next four lines are me playing with colors until I find a shade I like (purple!). My final line sets the brightness of all the NeoPixels to
0.5. The maximum brightness is 1, with 0 being off.
REPL makes it super fast and easy to tinker with settings and experiment with code. It’s great for trying out settings, playing with sensors, and working through problems. Once you know your way around the REPL you’ll never prototype another way!
Warning: Any code you write in the REPL is not saved, so if you want to keep your code, make sure to copy and paste it before you exit.
Python Projects in the Wild
There are many talented people in our community using Python to make awesome things. A fun, nostalgic example is Scott Shawcroft’s use of Circuit Python to hack old Game Boys (Figure E)using a game cartridge PCB with a SAMD51 chip (Figure F).
Another project using the SAMD51 is Bats ’n Gons from Sophi Kravitz and Ted Yapo, a super cool bat soundboard featuring emergent LED and sound behavior: Each bat-shaped board can plug into the next to communicate over RX/TX, creating changes in light and sound output that change with each new board that is connected (Figure G).
Into modular synths? You absolutely must put two projects from Thea Flowers at Winterbloom on your wish list. Sol (Figure H) is capable of translating MIDI to Eurorack-compatible frequencies and because it uses CircuitPython, it’s easy for even beginner programmers to create and customize their own sounds. Big Honking Button (Figure I below) is a very funny modular synth homage to everyone’s favorite naughty goose (honk honk!). Both projects make use of Circuit Python’s existing hardware and software to simplify their manufacture and code base: the Big Honking Button, for example, uses only 100 lines of code.
If you’re up for a technical challenge you can check out the open source projects Migen and LiteX, which take Python’s crossover into hardware to another level by exploring the ways in which the language can be used in FPGA and chip design.
And GreatFET (Figure J) is a fantastic project from Michael Ossman and the hardware hackers at Great Scott Gadgets. They take Python implementation in another direction by focusing on peripheral development rather than embedded development. Michael explains: “We believe that the best tool for rapid development and prototyping is not making firmware easier but making firmware unnecessary.” With its Hi-Speed USB host and peripheral ports, and a Python API, the GreatFET One board can serve as a custom USB peripheral or a “man in the middle” making it a versatile interface for reverse engineering, hacking, and physical computing.