Skill Level: Beginner
Table Of Contents
- What Is Needed
- Background Information
- What Is CircuitPython
- Installing CircuitPython
- Installing The Mu Python Editor
- Running Your First CircuitPython Program
- Using The Serial Console
- Using The REPL
- Working With Libraries
- Additional Resources
This tutorial will teach you how to get up and running with CircuitPython on a compatible microcontroller board. A basic understanding of electronics and programming is preferred, but not required.
What Is Needed
- Linux, macOS, Or Windows Based Computer With A USB Port
- CircuitPython Compatible Microcontroller Board With Compatible USB Cable
- Mu Python Editor (recommended)
I am using Adafruit’s Feather M4 Express microcontroller board connected to a macOS based computer with the Mu Python editor for this tutorial. If you are using a different CircuitPython compatible board, computer setup, or code editor, the vast majority of this tutorial should still apply, however, some minor changes may be necessary.
A list of boards currently supported by CircuitPython is available on the CircuitPython Downloads page.
If you need assistance with your particular setup, post a question in the comments section below and I, or someone else, can try to help you.
What Is CircuitPython
If you are a fan of the Python programming language and enjoy tinkering with electronics, you will certainly love CircuitPython. It is an open source programming language developed and maintained by Adafruit. According to Adafruit, it was “designed to simplify experimenting and learning to code on low-cost microcontroller boards”. It is “the easiest way to program microcontrollers”.
When a CircuitPython compatible microcontroller board is plugged into your host computer’s USB port, it will appear as a flash disk drive. Just drag your source code to the drive and it will run automatically. Any code edits are also run automatically when files are saved. There is no need to compile your programs or run any special tools. It just works!
CircuitPython is based on MicroPython which itself is based on Python. It adds strong hardware support to the Python language with a simplified Python interpreter. The Read-Evaluate-Print-Loop (REPL) is even supported. Almost all of the standard Python language can be used within a CircuitPython program, however, some features, such as interrupts and threading, are not currently supported.
Along with all of this amazing base functionality of being able to run Python programs on small microcontroller boards, CircuitPython also provides a multitude of libraries and drivers to support sensors, breakout boards, and other external hardware components. All of this makes CircuitPython an incredibly powerful ally in quickly developing your microcontroller based projects.
Device drivers are not required for Mac, Linux, or Windows 10 based platforms, but one is required for Windows 7. If you are using Windows 7, download and install the driver from GitHub before plugging in your board.
Most CircuitPython compatible boards, especially those from Adafruit, come with CircuitPython and a UF2 bootloader already installed. However, we should upgrade our boards to the latest versions.
Visit the Downloads page of the CircuitPython website and search for and click the link for your microcontroller board. Mine is the Feather M4 Express board by Adafruit. The left side of the page will provide general information about your board. The right side of the page provides the CircuitPython and bootloader versions available for your board. Select your native language and download the latest stable CircuitPython version by clicking the purple DOWNLOAD .UF2 NOW button in the top right corner of the page. The downloaded file will be named something like adafruit-circuitpython-<board>-<version>.uf2.
If a UF2 bootloader is also available, it will appear in the bottom right corner of the page. Click the gray DOWNLOAD UPDATER UF2 button in that section to download the bootloader update. The downloaded file will be named something like update-bootloader-<board>-<version>.uf2.
I will not be covering CircuitPython installation for boards that do not use a UF2 bootloader. If your particular board falls in that camp, please check out the Non-UF2 Installation page of Adafruit’s Welcome to CircuitPython! learning guide and/or the board manufacturer’s product page for more information.
Plug your microcontroller board into your computer’s USB port. When you first connect a CircuitPython compatible board to your computer, it will automatically be mounted and appear as a flash disk drive, named CIRCUITPY, on your computer’s desktop. You may get a system notification asking you to set up the new device, such as a new keyboard. You can ignore and close that notification as no further setup should be required. You can also ignore the CIRCUITPY drive for now, but we will come back to it soon.
Double-click the reset button on your board to enter the bootloader mode. The CIRCUITPY drive will disappear and a boot drive will appear. That drive will be named according to the board you are using, e.g. FEATHERBOOT, TRINKETBOOT, etc, following the <board>BOOT naming convention. You may also get another system notification letting you know that the disk was not ejected properly. That is okay and any notifications you get about this can be disregarded during the update process. Most CircuitPython compatible boards have a built-in Mini NeoPixel or RGB LED that changes colors and flashes based on the status of the CircuitPython program or board. If your board has one of these, it will flash red and then turn green once the bootloader mode is entered. You may have to try double-clicking the reset button again if the BOOT drive did not show up for you the first time.
If you downloaded a bootloader UF2 file, drag it to the BOOT drive now. The on-board LED will flash again, the drive will disappear while the bootloader is being updated, and then will reappear once installation is complete. A file named INFO_UF2.TXT will be located on the drive whose contents will contain the current bootloader version. Open the file and verify the version listed matches that shown on the download page.
Now we can install CircuitPython itself. Drag the CircuitPython installer we downloaded earlier to the BOOT drive. The BOOT drive will disappear and the CIRCUITPY drive will appear. The on-board LED will also flash red and then turn green once CircuitPython was installed successfully. A file named boot_out.txt will be located on the drive whose contents will contain the current CircuitPython version. Open the file and verify the version listed matches that shown on the download page. I installed CircuitPython 5.3.1 on my Feather M4 Express board.
You should now have the latest CircuitPython version loaded on your compatible microcontroller board and the CIRCUITPY drive should be visible on your computer’s desktop. The on-board NeoPixel or RGB LED should be flashing green letting you know it is waiting for a program to be loaded.
Installing The Mu Python Editor
Although not required, the easiest way to use CircuitPython with your compatible microcontroller board is to use the Mu Python editor. It was designed for CircuitPython and has a built-in serial console that provides immediate feedback from your board’s serial output. It will even autodetect your board making using the REPL very easy.
Before installing and opening the Mu editor, verify your board is connected to your computer and the CIRCUITPY drive is visible on your desktop.
Download and follow the instructions on the Mu website to install the Mu editor.
When you first open the Mu editor, it will ask you to select a mode. Choose Adafruit CircuitPython. Once selected, you should see the selected mode, Adafruit, shown in the bottom right corner of the Mu editor next to the gear icon. It will also automatically detect the connected board.
The main menu bar at the top of the Mu editor window contains all of the tasks you will need for writing your programs. Of immediate interest is the New, Load, and Save buttons that will allow you to create, open, and save your source code files.
We are now ready to begin programming.
Running Your First CircuitPython Program
Make sure the CIRCUITPY drive is visible on your computer’s desktop. This drive is where all of your CircuitPython source code, including libraries, will reside. CircuitPython looks for specific source code file names and runs the contents of the file it finds automatically when the board starts up, reloads, or when you save changes to the file. The preferred primary source file name is code.py, but main.py can also be used if you prefer.
Keep in mind that some code editors on some OS platforms do not immediately write files to disk. This can be a problem in that CircuitPython waits for a file to be saved before the code is automatically run. It can take over a minute on some platforms for files to be completely saved. You should also not reset or unplug your board while a file is being saved. Since the Mu editor enforces immediate saves, this is one reason why it is the recommended editor for CircuitPython programs.
Create a new file in your editor, preferably the Mu editor, with the code shown below. It is a simple program that will blink the on-board LED.
import board import digitalio import time led = digitalio.DigitalInOut(board.D13) led.direction = digitalio.Direction.OUTPUT while True: led.value = True time.sleep(0.5) led.value = False time.sleep(0.5)
All CircuitPython programs should import the
board module. This module defines the specifics for the microcontroller board you are using and is necessary for CircuitPython programs to access the board’s GPIO pins and hardware.
Most CircuitPython compatible microcontroller boards provide an on-board LED attached to pin
D13 of the board. If this is not the case for your board, change the pin to the appropriate one for your board. For example the Adafruit CLUE board uses
D17 for the on-board LED.
digitalio module interfaces to the digital GPIO pins on the board. We use this module to set up and update digital pin values; the pin connected to the on-board LED in this case.
while loop just repeatedly turns on and off the LED after half minute delays.
It is preferred that CircuitPython programs contain an infinite loop. If a program ends on its own, undesirable results may occur. If you are not using one in your program, just add the following simple loop to the end of your code.py source code.
while True: pass
Save your program as code.py at the top level of the CIRCUITPY drive. The program will immediately begin running and you should see the on-board red LED blinking. In addition, the on-board NeoPixel or RGB LED should have turned a steady green letting you know your program is running.
Using The Serial Console
If you are using the Mu editor, click the Serial icon within the menu bar at the top to open the serial console. It will appear at the bottom of the Mu editor’s window.
If you are using a different editor, you can open a serial console with the command line screen utility on Linux or macOS, or a terminal program, such as Putty, on a Windows system. The Quick Tip: Using The Screen Utility To View Arduino Serial Output tutorial I wrote recently shows you how to use the screen utility. It was written for use with Arduino boards, but the concept is the same and still applies here. I was able to connect to my CircuitPython board with the following command.
$ screen /dev/tty.usbmodem14201 115200
Edit your code.py program to add the following line between the
led.direction = digitalio.Direction.OUTPUT and
while True: statements.
Save the updated code.py program file and it will immediately begin running. You should see the following printed to the serial console.
soft reboot Auto-reload is on. Simply save files over USB to run them or enter REPL to disable. code.py output: Hello, CircuitPython!
Very nice. Anything you print in your program will be shown in the serial console.
Using The REPL
Press CTRL-C within the serial console to stop the program. The on-board NeoPixel or RGB LED will flash with multiple colors letting you know the program was paused. Information on why and where your program stopped will also be printed to the console along with asking how you want to proceed.
Press any key to enter the REPL. Use CTRL-D to reload.
Pressing CTRL-D will restart the program again. Pressing any other key will enter the Read-Evaluate-Print-Loop (REPL). The REPL allows you to enter individual CircuitPython statements and see the resulting output. Go ahead and enter the REPL. The on-board NeoPixel or RGB LED will turn white letting you know the REPL is running. The CircuitPython version and board information will be printed to the serial console and you will be provided with a >>> REPL prompt.
Let’s enter a few lines of code to explore the REPL. Enter the following statement at the prompt
that will print the following result.
Let’s try using some variables
>>> x = 50 >>> y = 50 * 2 >>> print(y) 100
and print the microcontroller board’s pins.
>>> import board >>> dir(board)
My Feather M4 Express provided the following list.
['__class__', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'BATTERY', 'D0', 'D1', 'D10', 'D11', 'D12', 'D13', 'D14', 'D15', 'D16', 'D17', 'D18', 'D19', 'D23', 'D24', 'D25', 'D4', 'D5', 'D6', 'D9', 'I2C', 'MISO', 'MOSI', 'NEOPIXEL', 'RX', 'SCK', 'SCL', 'SDA', 'SPI', 'TX', 'UART', 'VOLTAGE_MONITOR']
One I find particularly interesting, although maybe not as generally useful, is the ability to print the internal microcontroller’s temperature (if equipped) in degrees Celsius.
>>> import microcontroller; microcontroller.cpu.temperature 33.3419
help() method provides help on a given object. Without any arguments, it provides general help along with the CircuitPython version.
>>> help() Welcome to Adafruit CircuitPython 5.3.1! Please visit learn.adafruit.com/category/circuitpython for project guides. To list built-in modules please do `help("modules")`.
Given an object, it will print information about that object.
>>> help(x) object 50 is of type int from_bytes -- <classmethod> to_bytes -- <function>
The following lists the various built-in modules available with CircuitPython.
>>> help("modules") __main__ busio microcontroller storage _os collections micropython struct _pixelbuf digitalio neopixel_write supervisor _time displayio network sys analogio errno os terminalio array fontio ps2io time audiobusio framebufferio pulseio touchio audiocore frequencyio random ulab audioio gamepad re usb_hid audiomixer gc rgbmatrix usb_midi audiomp3 i2cslave rotaryio wiznet bitbangio io rtc board json samd builtins math socket Plus any modules on the filesystem
Play around and try entering other CircuitPython statements in the REPL. When you are done, press CTRL-D to exit the REPL and restart your program.
The CircuitPython REPL can be a very handy tool for allowing us to test various lines of code before adding them to our program.
Working With Libraries
The ability to access and utilize a vast collection of hardware specific libraries is one of the core tenets of the CircuitPython ecosystem. All of the currently available libraries are packaged together into a single Adafruit CircuitPython Libraries Bundle that can be downloaded to your computer. The libraries can then be individually copied to the CIRCUITPY drive for use in your own projects.
Download and unzip the bundle targeted to the CircuitPython version installed on your board. It is very important that the bundle and CircuitPython versions match, otherwise you may have compatibility issues in your program. One easy way to determine the CircuitPython version running on your board is to enter the REPL. When you do, the version will be printed on the first line.
The downloaded bundle will contain some informational text files along with the lib and examples directories. The lib folder contains all of the current libraries. The examples folder contains example code demonstrating how to use those libraries. Review the various files in the bundle to get acquainted with all it has to offer.
If CircuitPython was pre-installed on your microcontroller board, it may already have a lib folder on the CIRCUITPY drive. If it does not yet exist, create an empty lib directory on the drive. This lib folder is where all of the libraries used by your program will reside. CircuitPython already knows about this lib folder so all of your installed libraries can be imported and used normally within your code.py program.
Let’s grab one of the libraries to demonstrate how this all works. As mentioned earlier, your board probably has an on-board Mini NeoPixel. We will utilize a library to change the colors of the NeoPixel.
Drag (copy) the neopixel.mpy library file from the bundle’s lib folder to the lib folder on your CIRCUITPY drive. That’s it. The library is now installed and ready for use.
Exit the REPL if you are in that mode and modify your code.py program to match the following.
import board import neopixel import time pixels = neopixel.NeoPixel(board.NEOPIXEL, 1) pixels.brightness = 0.3 while True: pixels = (255, 0, 0) time.sleep(0.5) pixels = (0, 255, 0) time.sleep(0.5) pixels = (0, 0, 255) time.sleep(0.5)
The second line in the program imports the new
neopixel library we just installed.
pixels variable is assigned to the on-board NeoPixel. The last argument,
1, specifies that there is only one NeoPixel in the strip. It will be accessed as
pixel, the first (and only in this case) index of the NeoPixel strip sequence. The
brightness is then dimmed as the default full brightness of 1.0 is quite bright.
while loop repeatedly changes the NeoPixel to display red, green, and blue colors.
Save the program and you should see the NeoPixel immediately begin changing colors.
As this example should show, it is very intuitive and easy to install and use libraries with CircuitPython.
When you are finished exploring and playing around with CircuitPython on your compatible microcontroller board, properly eject the CIRCUITPY volume before unplugging your board from your computer in order to avoid any possible issues with your computer. We ignored the disk not ejected properly notifications earlier during the update process, but it is best to properly eject the board when you have the choice.
The following is a list of additional resources you may find helpful.
- CircuitPython Website (https://circuitpython.org)
- Mu Editor (https://codewith.mu)
- Welcome To CircuitPython! getting started guide (https://learn.adafruit.com/welcome-to-circuitpython)
- CircuitPython Essentials learning guide (https://learn.adafruit.com/circuitpython-essentials/)
- CircuitPython API Reference (https://circuitpython.readthedocs.io)
- CircuitPython GitHub repository (https://github.com/adafruit/circuitpython)
- Awesome CircuitPython (https://github.com/adafruit/awesome-circuitpython/)
- CircuitPython Cheatsheet (https://github.com/adafruit/awesome-circuitpython/blob/master/cheatsheet/CircuitPython_Cheatsheet.md)
- Adafruit Discord #help-with-circuitpython channel.
- Adafruit Forums > Supported Products & Projects > Adafruit CircuitPython and MicroPython (https://forums.adafruit.com/viewforum.php?f=60)
- List Of Available CircuitPython Libraries (https://github.com/adafruit/Adafruit_CircuitPython_Bundle/blob/master/circuitpython_library_list.md)
- Adafruit CircuitPython Libraries Bundle (https://circuitpython.org/libraries)
I would advise that you at least perform a cursory review of the above resources. They provide a wealth of information for learning more about CircuitPython.
If you run into any problems, the Welcome To CircuitPython! guide by Adafruit goes into much more detail than what I have covered here and may provide just the information you need to resolve your issues.
In addition, the CircuitPython Essentials learning guide is an excellent resource for learning about the built-in libraries.
In this tutorial, we learned how to get started using CircuitPython on a compatible microcontroller board.
Specifically, we learned
- what CircuitPython is and why you may want to use it for your microcontroller based projects,
- how to install CircuitPython, and the UF2 bootloader, on your compatible microcontroller board,
- why the Mu editor is the preferred editor for use with your CircuitPython based projects,
- how to use the serial console to display your program’s output,
- how to invoke and use the Read-Evaluate-Print-Loop (REPL) to run individual lines of code, and
- how to install and use libraries in your CircuitPython program.
Hopefully you have discovered that CircuitPython can be an invaluable part of your next microcontroller based project. In future articles, we will explore some of the hardware specific libraries to interface various components with our boards. This, in my opinion, is where CircuitPython really shines.
Thank you for joining me in this journey and I hope you enjoyed the experience. Please feel free to share your thoughts in the comments section below.