FadeLed Arduino library

This is going to be a small post. I came across the question how to fade a led. In basic it’s not that hard to do, just increment the brightness in steps every x period of time. But when you start to write code for it it starts to become more complicated. Not hard, but only more work then you might initially think. For example, how do you determined the steps and the periods you need? And do you want to fade with a constant speed or in a constant time?

To make it easy for everybody (including future me) to fade a led on an Arduino hardware PWM pin I started to write a small library. But mostly it became a practice of fully documenting a project using Doxygen, putting out releases on GitHub including main pages etc.

If you want to jump straight to the library:  septillion-git/FadeLed

I had two major specifications for the library

  • It needed to be simple to use and set parameters like time
  • I wanted a single function to update all the fading

Single function update

Let’s start with the second specification. I wanted a single function to update all the fading so I had no need to loop over every led I wanted to fade in my main code. And because it’s nice I wanted to make a nice class to do all the heavy lifting. So I went for a static function that will update all the instances. So when you create an instance of the class the constructor will add that instance to a static pile and I keep track of the number of instances.

FadeLed::FadeLed(byte pin) :_count(0),
                            _countMax(40),
                            _constTime(false){
  _pin = pin;
  
  //only add it if it fits
  if(_ledCount < FADE_LED_MAX_LED){
    _ledList[_ledCount++] = this;
  }
}

 

Now I can loop over each object in a static function. So I added an update methode to each object and made it protected so you can’t try to update just one. That’s because the static part of the class will take care of the timing. The update routine became

static void FadeLed::update(){
  unsigned int millisNow = millis();
  
  if(!_ledCount){
    return;
  }
  
  if(millisNow - _millisLast > _interval){
    //_millisLast = millisNow;
    //more accurate:
    _millisLast += _interval;
        
    //update every object
    for(byte i = 0; i < _ledCount; i++){ _ledList[i]->updateThis();
    }
  }
}

 

Ha, now I only need to call FadeLed::update() periodically no matter the amount and names of my objects.

How to fade in time

Yeah, just increase in steps. But how to calculate the time between steps etc. I went for a solution where each object is a fixed (but setable) interval. So you know in how many times that interval you want to fade. And if you take enough steps (aka small enough interval) you can get away with the fact you can’t linear map the brightness steps with the time steps. At least not in integers. I started to make a constant fade speed mapping. This meant I knew in how many steps (set by the fading time and interval) I had to fade the full range. To go from off to on this would be

newValue = _count * FADE_LED_RESOLUTION / _countMax;

With _count the current step in time and _countMax the total number of steps needed to go from 0 to max.

This is fine if you only want to go from 0 to max  but how about in between? Instead of saving the _count and go from there I interpolated it. You can also just start at the starting brightness and just add a new fade to that value until you reach the level you want.

newVal = _startVal + _count * FADE_LED_RESOLUTION / _countMax

And just by subtracting I can fade down.

newVal = _startVal - _count * FADE_LED_RESOLUTION / _countMax;

Nice, all done and all in integer math. I added some bit’s and pieces to allow for over/under flowing the variable and for overshooting the setValue. Otherwise, if it wanted to take a step of 2 in brightness and the set value was only 1 step away it would just step over and keep on fading and never exactly reach the set value.

Later on I also made the option to do a constant fade time fading. So each fade would take the same amount of time and would scale the steps accordingly.

newVal = _startVal + _count * (_setVal - _startVal) / _countMax;

So instead of using the whole resolution I now used the difference in brightness steps.

Documentation

After that became a process of documentation. I was not bad at documenting my code but I liked the explore files generated by Doxygen. You can see nicely what every method and class (if I would have had multiple). I opted for the QT style of documentation in the header file to keep it nice and compact. And to make the documentation look nice I started to dive into Markdown. Not that hard but it’s a bit like another language you need to remember.

Because a good Arduino library isn’t complete without some examples I wrote some heavy commented examples to show some interesting parts of the library.

And now I had a decent library with full documentation the landing page on GitHub was still pretty empty. Even when a person would go there is would need to dive into the documentation to see the possibilities of the code. So I started to make a nice README.md going over the possibilities of the library, basic use and a basic FAQ (which I will expand if I run into common mistakes/questions). After documenting in Markdown it became pretty easy to do. Especially because the online GitHub editor let’s you switch to a “live” preview. And now I had a nice README.md I could also use that as the Main Page of the full Doxygen documentation by setting USE_MDFILE_AS_MAINPAGE to the README.md. Nice!

Converting a part of the README to Media Wiki so I could add it to the Arduino Playground was a different story. Pff, must say, Wiki is great but Markdown is a whole lot easier!

Leave a Comment

Your email address will not be published. Required fields are marked *