Skip to content

Arduino: Controlling an RGB LED by Hue

2011 August 4
by Tedb0t

Hooking up an RGB LED to an Arduino isn’t hard by itself, but controlling it can be—if you know what color you want to display, how do you know what R, G and B values that is?

Here’s some Arduino code, adapted and simplified from Kasper Kamperman, that I am using in my Deconspectrum art installation to do just that:

void setLED(int hue, int l){
	int col[3] = {0,0,0};
	getRGB(hue, 255, l, col);
	ledWrite(col[0], col[1], col[2]);

void getRGB(int hue, int sat, int val, int colors[3]) {
	// hue: 0-259, sat: 0-255, val (lightness): 0-255
	int r, g, b, base;

	if (sat == 0) { // Achromatic color (gray).
	} else  {
		base = ((255 - sat) * val)>>8;
		switch(hue/60) {
			case 0:
				r = val;
				g = (((val-base)*hue)/60)+base;
				b = base;
			case 1:
				r = (((val-base)*(60-(hue%60)))/60)+base;
				g = val;
				b = base;
			case 2:
				r = base;
				g = val;
				b = (((val-base)*(hue%60))/60)+base;
			case 3:
				r = base;
				g = (((val-base)*(60-(hue%60)))/60)+base;
				b = val;
			case 4:
				r = (((val-base)*(hue%60))/60)+base;
				g = base;
				b = val;
			case 5:
				r = val;
				g = base;
				b = (((val-base)*(60-(hue%60)))/60)+base;

void ledWrite(int r, int g, int b){
	analogWrite(LED_RED, 255-r);
	analogWrite(LED_GREEN, 255-g);
	analogWrite(LED_BLUE, 255-b);

This gives you a very straightforward setLED function that takes a Hue from 0-359 and a Lightness from 0-255 (it could easily be adapted to specify the Saturation as well, which I have fixed at the maximum).

Note that the ledWrite function is designed for common-anode LEDs, where the microprocessor is current-sinking instead of sourcing; if you are current-sourcing, just take out the 255-val inversion.

Related Posts:

9 Responses
  1. August 19, 2011

    Ted, thanks for this post. I am working on a small personal project with RGB leds and this is exactly what I was looking for – code the get HSB color control on the Arduino. Thanks for sharing.

  2. Arduino Newbie permalink
    October 7, 2011

    Why use analogWrite() instead of digitalWrite()?

    • October 7, 2011

      digitalWrite() produces a binary value—it turns a voltage on or off completely. This would give us 2^3 = 8 total combinations of colors—not very exciting. analogWrite() produces 256 different “analog” voltages by turning it on and off rapidly, effectively dimming the red, green and/or blue channels, giving us 256^3 = 16.7 million color combinations. In reality the dimming isn’t perfectly linear, and some of the colors are stronger than others, but using analogWrite() still gives you a much smoother variation of colors.

  3. Jack Zylkin permalink
    October 31, 2011

    Hi, can I ask a question here? When you pass the variable col[] to the function getRGB(), doesn’t this just pass the VALUE of col[]? So, when you update colors[] within that function, why should it change the value of col[]?

    • November 1, 2011

      Your instinct is correct. However, because this is C, the col[] parameter that’s being passed in is actually a pointer to an array. Since we’re dealing with a pointer, the array indices are affected directly.

      In a language like Java, it would be more typical not to pass in an array and modify it but rather create a temporary local array and return it. Not so in C: attempting to return an array pointer is bad practice because there’s no guarantee the memory addresses that it points to after the function has returned will still be valid.

  4. Dave permalink
    November 1, 2012

    Hi there!

    Thanks for posting this code. I was wondering if it is open source and free to distribute? Thanks!

  5. Ivan permalink
    December 18, 2012

    Hello! Thank you for sharing! I put a link here in my code in case it’s ever “out-there.” Thanks again, this helped a lot!

Trackbacks and Pingbacks

  1. HSB to RGB [arduino library] « Julio Terra

Comments are closed.