This project uses two Circuit Playground Bluefruit boards. One acts as the Remote Control, the other as the NeoPixel Animator. There are two separate pieces of code used in this project: one for the remote control, and one for the NeoPixel animator. You'll load each piece of code onto a separate Circuit Playground Bluefruit.
This project requires the latest version of CircuitPython! Be sure to follow the instructions found on the CircuitPython on Circuit Playground Bluefruit page to download the latest version before continuing.
For this code to work, you'll need to install the necessary libraries first. Follow the instructions on the Circuit Playground Bluefruit CircuitPython Libraries page, and then continue with the instructions in the next section.
Installing CircuitPython LED Animation Library
In addition to the libraries listed on the Circuit Playground Bluefruit CircuitPython Libraries page, this project requires one more library to work. Follow the same instructions found on the Libraries page, and include the Adafruit CircuitPython LED Animation library as well.
To install the Adafruit CircuitPython LED Animation library, drag the following folder out of the CircuitPython library bundle lib folder to the lib folder on your CIRCUITPY drive:
- adafruit_led_animation
Before continuing, ensure you have ALL of the files and folders mentioned on the Circuit Playground Bluefruit CircuitPython Libraries page AND the adafruit_led_animation folder in the lib folder on your CIRCUITPY drive.
CircuitPython Code
Download the following file and save it as code.py to the Circuit Playground Bluefruit you'll be using as the Remote Control:
# SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries # # SPDX-License-Identifier: MIT """ Remote Control code for Circuit Playground Bluefruit NeoPixel Animation and Color Remote Control. To be used with another Circuit Playground Bluefruit running the NeoPixel Animator code. """ import time from adafruit_circuitplayground.bluefruit import cpb from adafruit_ble import BLERadio from adafruit_ble.advertising.standard import ProvideServicesAdvertisement from adafruit_ble.services.nordic import UARTService from adafruit_bluefruit_connect.color_packet import ColorPacket from adafruit_bluefruit_connect.button_packet import ButtonPacket def scale(value): """Scale a value from acceleration value range to 0-255 (RGB range)""" value = abs(value) value = max(min(19.6, value), 0) return int(value / 19.6 * 255) def send_packet(uart_connection_name, packet): """Returns False if no longer connected.""" try: uart_connection_name[UARTService].write(packet.to_bytes()) except: # pylint: disable=bare-except try: uart_connection_name.disconnect() except: # pylint: disable=bare-except pass return False return True ble = BLERadio() # Setup for preventing repeated button presses and tracking switch state button_a_pressed = False button_b_pressed = False last_switch_state = None uart_connection = None # See if any existing connections are providing UARTService. if ble.connected: for connection in ble.connections: if UARTService in connection: uart_connection = connection break while True: last_switch_state = None if not uart_connection or not uart_connection.connected: # If not connected... print("Scanning...") for adv in ble.start_scan(ProvideServicesAdvertisement, timeout=5): # Scan... if UARTService in adv.services: # If UARTService found... print("Found a UARTService advertisement.") uart_connection = ble.connect(adv) # Create a UART connection... break # Stop scanning whether or not we are connected. ble.stop_scan() # And stop scanning. while uart_connection and uart_connection.connected: # If connected... if cpb.button_a and not button_a_pressed: # If button A pressed... print("Button A pressed.") # Send a LEFT button packet. if not send_packet(uart_connection, ButtonPacket(ButtonPacket.LEFT, pressed=True)): uart_connection = None continue button_a_pressed = True # Set to True. time.sleep(0.05) # Debounce. if not cpb.button_a and button_a_pressed: # On button release... button_a_pressed = False # Set to False. time.sleep(0.05) # Debounce. if cpb.button_b and not button_b_pressed: # If button B pressed... print("Button B pressed.") # Send a RIGHT button packet. if not send_packet(uart_connection, ButtonPacket(ButtonPacket.RIGHT, pressed=True)): uart_connection = None continue button_b_pressed = True # Set to True. time.sleep(0.05) # Debounce. if not cpb.button_b and button_b_pressed: # On button release... button_b_pressed = False # Set to False. time.sleep(0.05) # Debounce. if cpb.switch is not last_switch_state: # If the switch state is changed... last_switch_state = cpb.switch # Set state to current switch state. if cpb.switch: print("Switch is to the left: LEDs off!") else: print("Switch is to the right: LEDs on!") # Send a BUTTON_1 button packet. if not send_packet(uart_connection, ButtonPacket(ButtonPacket.BUTTON_1, pressed=cpb.switch)): uart_connection = None continue if cpb.switch: # If switch is to the left... cpb.pixels.fill((0, 0, 0)) # Turn off the LEDs. else: # Otherwise... r, g, b = map(scale, cpb.acceleration) # Map acceleration values to RGB values... color = (r, g, b) # Set color to current mapped RGB value... print("Color:", color) cpb.pixels.fill(color) # Fill Remote Control LEDs with current color... if not send_packet(uart_connection, ColorPacket(color)): # And send a color packet. uart_connection = None continue time.sleep(0.1) # Delay to prevent sending packets too quickly.
Download the following file and save it as code.py to the Circuit Playground Bluefruit you'll be using as the NeoPixel Animator, i.e. the CPB with the NeoPixel strip(s) connected to it:
# SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries # # SPDX-License-Identifier: MIT """ NeoPixel Animator code for Circuit Playground Bluefruit NeoPixel Animation and Color Remote Control. To be used with another Circuit Playground Bluefruit running the Remote Control code. """ import board import neopixel from adafruit_circuitplayground.bluefruit import cpb from adafruit_led_animation.animation.blink import Blink from adafruit_led_animation.animation.comet import Comet from adafruit_led_animation.animation.sparkle import Sparkle from adafruit_led_animation.group import AnimationGroup from adafruit_led_animation.sequence import AnimationSequence import adafruit_led_animation.color as color 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.color_packet import ColorPacket from adafruit_bluefruit_connect.button_packet import ButtonPacket # The number of NeoPixels in the externally attached strip # If using two strips connected to the same pin, count only one strip for this number! STRIP_PIXEL_NUMBER = 30 # Setup for blink animation BLINK_SPEED = 0.5 # Lower numbers increase the animation speed BLINK_INITIAL_COLOR = color.RED # Color before Remote Control is connected # Setup for comet animation COMET_SPEED = 0.03 # Lower numbers increase the animation speed CPB_COMET_TAIL_LENGTH = 5 # The length of the comet on the Circuit Playground Bluefruit STRIP_COMET_TAIL_LENGTH = 15 # The length of the comet on the NeoPixel strip CPB_COMET_BOUNCE = False # Set to True to make the comet "bounce" the opposite direction on CPB STRIP_COMET_BOUNCE = True # Set to False to stop comet from "bouncing" on NeoPixel strip # Setup for sparkle animation SPARKLE_SPEED = 0.03 # Lower numbers increase the animation speed # Create the NeoPixel strip strip_pixels = neopixel.NeoPixel(board.A1, STRIP_PIXEL_NUMBER, auto_write=False) # Setup BLE connection ble = BLERadio() uart = UARTService() advertisement = ProvideServicesAdvertisement(uart) # Setup animations animations = AnimationSequence( AnimationGroup( Blink(cpb.pixels, BLINK_SPEED, BLINK_INITIAL_COLOR), Blink(strip_pixels, BLINK_SPEED, BLINK_INITIAL_COLOR), sync=True ), AnimationGroup( Comet(cpb.pixels, COMET_SPEED, color.MAGENTA, tail_length=CPB_COMET_TAIL_LENGTH, bounce=CPB_COMET_BOUNCE), Comet(strip_pixels, COMET_SPEED, color.MAGENTA, tail_length=STRIP_COMET_TAIL_LENGTH, bounce=STRIP_COMET_BOUNCE) ), AnimationGroup( Sparkle(cpb.pixels, SPARKLE_SPEED, color.PURPLE), Sparkle(strip_pixels, SPARKLE_SPEED, color.PURPLE) ), ) animation_color = None mode = 0 blanked = False while True: ble.start_advertising(advertisement) # Start advertising. was_connected = False while not was_connected or ble.connected: if not blanked: # If LED-off signal is not being sent... animations.animate() # Run the animations. if ble.connected: # If BLE is connected... was_connected = True if uart.in_waiting: # Check to see if any data is available from the Remote Control. try: packet = Packet.from_stream(uart) # Create the packet object. except ValueError: continue if isinstance(packet, ColorPacket): # If the packet is color packet... if mode == 0: # And mode is 0... animations.color = packet.color # Update the animation to the color. # Uncomment below to see the color tuple printed to the serial console. # print("Color:", packet.color) animation_color = packet.color # Keep track of the current color... elif mode == 1: # Because if mode is 1... animations.color = animation_color # Freeze the animation color. # Uncomment below to see the color tuple printed to the serial console. # print("Color:", animation_color) elif isinstance(packet, ButtonPacket): # If the packet is a button packet... # Check to see if it's BUTTON_1 (which is being sent by the slide switch) if packet.button == ButtonPacket.BUTTON_1: if packet.pressed: # If Remote Control switch is to the left... print("Remote Control switch is to the left: LEDs off!") else: # If the Remote Control switch is to the right... print("Remote Control switch is to the right: LEDs on!") # If the Remote Control switch is moved from right to left... if packet.pressed and not blanked: animations.fill(color.BLACK) # Turn off the LEDs. blanked = packet.pressed # Track the state of the slide switch. if packet.pressed: # If the buttons on the Remote Control are pressed... if packet.button == ButtonPacket.LEFT: # If button A is pressed... print("A pressed: animation mode changed.") animations.next() # Change to the next animation. elif packet.button == ButtonPacket.RIGHT: # If button B is pressed... mode += 1 # Increase the mode by 1. if mode == 1: # If mode is 1, print the following: print("B pressed: color frozen!") if mode > 1: # If mode is > 1... mode = 0 # Set mode to 0, and print the following: print("B pressed: color changing!")
The next section shows you how to use the Remote Control Circuit Playground Bluefruit with the NeoPixel Animator Circuit Playground Bluefruit to change color and animations. Check it out!
Text editor powered by tinymce.