Arduino sketch to fade a LED using PWM and a timer.

In the video of an Automatic Fading Kitchen Light we saw that we can slowly fade a LED strip on and off, controlled by an Arduino.

This video details one of the elements in the software: how to fade a LED. To do that we’ll use a millis() timer and analogWrite(pin,value) to generate Pulse Width Modulation.

To experiment with the code, we need to build this little circuit with a LED and a resistor. (Click the image to see a larger version.)



Light Emitting Diode (LED)

If you’rLEDe not familiar with LEDs yet, this article is a great read.

Current flows through a LED from + (long wire) to – (short wire). A LED acts as an electrical short, which means we can’t connect it directly to an Arduino output or chances are we damage the LED or the output or both. We need to limit the current through the LED. To accomplish that, we use a resistor in series. What value do we need?

Resistor and Ohm’s law to limit the current

Most miniature LEDs will light up bright with a current of 10 to 20 mA. The LED has a voltage drop, which depends on the LED’s color. For a red LED it is about 1.8V (see the table in this article). This means the voltage over the resistor is 5 – 1.8 = 3.2V. We use Ohm’s law, I = V / R, to calculate the resistor. The formula tells us that with 3.2V, a resistor of 220 ohm will give us  a current of around 15mA. Click these links for more info on resistors and on Ohm’s law.

analogWrite(pin,value), Pulse Width Modulation

OK, our LED will light when the Arduino output is HIGH, 5V. Now … how to fade it? For this we use the Arduino instruction called analogWrite(pin,value). This name is misleading, the Arduino does not have a digital to analog converter. In stead it uses a method called Pulse Width Modulation: the output is alternated between LOW and HIGH at a high frequency. If the pulse width is say 30%, the LED will burn 30% of the time and the other 70% it is off. Because our eyes + brain are too slow to see the switching frequency we perceive this as a lower brightness.

Fade: slowly increase or decrease the PWM value using a timer

So … when we set the PWM amount to a value below 100%, the LED will dim. The Arduino does not use percentages 0-100, it uses values between 0-255. This means we have 255 different brightness steps. To slowly fade the LED on, we have to gradually increase the PWM value. To fade it off we gradually decrease the PWM value. This is task is performed with a timer, using the Arduino’s millis() instruction.

TheArduino software sketch

The code can be downloaded here. After unzipping, move the folder to your Arduino sketches folder.

Configuration values that you can change to your liking

#define OUTPUT_PIN 3 // PWM pins are marked ~ (3,5,6,9,10,11)
#define START_FADE_PIN A5 // input pin, LOW: fade on, HIGH: fade off
#define MAX_BRIGHTNESS 200 // max value: 255
#define MIN_BRIGHTNESS 1 // min value: 0
#define FADE_INTERVAL 50 // ms between fade steps, smaller is faster

I always use capitals with defines to easily distinguish then from variables, for which I use lower case. Note that not all Arduino pins have PWM capability, only the pins that have a ~ symbol next to them on the PCB:  pins 3,9,10,11 have a PWM frequncy of 490Hz and 5,6 run at 980 Hz.

Declaration of varianbles

byte setpoint; // value to fade towards
byte value; // current value
unsigned long timeforfadestep; // fade step timer

Setup, which runs only once

void setup() {

Here we initialize the input pin that we use as on/off switch. The INPUT_PULLUP takes care that an internal resistor connects the pin to 5V, so it won’t float at an unknown state if we leave the input open. The Arduino will read a HIGH when not connected and our switch, that is connected to GND, pulls it down to LOW.

Note that the output pin is not initialized, this is not needed with analogWrite(pin,value).

Loop, which runs indefinitely

void loop() {
  if (!digitalRead(START_FADE_PIN)) setpoint = MAX_BRIGHTNESS;
  else setpoint = MIN_BRIGHTNESS;

  if (millis() > timeforfadestep) {
    timeforfadestep = millis() + (unsigned long)FADE_INTERVAL;
    if (value < setpoint) value++;     if (value > setpoint) value--;
    analogWrite(OUTPUT_PIN, value);

In the loop we first read the ‘start fade’ input pin, dependent on which we set the PWM setpoint to the MAX or MIN value we configured.

Then we check if it is time to change the PWM value. If not we skip the rest. If it’s time, we first set the timer to the next time. Then we check if the setpoint is already reached … if not, the PWM value is increased or decreased. Finally the (new) PWM value is written to the output pin.

Have fun experimenting

That’s all there is to it … we now have a fading LED. We can experiment some with different interval times to see what effect slower and faster fades have. Note that our eyes are more sensitive at lower light levels, which means we will easier see the brightness changes at the lower values than at the higher ones. Slower fades will show this non linearity of our eyes.

The software of the kitchen lights uses exactly this fade principle, surrounded by some more code to change between the different states the kitchen lighting can be in, to react to the PIR sensor input and to read out the rotary encoder and switch. More on those in later videos.

A video will be here soon.


— 0 —

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s