Some useless RGB LED experiment w/ Arduino

Disclaimer: The following article is written by a hungarian student, who had never learned english, so it may (and will) contain major grammatical and stylistical errors. It is also possible, that I do things badly, so if you follow my instructions , do it only at your own risk! I take no responsibility for any injuries or damage in your equipment. Anyway, I release the following informations under the CC BY-NC 3.0 license: http://creativecommons.org/licenses/by-nc/3.0/.

This evening as I came home from a paragliding appointment, I had a feeling that I must improve my yesterday-written RGB LED driver code. So I cleaned it up a bit, and wrote a lot of comments to make it more useful for educational purposes. I’m alredy over this level, but it’s fun to play with it.

An RGB LED is just three LEDs in a single package: red, green and blue, from here comes the TLA. If you have no RGB LEDs currently, you can replace it with a red, a green and a blue LED. For a good result, the LEDs’ (visible) brightnesses have to be similar.

The idea is, that from the three “basic” colors (r,g,b) a lot of colors (but not all) can be mixed. This mixing is performed by three individual PWM signal applied by the AVR controller on the Arduino board. See more about PWM at http://en.wikipedia.org/wiki/Pulse_width_modulation.

I think the whole thing is very simple, but it looks nice, and you can experiment with the generation of different waveforms. Try to modify the code to use a harmonic (sine) function as input for the lightness. For more advanced users: avoid the built-in sin() function, but produce sinusoidal output. Hint: arrays… 😉


AStech RGB LED experiment w/ Arduino

This video may not be as exciting as the previous one (see here) because my phone’s camera is unable to capture the fine changes in the color of the LED. It seems much more better in reality, so you really must build one. 🙂

The other side of the breadboard (and the rest of the parts) is used in another project and it’s not connected to the board now. I was just too lazy to disassemble it.

The circuit is very simple, it’s ideal for beginners. I sketched up the schematic in eagle:

RGB LED schematic, three LEDs connected to an arduino board

RGB LED schematic

This doesn’t need explanation. Just connect your RGB LED to the Arduino board in series with three 560Ω resistors as you can see on the figure above. (200Ω is fine too – these resistors define the current which flows through the LEDs. The current cannot exceed 50mA (each), as it could damage the microcontroller and the LED too.) If you have individual LEDs for red, green and blue, it’s fine too.

Tip: put the RGB LED or the three individual LEDs in a thin paper tube as it can be seen on my video. It diffuses and mixes the light and it becomes less direct.

The source code comes here (notice the comments):

/* AStech RGB LED driver example
 w/ HSL-to-RGB conversion
 and some magic 🙂
written by Pal BOLE
Hungary, 24. 03. 2011
 */

void setup() {
 pinMode(2, OUTPUT); // red
 pinMode(3, OUTPUT); // green
 pinMode(4, OUTPUT); // blue
 #ifdef DEBUG
 Serial.begin(9600); // for debug purposes
 #endif
}

struct Color { // RGB color structure
 byte r; // r for red, this is a member of the structure
 byte g; // g for green
 byte b; // b for blue
} color;

struct HSL { // HSL color (hue-saturation-lightness)
 byte h;
 byte s;
 byte l;
} hslcolor;

void applyColor(struct Color color) { // write Color to the LEDs
 analogWrite(2, color.r); // amount of red
 analogWrite(3, color.g); // amount of green
 analogWrite(4, color.b); // amount of blue
}

struct Color hslToRgb(struct HSL *hsl) { /* // not exactly, but something similar
 // ^ pass by reference:
 // the paramter is the memory address of the variable
 // instead of value of the variable itself. it's  faster and
 // consumes less memory. please note that the members of this
 // structure can be accessed using the "->" arrow operator
 // instead of the usual "." dot.  */
 Color rgb; // this will be the output
 word temp; // temporary two-byte integer number for calculations

 byte top = hsl->l;
 temp = (top * (255 - hsl->s)); //
 byte bottom = (byte) (temp /255 ); // temp >> 8 is wrong

 byte cont = top - bottom; // something like "contrast", but it isn't

 byte mod = hsl->h % 42; // 42 * 6 = 252, so 252 is the maximal hue
 byte segment = hsl->h / 42; // division by power of two would be some 200 times faster
 temp = mod * cont; // here it comes a big product, so our temp is needed
 byte x = (byte) (temp / 42); // scale it down

 switch (segment) { // to understand this part, please refer to: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
 case 0:
 rgb.r = top;
 rgb.g = bottom + x;
 rgb.b = bottom;
 break;
 case 1:
 rgb.r = top - x;
 rgb.g = top;
 rgb.b = bottom;
 break;
 case 2:
 rgb.r = bottom;
 rgb.g = top;
 rgb.b = bottom + x;
 break;
 case 3:
 rgb.r = bottom;
 rgb.g = top - x;
 rgb.b = top;
 break;
 case 4:
 rgb.r = bottom + x;
 rgb.g = bottom;
 rgb.b = top;
 break;
 case 5:
 rgb.r = top;
 rgb.g = bottom;
 rgb.b = top - x;
 break;
 default: // something is wrong (hue is more than 252)
 rgb.r = 0;
 rgb.g = 0;
 rgb.b = 0;
 }

 return rgb; // here you go!
}

boolean downcount = false; // true if we counting down

byte i = 0; // loop variable
byte j = 0; // loop variable

void loop() {

 /* a trimmer resistor voltage divider can be connected to the analog input
 so the color can be set up here. please note, that maximal value for hue
 is 252, not 255. larger values than 252 will produce RGB(0,0,0) output.  */
 hslcolor.h = i; // slow sawtooth-function as hue
 hslcolor.s = 255;  // some constant here
 hslcolor.l = 255-j; // lightness will change rapidly in a form of a triangle-wave

 color = hslToRgb(&hslcolor);  // convert HSL to RGB, which can be "written" to the LEDs
 applyColor(color); // here it comes!

#ifdef DEBUG // to see if something is wrong
 Serial.print("\t H: ");
 Serial.print(hslcolor.h, DEC);
 Serial.print("\t S: ");
 Serial.print(hslcolor.s, DEC);
 Serial.print("\t L: ");
 Serial.print(hslcolor.l, DEC);

 Serial.print("\t R: ");
 Serial.print(color.r, DEC);
 Serial.print("\t G: ");
 Serial.print(color.g, DEC);
 Serial.print("\t B: ");
 Serial.println(color.b, DEC);
#endif

 // increment the variables
 #define TOP 252

 if (j == 255) {
 i++; // change i 255 times slower than j
 }

 if (i > TOP) {
 i = 0;
 } // sawtooth wave with maximum value of TOP

 if (j == 255) { // maximum reached, now count down!
 downcount = true;
 }

 if (j == 0) { // minimum reached, now count up!
 downcount = false;
 }

 if (downcount) { // now increment/decrement - here it comes our triangle-wave
 j--;
 } else {
 j++;
 }

 delay(2); // spend some time here to slow things down
}

Well, the pass-by-reference can be a bit difficult to understand, but when every byte of the memory worth a lot – because of the limited space, which can happen often especially in microcontroller systems – it’s very important. And it speeds things up too. Read more at http://www.math.cam.ac.uk/undergrad/catam/ccatsl/manual/node50.html

The interesting part is the HSL-to-RGB conversion. HSL means hue-saturation-lightness and it’s a more natural description of colors than the RGB. However, RGB must be applied to the outputs since we only have red, green and blue LEDs. And that’s why you need to convert. You can find more information here: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV, especially this figure is important: http://en.wikipedia.org/wiki/File:HSV-RGB-comparison.svg.

That’s all. The whole project can be downloaded in a single zip file: rgbled Enjoy!

So long, and thanks for all the fish!

This entry was posted in experiments and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *