The pins that control the RGB LED can be controlled using pulse-width modulation. This allows us to mix colors by varying the brightness of each of the LEDs. The mixing effect works better if the light from the RGB LED is diffused. A ping pong ball with a hole in it placed over the RGB LED works as a great diffuser. We’ll look at the code and then explain it afterwards.

We used a simple algorithm to fade LED1 in Project 1.07. In this project we transition between colors more smoothly. We declare a variable for each pin in the RGB LED: int redLED = 9; int greenLED = 10; int blueLED = 11; We also declare a variable for the level of brightness of each LED: int redLevel = 0; int greenLevel = 0; int blueLevel = 0; We include two float variables. One is simply pi. float counter = 0; float pi = 3.14159; In the setup() block we set the LED pins to outputs: pinMode(redLED,OUTPUT); pinMode(greenLED,OUTPUT); pinMode(blueLED,OUTPUT); We start the loop() block by incrementing the variable counter: counter = counter + 1; We never reset counter the way we do with some variables. We don’t need to. We’re going to use the trigonometric sine function to set the brightness of each LED. Sine is a circular function. It keeps repeating the same set of values as counter goes higher and higher. redLevel = sin(counter/100)*1000; greenLevel = sin(counter/100 + pi*2/3)*1000; blueLevel = sin(counter/100 + pi*4/3)*1000; Remember that the sine describes the rotation of a point on a circle from 0 to 1, to -1, and back to zero over the course of 0 to 2π radians. The variable counter controls the rate of change in our program. It’s increments by 1 for each cycle of the loop() block, but the value is divided by 100 within the call to the sin function, so the rate of change is 0.01 radians per cycle. The values of the green and blue LEDs are offset from the red LED. The green LED is set ahead of the red LED by 1/3 of a rotation (2π/3) and the blue LED is ahead by 2/3 of a rotation (4π/3). The values returned by the sin function are multiplied by 1000 to yield values between -1000 and 1000. These values are stored by the redLevel, greenLevel, and blueLevelint variables. We then use the map function to rescale the range of values to between 0 and 100 (in this sketch, we don’t ever set the colors to their maximum brightness, which would be 255): redLevel = map(redLevel,-1000,1000,0,100); Here’s how the values of redLevel, greenLevel, and blueLevel change as the variable counter increases: We use analogWrite statements to set the brightness of each LED: analogWrite(redLED,redLevel); analogWrite(greenLED,greenLevel); analogWrite(blueLED,blueLevel); And finally a short delay and it’s back to the top of the loop() block: delay(10); }