Our eyes don’t see light as linear. Instead, to see it “one step brighter”, it
has to become 2x as bright. And the next x2 increment will be seen as another
similar step. In other words, our eyes see on a logarithmic scale. Or
exponential, depending on how you look at it.
For my electronics projects I often have the need to take the linear position
of a potentiometer, and translate it to an exponential value I can use to PWM
some LEDs. I had some Python scripts scattered around to do this, but figured it
was more convenient to have a web-based tool instead. So, here it is!
The number of required steps is too large, causing the max value to be out of range of the number of bits.
Either reduce the number of steps or increase the number of bits.
// ((pwmNumBits))-bit PWM light map.
// total steps : ((numSteps))
// linear steps: ((numLinearSteps))
// inverted : ((inverted))
static const ((dataType)) light_map_((pwmNumBits))bit[] = {
((lightMapString))
};
static const uint8_t light_map_((pwmNumBits))bit_max_index = ((numSteps-1));
/**
* Calculate the PWM value for a linear input value between 0 and 1.
*/
((dataType)) light_map_lookup(const float value /* range [0, 1] */)
{
if (value <= 0.0f) {
return light_map_((pwmNumBits))bit[0];
}
const float index = value * light_map_((pwmNumBits))bit_max_index;
const uint8_t lower_index = index;
if (lower_index >= light_map_((pwmNumBits))bit_max_index) {
return light_map_((pwmNumBits))bit[light_map_((pwmNumBits))bit_max_index];
}
const ((dataType)) lower_light_map_value = light_map_((pwmNumBits))bit[lower_index];
const ((dataType)) upper_light_map_value = light_map_((pwmNumBits))bit[lower_index + 1];
const float alpha = index - lower_index;
const float interpolated = (1.0f - alpha) * lower_light_map_value +
alpha * upper_light_map_value;
return interpolated + 0.5f;
}
The above code is in C, which I use for my microcontrollers. You can use the
above code in your project as-is, or just copy the values and write the rest
yourself.
This tool is also available as Python script, which you can use offline. See my
blog post
PWM and Visual Brightness for info on that. It also has some
more info on how to use the generated code.