Electronics Software Development

Getting Started With CircuitPython On Compatible Microcontroller Boards

Getting Started With CircuitPython Graphic
Written by John Woolsey

Skill Level: Beginner

Table Of Contents

Introduction

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

Background Information

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.

Installing CircuitPython

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.

The 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.

The while loop just repeatedly turns on and off the LED after half second 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.

print("Hello, CircuitPython!")

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

>>> print("Hello")

that will print the following result.

Hello

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

The 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[0] = (255, 0, 0)
    time.sleep(0.5)
    pixels[0] = (0, 255, 0)
    time.sleep(0.5)
    pixels[0] = (0, 0, 255)
    time.sleep(0.5)

The second line in the program imports the new neopixel library we just installed.

The 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[0], 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.

The 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.

Additional Resources

The following is a list of additional resources you may find helpful.

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.

Summary

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.

About the author

John Woolsey

John is an electrical engineer who loves science, math, and technology and teaching it to others even more.
 
He knew he wanted to work with electronics from an early age, building his first robot when he was in 8th grade. His first computer was a Timex/Sinclair 2068 followed by the Tandy 1000 TL (aka really old stuff).
 
He put himself through college (The University of Texas at Austin) by working at Motorola where he worked for many years afterward in the Semiconductor Products Sector in Research and Development.
 
John started developing mobile app software in 2010 for himself and for other companies. He has also taught programming to kids for summer school and enjoyed years of judging kids science projects at the Austin Energy Regional Science Festival.
 
Electronics, software, and teaching all culminate in his new venture to learn, make, and teach others via the Woolsey Workshop website.

6 Comments

Leave a Comment

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