Arduino – Fade LEDs without blocking

The simple LED fading demos are great for learning Arduino, but when you actually need your processor to be doing something — like receiving serial input or reading a sensor — fading your LEDS can get in the way.

Traditional Example

Here’s how LED fading usually works:

void loop()  { 
  analogWrite(led, brightness);    
  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ; 
  }  
  delay(30);                            
}

The problem is in that 30 millisecond delay. This stops your entire program for 30 milliseconds. If you want a slower fade, you have to set it to a higher value and a longer pause. If you’re fading multiple LEDs at different rates, the arduino ends up being paused more time than it’s processing. Which means it’s hard to do anything besides fade a bunch of LEDs.

Introducing LED Fader

LEDFader is a library I wrote while trying to individually fade 4 strips of RGB LEDs on an arduino mega — effectively controlling the PWM on 12 pins independently — while interfacing with a ultrasonic range sensor and an IR receiver.

This library works by tracking the current time adjusts the brightness of each LED accordingly without pausing.

Here’s a simple example:

#include <LEDFader.h>

// Create new LED Fader on pin 3
LEDFader led = LEDFader(3);

void setup() {
  // Fade from 0 - 255 in 3 seconds
  led.set_value(0);
  led.fade(255, 3000);
}

void loop() {
  led.update();
}

This will fade an LED attached to arduino pin 3 from 0 – 255 (full brightness) in 3 seconds without pausing your program at all.

Here’s a more complex example that will fade 6 LEDs to random intensities (between 100 – 255) at random durations (between 1 – 2 seconds):

#include <LEDFader.h>

#define LED_NUM 6

// 6 LEDs (perhaps 2 RGB LEDs)
LEDFader leds[LED_NUM] = {
  LEDFader(3),
  LEDFader(5),
  LEDFader(6),
  LEDFader(9),
  LEDFader(10),
  LEDFader(11)
};

void setup() {
}

void loop() {

  // Update all LEDs and start new fades if any are done
  for (byte i = 0; i < LED_NUM; i++) {
    LEDFader *led = &leds[i];
    led->update();

    // This LED is not fading, start a new fade
    if (led->is_fading() == false) {
      int duration = random(1000, 3000); // between 1 - 3 seconds

      // Fade Up
      if (led->get_value() == 0) {
        byte intensity = random(100, 255);
        led.fade(intensity, duration);
      }
      // Fade Down
      else {
        led.fade(0, duration);
      }
    }
  }
}

Even though this is managing 6 LEDs, the call to update() takes almost no time at all.

How it works

Each time the update() method is called, as long as a minimum time has passed since the last call, it figures out how far along the fade should be and adjust the PWM value accordingly.

For example, if we’re fading from 0 – 255 in 1 second, and for some reason the first update() call happens in 500 milliseconds, it will increase the PWM by 128, instead of 1, because we are 50% through the total duration (255 / 2 = 127.5).

Where to git it

You can grab the library from github and feel free to make contributions.