PWM Exponential LED Fading on Arduino (or other platforms)
For a project I am working on I needed to dim a LED strip light using the PWM (pulse width modulated) outputs on an Arduino. The most straightforward way to do this would have been to linearly vary the output frequency. Shown below in an Arduino sketch:
However the light outputted by the LED does not scale linearly. If you were to use the very scientific metric of “Perceived Brightness” vs. time for the above sketch it would look something like the below for a linear PWM signal:
To the naked eye this looks like an exponential brightening; big jump in brightness at the start then no perceptible change for the last 7 seconds.
In order to make the LED look like it is fading linearly we need to set the input PWM signal to counteract the natural exponential nature of the LED.
From trial and error I’ve found the most pleasing input curve to use is generated by:
Where x is the step (i.e. step 56 of the fade), y is the PWM value (0-255) and r is a factor that is calculated based on the number of steps and the required output.
r is calculated such that 2m/r=p. Where p is the maximum value of the PWM cycle (255 in Arduinos) and m is the number of steps the LED will fade over.
We can rearrange the equation so that it is expressed in terms of r:
You can generate this in Arduino code using:
This will give you a nice natural fading of the light over as long and as many steps as you like.
Noticed a typo or error in this post? Fork and edit it on Github!