Overview
Flower, gleam and glow
Let your power shine
Make the clock reverse
Bring back what once was mine- Rapunzel, Tangled
Let your power shine with this DIY light-up Rapunzel wig. The Circuit Playground Bluefruit uses its onboard microphone to listen for your voice and creates a golden light animation when it hears a sound. Sing your heart out, and the sound-reactive lights will make your hair glow with a warm magic light, reminiscent of Rapunzel's hair from Disney's Tangled movie.
This is a great project to do with kids, who will not be able to get enough of this fantastic cosplay prop. It's a fairly easy project involving just a little bit of tricky wiring. Example CircuitPython code is included so you can copy and paste to make the hair light up in a golden wave. The code is easy to customize, so it suits your cosplay character if yellow is not your color.
These NeoPixel slim LED dots are perfect for cosplay projects or kids' projects. They're lightweight and very tough. They're water resistant and can be flexed again and again without breaking. I used 3 strands of 20 lights, wired together in parallel.
There are a lot of battery options out there. If you're making this project for a child, it's a good idea to steer away from Lithium Polymer batteries since they're easy to break, and can be dangerous if they get punctured or wet.
One option is an AAA battery holder. It comes with an on/off switch so you don't need to add a separate one to the project.
Another power option is a USB battery pack. These are fantastic because they're rechargeable and really sturdy, but they are considerably more expensive. However, you won't need to keep buying batteries when your child forgets to turn the wig off, so it will save you money in the long run.
These batteries don't generally have on/off switches built in, but you can solve this problem by adding an inline power switch tail. The one linked below is a little bulky, but will work great with a USB battery.
Smaller switches with a shorter cable do exist, and you can find them online with some hunting. Be sure you're buying one that has a USB micro male connector on one end (to plug into your Circuit Playground Bluefruit), and a male connector on the other end that's compatible with the port on your battery. Many of these switches come male to female, so be sure you're buying the right one.
Additional Materials
- A Rapunzel wig. I used this kid-sized one from Amazon.
- A silk flower that's at least 3" across
- Hair clips or barettes
- A twist tie
- E6000 glue
- Needle & thread
- Alligator Clips for testing
Page last edited March 08, 2024
Text editor powered by tinymce.
Wiring Diagram
Cut the female connector off the LED strands. This is the IN end. These lights are directional so if you hook up the wrong end, they won't work.
With the resin bump facing you and the wires pointing up:
- Left wires go to VOUT
- Middle wires go to G
- Right wires go to A1
These LEDs are not manufactured by Adafruit so there may be variation in how the different lots are wired. If your lights don't work with this configuration, you might have a strand that's wired differently. Experiment by hooking up the different wires to alligator clips to figure out which wire is which.
Page last edited March 08, 2024
Text editor powered by tinymce.
CircuitPython on Circuit Playground Bluefruit
Install or Update CircuitPython
Follow this quick step-by-step to install or update CircuitPython on your Circuit Playground Bluefruit.
Click the link above and download the latest UF2 file
Download and save it to your Desktop (or wherever is handy)
Plug your Circuit Playground Bluefruit into your computer using a known-good data-capable 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 small Reset button in the middle of the CPB (indicated by the red arrow in the image). The ten NeoPixel LEDs will all turn red, and then will all turn green. If they turn all red and stay red, check the USB cable, try another USB port, etc. The little red LED next to the USB connector will pulse red - this is ok!
If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!
(If double-clicking doesn't do it, try a single-click!)
You will see a new disk drive appear called CPLAYBTBOOT.
Drag the adafruit_circuitpython_etc.uf2 file to CPLAYBTBOOT.
Page last edited March 08, 2024
Text editor powered by tinymce.
CircuitPython Code
Once you have CircuitPython installed on your board, it's time to add the project code and libraries.
Source Code and Example Images
CIRCUITPY drive. Then you need to update code.py with the example script.
Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, open the directory Rapunzel_Hair/ and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your CIRCUITPY drive.
Your CIRCUITPY
# SPDX-FileCopyrightText: Erin St Blaine and ChatGPT for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
import board
from adafruit_circuitplayground import cp
import neopixel
# Constants
NUM_PIXELS_STRIP = 20
NUM_PIXELS_FACE = 10 # Number of NeoPixels on the face
PIXEL_PIN_STRIP = board.A1
SOUND_THRESHOLD = 50 # Adjust this threshold based on your environment
# Variables
DELAY_AFTER_LIGHT_UP = 2.0
COLOR = (255, 100, 0) # Warm yellow color
SPEED = 0.3 # Animation speed (adjust as needed, higher number moves more slowly)
# Initialize NeoPixels on face
pixels_face = cp.pixels
pixels_face.brightness = 0.5
# Initialize NeoPixels on strip (A1)
pixels_strip = neopixel.NeoPixel(PIXEL_PIN_STRIP, NUM_PIXELS_STRIP, brightness=0.5)
# Main loop
while True:
# Read sound level
sound_level = cp.sound_level
# Debugging: Print sound level to the serial monitor
print("Sound Level:", sound_level)
# Check if sound threshold is reached
if sound_level > SOUND_THRESHOLD:
# Sequentially light up NeoPixels on the face
for i in range(NUM_PIXELS_FACE):
if i < len(pixels_face):
pixels_face[i] = COLOR
time.sleep(SPEED) # Adjust speed if needed
pixels_face.show() # Show all pixels at once
# Sequentially light up NeoPixels on strip (A1)
for i in range(NUM_PIXELS_STRIP):
if i < len(pixels_strip):
pixels_strip[i] = COLOR
time.sleep(SPEED) # Adjust speed if needed
pixels_strip.show() # Show all pixels at once
# Delay for the specified duration after lighting up all pixels
time.sleep(DELAY_AFTER_LIGHT_UP)
# Turn off all pixels on strip
pixels_strip.fill((0, 0, 0))
pixels_strip.show()
# Turn off all pixels on face
pixels_face.fill((0, 0, 0))
pixels_face.show()
# Add a delay to avoid rapid detection
time.sleep(0.1)
Code Walkthrough
Let's take a look at what's happening in the code.
First we import all the necessary libraries.
import time import board from adafruit_circuitplayground import cp import neopixel
The next section is where you can do all your customization.
-
NUM_PIXELS_STRIP: The total number of pixels in one strand. -
SOUND_THRESHOLD: Adjust this number until the sound sensitivity is right for your environment. A higher number means you need to sing louder to trigger the lights. -
DELAY_AFTER_LIGHT_UP: How long the lights stay on before turning off, in seconds and milliseconds. -
COLOR: An RGB tuple specifying how much red, green, and blue make up the light color. Choose a number between0-255for (red, green, blue) lights. -
SPEED: This number represents the delay between turning on one light and turning on the next light. A higher number means more delay, so the animation moves more slowly.
# Constants NUM_PIXELS_STRIP = 20 NUM_PIXELS_FACE = 10 # Number of NeoPixels on the face PIXEL_PIN_STRIP = board.A1 SOUND_THRESHOLD = 50 # Adjust this threshold based on your environment # Variables DELAY_AFTER_LIGHT_UP = 2.0 COLOR = (255, 100, 0) # Warm yellow color SPEED = 0.3 # Animation speed (adjust as needed, higher number moves more slowly)
Next we initialize the pixels:
# Initialize NeoPixels on face pixels_face = cp.pixels pixels_face.brightness = 0.5 # Initialize NeoPixels on strip (A1) pixels_strip = neopixel.NeoPixel(PIXEL_PIN_STRIP, NUM_PIXELS_STRIP, brightness=0.5)
And finally the main loop, where the action happens. Since most of the controls have been broken out into variables, you shouldn't need to change much here.
# Main loop
while True:
# Read sound level
sound_level = cp.sound_level
# Debugging: Print sound level to the serial monitor
print("Sound Level:", sound_level)
# Check if sound threshold is reached
if sound_level > SOUND_THRESHOLD:
# Sequentially light up NeoPixels on the face
for i in range(NUM_PIXELS_FACE):
if i < len(pixels_face):
pixels_face[i] = COLOR
time.sleep(SPEED) # Adjust speed if needed
pixels_face.show() # Show all pixels at once
# Sequentially light up NeoPixels on strip (A1)
for i in range(NUM_PIXELS_STRIP):
if i < len(pixels_strip):
pixels_strip[i] = COLOR
time.sleep(SPEED) # Adjust speed if needed
pixels_strip.show() # Show all pixels at once
# Delay for the specified duration after lighting up all pixels
time.sleep(DELAY_AFTER_LIGHT_UP)
# Turn off all pixels on strip
pixels_strip.fill((0, 0, 0))
pixels_strip.show()
# Turn off all pixels on face
pixels_face.fill((0, 0, 0))
pixels_face.show()
# Add a delay to avoid rapid detection
time.sleep(0.1)
Troubleshooting
If your code doesn't run, here are a few things to try:
- Be sure your CIRCUITPY drive looks just like the image above, with the library files inside the /lib folder and the code.py file at the root of the drive.
- Some older Circuit Playground Bluefruit boards may need their bootloader upgraded before the newest version of CircuitPython will run on them. Here's a guide showing how to update the bootloader.
- If the lights on the face of the Circuit Playground come on, but your LED dot strand doesn't, you may have it hooked up incorrectly. These strands are tricky in that they really don't have any markings at all. If you followed the wiring diagram but aren't getting lights, try hooking up to the other end of your strand, or experiment with different arrangements using alligator clips.
Page last edited March 08, 2024
Text editor powered by tinymce.
Code Writing with ChatGPT
This code was largely written by ChatGPT (version 3.5 was used). It took a few iterations and some testing and feedback from me, but for simple, straightforward effects in CircuitPython, ChatGPT is surprisingly easy to use. It's an amazing tool for folks who don't have a coding background, but have a clear vision of what the code should do. I first installed the Mu Editor to check each time I had changes.
I could copy and paste each iteration of ChatGPT's code into the Mu editor and load it onto my CircuitPlayground Bluefruit, testing and making requests until it did exactly what I wanted. ChatGPT made its share of mistakes, but when I told it what errors were being thrown, it came back every time with a corrected version.
Once I felt the code was finished, I ran it through Pylint to check for errors and it came back with a 100% perfect score the very first time.
Here is a transcription of the prompts I used and the testing process I went through.
Chat GPT Transcript
Erin: please write me some CircuitPython code that uses the sound sensor on the Circuit Playground Bluefruit. When the sound threshold is reached, I would like to sequentially light a strip of 20 NeoPixels soldered to pin A1 one at a time until they're all lit, then turn them off again all at once. Please have them turn on in a warm yellow color.
ChatGPT: Certainly! Below is a simple example of CircuitPython code that achieves the described functionality using the sound sensor and NeoPixels on the Circuit Playground Bluefruit:
(code sample using AudioIO library)
This code uses the Circuit Playground Bluefruit sound sensor to detect sound levels. When the sound level surpasses the defined threshold, it sequentially lights up the NeoPixels in a warm yellow color, then turns them off simultaneously. You can adjust the SOUND_THRESHOLD value and the delays to suit your specific requirements.
Erin: can you please use the Circuit Playground library instead of Audioio?
ChatGPT: Certainly! Below is an updated version of the CircuitPython code using the Circuit Playground library to interact with the sound sensor on the Circuit Playground Bluefruit:
(code sample using CircuitPlayground library)
In this code, I replaced the AudioIO library with the Circuit Playground library's cp.sound_level to read the sound level from the built-in microphone. The rest of the code remains similar, sequentially lighting up NeoPixels and turning them off when the sound threshold is reached. Adjust the SOUND_THRESHOLD value and delays as needed for your specific use case.
Erin: can you please add some code so the pixels on the face of the board also light up sequentially alongside the strip on A1?
ChatGPT: Certainly! You can modify the code to include the NeoPixels on the face of the Circuit Playground Bluefruit. Here's an updated version that lights up both the NeoPixels on pin A1 and the ones on the face of the board sequentially when the sound threshold is reached:
(code with NeoPixel onboard lights added)
This code introduces a new set of NeoPixels (pixels_face) for the face of the Circuit Playground Bluefruit. The code sequentially lights up both the NeoPixels on pin A1 and the face when the sound threshold is reached. Adjust the constants, colors, and delays according to your preferences.
Erin: great this is close. Can you please make it keep listening after turning the pixels off so it triggers each time the sound threshold is reached?
ChatGPT: Certainly! To keep the code continuously listening for sound and triggering the NeoPixels each time the sound threshold is reached, you can modify the structure of the code. Here's an updated version:
(code that keeps listening)
Now, the main loop keeps running continuously, allowing the code to keep listening for sound even after turning off the NeoPixels. The NeoPixels will trigger each time the sound threshold is reached. Adjust the delays and other parameters as needed for your specific use case.
Erin: This code throws an error in my serial monitor:
code.py output:Traceback (most recent call last): File "code.py", line 28, in IndexError: index out of range
ChatGPT: It seems there might be an issue with the loop that sequentially lights up the NeoPixels on the face of the Circuit Playground Bluefruit. Let's make sure the loop indices are within the valid range. Here's a corrected version:
(corrected code)
This version includes checks (if i < len(pixels_strip) and if i < len(pixels_face)) to ensure that the indices are within the valid range of the NeoPixels array. Try uploading this corrected code to your Circuit Playground Bluefruit and see if the issue persists.
Erin: That fixed it. Can you add some debugging code so it prints out the sound level in the serial monitor?
ChatGPT: Certainly! You can use the print statement to output the sound level to the serial monitor for debugging. Here's the modified code with debugging statements:
(code with sound level printing in serial monitor)
Now, the sound level will be printed to the serial monitor, helping you debug and understand the values being read from the microphone. Upload this modified code to your Circuit Playground Bluefruit and check the serial monitor for the sound level information.
Erin: here is the new code with a few changes I made. Can you please modify this code so that the pixels stay on for 2 seconds after they're all lit before going off?
(pasted in my modified code)
ChatGPT: Certainly! I've modified your code to include a 2-second delay after lighting up all the pixels. Here's the updated code:
(my modified code with 2 second delay)
Erin: This is great. Can you make the 2 second delay a variable so I can modify it from the top of the code?
ChatGPT: Certainly! You can introduce a variable for the delay duration at the top of the code. Here's the modified code with a variable for the delay duration:
(code with delay variable)
Now, you can easily modify the DELAY_AFTER_LIGHT_UP variable at the top of the code to adjust the delay duration after lighting up all pixels. Upload this modified code and experiment with different delay durations as needed.
Erin: Can we also make the color a variable so users can modify it together with the other variables at the top of the code?
ChatGPT: Certainly! You can introduce a variable for the color at the top of the code. Here's the modified code with a variable for the color:
(code with color variable added)
Erin: Thank you so much, this is perfect.
Page last edited March 08, 2024
Text editor powered by tinymce.
Electronics Assembly
Cut the female connector off the end of one of your LED strands. Hook up the three wires to your Circuit Playground Bluefruit as shown. On my strands, the left most wire (with the resin bump on the LEDs facing you) is power, the middle wire is ground, and the one on the right is data.
It's very important to test these and make sure you have the connections right. These strips are not marked in any way, and we've gotten inconsistent wiring with different lots, so testing is essential. If you can't get the lights to come on, play around with different configurations or try connecting data to the other end.
If you're having trouble, here is a guide showing how to set up your Circuit Playground Express as a tester using MakeCode.
Once you've established your wiring, it's a good idea to mark the wires with some heat shrink or tape so you keep them straight.
Strip a generous 1/4" of shielding from each wire. Do the same with your second strip and twist the wires together: power to power, ground to ground, and data to data.
Hook both wires back up to your tester and make sure they're both working. Add your third strand in and make sure that one comes on too.
Solder a red, black, and colored wire to the power, ground, and data clusters. Cover the connections with heat shrink.
Page last edited March 08, 2024
Text editor powered by tinymce.
Wig Assembly
It helps to have a wig head to hold the wig while you're working with it. Use sewing pins to hold it in place on the styrofoam head.
Unbraid the wig, keeping the three sections separate. This wig loves to get tangled up, so have a brush and some scissors handy, as well as a good helping of patience, to manage the tangles.
Costumes, especially kid's costumes, are prone to a lot of wiggling and tugging. The solder joints are not strong enough to withstand this kind of use. Strain relief is key for this kind of project to make it last.
I used a twist-tie through the unused holes on my CircuitPlayground to guarantee that any tugging will not be transferred to the delicate solder joints.
Don't use bare wire here -- the unused pads can still short out your board if they're connected by metal.
Glue a couple hair clips to the back of the Circuit Playground with E6000 or another very strong glue. Hot glue will probably not do the trick here, at least not for longer term use.
Another option is to put your Circuit Playground inside one of the Adafruit handy snap-fit cases. This will protect it from a lot of wear and tear.
Once the glue is dry, decorate the front of your Circuit Playground with a silk flower. This will diffuse the lights on the board beautifully. Use a needle and some strong thread to sew the lower petals to the board through the soldering holes. This works better than glue, since it won't damage or clog the sensors and buttons on the face of the board.
I also glued a jewel into the center of my flower.
Clip the flower securely into the wig at one of the temples. Cut a small hole in the wig's mesh lining just behind the flower and pull the light strands through to the inside. Weave them in and out of the cap a few times around the side of the head, so that they eventually emerge at the start of the braid. The idea here is to minimize any loose wires that may get caught on things as the wig is pulled on and off.
Place one strand in each of the three braid sections. Twist the sections to keep them separate and as tidy as possible, and to hide the lights inside. The hair works beautifully as a diffuser.
Place the wig on your wig head and pin it securely, or ask someone to wear it and hold it in place. It's much easier to get the braid in the right place and looking tidy if you do it while the wig is being worn.
Braid the hair tightly and secure with a rubber band. Trim off any extra lights that are sticking out the end of the braid -- I ended up trimming 1-2 lights off of each of my strands. Seal the ends with heat shrink to protect against dirt or moisture getting in.
Cut a slit in the wig cap behind the ear that's the right size for the clip on the battery case. Use some glue or thread or zip ties to secure the battery case so it doesn't fall out, making sure you still have the abilitiy to change the batteries as needed.
Page last edited March 08, 2024
Text editor powered by tinymce.