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, make sure you're running the most recent version of CircuitPython for the Feather nRF52840.

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.

Download the Code from GitHub

To use with CircuitPython, you need to first install a few libraries, into the lib folder on your CIRCUITPY drive. Then you need to update code.py with the example script.

Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, open the directory BLE_Synth/cpb_amp_code for the Circuit Playground Bluefruit and BLE_Synth/feather_keyboard_code for the Feather nRF52840 and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your respective CIRCUITPY drives.

Your CIRCUITPY drive on the Circuit Playground Bluefruit should now look similar to the following image:

CIRCUITPY

Your CIRCUITPY drive on the Feather nRF52840 should now look similar to the following image:

CIRCUITPY

Circuit Playground Bluefruit BLE Synth Code

# SPDX-FileCopyrightText: 2020 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

'''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

# SPDX-FileCopyrightText: 2020 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

'''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 Mar 29, 2024.

This page (CircuitPython Code Setup) was last updated on Mar 28, 2024.

Text editor powered by tinymce.