Sunday, August 9, 2015

ARDUINO: Controlling an RGB LED with a potentiometer


One of my upcoming projects will require me to control an RGB LED with a single potentiometer.
Scouting the internet for relevant code came out a tad fruitless as most code had poor transitions between each RGB value, as you could see each LED momentarily turning OFF between major transitions.

So after having a look how an RGB colour wheel works (http://www.colorspire.com/rgb-color-wheel/) I decided to write a simple function myself, thus giving the code below:
/////////////////////////////////////////////////////////////////////////////////////////////
// RGB LED control - v1.1                                                                  //
//                                                                                         //
// A simple program for controlling an RGB led with a single potentiometer.                //
// As per I/O pins below, the RED pin of the RGB LED is connected to pin #9 of the Arduino //
// GREEN pin to pin #10, and BLUE pin to pin #11. Also the output of the potentiomenter is //
// located on pin #A0.                                                                     //
//                                                                                         //
// ANTALIFE - 09.08.15                                                                     //
/////////////////////////////////////////////////////////////////////////////////////////////          

//MUH I/O PINS
int R_pin       = 9;
int G_pin       = 10; 
int B_pin       = 11;
int RGB_pot_pin = 0;

//MUH VARIABLES
int anal_val    = 0; // ;^)
int theta       = 0; 
int colour      = 0;

void setup()
{
  //MUH OUTPUTS
  pinMode(R_pin, OUTPUT);
  pinMode(G_pin, OUTPUT);   
  pinMode(B_pin, OUTPUT); 
}


void loop()
{
  //Using an RGB circle with RED being 0deg, GREEN being 120deg, and BLUE being 240deg
  //Here we map the 360deg circle to a value between 0 and 255 (aka the duty of the PWM)
  theta           = analogRead(RGB_pot_pin)/4;
  colour          = (6*theta)%255;
  
  //RED TO GREEN [0deg -> 120deg OR 0 -> 85]
  if (theta <= 42.5)
  {
    RGB_write(255,colour,0);
  }
  else if ((theta > 42.5) && (theta < 85))
  {
    RGB_write((255-colour),255,0);
  }
  //GREEN TO BLUE [120deg -> 240deg OR 85 -> 170]
  else if ((theta > 85) && (theta < 127.5))
  {
    RGB_write(0,255,colour);
  }
  else if ((theta > 127.5) && (theta < 170))
  {
    RGB_write(0,(255-colour),255);
  }
  //BLUE TO RED [240deg -> 360deg(or 0deg) OR 170 -> 255(or 0)]
  else if ((theta > 170) && (theta < 212.5))
  {
    RGB_write(colour,0,255);
  }
  else if ((theta > 212.5) && (theta < 255))
  {
    RGB_write(255,0,(255-colour));
  }
}


void RGB_write(int R_val, int G_val, int B_val)
{
  //A simple function that displays the desired LED colour by setting the duty of the
  //PWM on each RGB LED
  analogWrite(R_pin, R_val); 
  analogWrite(G_pin, G_val);
  analogWrite(B_pin, B_val);
}


To give a quick explanation of the code look at the picture below. You see how as you move around the colour wheel (or change the theta angle) the R G B values of the LED change accordingly giving you a certain colour. One other thing to note is that only two values are being changed at any given point, that is from 0deg to 120deg only the R and G values change while B stays constant (you can witness this by playing around with the colour wheel link above).
Knowing all this the above code maps the angle theta to a certain mixture of PWM duty on each LED, in the end giving you a pretty display of colours.


EDIT: Turns out humans see the brightness of colours differently, here is a good post about how this would have to be accounted for in software.

Just a simple blog for somewhat simple projects of mine.