PyLeap BLE Controlled NeoPixels with CLUE
2023-12-26 | By Adafruit Industries
License: See Original Project LED Strips
Courtesy of Adafruit
Guide By Liz Clark
Overview
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.
Easy No-Soldering Bluetooth Controlled Room Lights Learn Guide
Parts
- Adafruit CLUE - nRF52840 Express with Bluetooth LE
- Adafruit NeoPixel LED Strip w/ Alligator Clips - 60 LED/m
- Clear Acrylic Enclosure + Hardware Kit for Adafruit CLUE
- USB cable - USB A to Micro-B
- 3 x AA Battery Holder with On/Off Switch, JST, and Belt Clip
- Alkaline AA batteries (LR6) - 3 pack
Connect the NeoPixels to the CLUE
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 on 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 :)
Download the latest version of CircuitPython for CLUE from circuitpython.org
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! :)
Pairing
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 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:
- Check to see if your Circuit Playground Bluefruit is powered on. Verify that the green On light is lit.
- Make sure your Circuit Playground Bluefruit is running the correct firmware. See the CircuitPython page in this guide.
- Try resetting the Circuit Playground Bluefruit by pressing the small Reset button near the center of the board.
BLE Controlled NeoPixels Code
# 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()
Bluefruit Connect App
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.
Installation and Setup
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:
- Bluefruit LE nRF8001 Breakout
- Bluefruit LE Friend
- Flora Wearable Bluefruit LE Module
- Adafruit Bluefruit LE SPI Friend
- Adafruit Bluefruit LE Micro
- Adafruit Feather 32u4 Bluefruit LE
- Adafruit Feather M0 Bluefruit LE
- Adafruit Feather nRF52 Bluefruit LE - nRF52832
- Adafruit Feather nRF52840 Express
- Adafruit CLUE
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.
Scan for Devices
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.
Usage
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.
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum