# Controlling a Tricolor LED Using PWM

## Introduction

In the previous project, Breathing LED with Pulse-Width Modulation, the brightness of an LED was controlled via pulse-width modulation (PWM). In this project, we will use PWM to control the color of a tricolor LED. If you are not familiar with PWM, we recommend that you review the aforementioned project. This project will be very similar to the previous project, except the LED being used will change color. Generally, LEDs are manufactured to emit one color of light. These colors can range from any color in the rainbow to infrared or even ultraviolet. The LED's color is determined by the material it is made from and the voltage that is applied to it. Depending on the combination of the material and voltage, different wavelengths of light are emitted. We perceive these different wavelengths of light as colors. The tricolor LED we will use can only generate red, green, and blue wavelengths of light. This is because the tricolor LED actually consists of a red, green, and blue LED all in one bulb. By changing the intensities of each LED inside the bulb, we can generate the illusion of different colors. This is the same principle we would use when mixing paint. Mixing red and yellow paint results in orange paint, even though there is no naturally orange pigment in the mixture. This phenomenon occurs because our brains simply perceive this combination of red and yellow pigment the same way we perceive naturally orange pigment. Similarly, our brains perceive the combination of red and green wavelengths of light the same way the actual wavelength of yellow is perceived.

## Inventory:

Qty Description Typical Image Schematic Symbol Breadboard Image
1 Tricolor LED
3 220 Ω resistors

## Hardware Structure

Before we begin putting the circuit together, we must discuss the structure of the tricolor LED. Since tricolor LEDs are essentially a combination of a red, a green, and a blue LED, it would make sense to assume it will have three anodes and three cathodes for a total of 6 legs. Realistically, this isn't very practical. In fact, the red, green, and blue LEDs inside the bulb all share a common cathode to save room. This means our tricolor LED will have only four legs, as shown in Fig. 1.

The longest leg is the shared cathode, and it should always be connected to ground. Follow the steps below to construct the circuit. Note that the wire colors correspond to the LED color they will be controlling.

## Step 1: Setting up the Circuit

1. Place the tricolor LED in the breadboard, as shown in Fig. 2.
2. Connect the shared cathode of the tricolor LED (the longest leg) to ground (GND).
3. Connect a 220 Ω current-limiting resistor to each of the LED's remaining legs.
4. Connect PWM pin 6 (red brightness control) to the left-most leg of the tricolor LED.
5. Connect PWM pin 5 (green brightness control) to the leg just to the right of the shared cathode.
6. Connect PWM pin 4 (blue brightness control) to the right-most leg of the tricolor LED.

## Step 2: Color Control Basics

Having built the circuit, we can now write some simple code to control the color of the LED. Remember the value range for a PWM pin is 0 to 255. In the code below, the PWM pins that control red and blue are set to 200 using the setColorBrightness() function. This makes the tricolor LED purple.

              int pinRed = 6, pinGreen = 5, pinBlue = 3;

void setup()
{
pinMode(pinBlue, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinRed, OUTPUT);

analogWrite(pinBlue, 0);//Write 0 to pwm pin 3 (blue control)   This makes sure the LED starts off
analogWrite(pinGreen, 0);//Write 0 to pwm pin 5 (green control) This makes sure the LED starts off
analogWrite(pinRed, 0);////Write 0 to pwm pin 6 (red control)  This makes sure the LED starts off

//Make LED purple
setColorBrightness('r',200);//Sets Red to 200
setColorBrightness('b',200);//Sets Blue to 200
}

void setColorBrightness(char color, int brightness)
{
//if else tree used to select the correct color control pin
if(color == 'r')
{
analogWrite(pinRed, brightness);//Write to pwm pin 6  (red control)
}
else if(color == 'g')
{
analogWrite(pinGreen, brightness);//Write to pwm pin 5  (green control)
}
else if(color == 'b')
{
analogWrite(pinBlue, brightness);//Write to pwm pin 3  (blue control)
}

return;
}

void loop(){}//loop() is not used


The setColorBrightness() function may seem unnecessary, since the color can be changed directly with analogWrite(). While this is true, bear in mind that it is easy to mix up which pin number corresponds to the color we want to change. Using the if else tree inside of the setColorBrightness() function allows us to modify color values using intuitive color abbreviations, “r,” “g,” and “b.” Furthermore, the if else tree provides a good point of comparison for introduction of switch statements, which will be covered in the next section.

## Switch Statements

switch statements control the flow of a program and are very similar to if else trees. They compare a variable to a constant case value. If the variable matches the case value, the code contained within the particular case is executed. Otherwise, the case is skipped. In the event none of the cases match, the default case will be executed. The default case is optional and not needed for the switch statement to function properly. The following is an example of a switch statement.

              switch (variable)
{
case 1:
//do something when variable equals the integer 1

break;//break skips all remaining cases
case -1:
//do something when variable equals the integer -1

break;
case 'a':
//do something when variable equals the character a

break;
default:
// if nothing else matches, do the default

// default is optional
break;
}


In our example, the case values were int and char types. A case value can be any constant value which can be interpreted as an integer value. This includes the Boolean constants HIGH, LOW, INPUT, OUTPUT, true, and false. Doubles, floats, strings, and arrays are data types that cannot be used as case values. In addition to being careful with the case's data type, it is also important to be aware of including break lines at the end of every case. If you forget to add a break in a specific case, the switch statement will execute that case and all cases below it until it sees a break line.

So far, switch statements and if else trees appear to do the same thing. While this is mostly true, there are distinct advantages and disadvantages to using one or the the other. We know that switch statements have limited usage because they cannot compare dynamic variables and are restricted to specific data types. On the other hand, switch statements compare only one case, making them very efficient. Figures 3 and 4 illustrate the differences in efficiency between if else trees and switch statements.

The if else tree must evaluate every if statement before and after the targeted case. The switch statement, on the other hand, jumps directly to the targeted case and then exits once it is finished. This saves a lot of time in situations with a large number of cases. Furthermore, the efficiency of the switch statement is even greater inside of the loop, since only one case is compared every iteration. This will come in handy when writing the code for a basic color sweep.

## Color Sweeps

With a better understanding of how a switch statement works, we can begin coding writing a sketch to sweep through a combination of colors. This is similar to the code used for creating a breathing LED, except the principles are used to fade the individual colors of the tricolor LED in and out.

              int pinRed = 6, pinGreen = 5, pinBlue = 3;

void setup()
{
pinMode(pinBlue, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinRed, OUTPUT);

analogWrite(pinBlue, 0);//Write 0 to pwm pin 3 (blue control)   This makes sure the LED starts off
analogWrite(pinGreen, 0);//Write 0 to pwm pin 5 (green control) This makes sure the LED starts off
analogWrite(pinRed, 0);////Write 0 to pwm pin 6 (red control)  This makes sure the LED starts off
}

{
int brightness, incrementValue, limit;

{
//Setup variables so the the LED brightness will fade in from 0 to 255
incrementValue = 1;//Set incrementValue to add 1 to the brightness
brightness = 0;//Ensure the LED starts completely off (minimum brightness)
limit = 255;//Set the brightness limit to 255 (maximum brightness)
}
else
{
//Setup variables so the the LED brightness will fade out from 255 to 0
incrementValue = -1;//set incrementValue to subtract 1 from the brightness
brightness = 255;//Ensure the LED starts completely on (maximum brightness)
limit = 0;//Set the brightness limit to 0 (minimum brightness)
}

while(brightness != limit) //Loop until brightness has faded in or out completely
{

brightness += incrementValue;

switch(color)
{
case 'r':
analogWrite(pinRed, brightness);//Write to pwm pin 6  (red control)
break;
case 'g':
analogWrite(pinGreen, brightness);//Write to pwm pin 5  (green control)
break;
case 'b':
analogWrite(pinBlue, brightness);//Write to pwm pin 3  (blue control)
break;
}

//Wait for a specified number of miliseconds to control how fast the LED fades in or out
}
return;
}

void loop()
{
}


Much like in our Basic Color Control code, we want to use a single function changeColorBrightness() to control which color is being modified. The main difference here is that we have replaced the if else tree with a switch statement and put it inside of a while loop.

The while loop increments (or decreases) the brightness of a color until it reaches the limit of the PWM pin. Each iteration of the loop is delayed so that we have time to watch the color fade. The code given above should make the LED fade from red, to purple, to blue, to aqua blue, and then finally to green.

The sweep sequence is determined by the order in which fading occurs across the red, green, and blue LEDs. You can try rearranging the order to get different color combinations. In the next section, we will explore how to randomly select a color \ combination.

## Random Number Generation

In order to select a random color combination, a random number must be generated. This can be done using the random () function. The random() function can be used in two ways: the first way is to enter a max value as the only argument. This will return a random integer from 0 to the max, minus one. The second way is to enter a max and min value as the arguments. This will return a random integer from min to max minus one.

For example:

              random(11);//returns a random integer from 0 to 10
random(5,16);//returns a random integer from  5  to 15


## Step 3: Generating Random Color Combinations

Now that we know how to generate a random number, we can write the code to generate a random color combination. To begin, we should consider all the color combinations we want to implement. All of these combinations are listed below.

1. Red
2. Green
3. Blue
4. Red and green
5. Red and blue
6. Green and blue
7. Red, green, and blue
                  int pinRed = 6, pinGreen = 5, pinBlue = 3;

void setup()
{
pinMode(pinBlue, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinRed, OUTPUT);

analogWrite(pinBlue, 0);//Write 0 to pwm pin 3 (blue control)   This makes sure the LED starts off
analogWrite(pinGreen, 0);//Write 0 to pwm pin 5 (green control) This makes sure the LED starts off
analogWrite(pinRed, 0);////Write 0 to pwm pin 6 (red control)  This makes sure the LED starts off
}

void randomLEDColorCombo()
{
int colorCombo = random(7);//Generate a random value from 0 to 6 that corresponds to a color combination
int red = 0, green = 0, blue = 0;

switch(colorCombo)
{
case 0://Combination: Red
red = random(256);//Generate random number from 0 to 255
break;
case 1://Combination: Green
green = random(256);//Generate random number from 0 to 255
break;
case 2://Combination: Blue
blue = random(256);//Generate random number from 0 to 255
break;
case 3://Combination: Red, Green
red = random(256);//Generate random number from 0 to 255
green = random(256);//Generate random number from 0 to 255
break;
case 4://Combination: Red, Blue
red = random(256);//Generate random number from 0 to 255
blue = random(256);//Generate random number from 0 to 255
break;
case 5://Combination: Green, Blue
green = random(256);//Generate random number from 0 to 255
blue = random(256);//Generate random number from 0 to 255
break;
case 6://Combination: Red, Green, Blue
red = random(256);//Generate random number from 0 to 255
green = random(256);//Generate random number from 0 to 255
blue = random(256);//Generate random number from 0 to 255
break;
}

analogWrite(pinRed, red);//Write random red value to pwm pin 6  (red control)
analogWrite(pinGreen, green);//Write random green value to pwm pin 5  (green control)
analogWrite(pinBlue, blue);//Write random blue value to pwm pin 3  (blue control)

}

void loop()
{
randomLEDColorCombo();
delay(500);//Wait for 500 milliseconds between each random color
}


Uploading the sketch to your chipKIT™ board should make the tricolor LED randomly jump to new colors. The time between each jump is determined by the delay inside of the loop() function. You may notice some of the colors appear very dim. This is because inside of each case, random(256) has returned a value near 0. You can try experimenting with different min values for the random function to prevent dim colors. You can also specifically tweak the min values in cases 3 through 6. Currently, these cases have the possibility of generating a single primary color, like red, assuming the other colors in the case are randomly assigned a value near zero.

Now that we know how to generate random color combinations and implement color sweeps, we can combine the two concepts. In this section, we will write some code to randomly select a color sweep sequence. The order of the sequence will matter here. This means there will be six different color sequences, all of which are listed below.

List of color sequences

1. Red, green, blue
2. Red, blue, green
3. Green, red, blue
4. Green, blue, red
5. Blue, red, green
6. Blue, green, red

Each sequence will be implemented as a switch statement case. The case will be selected by using the random() function. Inside of each case, we will use the changeColorBrightness() function we wrote in the color sweeps section to fade the colors in or out. The code necessary to implement this is shown below inside of the randomColorSweep() function.

                  int pinRed = 6, pinGreen = 5, pinBlue = 3;

boolean brightnessDirection = 1;//If set to 1 the color brightness will increase

void setup()
{
pinMode(pinBlue, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinRed, OUTPUT);

analogWrite(pinBlue, 0);//Write 0 to pwm pin 3 (blue control)   This makes sure the LED starts off
analogWrite(pinGreen, 0);//Write 0 to pwm pin 5 (green control) This makes sure the LED starts off
analogWrite(pinRed, 0);////Write 0 to pwm pin 6 (red control)  This makes sure the LED starts off
}
{
int brightness, incrementValue, limit;

{
//Setup variables so the the LED brightness will fade in from 0 to 255
incrementValue = 1;//Set incrementValue to add 1 to the brightness
brightness = 0;//Ensure the LED starts completely off (minimum brightness)
limit = 255;//Set the brightness limit to 255 (maximum brightness)
}
else
{
//Setup variables so the the LED brightness will fade out from 255 to 0
incrementValue = -1;//set incrementValue to subtract 1 from the brightness
brightness = 255;//Ensure the LED starts completely on (maximum brightness)
limit = 0;//Set the brightness limit to 0 (minimum brightness)
}

while(brightness != limit)
{

//Loop until brightness has faded in or out completely
brightness += incrementValue;

switch(color)
{
case 'r':
analogWrite(pinRed, brightness);//Write to pwm pin 6  (red control)
break;
case 'g':
analogWrite(pinGreen, brightness);//Write to pwm pin 5  (green control)
break;
case 'b':
analogWrite(pinBlue, brightness);//Write to pwm pin 3  (blue control)
break;
}

//Wait for a specified number of miliseconds to control how fast the LED fades in or out

}
return;
}

void randomColorSweep()
{

randomNumber = random(6);//Generate random number from 0 to 5

switch(randomNumber)
{
case 0: //Color sequence 0: RGB
brightnessDirection = !brightnessDirection; //Invert fade direction
break;
case 1: //Color sequence 1: RBG
brightnessDirection = !brightnessDirection; //Invert fade direction
break;
case 2: //Color sequence 2: GRB
brightnessDirection = !brightnessDirection; //Invert fade direction
break;
case 3: //Color sequence 3: GBR
brightnessDirection = !brightnessDirection; //Invert fade direction
break;
case 4: //Color sequence 4: BRG
brightnessDirection = !brightnessDirection; //Invert fade direction
break;
case 5: //Color sequence 5: BGR
brightnessDirection = !brightnessDirection; //Invert fade direction
break;

}
}

void loop()
{
randomColorSweep();
}


Once this code is uploaded, the tricolor LED should randomly sweep through different color sequences. The sequence's fade time can be tweaked by changing a variable inside of the randomColorSweep() function. By default, it delays five milliseconds between each incrementation of a color's brightness. This is done using delay() called within changeColorBrightness(). If you want to delay for periods less than a millisecond, you can replace the delay() line with delayMicroseconds (fadeTime) for greater precision. Remember that one millisecond is equal to 1000 microseconds, so using delay times less than 300 with delayMicroseconds() will make the LED flash rather than fade.

## Summary:

In this project, we utilized pulse-width modulation to control the color of a tricolor LED. This project is very similar to the previous project, Breathing LED with Pulse-Width Modulation, except that we will be using a tricolor LED. Recall that the tricolor LED we will use can only generate red, green, and blue wavelengths of light, and by changing the intensities of each LED inside the bulb, we can generate the illusion of different colors.

##### Core Concepts:
• PWM
• Tricolor LEDs
##### Functions Introduced:
• random
• switch
• delayMicroseconds