I'm building a keyboard light with AVR micro controller.
There are two buttons, BRIGHT and DIM, and a white LED.
The LED isn't really linear, so I need to use a logarithmic scale (increase brightness faster in higher values, and use tiny steps in lower).
To do that, I adjust the delay between 1 is added or subtracted to/from the PWM compare match control register.
while (1) {
if (btn_high() && OCR0A < 255) OCR0A += 1;
if (btn_low() && OCR0A > 0) OCR0A -= 1;
if (OCR0A < 25)
_delay_ms(30);
else if (OCR0A < 50)
_delay_ms(25);
else if (OCR0A < 128)
_delay_ms(17);
else
_delay_ms(5);
}
It works nice, but there's a visible step when it goes from one speed to another. It'd be much better if the delay adjusted smoothly.
Is there some simple formula I can use? It must not contain division, modulo, sqrt, log or any other advanced math. I can use multiplication, add, sub, and bit operations. Also, I can't use float in it.
Or perhaps just some kind of lookup table? I'm not really happy with adding more branches to this if-else mess.
The scaling isn't quite logarithmic so simply using log()
isn't enough.
I have tackled this problem in the past by using a LUT with 18 entries and going an entire step at a time (i.e. the control variable varies from 0 to 17 and then is shoved through the LUT), but if finer control is required then having 52 or more is certainly doable. Make sure to put it in flash so that it doesn't consume any SRAM though.
Edit by MightyPork
Here's arrays I used in the end - obtained from the original array by linear interpolation.
Basic
#define BRIGHTNESS_LEN 60
const uint8_t BRIGHTNESS[] PROGMEM = {
0, 1, 1, 2, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 9,
10, 11, 13, 14, 16, 18, 21, 24, 27, 30, 32,
35, 38, 40, 42, 45, 48, 50, 54, 58, 61, 65,
69, 72, 76, 80, 85, 90, 95, 100, 106, 112,
119, 125, 134, 142, 151, 160, 170, 180, 190,
200, 214, 228, 241, 255
};
Smoother
#define BRIGHTNESS_LEN 121
const uint8_t BRIGHTNESS[] PROGMEM = {
0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5,
6, 6, 6, 7, 7, 8, 8, 8, 9, 10, 10, 10, 11, 12, 13, 14, 14,
15, 16, 17, 18, 20, 21, 22, 24, 26, 27, 28, 30, 31, 32, 34,
35, 36, 38, 39, 40, 41, 42, 44, 45, 46, 48, 49, 50, 52, 54,
56, 58, 59, 61, 63, 65, 67, 69, 71, 72, 74, 76, 78, 80, 82,
85, 88, 90, 92, 95, 98, 100, 103, 106, 109, 112, 116, 119,
122, 125, 129, 134, 138, 142, 147, 151, 156, 160, 165, 170,
175, 180, 185, 190, 195, 200, 207, 214, 221, 228, 234, 241,
248, 255
};