Setup Circuit Playground Bluefruit with CircuitPython

We'll need to get our board setup so we can run CircuitPython code. Let's walk through these steps to get the latest version of CircuitPython onto your board. 

Mu Python Editor

Mu is a simple Python editor that works with Adafruit CircuitPython hardware. It's written in Python and works on Windows, MacOS, Linux and Raspberry Pi. The serial console is built right in so you get immediate feedback from your board's serial output!

 Quick Start

  • Download the CircuitPython UF2 for Circuit Playground Bluefruit
  • Connect Circuit Playground Bluefruit to your computer over USB and press the Reset button
  • Drag-n-drop the CircuitPython UF2 onto the CPLAYBOOT drive - the drive will vanish and a new CIRCUITPY drive should appear.
  • Copy code and library files to the CIRCUITPY drive
This project needs version 5.0.0-beta.0 or higher.

Download Adafruit CircuitPython Library Bundle

In order to run the code, we'll need to download a few libraries. The download linked below will contain all the libraries available for CircuitPython. To run the code for this project, we need the libraries in the Required Libraries list below. Unzip the library bundle and search for the libraries. Drag and drop it onto a folder named lib on the CIRCUITPY drive (create the folder if it is not already on the Circuit Playground Bluefruit).

Required Libraries 

  • adafruit_ble
  • adafruit_bluefruit_connect
  • adafruit_bus_device
  • neopixel.mpy
  • simpleio.mpy

Upload Code

Click on the download link below to grab the main code directly from GitHub. Rename the file to code.py and drop it onto the CIRCUITPY main (root) directory. The code will run properly when all of the files have been uploaded including libraries.

Use any text editor or favorite IDE to modify the code. We suggest using Mu as noted above.

# Code written by Prof. John Gallaugher, modified by Noe Ruiz for Adafruit Industries
# Adafruit Circuit Playground Express Bluefruit

import time
import board
import digitalio
import neopixel

from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

from audiopwmio import PWMAudioOut as AudioOut
from audiocore import WaveFile

from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_bluefruit_connect.button_packet import ButtonPacket

# setup pixels
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=1, auto_write=True)

# name colors so you don't need to refer to numbers
RED = (255, 0, 0)
ORANGE = (255, 50, 0)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
PURPLE = (100, 0, 255)
YELLOW = (255,230, 0)
BLUE = (0, 0, 255)
# setup bluetooth
ble = BLERadio()
uart_service = UARTService()
advertisement = ProvideServicesAdvertisement(uart_service)

# External Audio Stuff
speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
speaker_enable.direction = digitalio.Direction.OUTPUT
speaker_enable.value = True

audio = AudioOut(board.SPEAKER)  # Speaker
wave_file = None

def play_wav(name, loop=False):
    """
    Play a WAV file in the 'sounds' directory.
    :param name: partial file name string, complete name will be built around
                 this, e.g. passing 'foo' will play file 'sounds/foo.wav'.
    :param loop: if True, sound will repeat indefinitely (until interrupted
                 by another sound).
    """
    global wave_file  # pylint: disable=global-statement
    print("playing", name)
    if wave_file:
        wave_file.close()
    try:
        wave_file = open('sounds/' + name + '.wav', 'rb') # using wave files from sounds folder
        wave = WaveFile(wave_file)
        audio.play(wave, loop=loop)
    except OSError:
        pass # we'll just skip playing then

while True:
    # set CPXb up so that it can be discovered by the app
    ble.start_advertising(advertisement)
    while not ble.connected:
        pass

    # Now we're connected

    while ble.connected:

        if uart_service.in_waiting:
            try:
                packet = Packet.from_stream(uart_service)
            except ValueError:
                continue # or pass.

            if isinstance(packet, ColorPacket): # check if a color was sent from color picker
                pixels.fill(packet.color)
            if isinstance(packet, ButtonPacket): # check if a button was pressed from control pad
                if packet.pressed:
                    if packet.button == ButtonPacket.BUTTON_1: # if button #1
                        pixels.fill(BLUE)
                        play_wav("bluefruit")
                        time.sleep(3)
                        pixels.fill(BLACK)
                    if packet.button == ButtonPacket.BUTTON_2: # if button #2
                        pixels.fill(ORANGE)
                        play_wav("halloween")
                        time.sleep(3)
                        pixels.fill(BLACK)
                    if packet.button == ButtonPacket.BUTTON_3: # if button #2
                        pixels.fill(PURPLE)
                        play_wav("muhaha")
                        time.sleep(2)
                        pixels.fill(BLACK)
                    if packet.button == ButtonPacket.BUTTON_4: # if button #2
                        pixels.fill(GREEN)
                        play_wav("neopixels")
                        time.sleep(3)
                        pixels.fill(BLACK)
                    if packet.button == ButtonPacket.UP: # if button #2
                        pixels.fill(YELLOW)
                        play_wav("organic")
                        time.sleep(2.6)
                        pixels.fill(BLACK)
                    if packet.button == ButtonPacket.DOWN: # if button #2
                        pixels.fill(PURPLE)
                        play_wav("python")
                        time.sleep(2)
                        pixels.fill(BLACK)
                    if packet.button == ButtonPacket.LEFT: # if button #2
                        pixels.fill(GREEN)
                        play_wav("smell")
                        time.sleep(2.5)
                        pixels.fill(BLACK)
                    if packet.button == ButtonPacket.RIGHT: # if button #2
                        pixels.fill(ORANGE)
                        play_wav("who")
                        time.sleep(2)
                        pixels.fill(BLACK)

Upload Sounds

Download the zip file containing the audio wave files using the link below. Create a new folder in the CIRCUITPY drive. Drag and drop the .wav files into the sounds directory.

Mapped Sounds

The audio files were voiced by Noe Ruiz and modified with a low-pitch effect. The audio files are assigned to the following buttons on the Bluefruit LE Connect App.

  • UP        – organic.wav
  • DOWN – python.wav
  • LEFT    – smell.wav
  • RIGHT – who.wav
  • 1           – bluefruit.wav
  • 2          – halloween.wav
  • 3          – muhaha.wav
  • 4          – neopixels.wav

Supported Audio Formats

Adafruit CircuitPython supports 16-bit, Mono, 22.050kHz .wav audio format. See this guide to help format any audio files you might want to use in this project besides the files provided.

NeoPixel Colors

Supported colors are in the list below. Optionally create custom colors using RGB values. List of colors are located in the code on line 19.

Download: file
# name colors so you don't need to refer to numbers
RED = (255, 0, 0)
ORANGE = (255, 50, 0)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
PURPLE = (100, 0, 255)
YELLOW = (255,230, 0)
BLUE = (0, 0, 255)
This guide was first published on Oct 28, 2019. It was last updated on Oct 28, 2019.
This page (Software) was last updated on Oct 24, 2020.