CircuitPython Code Setup

Take your Feather nRF52840 and plug it into your computer via a known good data + power USB cable. Have your Circuit Playground Bluefruit handy as you'll be performing most of the same steps for each. Your operating system will show a drive named CIRCUITPY when a board is plugged in. If you get a drive named CPLAYBTBOOT or FTHR840BOOT, you'll likely need to install CircuitPython. This is easy, see the steps below to do this, get library files, and copy the code to each board.

Feather nRF52840 CircuitPython Setup

First, to make sure you're running the most recent version of CircuitPython for the Feather nRF52840. You'll need at least version 5 for this project to work.

Feather nRF52840 Libraries

You'll need a few CircuitPython libraries in the lib folder on the Feather CIRCUITPY drive for the code to work. Head to https://circuitpython.org/libraries to download the latest library bundle matching the major version of CircuitPython now on your board (5 for CircuitPython 5.x, etc.).

Once you've downloaded the libraries bundle, add these libraries to the lib folder on the Feather:

  • adafruit_ble
  • adafruit_bluefruit_connect
  • adafruit_bus_device
  • adafruit_led_animation

Your Feather CIRCUITPY drive should look like this after you load the code below.:

Circuit Playground Bluefruit Circuit Python Setup

Just like with the Feather, make sure you're running the most recent version of CircuitPython for the Circuit Playground Bluefruit. You'll need at least version 5 for this project to work.

Circuit Playground Bluefruit Libraries

Again, you'll need a few CircuitPython libraries in the lib folder on the Circuit Playground Bluefruit for the code to work. Head to https://circuitpython.org/libraries to download the latest library bundle matching the major version of CircuitPython now on your board (5 for CircuitPython 5.x, etc.).

Once you've downloaded the libraries bundle, add these libraries to the lib folder on the CPB:

  • adafruit_ble
  • adafruit_bluefruit_connect
  • adafruit_bus_device
  • adafruit_circuitplayground
  • adafruit_led_animation
  • adafruit_thermistor.mpy
  • adafruit_lis3dh.mpy
  • neopixel.mpy

Your Circuit Playground Bluefruit CIRCUITPY drive should look like this after loading the code file below:

Download the Code from GitHub

Once your Circuit Playground Bluefruit and Feather nRF52840 are all setup with CircuitPython and the necessary libraries, you can click on the Download: Project Zip link above the code to get the code files for both boards.

The files will be named cpb_amp_code.py and feather_keyboard_code.py to avoid confusion. You'll need to rename the correct file to code.py when you load them onto the respective board CIRCUITPY flash drive.

Don't forget to rename your files to code.py!

Circuit Playground Bluefruit BLE Synth Code

'''BLE Synth
File for the Circuit Playground Bluefruit
Amp Portion'''
from adafruit_circuitplayground.bluefruit import cpb
from adafruit_led_animation.animation import Comet, AnimationGroup,\
    AnimationSequence
import adafruit_led_animation.color as color
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService
from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_bluefruit_connect.button_packet import ButtonPacket

#  easily call for NeoPixels to be off
off = (0, 0, 0)
#  state to debounce on CPB end
tone = False

# Setup for comet animation
COMET_SPEED = 0.04  # Lower numbers increase the animation speed
CPB_COMET_TAIL_LENGTH = 5  # The length of the comet on the Circuit Playground Bluefruit
CPB_COMET_BOUNCE = False  # Set to True to make the comet "bounce" the opposite direction on CPB

animations = AnimationSequence(
    AnimationGroup(
        Comet(cpb.pixels, COMET_SPEED, off, tail_length=CPB_COMET_TAIL_LENGTH,
              bounce=CPB_COMET_BOUNCE)))

#  note frequencies
C4 = 261.63
Csharp4 = 277.18
D4 = 293.66
Dsharp4 = 311.13
E4 = 329.63
F4 = 349.23
Fsharp4 = 369.99
G4 = 392
Gsharp4 = 415.3
A4 = 440
Asharp4 = 466.16
B4 = 493.88

#  note array
note = [C4, Csharp4, D4, Dsharp4, E4, F4,
        Fsharp4, G4, Gsharp4, A4, Asharp4, B4]

#  colors to recieve from color packet & for neopixels
color_C = color.RED
color_Csharp = color.ORANGE
color_D = color.YELLOW
color_Dsharp = color.GREEN
color_E = color.TEAL
color_F = color.CYAN
color_Fsharp = color.BLUE
color_G = color.PURPLE
color_Gsharp = color.MAGENTA
color_A = color.GOLD
color_Asharp = color.PINK
color_B = color.WHITE

#  color array
color = [color_C, color_Csharp, color_D, color_Dsharp, color_E,
         color_F, color_Fsharp, color_G, color_Gsharp, color_A,
         color_Asharp, color_B]

# Setup BLE connection
ble = BLERadio()
uart = UARTService()
advertisement = ProvideServicesAdvertisement(uart)

while True:
    #  connect via BLE
    ble.start_advertising(advertisement)  # Start advertising.
    was_connected = False
    while not was_connected or ble.connected:
        if ble.connected:  # If BLE is connected...
            was_connected = True
            #  start animations
            animations.animate()
            #  look for packets
            if uart.in_waiting:
                try:
                    packet = Packet.from_stream(uart)  # Create the packet object.
                except ValueError:
                    continue
                #  if it's a color packet:
                if isinstance(packet, ColorPacket):
                    for i in range(12):
                        colors = color[i]
                        notes = note[i]
                        #  if the packet matches one of our colors:
                        if packet.color == colors and not tone:
                            #  animate with that color
                            animations.color = colors
                            #  play matching note
                            cpb.start_tone(notes)
                            tone = True
                #  if it's a button packet aka feather's button has been released:
                elif isinstance(packet, ButtonPacket) and packet.pressed:
                    if packet.button == ButtonPacket.RIGHT and tone:
                        tone = False
                        #  stop playing the note
                        cpb.stop_tone()
                        #  turn off the neopixels but keep animation active
                        animations.color = off

Feather nRF52840 BLE Synth Code

'''BLE Synth
File for the Feather nFR52840
Keyboard Portion'''
import time
import board
import digitalio
import adafruit_led_animation.color as color
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_bluefruit_connect.button_packet import ButtonPacket

#  setup for LED to indicate BLE connection
blue_led = digitalio.DigitalInOut(board.BLUE_LED)
blue_led.direction = digitalio.Direction.OUTPUT

#  setting up the buttons
switch_pins = [board.D5, board.D6, board.D9, board.D10,
               board.D11, board.D12, board.D13, board.A0, board.A1, board.A2,
               board.A3, board.A4]
switch_array = []

#  creating the button array
for pin in switch_pins:
    switch_pin = digitalio.DigitalInOut(pin)
    switch_pin.direction = digitalio.Direction.INPUT
    switch_pin.pull = digitalio.Pull.UP
    switch_array.append(switch_pin)

#  states for button debouncing
switch1_pressed = False
switch2_pressed = False
switch3_pressed = False
switch4_pressed = False
switch5_pressed = False
switch6_pressed = False
switch7_pressed = False
switch8_pressed = False
switch9_pressed = False
switch10_pressed = False
switch11_pressed = False
switch12_pressed = False
switches_pressed = [switch1_pressed, switch2_pressed, switch3_pressed, switch4_pressed,
                    switch5_pressed, switch6_pressed, switch7_pressed, switch8_pressed,
                    switch9_pressed, switch10_pressed, switch11_pressed, switch12_pressed]

#  colors from Animation library to send as color packets
#  named for notes
color_C = color.RED
color_Csharp = color.ORANGE
color_D = color.YELLOW
color_Dsharp = color.GREEN
color_E = color.TEAL
color_F = color.CYAN
color_Fsharp = color.BLUE
color_G = color.PURPLE
color_Gsharp = color.MAGENTA
color_A = color.GOLD
color_Asharp = color.PINK
color_B = color.WHITE

#  array for colors
color = [color_C, color_Csharp, color_D, color_Dsharp, color_E,
         color_F, color_Fsharp, color_G, color_Gsharp, color_A,
         color_Asharp, color_B]

#  BLE send_packet function
def send_packet(uart_connection_name, packet):
    """Returns False if no longer connected."""
    try:
        uart_connection_name[UARTService].write(packet.to_bytes())
    except:  # pylint: disable=bare-except
        try:
            uart_connection_name.disconnect()
        except:  # pylint: disable=bare-except
            pass
        return False
    return True

ble = BLERadio()

uart_connection = None

if ble.connected:
    for connection in ble.connections:
        if UARTService in connection:
            uart_connection = connection
        break

while True:
    blue_led.value = False
    #  BLE connection
    if not uart_connection or not uart_connection.connected:  # If not connected...
        print("Scanning...")
        for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5):  # Scan...
            if UARTService in adv.services:  # If UARTService found...
                print("Found a UARTService advertisement.")
                blue_led.value = True #  LED turns on when connected
                uart_connection = ble.connect(adv)  # Create a UART connection...
                break
        ble.stop_scan()  # And stop scanning.
    #  while connected..
    while uart_connection and uart_connection.connected:
    #  iterate through buttons and colors
        for switch_pin in switch_array:
            i = switch_array.index(switch_pin)
            switches_pressed_state = switches_pressed[i]
            colors = color[i]
            #  if the button is released
            #  worked best if placed before the button press portion
            if switch_pin.value and switches_pressed_state:
                print("button off")
                #  send button packet to stop tone & color (happens on CPB)
                if not send_packet(uart_connection,
                                   ButtonPacket(ButtonPacket.RIGHT, pressed=True)):
                    uart_connection = None
                    continue
                switches_pressed[i] = False  # Set to False.
                #  time delay for BLE, otherwise issues can arrise
                time.sleep(0.05)
            #  if button is pressed:
            if not switch_pin.value and not switches_pressed_state:  # If button A pressed...
                #  send color packet
                if not send_packet(uart_connection, ColorPacket(colors)):
                    uart_connection = None
                    continue
                switches_pressed[i] = True  # Set to True.
                time.sleep(0.05)  # Debounce.
This guide was first published on Feb 07, 2020. It was last updated on Feb 07, 2020. This page (CircuitPython Code Setup) was last updated on May 31, 2020.