Instantly share code, notes, and snippets.

Embed
What would you like to do?
Arduino sketch to cycle an RGB LED through the colour spectrum.
const int redPin = 11;
const int greenPin = 10;
const int bluePin = 9;
void setup() {
// Start off with the LED off.
setColourRgb(0,0,0);
}
void loop() {
unsigned int rgbColour[3];
// Start off with red.
rgbColour[0] = 255;
rgbColour[1] = 0;
rgbColour[2] = 0;
// Choose the colours to increment and decrement.
for (int decColour = 0; decColour < 3; decColour += 1) {
int incColour = decColour == 2 ? 0 : decColour + 1;
// cross-fade the two colours.
for(int i = 0; i < 255; i += 1) {
rgbColour[decColour] -= 1;
rgbColour[incColour] += 1;
setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
delay(5);
}
}
}
void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
@peterrus

This comment has been minimized.

Show comment
Hide comment
@peterrus

peterrus Sep 26, 2012

Wouldn't it be better to use PWM here? Leds have a nonlinear voltage response

peterrus commented Sep 26, 2012

Wouldn't it be better to use PWM here? Leds have a nonlinear voltage response

@BubbaTheHub

This comment has been minimized.

Show comment
Hide comment
@BubbaTheHub

BubbaTheHub Nov 9, 2012

Well written jamesotron, thanks.

Peterrus: analogWrite() is PWM.

BubbaTheHub commented Nov 9, 2012

Well written jamesotron, thanks.

Peterrus: analogWrite() is PWM.

@razic

This comment has been minimized.

Show comment
Hide comment
@razic

razic Sep 12, 2013

Perfect. Just what I was looking for!

razic commented Sep 12, 2013

Perfect. Just what I was looking for!

@stonez56

This comment has been minimized.

Show comment
Hide comment
@stonez56

stonez56 Jan 7, 2014

Very well written codes! Thank you so much!!

stonez56 commented Jan 7, 2014

Very well written codes! Thank you so much!!

@Nihilus89

This comment has been minimized.

Show comment
Hide comment
@Nihilus89

Nihilus89 Apr 3, 2015

Neat code! Thank you!

Nihilus89 commented Apr 3, 2015

Neat code! Thank you!

@whalemare

This comment has been minimized.

Show comment
Hide comment
@whalemare

whalemare Jun 14, 2015

Yeah, thanks!)

whalemare commented Jun 14, 2015

Yeah, thanks!)

@VolandiYisser

This comment has been minimized.

Show comment
Hide comment
@VolandiYisser

VolandiYisser Oct 15, 2015

Hello Arduino World,
I'm trying to work out how this sketch works. I understand it up to the line 20.
int incColour = decColour == 2 ? 0 : decColour + 1;
I think it starts by declaring an integer called incColour and sets it equal to the other int decClour but then I get lost with the two = signs and then the quesion mark. Is there a long way to write this line that will be easier to understand?
Regards,
Volandi

VolandiYisser commented Oct 15, 2015

Hello Arduino World,
I'm trying to work out how this sketch works. I understand it up to the line 20.
int incColour = decColour == 2 ? 0 : decColour + 1;
I think it starts by declaring an integer called incColour and sets it equal to the other int decClour but then I get lost with the two = signs and then the quesion mark. Is there a long way to write this line that will be easier to understand?
Regards,
Volandi

@pizen

This comment has been minimized.

Show comment
Hide comment
@pizen

pizen Oct 25, 2015

Volandi,

? is a ternary operator. Line 20 is the same logic as:

int incColour;
if (decColour == 2) {
    incColour = 0;
} else {
    incColour = decColour +1;
}

pizen commented Oct 25, 2015

Volandi,

? is a ternary operator. Line 20 is the same logic as:

int incColour;
if (decColour == 2) {
    incColour = 0;
} else {
    incColour = decColour +1;
}
@kaptainkommie

This comment has been minimized.

Show comment
Hide comment
@kaptainkommie

kaptainkommie commented Jan 6, 2016

Thanks!

@doublejosh

This comment has been minimized.

Show comment
Hide comment
@doublejosh

doublejosh Feb 1, 2016

You can skip a block of code by assigning values when you initialize the array...

unsigned int rgbColor[3] = {255, 0, 0};

Also, thanks for this example.

doublejosh commented Feb 1, 2016

You can skip a block of code by assigning values when you initialize the array...

unsigned int rgbColor[3] = {255, 0, 0};

Also, thanks for this example.

@ManciuStefan

This comment has been minimized.

Show comment
Hide comment
@ManciuStefan

ManciuStefan Aug 11, 2016

You can also write that line as:
incColour = (decColour + 1) % 2

ManciuStefan commented Aug 11, 2016

You can also write that line as:
incColour = (decColour + 1) % 2

@Cellane

This comment has been minimized.

Show comment
Hide comment
@Cellane

Cellane Oct 10, 2016

@ManciuStefan Not really, that line only ever gives you 0 or 1 as an output. The original line with ternary operator gives you either 0, 1, or 2.

Cellane commented Oct 10, 2016

@ManciuStefan Not really, that line only ever gives you 0 or 1 as an output. The original line with ternary operator gives you either 0, 1, or 2.

@nizamky

This comment has been minimized.

Show comment
Hide comment
@nizamky

nizamky Oct 11, 2016

i need to control rgb light via blutooth from mobile?. any advice?

nizamky commented Oct 11, 2016

i need to control rgb light via blutooth from mobile?. any advice?

@hideyhole1

This comment has been minimized.

Show comment
Hide comment
@hideyhole1

hideyhole1 Feb 5, 2017

@jamesotron Your schetche works but, you need to explain stuff and add comments. Explain what this means(on line 20):

int incColour = decColour == 2 ? 0 : decColour + 1;

hideyhole1 commented Feb 5, 2017

@jamesotron Your schetche works but, you need to explain stuff and add comments. Explain what this means(on line 20):

int incColour = decColour == 2 ? 0 : decColour + 1;

@XombyCraft

This comment has been minimized.

Show comment
Hide comment
@XombyCraft

XombyCraft Feb 18, 2017

This works great for common cathode LEDS.
If you're using common Anode LEDS, change line 27 to:
setColourRgb(255-rgbColour[0], 255-rgbColour[1], 255-rgbColour[2]); //quick and ugly invert

XombyCraft commented Feb 18, 2017

This works great for common cathode LEDS.
If you're using common Anode LEDS, change line 27 to:
setColourRgb(255-rgbColour[0], 255-rgbColour[1], 255-rgbColour[2]); //quick and ugly invert

@thebigsmileXD

This comment has been minimized.

Show comment
Hide comment
@thebigsmileXD

thebigsmileXD Apr 18, 2017

Interesting code, but for me only blue changes

thebigsmileXD commented Apr 18, 2017

Interesting code, but for me only blue changes

@jdimpson

This comment has been minimized.

Show comment
Hide comment
@jdimpson

jdimpson Jan 9, 2018

I just noticed a minor bug. A stickler (such as myself) may wish to call setColourRgb(rgbColour[0],rgbColour[1],rgbColour[2]); delay(5); immediately after rgbColour gets initialized to {255,0,0}, before hitting the for loops. Otherwise the LED doesn't ever hit a pure red output.

Alternatively, you could initialize rgbColour to {256,-1,-1}, but then you'd need to change the declaration of rgbColour to signed and make similar change to the arguments to setRgbColour() function. I'm pretty sure making it signed won't hurt anything; at worst analogRead() will complain about implicit casting. If that bothers you (and it should) you can safely cast it to unsigned in setRgbColour()

I noticed that the red output seemed underpowered a few months ago, but assumed I used too large a value of resistor on the red pin. That may still be true, but this fix should help a bit.

I love this gist, by the way. I've come back to it several times since I first saw it a couple years ago. Thank you, @jamesotron !

jdimpson commented Jan 9, 2018

I just noticed a minor bug. A stickler (such as myself) may wish to call setColourRgb(rgbColour[0],rgbColour[1],rgbColour[2]); delay(5); immediately after rgbColour gets initialized to {255,0,0}, before hitting the for loops. Otherwise the LED doesn't ever hit a pure red output.

Alternatively, you could initialize rgbColour to {256,-1,-1}, but then you'd need to change the declaration of rgbColour to signed and make similar change to the arguments to setRgbColour() function. I'm pretty sure making it signed won't hurt anything; at worst analogRead() will complain about implicit casting. If that bothers you (and it should) you can safely cast it to unsigned in setRgbColour()

I noticed that the red output seemed underpowered a few months ago, but assumed I used too large a value of resistor on the red pin. That may still be true, but this fix should help a bit.

I love this gist, by the way. I've come back to it several times since I first saw it a couple years ago. Thank you, @jamesotron !

@michalmonday

This comment has been minimized.

Show comment
Hide comment
@michalmonday

michalmonday Feb 8, 2018

Simultaneous increasing and decreasing of 2 colours leads to the situation where the colors "meet" at midpoint between 0 and 255 so the RGB status is like 127,128,0 which gives a darker shade. If you take a look at "color picker" in google, set the color to be the brightest and play with the slider you'll notice that it always changes 1 of the RGB variables at a time leading it to reach 6 main states that gradually switch between themselves, these states are:

  1. 255, 0, 0
  2. 255, 255, 0
  3. 0, 255, 0
  4. 0, 255, 255
  5. 0, 0, 255
  6. 255, 0, 255
  7. 255, 0, 0 (whole cycle ends, it's the same as 1st step)

Your implementation is providing the following states:

  1. 255, 0, 0
  2. 127, 128, 0
  3. 0, 255, 0
  4. 0, 128, 127
  5. 0, 0, 255
  6. 127, 0, 128
  7. 255, 0, 0

Here's a python implementation which shows how to loop through RGB without getting the darker shade:
https://github.com/michalmonday/RGB_rainbowLoop/blob/master/RGB_rainbowLoop.py

I guess it would be better without the section list but it does the thing... On the other side it allows for other operations being executed without the need to complete the whole cycle from red to blue, also it would be easy to implement custom sequences of colours with it.

michalmonday commented Feb 8, 2018

Simultaneous increasing and decreasing of 2 colours leads to the situation where the colors "meet" at midpoint between 0 and 255 so the RGB status is like 127,128,0 which gives a darker shade. If you take a look at "color picker" in google, set the color to be the brightest and play with the slider you'll notice that it always changes 1 of the RGB variables at a time leading it to reach 6 main states that gradually switch between themselves, these states are:

  1. 255, 0, 0
  2. 255, 255, 0
  3. 0, 255, 0
  4. 0, 255, 255
  5. 0, 0, 255
  6. 255, 0, 255
  7. 255, 0, 0 (whole cycle ends, it's the same as 1st step)

Your implementation is providing the following states:

  1. 255, 0, 0
  2. 127, 128, 0
  3. 0, 255, 0
  4. 0, 128, 127
  5. 0, 0, 255
  6. 127, 0, 128
  7. 255, 0, 0

Here's a python implementation which shows how to loop through RGB without getting the darker shade:
https://github.com/michalmonday/RGB_rainbowLoop/blob/master/RGB_rainbowLoop.py

I guess it would be better without the section list but it does the thing... On the other side it allows for other operations being executed without the need to complete the whole cycle from red to blue, also it would be easy to implement custom sequences of colours with it.

@susumakeit

This comment has been minimized.

Show comment
Hide comment
@susumakeit

susumakeit Apr 11, 2018

very nice to use make the prototype. and I can save time by using this function.
I will make a led lamp using contained register led(NeoPixel)that operate by data but
previous products are consist of normal type led to controlled ON or OFF voltage

susumakeit commented Apr 11, 2018

very nice to use make the prototype. and I can save time by using this function.
I will make a led lamp using contained register led(NeoPixel)that operate by data but
previous products are consist of normal type led to controlled ON or OFF voltage

@surik00

This comment has been minimized.

Show comment
Hide comment
@surik00

surik00 May 24, 2018

I've implemented a non-blocking version of it using @michalmonday's algorithm for Arduino:
https://gist.github.com/surik00/6eb44d102d207bc94b9f9bd1c7e87c42

surik00 commented May 24, 2018

I've implemented a non-blocking version of it using @michalmonday's algorithm for Arduino:
https://gist.github.com/surik00/6eb44d102d207bc94b9f9bd1c7e87c42

@rvt

This comment has been minimized.

Show comment
Hide comment
@rvt

rvt Aug 28, 2018

You can also use the HSB model for your colors (if your mc is fast enough) then cycling through all colors will start to feel very natural. C++ for this can be found here https://github.com/rvt/Arilux_AL-LC0X

rvt commented Aug 28, 2018

You can also use the HSB model for your colors (if your mc is fast enough) then cycling through all colors will start to feel very natural. C++ for this can be found here https://github.com/rvt/Arilux_AL-LC0X

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment