Introduction: Smartphone Controlled Bluetooth LEDs (with Live Music Sync)
I've always loved building things, after I found that my new college dorm had terrible lighting, I decided to spice it up a little.
***WARNING*** If you build this project on the same scale as my setup, you will be working with a decent amount of electrical power. BE SAFE, use common sense, and if you are not sure, ASK! Don't risk burning your house down.
Step 1: Acquiring Materials
For this project you will need:
- Addressable WS2812B LED strip(s). 5V is by far the most common type and highly preferred in this project. This project is designed for RGB LEDs, not RGBW. I Strongly recommend Adafruit's NeoPixels. (~$25 per 60 LEDs)
- A CurieNano (still sold), an Arduino 101 (discontinued but the one I'm using), or another micro-controller that can access BLE. (~$35)
- A smartphone (both Apple and Android work)
- A power supply. Most addressable LEDs on the market are 5V. The amperage needed depends on the size of your setup*. (~$10-50 depending on your setup)
- Wiring** (you may also need the appropriate 3-pin or 2-pin JST connectors and Arduino pins) (~$20-30)
- 2.1x5.5mm barrel jack connectors, you can find them here. (~$5)
- A small Phillips screwdriver
- Soldering Iron & Solder (~$20)
- Double sided mounting tape (1/4 inch width). I use this. (~$10)
- (Recommended) A microphone for the music sync. (To have working music sync you must have one) You can find one from Adafruit here. (~$7)
(Optional) An Arduino case, such as this. (~$10)
(Optional) a capacitor of at least 10 μF (This protects against voltage spikes when first powering on your power supply. Note that some of the larger, fancier, power supplies may already have built in protection.) (~$5)
I strongly recommend you stick to the linked materials on this list since I have used them most of the day, every day, for months without failures-- especially the LEDs. Otherwise, you may run into unexpected hiccups or find that you are lacking certain specific materials or tools.
-------------------Extra Information (*)-----------------------
* For extremely small strips (~30 Pixels or less) or Arduino has enough power to run these and you won't need a power supply. (THIS IS NOT RECOMMENDED FOR THIS GUIDE. There are many instructional guides on building small, addressable LED setups, those will be more specific to your situation.)
Most of you, however, will probably need a power supply. The calculation is (Amperage) = 0.075*(Number of Pixels). This is with a safety margin built in (at full draw your power supply will be operating at ~75% of capacity. This will keep your power supply running cool and thus consistently for long periods of time). Going significantly below this runs risks of overheating and even fire. Some power supplies will also require you to attach your own AC wall plug. For displays that use multiple full led reels, I highly recommend you power inject. This will be talked about in the next section.
** Size your wire properly! SAFETY FIRST spending an extra few dollars might save your home.
(If you are curious I am using two 5V power supplies each with two 30A outputs, and 12 gauge speaker wire. This allows me to inject sufficient power at four points along my LED strip. I am using ~21 meters with density of 60 LEDs/meter.)
Step 2: Power
If you bought the full reel Adafruit NeoPixels, your LEDs should come with the appropriate JST connectors, if not you may need to pick up your own (pay attention to the number of pins-- usually it's 3 but some of their models are different). Full reels can be directly connected to each other and strung up like a daisy chain so long as you have enough power.
First let's set up the LED strip for powering:
The first picture gives a great overview on how things are assembled. (The resistor is not necessary)
If yours does not come with the connector pre-attached (the second picture shows a strip with a connector), you will need to solder them on at the start of your string. The direction is indicated by the arrows printed on the led strip (seen in the third picture). The arrows point towards the end of your string:
- The positive wire goes to the copper pad marked with a '+' or '5V' (the color convention is red)
- The data wire goes to the pad marked with a 'D' or 'D in' (the color convention is green or white)
- The ground wire goes to the pad marked with '-' or 'GND' (the color convention is black or sometimes white)
It should be obvious, but avoid the same colors for different things. Really, just pick any 3 distinct colors and be consistent when using them and you will be fine.
For your first strip, you will need, at minimum, to attach one wire to the positive padand one wire to the data pad, but two wires to the ground pad (one if very small set up [see below]).
- Positive and ground go to the female barrel jack and the other ground and data go to the Arduino
For those of you using multiple strips, simply solder or connect the corresponding pads from the former strip, including the positive leads. The section on power injection [below] will describe how to do this without having to solder.
The full reels of the Adafruit LEDs will have this already, so you will not need to do anything.
The fourth picture shows a female barrel jack (although if you've purchased the pairs this doesn't really matter, certain power supplies will come pre-attached with the male connector, this will give you more options). You will need to place the positive wire in the screw-end marked with '+' and the negative wire into the end with the '-'. (At this step, if you have bought the capacitor, pinch one leg in each screw terminal with the wires, orientation does not matter).
- If your power supply does not have one already, attach the male barrel jack to it following the same rules.
WARNING: CHECK YOU LEDs' VOLTAGE RATING. MOST ARE 5V, SOME ARE 12V.
Powering the Arduino (5V LEDs Only):
I highly recommend you power the Arduino separately from the LED strip with a USB cord connected to a wall plug (e.g. via a cellphone charger). However, you can power the Arduino from the strip if your location is short on power outlets. To do this, you plug the positive wire (seen in red in the fifth picture) into the pin marked 5V on the Arduino.
Why do I not recommend this? Because LED strips, especially addressable ones running patterns and executing commands can have varying power draw. If you are not careful with how and where you mount your Arduino relative to your power source, the LED strips may suck away the power your Arduino needs, freezing your display. For example if you start at dim lighting and go very bright, the Arduino may stop working and you wont be able to dim your strip again without having to reset the display. This happened to me while prototyping.
Small setups: (5V LEDs Only, Not Recommended)
For those of you powering only a few LEDs, an Arduino can serve as the power supply. To do this, simply, again, attach the positive wire to the 5V pin. In this case, your Arduino must be powered via a USB cord, a battery, etc.
Power Injection for Large Setups:
The general idea is shown in the fifth picture.
As promised, lets talk about power injection. You may quickly realize that if you are using one set of wires to power a large number of LEDs, you will get quite a ridiculous amperage value. For example, following the formula presented in the materials page, powering 1000 LEDs will require 75 Amps of power! Running wires from floor to ceiling and then along walls capable of properly carrying that current would each need to be a roughly a centimeter thick! Not to mention how pricey it would be to find a power supply capable of delivering that kind of power.
The sixth picture shows a power injection point.
If you are reading this section with the intent to use it's info, you will probably be using multiple reels of LEDs. Every 240 LEDs (A full 4 meter reel at 60 LEDs/meter) will require 18A of juice, thus a 20A (surprisingly, while I'm writing this, the 30A power supply is cheaper on Amazon) will be perfect for this type of reel. If you are stringing multiple NeoPixels together. You will need to:
Attach the end of the previous reel to the beginning of the next with the included connectors.
After doing this you will realize that at the start and end of each reel, there is a place to attach abarrel jack so you can power inject.
For optimal results, allow the power injection to flow both ways, into the front of the next string but also into the previous. Do this by placing both positive wires from the end of the previous strip and the beginning of the incoming strip into the positive screw terminal (Again look closely at the sixth picture). This allows us to connect the power between strips without firing up the soldering iron.
Many of the larger power supplies have multiple output pairs (Two as seen in the example in the seventh picture).
This is great for us since we can attach each output from our power supply to the beginning of each of our LED reels and distribute the power separately to each reel at much more manageable amperages. You will just need to get enough such power supplies so that each reel can connect to its own 5V output pair.
You could also use fewer, but larger capacity power supplies (30A, 35A, etc. although they get pricy). If you want optimal results in any power injection, you should try to distribute the power injection points as evenly as possible along the string. The only downside is that the injection points probably will not align with the pre-attached injection points, possibly requiring you to do some cutting and soldering.
Step 3: The Arduino Setup
The Arduino is the brains of the LED lights, it will give the commands to make all those pretty lighting patterns.
Hooking the LED strip to the Arduino:
This is pretty straightforward, you can pretty much just look at the first picture to get everything, although you may need to solder or make pins that fit into the Arduino pinholes (If you have thin enough wires, like the ones that Adafruit uses, you can make your own pins straight out of the wiring with some solder, as shown in the second picture. I believe the wire is ~22 Gauge):
Connect the ground wire to any Arduino pin that's labeled 'GND'
Connect the data wire to any of the Arduino's digital pins (the default in the source code given later is Pin #6).
Most of you, I'm assuming, will be using dedicated power supplies. For those of you using small setups, as mentioned in the previous section, you can use the Arduino alone to power your LEDs if they are the 5V version. To do this, insert the positive wire into the pin labeled 5V, and plug the Arduino into a wall socket via the right USB cable (cellphone charging blocks work great). You can also use a battery instead if you choose.
How to Power the Arduino:
For the majority of you using power supplies, I, again, recommend you find another outlet to plug your Arduino into via its USB. This gives consistent power to the brains of your operation, but in a pinch, this is not absolutely necessary, given you have the 5V strips. To power your Arduino without a second outlet, plug the positive wire from the front of your LED strip into the Arduino's 5V pin (you may need two positive wires so you can also attach power from the power supply here). This will look very similar to the setup where the Arduino is powering the LEDs. The difference is the Arduino is no longer doing the powering, rather its receiving it from the strip, attached to the power supply.
***Attaching the Microphone (For Music Sync)***
If you're using aiming to build the music sync as well, you will need a microphone such as the one that was linked in the materials section. You will need to:
Plug the pin marked VCC on the microphone into the Arduino pin slot marked 3.3V.
Plug the pin marked GND into any other Arduino pin marked also GND.
Plug the pin marked OUT into one of the Analog pins, the code default is A0.
Step 4: Putting Up Your LEDs and Setting Up BLYNK
Now you should figure out where you want to put your LEDs and tape them up there with the fastening tape. If you want the setup to look really nice, measure the distance from some reference (e.g. ceiling or floor-line), mark the distance periodically, and put the double-sided tape up first, following your marks, and finally stick the LED strip on.
The code is built in consideration that the LED strip(s) form a loop like shown in the first picture. Thus some patterns are constrained so that the start color and end color are continuous in context of the pattern. For those of you building straight strips, this shouldn't change the integrity of the pattern, but it can be changed with some coding experience.
BLYNK Set Up:
To get BLYNK on your smartphone you will first need to download the app from your device store and create an account. You can find the instructions here. You will find both iOS and Android downloads for the app at this site. But I will give a quick summary below on an important step, getting your Auth Token (used in code):
- Create an account with your email and log in.
- Hit 'New Project' as seen in the second picture
- Give your Project any title you wish. Picture three
- Set the device you are using. Picture four.
- Set the connection type, use BLE not Bluetooth for the Arduino 101. Picture five.
- Retrieve your Auth Token from your email. Picture six.
hang onto your Auth Token, you will need it in the next step.
Time to build BLYNK remote on your phone:
BLYNK will give you a certain amount of currency for widgets to start, called energy. You may realize that you can buy more energy, but this is not necessary for the remote I will show-- the amount allotted to you is enough.
Picture eight shows the remote control in its complete form. I'm sure with just a bit of fiddling around, you can copy the setup with little difficulty, but just in case, the widget list is provided below. To get widgets make sure there's a little triangle in the top right corner, not a square. This is edit mode-- you can then drag and drop the following widgets into the project space and edit their shape, size, and characteristics. You will need:
- 2x Buttons
- 1x zeRGBra or 3x Sliders*
- 1x Slider
- 1x LCD
- 1x BLE
- 1x Menu
It is not enough to simply have these widgets, you must set them up also. To do this, tap on a widget while still in edit mode. Feel free to change all titles, labels, and colors to your liking:
One Button is your on/off switch:
- the virtual output pin is V0,
- (use default values for all buttons (0,1))
- set this widget to 'switch' mode
The other Button is for switching from the default, full white, to the Color Picker:
- the virtual output pin is V7,
- set this widget to 'switch' mode
The zeRGBra* (color picker) sends the app chosen RGB values
- set this widget to send the RGB data in the 'split' configuration
- set R to the virtual output pin V2
- set G to the virtual output pin V3
- set B to the virtual output pin V4
- set R,G and B value limits, the range is 0 to 255. I recommend not going up to the full 255, a white where each pixel is 160 is plenty.
- set "send values on release only" to 'off' if you want live updating as you choose colors.
The Slider will control your brightness by a percentage
- the virtual output pin is V5,
- the values are 100, and 10 respectively (order matters, makes the default full brightness). There is no point going lower than ~10% brightness, at that point just turn your strip off.
- integers are good enough for our purposes, set decimals to '#'
- set "send values on release only" to 'off'.
- I like to turn "show values" to 'on', although not necessary
The LCD displays info like the current mode
- the 'simple' option will suffice
- the virtual output pins are V8, and V9respectively.
- The values used are both 0 to 1023 respectively.
- we can leave the "refresh interval" at every push.
- no message is necessary
The Menu gives us a list of modes to choose from
- the virtual output pin is V1.
- we can leave the "hint text" blank.
- set option 1 to 'Default', option 2 to 'Rainbow', option 3 to 'Wipe', option 4 to 'Fade', option 5 to 'Lava',
- option 6 to 'Canopy', option 7 to 'Ocean', option 8 to 'Wave', option 9 to 'Fireflies', option 10 to 'Confetti',
- option 11 to 'Comet', option 12 to 'Sunset', option 13 to 'Music Sync', and option 14 to 'PixelFinder'
-------------------Extra Information (*)-----------------------
* You can also use three sliders, one for each color (R,G,B) and set the each slider to the corresponding virtual pins (V2, V3, V4). This will give you more color options than the zeRGBra, but is less intuitive.
Step 5: Software
So now that you've got your LEDs mounted at the place of your liking, lets code in the Arduino before we attach everything together.
The software has been uploaded below (also to github here). It is built for the Arduino 101, some small modifications might be necessary to get it to work with a device with a BLE shield. Unfortunately, especially for those of you looking to modify, it is very long. One reason for this is that the FastLED Library isn't supported on the Arduino 101 currently, another is that the BLYNK and NeoPixel Libraries must be integrated together so that the program constantly polls for bluetooth commands. That said I should give credit to some references:
The code is set up so you just have to answer a few questions (and enter a few values) at the beginning. Replace the ??? with your answer.
Some of the user inputs in the code may need some explanation despite the comments. In order they are:
- auth - Auth token from the BLYNK app. (The BLYNK Page good instructions)
- deviceName - Your Arduino's name among other bluetooth devices
- pinNum - The data output pin you attached your LEDs strip to (default is #6).
- audPin - The data pin from the microphone (change only if you want music sync, default is A0)
- stripLen - Length of the your strip
- numRainbow - The number of complete rainbow cycles in the strip for mode 1
- seed - The start Pixel of Color Wipe, you may not want it to start where your strip does.
- modif - Modify your strLen slightly so that you can divide by the numbers you want
- divBy - number of LEDs you want each guide point to control
- pts - number of guide points.
- If you did this correctly, pts*divBy = modif > strLen ...
- ... and modif should be almost equal to strLen
- The best results occurs when divBy is between 10 and 50
- Used by modes 4, 5, 6, and 7
There is a table of contents for those of you adventurous enough to write your own modes or make changes. Do at your own risk-- making a backup is a good idea.
Currently, the Arduino 101's requires it's own driver to communicate with the Arduino IDE. Unfortunately, the BLE in the latest driver version is bugged. Thus, you want to go to: Tools > Board > (Make sure you have "Arduino/Genuino 101" selected) > Boards Manager... > Under "Intel Curie Boards by Intel Version ..." click "more info" and select version 1.0.7 (NOT the latest 2.0.2) and Install. Afterwards navigate to: Tools > Programmer > and select Arduino/Genuino 101 Firmware Updater. Finally, hit Burn Bootloader. This will sync your programmer to the previous version. Now you should be able to use BLE without issues.
Step 6: Modes and Tuning
There are a two modes that ask for the pixel number at start points: mode 2 (Color Wipe) and mode 12 (Music Sync). If you have many LEDs, its a massive pain counting to which exact pixel you want as a start so I have built a tool. In the last item of the mode menu on your BLYNK app, you will find a mode called "Pixel Finder". To use this you will probably have to modify your widget settings.
- First make sure you are in edit mode
- Select the slider
- Change you brightness values so that the pixel number you are searching for is within the brightness range entered.
When you use this Pixel Finder mode, the pixel number of your brightness value lights up in Green. This way you can quickly scroll to a desired location, and read off the pixel number from your phone.
You can see this in Pictures [5 and 6] and [7 and 8]. (You may notice that in this screenshot I am using the Color Sliders instead of the zeRGBra). Also note that the first pixel's index is 0 not 1.
This should help you set up your patterns where you want them.
One more thing I should mention is that "Brightness" in the Comet (mode 10) and Music Sync (mode 12) modes adjust the length of the "tails". This is how the code is supposed to work as "Brightness" doesn't really make sense in these modes.
Step 7: Hooray! You're Done! (Read on for Extras About the Code)
To use your LEDs:
- Be within range of your Arduino
- Tap the BLE icon
- Find your device (answer for deviceName) and choose it
You will now be able to use your remote.
Go enjoy all your hard work!
*****************************Advanced (About the Code)********************************
I tried to make the code well commented, it is probably not optimized by any means, but I do know it runs my 1200+ lights fast enough. The table of contents has the code sectioned off by line number.
The parts of the code containing the modes and the user interface are quite separable, technically you could ditch bluetooth and use a hard-wired switchboard, or a simple timer that cycles through all the modes. You really just have to fill in the cmdArr array to give instructions.
- Index 0 stores info about the strip being on/off,
- Index 1 stores the mode number from the menu
- Indicies 2, 3, and 4 store the R,G, and B values from the color picker respectively.
- Index 5 stores percent brightness
- Other indicies are currently unused
You many notice in the code there are many lines which read "SetPixelColorAdj(..." despite the function just being simply "setPixelColor(...". This is because this is a bit of left over code used to map parts of the LED strip around. For example, if you use one strip to make two loops, it would be a pain to address patterns with a break until where the loop merges back into itself. With this, you can artificially splice the internal feature of the LED strip to the end and also splice the main loop back together so that within the code, it is intuitive to work with.
I will also provide an explanation behind how some of the more complicated modes work. Some of them (Rainbow, Color Wipe, and Fade [1,2,3]) are already in the NeoPixel Library as example code.
- Lava, Canopy, Ocean [4,5,6] - These modes use the guide-points as mentioned earlier, each guide point gets a random color within a realm assigned to it. Lava is mostly red, Canopy is mostly green, and Ocean is mostly blue. The Fade pattern  already provides a great linear fade algorithm. This is repurposed to fade from the color of one guide point to the next using the pixels in between, creating a smooth fluctuation. The three fade arrays store the steps of a time fade of the guide points (the start, transition, and end states). When the guide points fade in time, the pixels near them also update their colors as well. When a time cycle is completed, the just-reached endpoint becomes the new start-point. This way the pattern remains smooth in time.
- Color Wave  - This is similar to the previous modes, but the colors for the guide-points are picked differently. There is a deviation given to a base color which fades around the color wheel in time.
- Fireflies - The 2D array stores location and direction for 90 chosen fireflies. It decides, at each time-step, whether a firefly will move left, right, or not at all. Their overall brightness follows a fade on, fade off cycle.
- Confetti - You cannot reuse parts from firefly here although they seem similar-- this is because you prefer an overall consistent brightness to best see the color shift. The idea however is not too different. I achieved even lighting by assigning 1/3 of all the confetti sparkles to 3 co-periodic sine functions separated by a shift of 1/3 of the period each.
- Comet - Very similar to Adafruit's Scanner, the difference is the direction is now randomly generated each time and doesn't change, there is a slight variation in color as the pixel moves around creating a more "fire" like effect on the tail. The call of the dimming each update is what creates the fading away or the "tail" of the pattern.
- Music Sync- Two parameters are calculated based off volume (voltage from A0): A color and length. The music sync then fades from a center color to the calculated color, while simultaneously fading to black in the given length. The center color smoothly fades around the color wheel, thus you get both flashy effects and smoothness so it isn't obnoxious.