One of the CLUE's many features is BLE connectivity, which opens up possibilities for utilizing wireless communication. In this project, you'll use the PyLeap app to wirelessly load the project code onto your CLUE. Then, you'll connect to the CLUE with the Adafruit Bluefruit Connect app to change the colors and animations of a strip of NeoPixels over BLE.

Original Project

This project was originally created by Erin St. Blaine and Kattni Rambor with CircuitPython and a Circuit Playground Bluefruit. The code has been adapted for the CLUE to make use of the CLUE's screen to display animation and RGB color information. You can check out the original Learn Guide for more information on how the code works.

Parts

Animated GIF showing CLUE board  displaying data from the many on-board sensors.
Do you feel like you just don't have a CLUE? Well, we can help with that - get a CLUE here at Adafruit by picking up this sensor-packed development board. We wanted to build some...
$44.95
In Stock
Adafruit NeoPixel LED 0.5 meter Strip with Alligator Clips wired to Circuit Playground, lighting up rainbow
Adding glowy color to your projects has never been easier: no more soldering or stripping wires, clip 'em on and glow! This Adafruit NeoPixel LED Strip with Alligator...
$12.50
In Stock
Angled shot of a Clear Acrylic Enclosure + Hardware Kit for Adafruit CLUE.
Here is a chic minimalist enclosure for your CLUE board! This case has been laser-cut specifically to accommodate the TFT display, tactile buttons, and...
$4.95
In Stock
USB cable - USB A to Micro-B - 3 foot long
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or...
$2.95
In Stock
Angled shot of 3 x AA battery holder with on/off switch, JST, and belt clip.
This battery holder connects 3 AA batteries together in series for powering all kinds of projects. We spec'd these out because the box is compact, and 3 AA's add up to about...
$2.95
In Stock
Angled shot of 3 AA batteries.
Battery power for your portable project! These batteries are good quality at a good price, and work fantastic with any of the kits or projects in the shop that use AAs. This is a pack...
$2.25
In Stock

To wire up the strip of NeoPixels to the CLUE, you'll clip the NeoPixel strip's alligator clips to the CLUE's pads located at the bottom of the board. The alligator clips are color coded so that you can tell which connection goes where.

Wiring Diagram

  • NeoPixel Data In to CLUE pad 0 (white wire)
  • NeoPixel Power to CLUE 3V pad (red wire)
  • NeoPixel Ground to CLUE GND pad (black wire)

Assembly

First, make sure that your CLUE is disconnected from power. Then, clip the NeoPixel strip's white alligator clip to the CLUE's pad 0. This is the data input for the NeoPixel strip.

Next, clip the NeoPixel strip's red alligator clip to the CLUE's 3V pad. This is the power input for the NeoPixel strip.

Finally, clip the NeoPixel strip's black alligator clip to the CLUE's GND pad. This is the ground connection for the NeoPixel strip.

Now your NeoPixel strip is connected to your CLUE!

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY flash drive to iterate.

The following instructions will show you how to install CircuitPython. If you've already installed CircuitPython but are looking to update it or reinstall it, the same steps work for that as well!

Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Click the link above to download the latest version of CircuitPython for the CLUE.

Download and save it to your desktop (or wherever is handy).

Plug your CLUE into your computer using a known-good USB cable.

A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.

Double-click the Reset button on the top (magenta arrow) on your board, and you will see the NeoPixel RGB LED (green arrow) turn green. If it turns red, check the USB cable, try another USB port, etc. Note: The little red LED next to the USB connector will pulse red. That's ok!

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

You will see a new disk drive appear called CLUEBOOT.

Drag the adafruit-circuitpython-clue-etc.uf2 file to CLUEBOOT.

The LED will flash. Then, the CLUEBOOT drive will disappear and a new disk drive called CIRCUITPY will appear.

If this is the first time you're installing CircuitPython or you're doing a completely fresh install after erasing the filesystem, you will have two files - boot_out.txt, and code.py, and one folder - lib on your CIRCUITPY drive.

If CircuitPython was already installed, the files present before reloading CircuitPython should still be present on your CIRCUITPY drive. Loading CircuitPython will not create new files if there was already a CircuitPython filesystem present.

That's it, you're done! :)

Now that you're done uploading the correct firmware, disconnect your device from your computer and power it via LiPoly or AAA battery pack.

Pairing device to PyLeap

Once powered, press the small Reset button in the center of the board (Circuit Playground Bluefruit) or on the top right of the board (CLUE). When the blue light flashes, press the Reset button again.

Circuit Playground Bluefruit with a small Reset button in the center of the board
Adafruit
Adafruit CLUE Reset Button (Highlighted on the upper right)

When done correctly, the LEDs will flash yellow followed by solid blue. Once this occurs, the board will continuously be in discovery mode.

Scan & Connect

When your Circuit Playground Bluefruit or Adafruit CLUE is in discovery mode, hold it very closely to your iPhone or iPadOS to pair. 

Below the spinning Blinka, you'll notice a status indicator that will let you know your current pairing status.

Once you've found your device and received the Bluetooth Pairing Request message, press Pair to pair your board to your iPhone or iPadOS.

If your Circuit Playground Bluefruit doesn't appear:

  1. Check to see if your Circuit Playground Bluefruit is powered on. Verify that the green On light is lit.
  2. Make sure your Circuit Playground Bluefruit is running the correct firmware. See the CircuitPython page in this guide.
  3. Try resetting the Circuit Playground Bluefruit by pressing the small Reset button near the center of the board.
# SPDX-FileCopyrightText: 2020 Kattni Rembor for Adafruit Industries
# SPDX-FileCopyrightText: 2020 Erin St Blaine for Adafruit Industries
#
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries (Adapted for CLUE)
#
# SPDX-License-Identifier: MIT

# pylint: disable=attribute-defined-outside-init
# pylint: disable=too-few-public-methods

import board
import neopixel
import displayio
import terminalio
from adafruit_display_text import label
from rainbowio import colorwheel
from adafruit_display_shapes.rect import Rect
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.rainbow import Rainbow
from adafruit_led_animation.animation.rainbowcomet import RainbowComet
from adafruit_led_animation.animation.sparkle import Sparkle
from adafruit_led_animation.animation.sparklepulse import SparklePulse
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.group import AnimationGroup
from adafruit_led_animation.animation import Animation
from adafruit_led_animation.sequence import AnimateOnce
from adafruit_led_animation.color import (
    AMBER,
    ORANGE,
    WHITE,
    RED,
    BLACK
)

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.button_packet import ButtonPacket
from adafruit_bluefruit_connect.color_packet import ColorPacket

NUM_LEDS = 60                   # change to reflect your LED strip
NEOPIXEL_PIN = board.D0        # change to reflect your wiring

# Declare a NeoPixel object on NEOPIXEL_PIN with NUM_LEDS pixels,
# no auto-write.
# Set brightness to max, we'll control it later in the code
pixels = neopixel.NeoPixel(NEOPIXEL_PIN, NUM_LEDS, brightness=1.0,
                           auto_write=False,
                           )

ble = BLERadio()
uart_service = UARTService()
advertisement = ProvideServicesAdvertisement(uart_service)

display = board.DISPLAY
clue_group = displayio.Group()

rect = Rect(0, 0, 240, 240, fill=0x0)
clue_group.append(rect)

text_area = label.Label(terminalio.FONT, text="CONNECT TO BLE", color=WHITE)
text_area.anchor_point = (0.5, 0.5)
text_area.anchored_position = (240 / 2, 240 / 2)
text_area.scale = 2
clue_group.append(text_area)

display.root_group = clue_group

class RainbowFade(Animation):
    ''' fades the entire strip through the whole spectrum '''
    _color_index = 150 # choose start color (0-255)
    def __init__(self, pixel_object, speed, name): # define animation
        super().__init__(pixel_object, speed=speed, color=WHITE, name=name)

    def draw(self): # draw the animation
        ''' fades the entire strip through the whole spectrum '''
        self.color = colorwheel(self._color_index + 1)
        self._color_index = (self._color_index + 1) % 256
        self.fill(self.color)

# ANIMATION DEFINITIONS --
#    create as many animations as you'd like and define their attributes here.
#    They can be a single line or a group of animations - the groups will play
#    at the same time, overlaid on top of each other.


readingLight = Solid(pixels, color=0xFF7D13, name="reading light") #warm white color HEX code
brightWhite = Solid(pixels, color=(150, 150, 150), name="bright white")
rainbow = Rainbow(pixels, speed=0.1, period=10, step=0.5, name="rainbow")
rainbowfade = RainbowFade(pixels, speed=0.4, name="rainbowfade")
powerup = RainbowComet(pixels, speed=0, tail_length=50, bounce=False, name="rainbow comet")
off = Solid(pixels, color=BLACK, name="off")

#startup animation will play just once
startup = AnimateOnce(powerup)

#starrynight and fire are animation groups with layered effects.
starrynight = AnimationGroup(
    SparklePulse(pixels, speed=0.01, color=(0, 0, 150), period=1),
    Comet(pixels, speed=0, tail_length=8, color=(150, 150, 150), bounce=False),
    name = "starrynight")

fire = AnimationGroup(
    Comet(pixels, speed=0.1, tail_length=1, color=BLACK),
    Sparkle(pixels, speed=0.1, num_sparkles=10, color=AMBER),
    Sparkle(pixels, speed=0.1, num_sparkles=10, color=RED),
    Sparkle(pixels, speed=0.1, num_sparkles=20, color=ORANGE),
    Sparkle(pixels, speed=0.1, num_sparkles=5, color=0xFF7D13),
    Sparkle(pixels, speed=0.1, num_sparkles=10, color=BLACK),
    name = "fire"
    )

# Here is the animation playlist where you set the order of modes

animations = AnimationSequence(
        readingLight,
        fire,
        rainbow,
        starrynight,
        rainbowfade,
        brightWhite,
        auto_clear=True,
        )


current_color = BLACK
MODE = 0

while True:
    if MODE == 0:  # If currently off...
        startup.animate()
        while startup.animate():
            pass
        MODE = 3
    # Advertise when not connected

    elif MODE >= 1:  # If not OFF MODE...
        ble.start_advertising(advertisement)
        while not ble.connected:
            text_area.text = "CONNECT TO BLE"
            if MODE == 2:
                pass
            elif MODE == 1:
                animations.animate()
    # Now we're connected

    while ble.connected:
        if uart_service.in_waiting:
            packet = Packet.from_stream(uart_service)
            # Color Picker Functionality
            if isinstance(packet, ColorPacket):
                MODE = 2
                # Set all the pixels to one color and stay there.
                pixels.fill(packet.color)
                pixels.show()
                text_area.text = str(packet.color)
            # Control Pad Functionality
            elif isinstance(packet, ButtonPacket):
                if packet.pressed:
                    if packet.button == ButtonPacket.BUTTON_1:
                        MODE = 1
                        animations.activate(1)
                    elif packet.button == ButtonPacket.BUTTON_2:
                        MODE = 1
                        animations.activate(2)
                    elif packet.button == ButtonPacket.BUTTON_3:
                        MODE = 1
                        animations.activate(3)
                    elif packet.button == ButtonPacket.BUTTON_4:
                        MODE = 1
                        animations.activate(4)
                    # change the mode with right arrow
                    elif packet.button == ButtonPacket.RIGHT:
                        MODE = 1
                        animations.next()
                    elif packet.button == ButtonPacket.LEFT:
                        MODE = 4
                        off.animate()
                    #change the brightness with up and down arrows
                    elif packet.button == ButtonPacket.UP:
                        pixels.brightness = pixels.brightness + 0.1
                        pixels.show()
                        if pixels.brightness > 1:
                            pixels.brightness = 1
                    elif packet.button == ButtonPacket.DOWN:
                        pixels.brightness = pixels.brightness - 0.1
                        pixels.show()
                        if pixels.brightness < 0.1:
                            pixels.brightness = 0.1
                    if MODE == 1:
                        text_area.text = str(animations.current_animation.name)
                    if MODE == 4:
                        text_area.text = str(off.name)
        if MODE == 1:
            animations.animate()
        if MODE == 3:
            text_area.text = "CONNECTED"
        if MODE == 4:
            animations.freeze()

After loading the project onto your CLUE with PyLeap, close out of the PyLeap app. This disconnects the CLUE from PyLeap.

Now, your CLUE display will show "CONNECT TO BLE", signaling that it's ready to connect to the Bluefruit Connect App. Follow along with the next two pages to download and install the app and then connect to the CLUE with it.

You need to close out of PyLeap before connecting to the Bluefruit Connect App. The CLUE can only be connected to one app at a time.

The Bluefruit LE Connect app provides iOS & Android devices with a variety of tools to communicate with Bluefruit LE devices. These tools cover basic communication and info reporting as well as more project specific uses such as Arduino Pin Control and a Color Picker.

The iOS app is a free download from Apple's App Store. It requires iOS 11.3 or later and works on iPhones, iPads, and iPod Touches.

The Android app is a free download from the Google Play Store. It requires Android 4.4 or later.

The app is compatible with these BLE devices from Adafruit, and possibly more:

First off - install the app from one of the App stores listed above if you haven't already.

Enable Bluetooth

If Bluetooth is disabled on your device, enable it by going to Settings->Bluetooth on your iOS device, or the analogous setting on your Android device.

Enable Location Services

If you plan to use the app to send location/GPS data to Bluefruit LE, enable Location Services. Enable it on iOS using Settings->Privacy->Location Services.

On launch, the app will automatically begin to scan for nearby Bluetooth LE devices.  Devices are presented in a table view in the order in which they were discovered.

Don't forget to turn on Bluetooth on your device! Airplane Mode turns off BLE.

iPhone

The following images depict the app when used on the iPhone. The Android app looks similar.

The device list will display all BLE devices discovered by the app (not just Bluefruit hardware) - so you may see a quite a few "" or <Unknown> entries for devices that don't advertise their name, as seen above.

  • To refresh the list and start a new scan, simply swipe down on the current list.
  • Each device's signal strength is displayed in the left side of its row.

If you tap on the device entry (not on Connect), you'll see more detail about a particular device:

iPad

The following images depict the app when used on the iPad

Tap the middle of a device's table row to reveal its relevant advertisement data.

  • Any device listed with a "Connect" button at the right can be accessed in Info mode.
  • Any device listed as "UART Capable" can be used with all modes - Info, UART, Pin I/O, & Controller.
To use the Bluefruit Connect app with your device it must be "UART capable"! All Adafruit BLE devices implement the UART interface, but other devices may not

Multiple UART Mode

The Multiple UART feature allows to monitor incoming data from, and send data to multiple devices simultaneously.

To use it:

  • Activate the Multiple UART Mode switch
  • Tap Connect next to each device you'd like to include
  • Tap the Start button below the Multiple UART mode to begin.

Once connected, you can choose UART or Plotter module to view incoming data from all connected peripherals. In the UART module, you can send data to one or all connected devices at once.

Connect

Tap the Connect button on the UART capable list entry you wish to use and choose a connection mode from the menu that appears.

Troubleshooting

If you’re having trouble finding your Bluefruit device in the scanned peripherals list, ensure the board is powered and not paired with any other BLE devices. If the problem persists, it could be due to caching issues in the iOS or Android operating system. For a fix, try the following:

  • Cycle Bluetooth - Turn your mobile device’s Bluetooth radio off and on again in the Settings app.
  • Relaunch App - Quit the Bluetooth LE Connect app and restart it. (instructions for iOS & Android)
  • Cycle Power - Restart your mobile device by powering it off and restarting.

Doing one or both of the above solves most peripheral scanning issues. If you're still having trouble, try searching the Adafruit Support forum for your issue.

After connecting your CLUE to the Bluefruit app, your CLUE display will show "CONNECTED". Now you can start controlling the NeoPixel strip's animations and colors with the app.

In the app, select the Controller module. Then select the Control Pad on the next screen.

You can press the different onscreen number buttons to select the NeoPixel animations. The CLUE screen will display the name of the animation.

  • 1 - Fire animation
  • 2 - Rainbow animation
  • 3 - Starry night animation
  • 4 - Rainbow fade animation

The arrow buttons can also affect the NeoPixels.

  • Up - increase brightness
  • Down - decrease brightness
  • Right - advance through the animations in order
  • Left - turn the NeoPixels off

Go back to the main Controller module page and select the Color Picker.

Select your color in the color wheel and then press Send selected color to change the color of the NeoPixels. The CLUE screen will display the RGB color code.

You can change the saturation of the color by moving the slider under the color wheel.

This guide was first published on Oct 05, 2022. It was last updated on Jun 25, 2024.