Setup Adafruit Feather M0 Express for CircuitPython

We'll need to get our Feather board setup so we can run CircuitPython code. First thing we'll need to do is connect the board to your computer with a microUSB cable. Then double-click on the reset button to put it in "UF2" boot-loader mode. The NeoPixel will turn green. The board will then show up as a USB storage device on your computer named "FEATHERBOOT". 

After you've dragged the UF2 onto the FEATHERBOOT drive, wait for a few moments, and a CIRCUITPY drive will appear letting you know that circuit python has been loaded correctly. You may need to unplug-replug the Feather to reset it.

Download Adafruit CircuitPython HID Library

Now we need to get the HID library from github. This allows us to have the Feather act like a keyboard

Visit our library installation page to learn how to download and install the latest driver bundle!

You can install the whole bundle if you have an Express board, or just the adafruit_hid folder. If you're just installing the individual driver, stick the adafruit_hid folder into the CIRCUITPY/lib folder or just into CIRCUITPY

Upload The Code

Copy and paste the code below into a new text document (we recommend using Mu as your editor, which is designed for CircuitPython.). Save the file and name it as

Once the files has been uploaded to the drive, the Feather will automatically reboot and run the code. No upload button (say whaaat?!).

Text Document Formatting

We recommend using Mu as your editor, which is designed for CircuitPython.


If you're using something else, watch out for formatting! When making your text document, you need to ensure the file is set as Plain Text. Most common text editing applications, like TextEdit for MacOS will save text documents as .RTF (rich text format) by default. You can quickly change an RTF text document to plain text by using selecting "Make Plain Text" under the Format menu. You can also change the format in the applications "Preferences" menu.

Line Spaces and Invisible Characters

If you are still finding your code isn't quite working and running. You can try copying the code into a different code or text editing software, save it out as a .txt format with line spacing and then convert it to the .py file extension. Sometimes text editors will add invisible characters like line breaks and tabbed spaces.

# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries
# SPDX-License-Identifier: MIT

import time

import digitalio
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
import board
import usb_hid

# A simple neat keyboard demo in circuitpython

# The button pins we'll use, each will have an internal pullup
buttonpins = [board.D12, board.D11, board.D10, board.D9, board.D6, board.D5]
ledpins = [board.A0, board.A1, board.A2, board.A3, board.A4, board.A5]

# The keycode sent for each button, will be paired with a control key
buttonkeys = [Keycode.A, Keycode.B, Keycode.C, Keycode.D, Keycode.E, Keycode.F]
controlkey = Keycode.LEFT_CONTROL

# the keyboard object!
kbd = Keyboard(usb_hid.devices)
# our array of button objects
buttons = []
leds = []

# make all pin objects, make them inputs w/pullups
for pin in buttonpins:
    button = digitalio.DigitalInOut(pin)
    button.direction = digitalio.Direction.INPUT
    button.pull = digitalio.Pull.UP
for pin in ledpins:
    led = digitalio.DigitalInOut(pin)
    led.direction = digitalio.Direction.OUTPUT

led = digitalio.DigitalInOut(board.D13)

print("Waiting for button presses")

while True:
    # check each button
    for button in buttons:
        if not button.value:  # pressed?
            i = buttons.index(button)
            leds[i].value = True

            print("Button #%d Pressed" % i)

            # turn on the LED
            led.value = True

            while not button.value:
                pass  # wait for it to be released!
            # type the keycode!
            k = buttonkeys[i]  # get the corresp. keycode
  , k)

            # turn off the LED
            led.value = False
            leds[i].value = False


Modify the Code

Now that the code lives on the Adafruit Feather board, it's super easy to change or update it. We can change the number of pins, their wiring, and what key-codes they send.

Open up the file in your favorite text editor and take a look at the code.

If you want to change the pins for the buttons, look for the buttonpins list variable:

# The button pins we'll use, each will have an internal pullup
buttonpins = [D12, D11, D10, D9, D6, D5]

The "ledpins" variable lists which analog pins we're using, they correspond with the button pins one-to-one

ledpins = [A0, A1, A2, A3, A4, A5]

So here, the first pin name is the LED connected to pin A0, which matches up with the first button input pin D12. They match up A1+D11A2+D10, A3+D9, A4+D6, and A5+D5.  To change the connections, simply change the pin names in the list and save

Changing Key Presses

The buttonkeys and controlkey variables list which characters we want the buttons to output. 

# The keycode sent for each button, will be paired with a control key
buttonkeys = [Keycode.A, Keycode.B, Keycode.C, Keycode.D, Keycode.E, Keycode.F]

 For example, when the D12 button is pressed, it will emit a Keycode.A. and when D11's button is pressed, you'll see a Keycode.B. You can pick a wide variety of keycodes, see the full list here.

Note that keycodes aren't the same as ASCII codes. So for example if you want to send a upper case A you need to send both a control key that is 'shift' and then the keycode Keycode.A. Together, they will make your computer recognize it's an A you want. You can set the control keycode that goes with each key on the next line:

controlkey = Keycode.LEFT_CONTROL

In this case, we want to send a Left "Control" keypress at the same time. Try changing this to

controlkey = Keycode.SHIFT

and save to see how it now sends uppercase letters.

If you want to get really creative with what keypresses to send, see this line:, k)

You can have up to 6 keycodes sent at once - so if you need control-shift-A, turn it into:,Keycode.LEFT_CONTROL, k)


Coding Video

You have the option to add up to 6 buttons. You can watch Limor walkthrough the development of the software and explain how everything works. The CircuitPython HID Keyboard library is by Dan Halbert and Scott Shawcroft.

Prototyping Circuit

Once the code has been uploaded to the board, you can quickly test to ensure everything is working as expected. Using a jumper cable, you can testing the keystrokes by tying D12-D5 and ground together. You should see key presses happen on your computer with accompanying red LED on the feather board.

Testing LEDs

The 24mm LED buttons have two sets of electrodes. It's a good idea to test out the LEDs and note the correct electrodes and polarity. The assembly page shows which electrodes goes to what. Use the icon marked on the button housing to determine orientation. 

This guide was first published on Jun 28, 2017. It was last updated on Jul 24, 2024.

This page (Software) was last updated on Jul 24, 2024.

Text editor powered by tinymce.