Skill Level: Intermediate
Table Of Contents
- What Is Needed
- Background Information
- What Is CircuitPython
- What Is Blinka
- Building The Circuit
- Installing Blinka
- Writing Your First CircuitPython Program
- Using The REPL
- Working With Libraries
- Additional Resources
This tutorial will teach you how to get up and running with CircuitPython on a Raspberry Pi using the Blinka library.
We will cover the following topics:
- What CircuitPython and Blinka are and why you may want to use them in your projects.
- How to install the Blinka library to add CircuitPython hardware support to your Python programs.
- How to invoke and use the Read-Evaluate-Print-Loop (REPL) to run individual lines of code.
- How to install and use libraries in your CircuitPython program.
A basic understanding of electronics and programming is expected along with some familiarity with the Raspberry Pi platform. If you are new to Raspberry Pi or would just like to refresh your knowledge, please see our Blink: Making An LED Blink On A Raspberry Pi tutorial before proceeding with this one. In addition, this tutorial will use a solderless breadboard to build a circuit from a schematic diagram. The All About Circuit’s Understanding Schematics, SparkFun’s How to Read a Schematic, Core Electronics’ How to Use Breadboards, and Science Buddies’ How to Use a Breadboard guides are good resources for learning how to translate a schematic to a breadboard.
What Is Needed
- Raspberry Pi Running Raspberry Pi OS Or Similar Linux Based OS (available on Raspberry Pi Foundation and Adafruit)
- Solderless Breadboard (available on Adafruit and SparkFun)
- 2 x Female/Male Jumper Wires (available on Adafruit and Arrow)
- Standard 5mm Red LED (available on Adafruit and SparkFun)
- 330 Ω Resistor (available on SparkFun and Amazon)
My development board is the Raspberry Pi 3 Model B running the Raspberry Pi OS operating system. If you are using a different Raspberry Pi model or a different OS that is similar to Raspberry Pi OS, the vast majority of this tutorial should still apply, however, some minor changes may be necessary.
A list of all single board computers (SBCs) currently supported by Blinka, and the CircuitPython API, is available on the CircuitPython Blinka 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”.
CircuitPython is based on MicroPython which itself is based on Python. CircuitPython adds strong hardware support to the Python language. It also provides a multitude of libraries and drivers to support sensors, breakout boards, and other external hardware components. This makes CircuitPython an incredibly powerful ally in quickly developing your own hardware interfaced projects.
What Is Blinka
CircuitPython was originally developed to run on small microcontroller boards using a simplified Python interpreter. However, the Raspberry Pi and other SBCs are full-fledged computers running their own operating systems. Blinka is a Python library that provides the CircuitPython hardware API compatibility layer for SBCs, like the Raspberry Pi, so that they can run CircuitPython programs using the standard Python interpreter.
Blinka translates the CircuitPython hardware API to whatever libraries the Linux board provides. On the Raspberry Pi, for instance, the RPi.GPIO library is used for GPIO access, the spidev library is used for SPI, and ioctl messaging is used for I2C. This allows us to use the CircuitPython built-in libraries, e.g. board, microcontroller, digitalio, etc. so that our CircuitPython programs can be agnostic to the hardware they are running on and just work as expected.
CircuitPython adds hardware support to the Python language along with a large selection of hardware libraries. With Blinka, we can take advantage of those fantastic libraries developed for CircuitPython and use them in our SBC based projects.
Building The Circuit
Before connecting any circuitry to your Raspberry Pi, shutdown and disconnect it from power. This avoids accidental damage during wiring.
Using a breadboard and jumper wires, connect a red LED in series with a 330 Ω resistor to GPIO21 (physical pin 40) of the Raspberry Pi according to the schematic diagram shown below.
Once the circuit is built, connect power to your Raspberry Pi and boot it up.
I assume you are already comfortable installing and using Raspberry Pi OS so I won’t go into those details, but it is safe to say, you should be running a very recent and stable OS version. You should also make sure the I2C and SPI interfaces are enabled on your Raspberry Pi.
Python 3 is required to support Blinka and CircuitPython, so use python3 and pip3 in your commands.
Open a terminal window on your Raspberry Pi and install Blinka, which also installs various supporting libraries, using the following command.
$ pip3 install Adafruit-Blinka
Now let’s verify Blinka was installed correctly. Open your favorite text editor and create a Python program named blinkatest.py with the code shown below that I retrieved from Adafruit’s learning guide.
import board import digitalio import busio print("Hello blinka!") # Try to great a Digital input pin = digitalio.DigitalInOut(board.D4) print("Digital IO ok!") # Try to create an I2C device i2c = busio.I2C(board.SCL, board.SDA) print("I2C ok!") # Try to create an SPI device spi = busio.SPI(board.SCLK, board.MOSI, board.MISO) print("SPI ok!") print("done!")
Run the program to test the hardware interfaces used by Blinka.
$ python3 blinkatest.py
You should see the following printed to your screen if everything passed.
Hello blinka! Digital IO ok! I2C ok! SPI ok! done!
Writing Your First CircuitPython Program
Now let’s write that old-time standard first program, blinking an LED, that covers the basics for what you need to run a very simple CircuitPython program. Create a file named blink.py with the code shown below.
import board import digitalio import time import RPi.GPIO print("Hello, CircuitPython!") led = digitalio.DigitalInOut(board.D21) led.direction = digitalio.Direction.OUTPUT print("Press CTRL-C to exit.") try: while True: led.value = True time.sleep(0.5) led.value = False time.sleep(0.5) except KeyboardInterrupt: RPi.GPIO.cleanup() print("\nCleaned up GPIO resources.")
All CircuitPython programs should import the
board module. This module defines the specifics for the development board you are using and is necessary for CircuitPython programs to access the board’s GPIO pins and hardware.
Line 6 of the program welcomes us to CircuitPython.
digitalio library is used to interface to the GPIO pins of the Raspberry Pi. Lines 8 and 9 set the
led variable to point to pin GPIO21 and define it as an output in order to drive our LED.
while loop repeatedly turns on and off the LED with half second delays in between.
When CTRL-C is pressed, the
except KeyboardInterrupt clause of the try/except block runs the
cleanup() function directly to ensure all GPIO pins are reset to their default state before exiting the program.
Run our new blink program
$ python3 blink.py
and you should see the LED on your breadboard now blinking. Press CTRL-C to exit the program.
Using The REPL
Since CircuitPython programs are really just running the standard Python interpreter using the Blinka library for hardware support on the Raspberry Pi, we can still use Python’s standard Read-Evaluate-Print-Loop (REPL) functionality.
Enter the REPL by simply executing the python3 command without any arguments.
Let’s try some CircuitPython specific constructs by typing them in at the >>> REPL prompt.
Start with importing CircuitPython’s
board library and printing the board’s ID.
>>> import board >>> board.board_id 'RASPBERRY_PI_3B'
As you can see, I am running on a Raspberry Pi 3 Model B.
We can also list all of the Raspberry Pi’s pins known by CircuitPython, along with some other items.
>>> dir(board) ['CE0', 'CE1', 'D0', 'D1', 'D10', 'D11', 'D12', 'D13', 'D14', 'D15', 'D16', 'D17', 'D18', 'D19', 'D2', 'D20', 'D21', 'D22', 'D23', 'D24', 'D25', 'D26', 'D27', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'I2C', 'MISO', 'MISO_1', 'MOSI', 'MOSI_1', 'RX', 'RXD', 'SCK', 'SCK_1', 'SCL', 'SCLK', 'SCLK_1', 'SDA', 'SPI', 'TX', 'TXD', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'ap_board', 'board_id', 'detector', 'pin', 'sys']
Want to update the LED manually from the REPL? Enter the
digitalio statements from our program we wrote earlier.
>>> import digitalio >>> led = digitalio.DigitalInOut(board.D21) >>> led.direction = digitalio.Direction.OUTPUT >>> led.value = True >>> led.value = False
When you are done playing with the REPL, press CTRL-D to exit.
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 can be viewed from the Adafruit_CircuitPython_Bundle GitHub repository.
Let’s utilize one of the libraries to demonstrate how this all works. So you don’t need an extra piece of hardware, I selected a library that just converts between binary (ASCII) and hexadecimal representations.
On microcontroller boards solely running the simplified CircuitPython interpreter, libraries are installed by simply copying the necessary libraries from the bundle. However, on the Raspberry Pi running the standard Python interpreter, we install CircuitPython libraries in the usual Python fashion with pip3.
Install the adafruit_binascii library by running the following command.
$ pip3 install adafruit-circuitpython-binascii
Create a file named binascii.py with the code shown below.
from adafruit_binascii import hexlify, unhexlify # Binary data. data = b"CircuitPython is Awesome!" print("Original Data: ", data) # Get the hexadecimal representation of the binary data hex_data = hexlify(data) print("Hex Data: ", hex_data) # Get the binary data represented by hex_data bin_data = unhexlify(hex_data) print("Binary Data: ", bin_data)
This is a modified program that I retrieved from the example listed in the adafruit_binascii library’s GitHub repository. It converts binary based ASCII characters to their hexadecimal representation and then back again.
Run the program
$ python3 binascii.py
and you should see the following printed to the screen.
Original Data: b'CircuitPython is Awesome!' Hex Data: b'43697263756974507974686f6e20697320417765736f6d6521' Binary Data: b'CircuitPython is Awesome!'
That’s all there is to it.
The following is a list of additional resources you may find helpful.
- CircuitPython Website (https://circuitpython.org)
- CircuitPython On Linux And Raspberry Pi Learning Guide (https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/)
- CircuitPython Essentials Learning Guide (https://learn.adafruit.com/circuitpython-essentials/)
- CircuitPython API Reference (https://circuitpython.readthedocs.io)
- Awesome CircuitPython (https://github.com/adafruit/awesome-circuitpython/)
- CircuitPython Cheatsheet (https://github.com/adafruit/awesome-circuitpython/blob/master/cheatsheet/CircuitPython_Cheatsheet.md)
- Blinka On GitHub (https://github.com/adafruit/Adafruit_Blinka)
- Blinka Documentation (https://circuitpython.readthedocs.io/projects/blinka/)
- 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)
- Library API documentation (https://circuitpython.readthedocs.io/projects/bundle/)
I recommend reviewing the above resources. They provide a wealth of information for learning more about CircuitPython.
If you run into any problems, the CircuitPython on Linux and Raspberry Pi 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 Blinka to run CircuitPython programs on a Raspberry Pi.
Specifically, we learned
- what CircuitPython and Blinka are and why you may want to use them in your projects,
- how to install the Blinka library to add CircuitPython hardware support to your Python programs,
- 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, by way of the Blinka library, can be an invaluable part of your next Raspberry Pi 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.