Project 1 Basic Color Mixing
Overview
In this section, we'll explore basic wiring and our nifty RGB/fullspectrum LED.
RGB LED

The onboard Atmex LED is red, which is all fine and everything but we want to make other nifty colors. Like fuscia and turquoise and orangeyellow. There's no such thing as a fuscia LED, so instead we will take 3 LEDs (red, green & blue) and power them at different brightness to combine into a virtual rainbow. A lot of people are familiar with the "additive color wheel" diagram[1]: Red plus green is yellow. Red plus purple is magenta (purplish). Green plus blue is cyan (light bluish). Add them together and you make white.

Whats neat about the RGB LED is that the three different chunks of semiconductor are in one small plastic package. In order to wire up the LED properly, we need to look at the datasheet, like we did for the plain red LED. Only problem is, there doesn't seem to be one (well let me know if you find one for it, but I couldn't). There is some information in the mouser catalog, so lets read that.

Despite lacking a datasheet, pretty much all the data necesary is here. The forward voltages (Vf) of red, green and blue: 2V, 2.2V and 3.8V. The brightness, 90mcd, 70mcd and 12.5mcd. Note that there are 2 blue LEDs, probably to make up for the fact that each one is pretty dim.

The "cathode" of an LED is the part that always gets connected to ground (or is closest to ground): current in a diode wants to flow from the "anode" to the "cathode." One way to remember that is that, alphabetically, anode comes before cathode. The reason its called a "common cathode" is that all the LEDs are connected together to the two cathode pins. Its not really clear why there are two cathode pins, probably just easier to manufacture.

Lets calculate the resistor values we want for each LED. Say we want 10mA through each LED. That means that for the red LED, (5-2)V/0.01A = 300 ohms. For the green, (5 - 2.2)/0.01 = 280 ohms. Blue, (5 - 3.8)/0.01 = 120 ohms. Lets just say that 280 = 300, its pretty close anyways. OK we're ready to wire it up!

Breadboarding

To start, lets use a solderless breadboard (the white slab thing) to wire up the LED. You don't have to breadboard the LED, its a rather simple circuit. But its also pretty common to screw things up (in general) and with a solderless breadboard, screwing up is easy to fix whereas if you solder the LED directly, before you know 100% that you're doing it right, well its a real pain to desolder and fix that sort of thing.

To start, clip the leads so they're all the same length, this just makes it to work with. Now bend the four anode leads so that are seperated like so.

And plug it into the breadboard so that you use up five rows.

Now clip and bend the two 300ohm and two 120ohm resistors and use them to bridge the two columns.

Now connect the cathodes to ground, and the green LED's resistor to port B2, the red one's to B3 and the two blue ones to B4.

If you want to test/play with the RGB led, take the wires that connect from the resistor to the port and try plugging them directly into 5V to light them up.

Basic colormixing code

OK lets write some basic code to color mix:

00001 // this is the header file that tells the compiler what pins and ports, etc.
00002 // are available on this chip.
00003 #include <avr/io.h>
00004 
00005 // define what pins the LEDs are connected to.
00006 // in reality, PB2/PB3/PB4 are also constants. e.g PB2 is 2
00007 #define GREEN PB2
00008 #define RED PB3
00009 #define BLUE PB4
00010 
00011 // Some macros that make the code more readable
00012 #define output_low(port,pin) port &= ~(1<<pin)
00013 #define output_high(port,pin) port |= (1<<pin)
00014 #define set_input(portdir,pin) portdir &= ~(1<<pin)
00015 #define set_output(portdir,pin) portdir |= (1<<pin)
00016  
00017 int main(void) {
00018   // initialize the direction of the B port to be outputs
00019   // on the 3 pins that have LEDs connected
00020   set_output(DDRB, RED);  
00021   set_output(DDRB, GREEN);
00022   set_output(DDRB, BLUE);
00023 
00024   // turn on RED and BLUE to make...magenta (purple)!
00025   output_high(PORTB, RED);
00026   output_low(PORTB, GREEN);
00027   output_high(PORTB, BLUE);
00028 
00029   return 0;
00030 }
This is pretty much just like the ledblink.c code, except we're not blinking and we're using different pins. Compile and upload it as before. Pretty simple. You can go through and experiment with mixing in different ways to make all 7 colors in the colorwheel. You'll note that the colors aren't exactly what they ought to be (particularly white)...this LED isn't really perfectly calibrated.
Blinking colormix

Now we go back & combine ledblink.c and the basic colormixing code to make a blinking colormix

00001 // this is the header file that tells the compiler what pins and ports, etc.
00002 // are available on this chip.
00003 #include <avr/io.h>
00004 
00005 // define what pins the LEDs are connected to.
00006 // in reality, PB2/PB3/PB4 are also constants. e.g PB2 is 2
00007 #define GREEN PB2
00008 #define RED PB3
00009 #define BLUE PB4
00010 
00011 // Some macros that make the code more readable
00012 #define output_low(port,pin) port &= ~(1<<pin)
00013 #define output_high(port,pin) port |= (1<<pin)
00014 #define set_input(portdir,pin) portdir &= ~(1<<pin)
00015 #define set_output(portdir,pin) portdir |= (1<<pin)
00016 
00017 // this is just a program that 'kills time' in a calibrated method
00018 void delay_ms(uint8_t ms)
00019 {
00020   uint16_t delay_count = F_CPU / 17500;
00021   volatile uint16_t i;
00022 
00023   while (ms != 0) {
00024     for (i=0; i != delay_count; i++);
00025     ms--;
00026   }
00027 }
00028 
00029  
00030 int main(void) {
00031   // initialize the direction of the B port to be outputs
00032   // on the 3 pins that have LEDs connected
00033   set_output(DDRB, RED);  
00034   set_output(DDRB, GREEN);
00035   set_output(DDRB, BLUE);
00036 
00037   while (1) {
00038     // start with all the LEDs off
00039     output_low(PORTB, RED);
00040     output_low(PORTB, GREEN);
00041     output_low(PORTB, BLUE);
00042 
00043     // turn on the red light for 200ms
00044     output_high(PORTB, RED);
00045     delay_ms(200);
00046 
00047     // turn on red & green -> yellow for 200ms
00048     output_high(PORTB, GREEN);
00049     delay_ms(200);
00050 
00051     // now turn off red to make just green
00052     output_low(PORTB, RED);
00053     delay_ms(200);
00054 
00055     // now turn on green & blue to make greenish-blue
00056     output_high(PORTB, BLUE);
00057     delay_ms(200);
00058 
00059     // turn off green -> blue
00060     output_low(PORTB, GREEN);
00061     delay_ms(200);
00062 
00063     // turn on red again to make purple
00064     output_high(PORTB, RED);
00065     delay_ms(200);
00066 
00067     // now start over
00068   }
00069 }
OK. Compile and upload it. Congrats, you have a raver toy!
Exercises
  1. Change the blinking color mix code to blink out a customized set of colors and speeds (ie green, blue, white & turquoise)
August 24, 2009 15:13