Now we'll install the libraries that we need to run the code on the Circuit Playground Bluefruit.
Download the Project Bundle link in the code embed element below.
Uncompress the .zip file and then copy the following directories and .mpy files from the version of CircuitPython you are using to the lib directory of the CIRCUITPY drive:
- adafruit_ble
- adafruit_bluefruit_connect
- adafruit_bus_device
- adafruit_lis3dh.mpy
- neopixel.mpy
Your lib directory on the CIRCUITPY drive should be similar to the picture here.
The Mu Editor
Adafruit recommends using the free program Mu to edit your CircuitPython programs and save them on your Circuit Playground Bluefruit. You can use any text editor, but Mu has some handy features.
See this page on the Circuit Playground Bluefruit guide on the steps used to install Mu.
Snow Globe Code
Here is the code that we'll run on the Circuit Playground Bluefruit.
Copy this code and then paste it into a new document in Mu, then save it to your CIRCUITPY drive as code.py
# SPDX-FileCopyrightText: 2019 Carter Nelson for Adafruit Industries # # SPDX-License-Identifier: MIT import time import random import board import busio import neopixel import adafruit_lis3dh from adafruit_bluefruit_connect.packet import Packet from adafruit_bluefruit_connect.color_packet import ColorPacket from adafruit_bluefruit_connect.button_packet import ButtonPacket from adafruit_ble import BLERadio from adafruit_ble.advertising.standard import ProvideServicesAdvertisement from adafruit_ble.services.nordic import UARTService #===| User Config |================================================== SNOWGLOBE_NAME = "SNOWGLOBE" # name that will show up on smart device DEFAULT_ANIMATION = 0 # 0-3, index in ANIMATIONS list DEFAULT_DURATION = 5 # total seconds to play animation DEFAULT_SPEED = 0.1 # delay in seconds between updates DEFAULT_COLOR = 0xFF0000 # hex color value DEFAULT_SHAKE = 20 # lower number is more sensitive # you can define more animation functions below # here, specify the four to be used ANIMATIONS = ('spin', 'pulse', 'strobe', 'sparkle') #===| User Config |================================================== # Configuration settings snow_config = { 'animation' : DEFAULT_ANIMATION, 'duration' : DEFAULT_DURATION, 'speed' : DEFAULT_SPEED, 'color' : DEFAULT_COLOR, 'shake' : DEFAULT_SHAKE, } # Setup NeoPixels pixels = neopixel.NeoPixel(board.NEOPIXEL, 10) # Setup accelo accelo_i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA) accelo = adafruit_lis3dh.LIS3DH_I2C(accelo_i2c, address=0x19) # Setup BLE ble = BLERadio() uart = UARTService() advertisement = ProvideServicesAdvertisement(uart) ble._adapter.name = SNOWGLOBE_NAME #pylint: disable=protected-access #--| ANIMATIONS |---------------------------------------------------- def spin(config): start_time = time.monotonic() last_update = start_time p = -1 while time.monotonic() - start_time < config['duration']: if time.monotonic() - last_update > config['speed']: pixels.fill(0) pixels[p % 10] = config['color'] p -= 1 last_update = time.monotonic() def pulse(config): start_time = time.monotonic() last_update = start_time brightness = 0 delta = 0.05 pixels.brightness = 0 pixels.fill(config['color']) while time.monotonic() - start_time < config['duration']: if time.monotonic() - last_update > config['speed']: brightness += delta if brightness > 1: brightness = 1 delta *= -1 if brightness < 0: brightness = 0 delta *= -1 pixels.brightness = brightness last_update = time.monotonic() def strobe(config): start_time = time.monotonic() last_update = start_time turn_on = True while time.monotonic() - start_time < config['duration']: if time.monotonic() - last_update > config['speed']: if turn_on: pixels.fill(config['color']) else: pixels.fill(0) turn_on = not turn_on last_update = time.monotonic() def sparkle(config): start_time = time.monotonic() last_update = start_time while time.monotonic() - start_time < config['duration']: if time.monotonic() - last_update > config['speed']: pixels.fill(0) pixels[random.randint(0, 9)] = config['color'] last_update = time.monotonic() #--| ANIMATIONS |---------------------------------------------------- def play_animation(config): #pylint: disable=eval-used eval(ANIMATIONS[config['animation']])(config) pixels.fill(0) def indicate(event=None): if not isinstance(event, str): return event = event.strip().upper() if event == 'START': for _ in range(2): for i in range(10): pixels[i] = DEFAULT_COLOR time.sleep(0.05) pixels.fill(0) if event == 'CONNECTED': for _ in range(5): pixels.fill(0x0000FF) time.sleep(0.1) pixels.fill(0) time.sleep(0.1) if event == 'DISCONNECTED': for _ in range(5): pixels.fill(0x00FF00) time.sleep(0.1) pixels.fill(0) time.sleep(0.1) indicate('START') # Are we already advertising? advertising = False while True: # While BLE is *not* connected while not ble.connected: if accelo.shake(snow_config['shake'], 5, 0): play_animation(snow_config) if not advertising: ble.start_advertising(advertisement) advertising = True # connected indicate('CONNECTED') while ble.connected: # Once we're connected, we're not advertising any more. advertising = False if accelo.shake(snow_config['shake'], 5, 0): play_animation(snow_config) if uart.in_waiting: try: packet = Packet.from_stream(uart) except ValueError: continue if isinstance(packet, ColorPacket): # # COLOR # snow_config['color'] = packet.color pixels.fill(snow_config['color']) time.sleep(0.5) pixels.fill(0) if isinstance(packet, ButtonPacket) and packet.pressed: # # SPEED # if packet.button == ButtonPacket.UP: speed = snow_config['speed'] - 0.05 speed = 0.05 if speed < 0.05 else speed snow_config['speed'] = speed play_animation(snow_config) if packet.button == ButtonPacket.DOWN: speed = snow_config['speed'] + 0.05 snow_config['speed'] = speed play_animation(snow_config) # # DURATION # if packet.button == ButtonPacket.LEFT: duration = snow_config['duration'] - 1 duration = 1 if duration < 1 else duration snow_config['duration'] = duration play_animation(snow_config) if packet.button == ButtonPacket.RIGHT: duration = snow_config['duration'] + 1 snow_config['duration'] = duration play_animation(snow_config) # # ANIMATION # if packet.button == ButtonPacket.BUTTON_1: snow_config['animation'] = 0 play_animation(snow_config) if packet.button == ButtonPacket.BUTTON_2: snow_config['animation'] = 1 play_animation(snow_config) if packet.button == ButtonPacket.BUTTON_3: snow_config['animation'] = 2 play_animation(snow_config) if packet.button == ButtonPacket.BUTTON_4: snow_config['animation'] = 3 play_animation(snow_config) # disconnected indicate('DISCONNECTED')
Once you've saved the code to the board, the Circuit Playground Bluefruit will swirl the NeoPixel ring once in the default color. It is now ready to be shaken, try it out!
The default animation will play each time you shake the CPB. You can now connect to it with the Bluefruit app on iOS or Android to adjust the color, animation pattern, speed, and duration.
We'll take a closer look at those settings on the next page after we build the snow globe!
Page last edited January 21, 2025
Text editor powered by tinymce.