Learn to Program Custom LED Lights

Love em or hate em, it’s hard to deny the wave of RGB that has swept over much of the consumer tech market. And for good reason, they grant an incredible amount of customization and are more affordable than ever.

While there are plenty of “LED kits” across the internet, the vast majority of them can, at best, cycle through a single color at a time. Maybe they can sporadically flash if you’re lucky. However, with a little bit of work and creativity there is all sorts of opportunity for those willing to go the extra mile. This guide will demystify how the LEDs work and show you step by step how to set them up. Even with zero programming experience you can create your own custom light setup!

So, what makes these LEDs special? Why spend the extra time and effort working with these lights? Unlike most LED strips, you have the ability to control every single pixel and change it’s color individually. This mean we can create all sorts of custom animations. They can flash, chase, dance in all sorts of unique ways.

Alright, so what do we absolutely need to get started? We’ll need the LED strip, but we also need something to control them. Because our LEDs have so much customizability, we need something to tell them what colors to be and when. This is where the Arduino comes in. Don’t worry, even if you have no programming experience we’ll work through the basics in no time. Lastly we need a way to power everything. For this we’ll just grab a 5V power brick and we’re good to go.

Components for this project:

  • Arduino Uno - <Amazon>

  • 5 Meter 150 LED WS2812b Strip - <Amazon>

  • 5V-10A Power Supply - <Amazon>

  • DC Barrel Connector (included with Power Supply)

  • Jumper Wires - <Amazon>

*Amazon links are affiliate and purchases made help support our content. Thank you!

Let’s start by hooking it all up. Our LED strip has 3 inputs we need to connect. The power/ground to the supply and data to the Arduino. We also need to connect our Arduino to the computer and give it a connect to the same ground as the LEDs.

hookup.png

Most LED strips, including the one linked above also come with a handy little 3 pin connector. If you want to avoid soldering you can use a pair of jumper wires to connect your Arduino and the barrel jack to connect the power supply. While the power and ground can be connected to either side, be sure to double check you have the input side of the strip for the data wire. Worth noting, it is common practice to add a small resistor to the data line to protect the LED strip, however strips such as the one linked above have this resistor already built in.

If you’re up for a little soldering you can create a nice little plug with accompanying male/female side of the 3 pin connector. A little bit of heat-shrink tubing gives it a nice professional look however it’s nothing a bit of electrical tape can’t handle.

solder.jpg

Before we jump straight into programming, let’s take a step back and think about how we get from a statement like “I want the LEDs to be green” or “I want two different sections of the LEDs to alternate from blue to purple” into something the Arduino and lights can understand. Well, since each of our LEDs can be a different color we need a way to describe that to the Arduino. Let’s examine what happens when we set the first pixel of our strip to purple and the second to yellow.

If we zoom in a bit and take a look at each of our LED pixels, we can see they are made of 3 LEDs, a red, green, and blue. By controlling the brightness of each of these three colors we can combine them to create just about any color we want. Each of the three colors can be any value from 0 to 255 where 0 is off and 255 is max brightness.

ws2812bzoom.png

If we want to get a green, red, or blue light it is as easy as turning on that particular LED. However if we want a more complex color we have to play around with the brightness of multiple LEDs. To get our first LED purple we set the red and blue values to 255 and turn off the green. To get yellow we set the red and green values to 255 and turn off the blue.

purpleyellowwithlabels.png

The next issue we need to address is the Arduino only understands 1s and 0s therefore our numbers need to be stored in binary. In decimal it only takes three digits to represent a number between 0 and 255, but in binary we need 8 digits. Therefore each color gets 8 bits (aka 1s or 0s) to hold a value from 0 to 255. Since we have 3 colors per pixel we get a total of 24 bits for the whole pixel. Now we have a sequence of 24 (1s or 0s) that describe the color of a pixel. In our example we have our colors maxed at 255 but we could scale them down to reduce their brightness.

Here’s a great little video that visually shows how to count in binary. With 6 digits it can count from 0 to 63. By adding 2 more digits we can get from 0 to 255.

Alright now that we know a little more about how the LEDs understand color, let’s jump into the code. Rather than copy pasting a bunch of code and calling it a day, lets work through line by line and understand exactly what we’re doing. This way we’ll have better intuition on how to make more complex animations. Here’s the Arduino sketch we’ll look at. If this is your first time with an Arduino sketch or want a refresher on downloading libraries, check out our quick start guide.


#include <FastLED.h>
 
CRGB leds[2];
 
void setup() 
{
  FastLED.addLeds<WS2812, 2, GRB>(leds, 2);
}
 
void loop() 
{
  leds[0] = CRGB(255, 0, 255); //purple
  leds[1] = CRGB(255, 255, 0); //yellow
  FastLED.show();
  delay(1000);
}

The first section of code runs the setup. The Arduino goes line by line and executes each command once. Lets take a look at what each of them are doing.

  1. The first thing we do is include the FastLED library. This allows the Arduino to understand the next few commands we are going to use. The FastLED library knows how to convert our decimal numbers into the binary the Arduino needs.

  2. Second we have to let the Arduino know how many LEDs we plan on using. For this example we are just using 2 LEDs. If you want use more change this number accordingly.

  3. Third we have to tell the FastLED library what type of strip/lights we are using. The FastLED library can be used to control many different types so we have to specify WS2812 (even though technically we are using WS2812b).

  4. Next we tell the Arduino what PIN we are using. This is where we are plugging the data wire into the Arduino. In our hookup diagram we have it connected to PIN 2 but it could just as easily be PIN 3, 4 or 5…. just make sure this value matches the location your strip is plugged in.

  5. Fifth is the order of our colors. This tells FastLED that we want use green, then red, then blue.

  6. Finally we give it the name we used for our strip in step 2.

  7. And again the number of LEDs in our strip.

code1.png

So where has our efforts gotten us so far? Well as mentioned above, the Arduino needs to know how many LEDs we plan on using. Under the hood, our Arduino is setting aside bits to store the color for each of our LEDs. Since our example code only uses 2 LEDs, the Arduino allocated space for 2 sets or 24 bits. If we had 150 LEDs this would be the same except we would have 150 sets of 24 bits.

The second section of code is call the loop. This is because instead of running once it runs through the lines of code and then returns to the top of the loop and starts again.

1. First we choose the LED we want to make changes to. This is made slightly more confusing by the programming convention to start counting from 0. Therefore our “first” LED is actually number 0 and our “second” LED is number 1.

2. Next we actually tell the Arduino what color we want each LED to be. In our example we set the red and blue values to max on the first LED making it purple. Then we set the second LED to be yellow by turning up the red and green with the blue off. The “CRGB” is from the FastLED library and does the magic of taking our (255, 0, 255) and changing all the bits in the memory to match the desired color.

loop.png

3. Finally we have to get color data out to our LEDs. Up until this point only our Arduino knows what colors we want the LEDs to be. When we use the show command, we are effectively pushing all the data out of the Arduino and into the LEDs. At this point, assuming we did everything correctly we should have one purple and one yellow LED.

4. Last but not least we stick a delay command at the end. This makes the Arduino wait for 1000 milliseconds or 1 second before moving onto the next line. However since we have reached the end of our loop we go back to the top and start over again. The Arduino once again sets the values of the two LEDs and pushes them out to the lights. The only difference is this time the lights are already on and the color values haven’t changed so we don’t see any difference in the lights even though they continue updating every second.


Okay enough with the 2 LEDs. We’ve got 150 LEDs on this strips not 2. Here are few different ways you can use the whole strip. If you are looking to maximize the brightness or connect multiple strips be sure to check out our comprehensive power guide here.

RBG Chase

This first little animation just cycles through changing the LEDs between the three primary colors. There is a red, green, and then blue section in the code. In each section we loop through every single pixel and change them one at a time. Notice how the “FastLED.show” command is inside the loop. If we move it out it will update the LEDs only once we have changed them all. Also don’t forget to change the number of LEDs to 150.

#include <FastLED.h>
 
CRGB leds[150];
 
void setup() 
{
  FastLED.addLeds<WS2812, 2, GRB>(leds, 150);
}
 
void loop() 
{
  for(int i = 0; i < 150; i++)
  {
    leds[i] = CRGB(100, 0, 0);
    FastLED.show();
  }
  
  for(int i = 0; i < 150; i++)
  {
    leds[i] = CRGB(0, 100, 0);
    FastLED.show();
  }
  
  for(int i = 0; i < 150; i++)
  {
    leds[i] = CRGB(0, 0, 100);
    FastLED.show();
  }
}


Yellow/Purple Flash

This animation rapidly adjusts the brightness of the purple and yellow sections. The j loop adjusts the brightness while the i loop defines the sections. Change the values in the i loop to adjust where each color section begins and ends.

#include <FastLED.h>
 
CRGB leds[150];
 
void setup() 
{
  FastLED.addLeds<WS2812, 2, GRB>(leds, 150);
}
 
void loop() 
{
  for(int j = 0; j < 100; j++)
  {
    for(int i = 0; i < 75; i++)
    {
      leds[i] = CRGB(j, j, 0);
    }
    FastLED.show();
  }

  for(int j = 0; j < 100; j++)
  {
    for(int i = 75; i < 150; i++)
    {
      leds[i] = CRGB(j, 0, j);
    }
    FastLED.show();
  }
}

Rainbow

The rainbow animation is your classic color cycle. Every time it loops through the RGB values are updated in the top section of the loop. It starts with red at max and quickly changes the colors one by one fading through.

#include <FastLED.h>
 
CRGB leds[150];

int r = 255;
int b = 0;
int g = 0;
 
void setup() 
{
  FastLED.addLeds<WS2812, 2, GRB>(leds, 150);
}
 
void loop() 
{
  if(r > 0 && b == 0){
    r--;
    g++;
  }
  if(g > 0 && r == 0){
    g--;
    b++;
  }
  if(b > 0 && g == 0){
    r++;
    b--;
  }

  for(int i = 0; i < 150; i++)
  {
    leds[i] = CRGB(r, g, b);
  }
  FastLED.show();
}

With this we conclude our introduction to WS2812b addressable LEDs. Hopefully you have a better idea how these lights work and how to get started with your own setup. To go further check out our additional guides and get creative!

What guides should we do next? Leave feedback here.

Previous
Previous

Animating Music - How to Create a Light Show (Part 1)

Next
Next

Powering Any WS2812b Setup