Help please with 3 channel LED dimming with master dimmer

Hello All, My first post. I hope someone can help me please or at least point me in the right direction if possible. Im trying to create a constant current high power 3 channel RGB LED lamp. I can run my drivers via the PWM pins with a potentiometer for each channel on the analogue pins with a separate 12v supply so all good there.

Being a complete novice with Arduino code Im looking for help please. I would like to add a forth dimmer to act as a master dimmer over the other 3 LED channels once the colour is set via the other 3 dimmers. Im sure its possible but I have no idea how to do it and how to modify the code below.

the code that I have copied and pasted is at Arduino Playground - HomePage

Many thanks in advance

Jason

Hi Jason,

You don't need any extra hardware on the 12V side for the "master channel", that can all be done in the sketch.

How do you intend to control the colour and brightness? Were you thinking 3 pots for r, g & b plus a fourth for the master brightness control? You could have one pot for colour selection and one for brightness. The sketch could then translate the two pot values into r, g & b pwm values.

If you want it, a third pot could control the colour "saturation", ie. how strong or pale/pastel the colour is.

Paul

Hi Paul, thanks for your reply. I was intending to use a pot for each of the RGB channels and a 4th for the master dimmer. Also then as an option for a BI-colour lamp I could then adapt the code too maybe just 2 LED channels, one for warm white LED and one for cool white LED with a third as a master dimmer.

Im at a point where Ive got my 2 external 350ma constant 12v drivers dimmerable using the PWM pins and pots on the Uno.

Any ideas on how I could do any of that in the below sketch please? Im on a steep learning curve here, my pea brain hurts!

http://playground.arduino.cc//Main/RGBLEDPWM

Many thanks Jason

You mean this code?

// Init the Pins used for PWM
const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;
 
// Init the Pins used for 10K pots
const int redPotPin = 0;
const int greenPotPin = 1;
const int bluePotPin = 2;
 
// Init our Vars
int currentColorValueRed;
int currentColorValueGreen;
int currentColorValueBlue;
 
void setup()
{
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}
 
void loop()
{
// Read the voltage on each analog pin then scale down to 0-255 and inverting the value for common anode
  currentColorValueRed = (255 - map( analogRead(redPotPin), 0, 1024, 0, 255 ) );
  currentColorValueBlue = (255 - map( analogRead(bluePotPin), 0, 1024, 0, 255 ) );
  currentColorValueGreen = (255 - map( analogRead(greenPotPin), 0, 1024, 0, 255 ) );
 
// Write the color to each pin using PWM and the value gathered above
  analogWrite(redPin, currentColorValueRed);
  analogWrite(bluePin, currentColorValueBlue);
  analogWrite(greenPin, currentColorValueGreen);
 
}

Here is some code for hsl to rgb conversion that might work ok.

void HSL_to_RGB(int hue, int sat, int lum, int* r, int* g, int* b)
{
    int v;

    v = (lum < 128) ? (lum * (256 + sat)) >> 8 :
          (((lum + sat) << 8) - lum * sat) >> 8;
    if (v <= 0) {
        *r = *g = *b = 0;
    } else {
        int m;
        int sextant;
        int fract, vsf, mid1, mid2;

        m = lum + lum - v;
        hue *= 6;
        sextant = hue >> 8;
        fract = hue - (sextant << 8);
        vsf = v * fract * (v - m) / v >> 8;
        mid1 = m + vsf;
        mid2 = v - vsf;
        switch (sextant) {
           case 0: *r = v; *g = mid1; *b = m; break;
           case 1: *r = mid2; *g = v; *b = m; break;
           case 2: *r = m; *g = v; *b = mid1; break;
           case 3: *r = m; *g = mid2; *b = v; break;
           case 4: *r = mid1; *g = m; *b = v; break;
           case 5: *r = v; *g = m; *b = mid2; break;
        }
    }
}

I'll help you adapt your code to use it later if you like.

Yes Paul, thats the code, do you think it can be modified to include a master dimmer to dim the RGB channels once the colour is set?

Cheers J

Sorry Paul, I didn't notice your offer of help to adapt the code, mental note "must scroll down page!" :confused: That would be amazing if you could help me out. Greatly appreciated.

Thanks J

Right then. Give this a go. I have not been able to test it, but it compiles OK.

// Init the Pins used for PWM
const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;

// Init the Pins used for 10K pots
const int huePotPin = A0;
const int satPotPin = A1;
const int briPotPin = A2;

// Init our Vars
int currentColorValueRed;
int currentColorValueGreen;
int currentColorValueBlue;
int currentColorValueHue;
int currentColorValueSat;
int currentColorValueBri;

void HSL_to_RGB(int hue, int sat, int lum, int* r, int* g, int* b)
{
  int v;

  v = (lum < 128) ? (lum * (256 + sat)) >> 8 :
      (((lum + sat) << 8) - lum * sat) >> 8;
  if (v <= 0) {
    *r = *g = *b = 0;
  } else {
    int m;
    int sextant;
    int fract, vsf, mid1, mid2;

    m = lum + lum - v;
    hue *= 6;
    sextant = hue >> 8;
    fract = hue - (sextant << 8);
    vsf = v * fract * (v - m) / v >> 8;
    mid1 = m + vsf;
    mid2 = v - vsf;
    switch (sextant) {
      case 0: *r = v; *g = mid1; *b = m; break;
      case 1: *r = mid2; *g = v; *b = m; break;
      case 2: *r = m; *g = v; *b = mid1; break;
      case 3: *r = m; *g = mid2; *b = v; break;
      case 4: *r = mid1; *g = m; *b = v; break;
      case 5: *r = v; *g = m; *b = mid2; break;
    }
  }
}

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

void loop()
{
  // Read the voltage on each analog pin then scale down to 0-255
  currentColorValueHue = map( analogRead(huePotPin), 0, 1024, 0, 255 );
  currentColorValueSat = map( analogRead(satPotPin), 0, 1024, 0, 255 );
  currentColorValueBri = map( analogRead(briPotPin), 0, 1024, 0, 255 );

  HSL_to_RGB(currentColorValueHue, currentColorValueSat, currentColorValueBri,
             &currentColorValueRed, &currentColorValueBlue, &currentColorValueGreen);

  // Write the color to each pin using PWM and the value gathered above, inverting the value for common anode
  analogWrite(redPin, 255 - currentColorValueRed);
  analogWrite(bluePin, 255 - currentColorValueBlue);
  analogWrite(greenPin, 255 - currentColorValueGreen);

}

If it doesn't work, please don't be a newbie. Don't just say "it doesn't work". Tell us what it does do and what you wanted it to do.

Thanks so much Paul for your effort. I have just verified and up loaded your sketch. It doesn't work. Just to be clear I have 10k pots on each Analogue channels A0,A1,A2 and I have A single 5mm blue LED on PWM channel 11, a single 5mm Green Led on 10 and a single 5mm Red led on 9.
So in an ideal world I would like to be able to dim each of these 5mm leds separately with its own POT then once the correct colour temp is achieved use a forth Pot to dim all three to the desired level of brightness.

The Leds Im using don't need to be coloured, I may just use three different whites e.g warm white 2700k, 3200k and 5500k instead of the RGB colours.

At the moment all three leds are on and the three pots don't do anything when twisted using your sketch.

Thanks Jason

Understood Jason. I will have to put together the same circuit and figure out the problem with my code, when i have a little time.

Thanks Paul.

Doing it in the HSV color space is indeed nice. But if you want a read master effect then here you go

// Init the Pins used for PWM
const byte RedPin = 9; //byte is already big enough ;)
const byte GreenPin = 10;
const byte BluePin = 11;
 
// Init the Pins used for 10K pots
const byte RedPotPin = A0; //Use A0, A1 etc to make it clear it's the analog
const byte GreenPotPin = A1;
const byte BluePotPin = A2;
const byte MasterPotPin = A3;
 
 /* No need to be global
// Init our Vars
int currentColorValueRed;
int currentColorValueGreen;
int currentColorValueBlue;
*/
 
void setup()
{
  pinMode(RedPin, OUTPUT);
  pinMode(GreenPin, OUTPUT);
  pinMode(BluePin, OUTPUT);
}
 
void loop()
{
// Read the voltage on each analog pin then scale down to 0-255 and inverting the value for common anode
  int value = 0;
  int masterValue = analogRead(MasterPotPin) >> 2; //Make it 8-bit
 
  //Red
  value = analogRead(RedPotPin) >> 2; //make it 8-bit
  value = (value * masterValue + 127) / 255; //scale it to master
  analogWrite(RedPin, 255 - value); //invert and write
  //Green
  value = analogRead(GreenPotPin) >> 2;
  value = (value * masterValue + 127) / 255;
  analogWrite(GreenPin, 255 - value);
  //Blue
  value = analogRead(BluePotPin) >> 2;
  value = (value * masterValue + 127) / 255;
  analogWrite(BluePin, 255 - value);
}

Hi Septillion, thanks for all your effort in trying to solve my problem. Sorry for my late reply, just got in from work. Ive just uploaded your code. There seems to be a few bugs. Only PWM pin 10 LED is working. LEDs on PWM 9 & 11 aren't illuminated. Also the A0 Pot dims the pin 10 LED and A1 Pot also dims the pin 10 LED. Nothing happening with pots A2 or A3.

your thoughts,

Thanks Jason

I'm surprised any of the leds lit.

There are 3 similar errors:

analogWrite(255 - RedPin, value); //invert and write

should be:

analogWrite(RedPin, 255 - value); //invert and write

Here's attempt no. 2 of HSL to RGB:

// Init the Pins used for PWM
const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;

// Init the Pins used for 10K pots
const int huePotPin = A0;
const int satPotPin = A1;
const int briPotPin = A2;

// Init our Vars
unsigned int currentColorValueRed;
unsigned int currentColorValueGreen;
unsigned int currentColorValueBlue;
unsigned int currentColorValueHue;
unsigned int currentColorValueSat;
unsigned int currentColorValueBri;

void hsvtorgb(unsigned int *r, unsigned int *g, unsigned int *b, unsigned int h, unsigned int s, unsigned int v)
{
  unsigned int region, fpart, p, q, t;

  if (s == 0) {
    /* color is grayscale */
    *r = *g = *b = v;
    return;
  }

  /* make hue 0-5 */
  region = h / 43;
  /* find remainder part, make it from 0-255 */
  fpart = (h - (region * 43)) * 6;

  /* calculate temp vars, doing integer multiplication */
  p = (v * (255 - s)) >> 8;
  q = (v * (255 - ((s * fpart) >> 8))) >> 8;
  t = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8;

  /* assign temp vars based on color cone region */
  switch (region) {
    case 0:
      *r = v; *g = t; *b = p; break;
    case 1:
      *r = q; *g = v; *b = p; break;
    case 2:
      *r = p; *g = v; *b = t; break;
    case 3:
      *r = p; *g = q; *b = v; break;
    case 4:
      *r = t; *g = p; *b = v; break;
    default:
      *r = v; *g = p; *b = q; break;
  }

  return;
}


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

void loop()
{
  // Read the voltage on each analog pin then scale down to 0-255
  currentColorValueHue = map( analogRead(huePotPin), 0, 1024, 0, 255 );
  currentColorValueSat = map( analogRead(satPotPin), 0, 1024, 0, 255 );
  currentColorValueBri = map( analogRead(briPotPin), 0, 1024, 0, 255 );

  hsvtorgb(&currentColorValueRed, &currentColorValueBlue, &currentColorValueGreen,
           currentColorValueHue, currentColorValueSat, currentColorValueBri);

  // Write the color to each pin using PWM and the value gathered above, inverting the value for common anode
  analogWrite(redPin, 255 - currentColorValueRed);
  analogWrite(bluePin, 255 - currentColorValueBlue);
  analogWrite(greenPin, 255 - currentColorValueGreen);

}

Hi Paul, thanks for trying again, as soon as i get back from work tonight I shall try it out.

Many thanks and fingers crossed that it works!

Cheers J

Haha, yeah, Paul is right :smiley: Little f* up of me... Fixed the code (A)

Hello again Paul, thanks again for your efforts. I have just uploaded your last sketch, there seems to be progress however there seems to be a few bugs in it still.
I will try and explain whats going on if I can.

When POT A2 is on max brightness all LEDs are on full the POTs A0 & A2 don't do anything.
When POT A2 is fully dimmed all LEDs are on a low glow and POT A1 works but only with PINS 11 & 10 but pin 9 stays on a low glow. Then if POT A2 is left at the fully dimmed position and A1 on max brightness then AO pot when twisted flashes all three LEDs alternately like a disco, its kinda cool but that feature isn't really required! :o :slight_smile:

If you can figure this out you are a better man than me.

Thanks again for you time Paul.

A very confused Jason