Introductory Examples - Adafruit Circuit Playground Bluefruit

The following short Python programs will demonstrate essential features of the Bluefruit board. These use only the onboard hardware and the serial console. Each can be run by copying the program into code.py on the CIRCUITPY drive offered by the board. The text can be pasted directly from this page, or each file can be downloaded from the CircuitPython sample code folder on this site.

Related Pages

Essential Documentation

Hello, World

Direct download: cpb_hello_world.py.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# cpb_hello_world.py

# "Hello, world" test for the Adafruit Circuit Playground Bluefruit board.
# This program uses only onboard hardware: NeoPixel LEDs.
# The text output can be seen on the serial console.

# Import the standard Python time functions.
import time

# Import the board-specific input/output library.
from adafruit_circuitplayground import cp

# Print a message to the serial console.
print("Hello, world.")

# Initialize global variables for the main loop.
led_index = 0

# Enter the main event loop to animate the NeoPixel LEDs by lighting them up
# in sequence.
while True:
    cp.pixels[led_index] = (0,0,0)
    led_index = (led_index + 1) % 10
    cp.pixels[led_index] = (0,0,255)
    time.sleep(0.2)

Mary Had a Little Lamb

Direct download: cpb_little_lamb.py.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# cpb_little_lamb.py

# Play "Mary had a Little Lamb" on the Adafruit Circuit Playground Bluefruit board.
# This program uses only onboard hardware: speaker.

# This example shows the use of Python tuples to create ad hoc data structures,
# in this case to store note value and duration pairs representing a melody.

# Please note that this example only uses simple tones, but the library supports
# audio sample playback from .mp3 and .wav files (use 22kHz mono 16-bit).

# ----------------------------------------------------------------
# Import the standard Python math library and time functions.
import math, time

# Import the board-specific input/output library.
from adafruit_circuitplayground import cp

# ----------------------------------------------------------------
# Define a function to convert MIDI note values to frequency. This applies an
# equal temperament scale.
def midi_to_freq(midi_note):
    MIDI_A0 = 21
    freq_A0 = 27.5
    return freq_A0 * math.pow(2.0, (midi_note - MIDI_A0) / 12.0)

# Define the melody as (note, duration) tuples.  Middle C is MIDI 60.
# The duration unit is the quarter note.

mary = ((64, 1), (62, 1), (60, 1), (62, 1), (64, 1), (64, 1), (64, 2), (62, 1),
        (62, 1), (62, 2), (64, 1), (67, 1), (67, 2), (64, 1), (62, 1), (60, 1), (62, 1),
        (64, 1), (64, 1), (64, 1), (64, 1), (62, 1), (62, 1), (64, 1), (62, 1), (60, 4))

# ----------------------------------------------------------------
# Initialize global variables for the main loop.
tempo = 144   # in beats per minute

# ----------------------------------------------------------------
# Enter the main event loop to play each tone in sequence.
while True:

    # Calculate the quarter note duration.
    quarter = 60.0 / tempo

    # Play each note tuple.
    for note in mary:
        freq      = midi_to_freq(note[0])
        duration  = quarter * note[1]

        # Play a single note.  The function won't return until the duration has elapsed.
        cp.play_tone(freq, 0.9*duration)

        # Articulate each note with a brief inter-note silence.
        time.sleep(0.1 * duration)

    # Pause briefly before repeating.
    time.sleep(2)

    # Speed up a little each time.
    tempo = tempo * 1.2

Visual Inclinometer

Direct download: cpb_visual_inclinometer.py.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# cpb_visual_inclinometer.py

# Use the CPB as a visual inclinometer by lighting the onboard NeoPixel LEDS to
# indicate the highest point as it tilts.

# This program uses only onboard hardware: accelerometer, NeoPixel LEDs.

# The sensor data is printed to the serial console in a format suitable for
# plotting.

# This example also demonstrates signal smoothing using a first-order filter.

# ----------------------------------------------------------------
# Import the standard Python math library and time functions.
import math, time

# Import the board-specific input/output library.
from adafruit_circuitplayground import cp

# Configure the NeoPixel LED array for bulk update using show().
cp.pixels.auto_write = False

# Turn down the NeoPixel brightness, otherwise it is somewhat blinding.
cp.pixels.brightness = 0.5

# ----------------------------------------------------------------
# Initialize global variables for the main loop.
plot_timer = 0.0
last_time = time.monotonic()
x = 0
y = 0

# ----------------------------------------------------------------
# Begin the main processing loop.  Empirically, this loop runs about 200 Hz.
while True:
    # Read the accelerometer, which functions primarily as a tilt sensor.
    raw_x, raw_y, z = cp.acceleration

    # Apply first-order low-pass smoothing filters to the acceleration signals.
    x += 0.1 * (raw_x - x)
    y += 0.1 * (raw_y - y)
        
    # Convert the x,y acceleration components to an angle in degrees with
    # respect to the USB connector, increasing clockwise.
    acc_angle = math.atan2(x, y) * 180/math.pi
    
    # Project the tilt angle onto the NeoPixels. The list assumes the Neopixels
    # are uniformly spaced at 30 degree intervals, with the top and bottom
    # positions absent.  The angles are measured analogous to a clock with zero
    # at the top.  Up to three LEDs are lit in proportion to the relative
    # position of the tilt vector and their position.
    for i, led_angle in enumerate((-30, -60, -90, -120, -150, 150, 120, 90, 60, 30)):
        diff = abs(acc_angle - led_angle)
        if diff < 32:
            c = 255 - 8*diff
            cp.pixels[i] = (c, c, c) # shade of gray
        else:
            cp.pixels[i] = (0,0,0)   # no light

    # Send new data to the physical LED chain.
    cp.pixels.show()

    # Periodically generate data in a format suitable for plotting within the Mu Editor.
    now = time.monotonic()
    interval = now - last_time
    last_time = now
    plot_timer -= interval
    if plot_timer < 0.0:
        plot_timer += 0.05  # 20 Hz data
        # scale the angle to radians so it can be plotted on the same scale as X and Y
        radians = acc_angle * (math.pi / 180.0)
        print(f"({x:6.3f},{y:6.3f},{radians:6.3f})")

Touch Diffusion

Direct download: cpb_touch_diffusion.py.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# cpb_touch_diffusion.py

# Use touch sensitive pads and sound to control a lighting display.  The display
# models a diffusion process, with each touch pad contributing an activation.  A
# loud sound or physical tap will trigger a single flash.

# This program uses only onboard hardware: capacitive touch sensing, sound level
# sensor, NeoPixel LEDs.

# ----------------------------------------------------------------
# Import the standard Python math library and time functions.
import math, time

# Import the board-specific input/output library.
from adafruit_circuitplayground import cp

# Configure the NeoPixel LED array for bulk update using show().
cp.pixels.auto_write = False

# ----------------------------------------------------------------
# Initialize global variables for the main loop.

# The display update rate is precisely regulated using the following timer variables.
# The default is 20 Hz frame rate as set by step_interval.
step_timer    = 0.0
last_time     = time.monotonic()
step_interval = 0.05

# The core model state is an array of state variables.  Note that the state is
# modeled for 12 uniformly spaced positions, even though only ten are populated
# with NeoPixels.  This state is abstract but might represent heat moving
# through a ring of material.
state = [0.0] * 12  # create 12 element array of zeros

# ----------------------------------------------------------------
# Begin the main processing loop.
while True:

    # Measure elapsed time and wait until the update timer has elapsed.
    now = time.monotonic()
    interval = now - last_time
    last_time = now
    step_timer -= interval
    if step_timer < 0.0:
        step_timer += step_interval

        # Apply a first-order diffusion model to the state.  This loop creates a new
        # array to replace the previous state.  The modulo operator (%) is used to 'wrap
        # around' the end of the array to close the loop.
        N = len(state)
        new = [0.0] * N
        for i in range(N):
            new[i] = 0.9 * state[i] + 0.05 * state[(i-1) % N] + 0.05 * state[(i+1) % N]

        # Replace the previous state.
        state = new

        # Apply a slow decay to represent leakage outside the ring.
        for i in range(N):
            state[i] = 0.97 * state[i]

        # Apply touch inputs as excitation blended into nearby samples.
        if cp.touch_A1: state[8]  += 0.1 * (1.0 - state[ 8])
        if cp.touch_A2: state[10] += 0.1 * (1.0 - state[10])
        if cp.touch_A3: state[11] += 0.1 * (1.0 - state[11])
        if cp.touch_A4: state[ 2] += 0.1 * (1.0 - state[ 2])
        if cp.touch_A5: state[ 3] += 0.1 * (1.0 - state[ 3])
        if cp.touch_A6: state[ 4] += 0.1 * (1.0 - state[ 4])

        # Update the LED colors to reflect the state.  Note that states 0 and 6
        # are invisible as these positions do not have LEDs.
        for i, s in enumerate(state):
            if i != 0 and i != 6:
                # Clamp the state value between 0.0 and 1.0.
                value = min(max(s, 0.0), 1.0)

                # Map the state index to an LED position index.
                pos = i-1 if i < 6 else i-2

                # Map 0.0 to dim blue and 1.0 to bright red.
                cp.pixels[pos] = (255 * value, 0, 50 * (1.0 - value))

        # If a loud sound is detected, override the normal display to flash white.
        # A physical tap will also trigger the flash.
        if cp.loud_sound():
            cp.pixels.fill((255,255,255))

        # Send new data to the physical LED chain.
        cp.pixels.show()