How to dim an LED linearly with an Arduino?

I have made myself an RGB LED nametag and want to dim its RGB LED, but with normal dimming, the dimming doesn´t seem to be linear.

To control it, I use a default LED strip remote control like this one:
image

The top left buttons are for dimming. In my code, I have a variable called dimmingFactor which can have values between 1 and 10. So how can I correctly dim the RGB LED linearly without changing the given color?

show

Read this

2 Likes

@jim-p I already tried it with this table, but it doesnt seem to work any better. But I'm also unsjre if i have implemented it correctly with my dimmingFactor with values between 1 and 10. Could you give me a piece of example code for dimming with the table?

Do you mean interger values only 1,2,3,4,5,6,7,8,9,10.

Post your current sketch to see how we can help.

@paulpaulson @kolaha Heres the code. The intensity always has a value between 1 and 10, where 1 is the lowest and 10 is the highest. And with this code, the LED even turns off if the intensity is too low.

const uint8_t gammaCorrectionTable[] = {
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
    2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
    5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
   10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
   17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
   25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
   37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
   51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
   69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
   90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
  115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
  144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
  177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
  215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };

void RGBLED::setColor(byte r, byte g, byte b) {
  if(!isOn()) {
    return;
  }
  
  int dimFactor = 11 - intensity;
  int dimmedRed = gammaCorrectionTable[r / dimFactor];
  int dimmedGreen = gammaCorrectionTable[g / dimFactor];
  int dimmedBlue = gammaCorrectionTable[b / dimFactor];

  analogWrite(rPin, dimmedRed);
  analogWrite(gPin, dimmedGreen);
  analogWrite(bPin, dimmedBlue);

  currentRValue = r;
  currentGValue = g;
  currentBValue = b;
}

yes

Try this:

index = 30+(intensity-1)*25)
PWM_val = gammaCorrectionTable[index]
analogWrite(xPin,PWM_val)

@jim-p Seems to work, thank you :slight_smile: But why does it work?

@jim-p and actually, this only works for a single led. But i have a rgb led and somehow have to consider the r, g and b values provided by the arguments of setColor

Check the (datasheet) power usage of LEDs (red, blue and green). Higher power consumption will show a greater effect with decreasing PWM duty cycle. Maybe use an LDR directly "on top" of each LED, in a black box, to measure the brightness (compare brightness?). The results should help with the different dimming-step levels.

Do the same thing 3 times, once for each color.

why does it work?

You have 10 intensity levels and the array size is 256.
256/10=25.6, so I incremented the index by 25

If I start at 30 rather than 25, the last index will be 255

@jim-p but how do i take the original colour value and the intensity in mind? Because that are two values. is it e.g. for red only r/(11-intensity)?

@jim-p and is there a reason you add 30 instead of 5 and subtract 1 from the intensity?

They probably are very close to linear. It's our human eyes that are not linear!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.