
The apparent brightness of an LED does not rise in a linear fashion as voltage or current is increased. Here is a simple lookup array that provides 32 steps of brightness by substituting appropriate PWM values.
int pwmActual[] = {
0, 1, 2, 3, 4, 5, 7, 9,
12, 15, 18, 22, 27, 32, 37, 44,
50, 58, 66, 75, 85, 96, 107, 120,
133, 147, 163, 179, 196, 215, 234, 255
};
Full example code:
// accurate brightness to the human eye. 0-31. 31=100% brightness.
int pwmActual[] = {
0, 1, 2, 3, 4, 5, 7, 9,
12, 15, 18, 22, 27, 32, 37, 44,
50, 58, 66, 75, 85, 96, 107, 120,
133, 147, 163, 179, 196, 215, 234, 255
};
int brightness = 0;
int fadeAmount = 1;
void setup() {
pinMode(9, OUTPUT);
}
void loop() {
analogWrite(9, pwmActual[brightness]);
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
// reverse the direction of the fading at the ends of the fade:
if (brightness == 0 || brightness == 31) {
fadeAmount = -fadeAmount ;
}
delay(100);
}
Here is the best way to do it using PROGMEM if you need the quickest possible processor execution:
#include
#define CIELPWM(a) (pgm_read_word_near(CIEL8 + a)) // CIE Lightness lookup table function
prog_uint8_t CIEL8[] PROGMEM = {
0, 1, 2, 3, 4, 5, 7, 9,
12, 15, 18, 22, 27, 32, 37, 44,
50, 58, 66, 75, 85, 96, 107, 120,
133, 147, 163, 179, 196, 215, 234, 255
};
…
analogWrite(9, CIELPWM(brightness));
Getting Smoother Output:
You can smooth the steps between each level of brightness using a simple resistor-capacitor filter. You can make lookup tables with greater resolution but there are then some repeated values. You can also get higher resolution PWM output with an external chip such as the TLC5947 or TLC 59711.
Leave a Reply