RGB on knob

I'm looking for some sample code.

I want to adjust from Red to Blue to Green with a single potentiometer, and can't quite picture the best way to do it.

Adjust what?

I think he wants to control an RGB LED with a single potentiometer, "scrolling" through the different hues.

That's really difficult. I've yet to find a solid program that does that, so for my project I'm using 3 separate pots with this code (common cathode LED):

const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;

const int redPot = 2;
const int bluePot = 1;
const int greenPot = 3;

int currentRed;
int currentGreen;
int currentBlue;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}

void loop(){  
   currentRed = map(analogRead(redPot), 0, 1024, 0, 255);
   currentGreen = map(analogRead(greenPot), 0, 1024, 0, 255);
   currentBlue = map(analogRead(bluePot), 0, 1024, 0, 255);
    
   analogWrite(redPin, 255 - currentRed);
   analogWrite(greenPin, 255 - currentGreen);
   analogWrite(bluePin, 255 - currentBlue);
    
}

However, this is the best code I've found for scrolling through hues (not mine):

// Potentiometer connected to analog pin 2 w/ pos 5v and grounded neg
// RGB LED connections are in this order when looking at LED:  Red, Common Annode(Longest - also where 5v power is connected), Green, Blue
// RGB LED attached from digital pin 9(red), 10(green), 11(blue) w/ common annode to 5v power.

//Created 8 May 2010
//Commented by Dave a.k.a Ka0ticstyle

//*/

int potpin = 2;              // POT connected to digital pin 2 - pos/neg are left and right connections on POT
int rpin = 9;                // Red
int gpin = 10;               // Green
int bpin = 11;               // Blue
float h;                     // Hue range
int h_int;                   // Hue color
int r = 0, g = 0, b = 0;           // Default RGB values

int val = 0;                   // Set POT value to default 0

void h2rgb(float h, int& R, int& G, int& B); // Instantiate h2rgb and it's variables  a.k.a  Hue to RGB

void setup()                    // Run once, when the sketch starts
{
 Serial.begin(9600);          // Begin the output of data to serial
}


void loop()                     // Run over and over again
{
 val = analogRead(potpin);    // Read the pin and display the value
 h = ((float)val)/1024;       // Get the range. pot value / 1024
 h_int = (int) 360*h;         // Get the color hue by multiplying by 360

 h2rgb(h,r,g,b);              // Call the h2rgb function passing it the hue value

 Serial.print("POT value: ");
 Serial.print(val);           // Pot value
 Serial.print(" = Hue of ");
 Serial.print(h_int);         // Color Hue value
 Serial.print(" degrees. RGB values: ");
 Serial.print(r);             // Red value
 Serial.print(" ");
 Serial.print(g);             // Green value
 Serial.print(" ");
 Serial.println(b);           // Blue value

 analogWrite(rpin, (255-r));        // Changes red led
 analogWrite(gpin, (255-g));        // Changes green led
 analogWrite(bpin, (255-b));
 
}

void h2rgb(float h, int& R, int& G, int& B) {

 // Used HSV --> RGB function
 // HSV - Hue, Saturation, Value
 // RGB - Red, Green, Blue - example (255,255,255)
 // Function below does a bunch of math to convert HSV values to RGB
 int var_i;
 float S=1, V=1, var_1, var_2, var_3, var_h, var_r, var_g, var_b;

 if ( S == 0 )                       //HSV values = 0 ÷ 1
 {
   R = V * 255;
   G = V * 255;
   B = V * 255;
 }
 else
 {
   var_h = h * 6;
   if ( var_h == 6 ) var_h = 0;      //H must be < 1
   var_i = int( var_h ) ;            //Or ... var_i = floor( var_h )
   var_1 = V * ( 1 - S );
   var_2 = V * ( 1 - S * ( var_h - var_i ) );
   var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) );

   if      ( var_i == 0 ) {
     var_r = V     ;
     var_g = var_3 ;
     var_b = var_1 ;
   }
   else if ( var_i == 1 ) {
     var_r = var_2 ;
     var_g = V     ;
     var_b = var_1 ;
   }
   else if ( var_i == 2 ) {
     var_r = var_1 ;
     var_g = V     ;
     var_b = var_3 ;
   }
   else if ( var_i == 3 ) {
     var_r = var_1 ;
     var_g = var_2 ;
     var_b = V     ;
   }
   else if ( var_i == 4 ) {
     var_r = var_3 ;
     var_g = var_1 ;
     var_b = V     ;
   }
   else                   {
     var_r = V     ;
     var_g = var_1 ;
     var_b = var_2 ;
   }

   R = (1-var_r) * 255;                  //RGB results = 0 ÷ 255
   G = (1-var_g) * 255;
   B = (1-var_b) * 255;
 }
}

That's really difficult. I've yet to find a solid program that does that, so for my project I'm using 3 separate pots with this code (common cathode LED):

Really? have you tried to multiply the pots range (0 - 1023) by 64 to give you the max value of an unsigned int then convert the int back to RGB values?

void _565ToRGB( unsigned int color, byte * R, byte * G, byte * B)
{
  *R = (color & 0xf800) >> 8;
  *G = (color & 0x0FC0) >> 3;
  *B = (color & 0x001f) << 3;
}

It will skip of course, but it is not very difficult to do. Perhaps you can use a DUE because I have heard they are capable of 12bit resolution instead of the 10bit that the analogRead() function uses now.

HazardsMind:
It will skip of course, but it is not very difficult to do. Perhaps you can use a DUE because I have heard they are capable of 12bit resolution instead of the 10bit that the analogRead() function uses now.

As it is human controlled, things can be slower than usual.

By oversampling you can achieve 11 up to 16 bits of resolution. Check out this article: http://www.atmel.com/images/doc8003.pdf

Aiming for 15 bits of resolution could allow around 7 samples per second. Or around 29hz for 14 bits. Just need to do lots of samples: 4n where n is the number of extra bits.

I did it with some RGB LED's on my truck a few years ago and it worked pretty good. Full post here but the relevant code is below.

The basic process it just cutting the 1023 steps 6 sections. Each of these 6 sections has a specific combination of 1 or more of the colors. For reference the abbreviations for the variable is fr, fg, fb for front red green and blue respectively. Then it's rr, rg, and rb for the rear colors.

I was using these calls:

intLights (0, 175, 0, rr, 0, fr); // takes a value from the pot (0-1023) and uses that value to change the colors on the led
intLights (165, 345, rr, rb, fr, fb);
intLights (335, 515, rb, rg, fb, fg);
intLights (505, 685, rg, rr, fg, fr);
intLights (675, 855, 0, rb, 0, fb);
intLights (845, 1015, 0, rg, 0, fg);

To feed this funtion:

void intLights (int low, int high, int LEDlower1, int LEDraise1, int LEDlower2, int LEDraise2){ //takes the value from the pot and turns it into led values
    
  if(colorValue == 0) {
    digitalWrite(rr, LOW);
    digitalWrite(fr, LOW);
    
    digitalWrite(rg, LOW);
    digitalWrite(fg, LOW);
    
    digitalWrite(rb, LOW);
    digitalWrite(fb, LOW);
  }
  
  else if(colorValue >1000){
    digitalWrite(rr, HIGH);
    digitalWrite(fr, HIGH);
    
    digitalWrite(rg, HIGH);
    digitalWrite(fg, HIGH);
    
    digitalWrite(rb, HIGH);
    digitalWrite(fb, HIGH);
  }

else if (colorValue > low && colorValue < high){
  
  int LED1 = map (colorValue, low, high, 255, 10);
  int LED2 = map (colorValue, low, high, 10, 255);
  int LED3 = map (colorValue, low, high, 255, 10);
  int LED4 = map (colorValue, low, high, 10, 255);
  
  analogWrite (LEDlower1, LED1);
  analogWrite (LEDraise1, LED2);
  analogWrite (LEDlower2, LED3);
  analogWrite (LEDraise2, LED4);
  
}
}

i believe this sketch takes one pot and an rgb LED

// INPUT: Potentiometer should be connected to 5V and GND
int potPin = 3; // Potentiometer output connected to analog pin 3
int potVal = 0; // Variable to store the input from the potentiometer

// OUTPUT: Use digital pins 9-11, the Pulse-width Modulation (PWM) pins
// LED's cathodes should be connected to digital GND
int redPin = 9;   // Red LED,   connected to digital pin 9
int grnPin = 10;  // Green LED, connected to digital pin 10
int bluPin = 11;  // Blue LED,  connected to digital pin 11

// Program variables
int redVal = 0;   // Variables to store the values to send to the pins
int grnVal = 0;
int bluVal = 0;

void setup()
{
  pinMode(redPin, OUTPUT);   // sets the pins as output
  pinMode(grnPin, OUTPUT);   
  pinMode(bluPin, OUTPUT); 
}

// Main program
void loop()
{
  potVal = analogRead(potPin);   // read the potentiometer value at the input pin

  if (potVal < 341)  // Lowest third of the potentiometer's range (0-340)
  {                  
    potVal = (potVal * 3) / 4; // Normalize to 0-255

    redVal = 256 - potVal;  // Red from full to off
    grnVal = potVal;        // Green from off to full
    bluVal = 1;             // Blue off
  }
  else if (potVal < 682) // Middle third of potentiometer's range (341-681)
  {
    potVal = ( (potVal-341) * 3) / 4; // Normalize to 0-255

    redVal = 1;            // Red off
    grnVal = 256 - potVal; // Green from full to off
    bluVal = potVal;       // Blue from off to full
  }
  else  // Upper third of potentiometer"s range (682-1023)
  {
    potVal = ( (potVal-683) * 3) / 4; // Normalize to 0-255

    redVal = potVal;       // Red from off to full
    grnVal = 1;            // Green off
    bluVal = 256 - potVal; // Blue from full to off
  }
  analogWrite(redPin, redVal);   // Write values to LED pins
  analogWrite(grnPin, grnVal); 
  analogWrite(bluPin, bluVal);  
}

This last one looks the most interesting.

It's really just dividing the pot into three regions that is a bit of a mental roadblock.

I think that red from full then fade in green, then fade green into blue with only blue at the top would be a good way.

Do share your results if you try it... Heck i might even give it a shot, Im curious to see how it performs.

Ok, I probably will.

the only thing i think that i was trying to do with my code that i don't think is captured in the one User0689 posted is the rest of the potential combinations. To catch "all" possible colors I think you have six distinct transitions.

The way i see it these are:

  • Red is full on to start (So full Red is a fully counter-clockwise on the pot)
  • Blue coming up with Red still on Full
  • Red coming down with Blue full on
  • Green coming up with Blue full on
  • Red coming up with Green full on
  • Blue coming up with Red and Green on Full (To end with White as fully clockwise on the pot)