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!

6 thoughts on “FadeLed Arduino library

  1. Hi Timo,
    First let me thank you for this library, much effort you’ve put here i believe, everything is understandable for newbies like me.
    I’m controlling 3 Led strips, creating many patterns, everything’s working good.
    I need a hint on how to create the more complex pattern if you can:
    Led 1 goes down from full power(100 pwm) to zero, and when it’s halfway through (50), led2 start powering up to 100 –>Wait 1 sec –> led 2 goes down to 0, and when halfway led3 starts powerin up.
    Problem is : How can i code the 1 sec Wait properly without using delay?

    Thanks again

    1. Hi Anthony,

      My pleasure :)

      The wait is pretty easy to do with millis(). Have a look at Blink without delay on the Arduino site.

      And I think everything is easier if you build some sort of state machine by saving which led needs to change next. And you can check the current brightness with .getCurrent(). So you can check it like

      if(nextLed == 2 && led[1].getCurrent() < 50){
        led[2].on();
      }
      

      Hope this all is useful?

      Timo

      1. Thank you Timo,

        Yes, i learnt how to use millis(); i thought there must be a way to “Pause” what FadeLed is doing while everything else is running. By everything else, i mean the ability to change the patterns (I am using an interrupt with a button used to change between patterns). Anyway, need to test code, then i could show this to you.

        Many thanks

        1. Hi Anthony,
          What do you mean by pause FadeLed? If you mean to stop fading, simply call led.stop(). If you mean, do other stuff in the mean time, then you can just do so. FadeLed is written non-blocking so all calls to FadeLed don’t take long. As long as you call FadeLed::update() regularly (aka, don’t use blocking code like delay() anywhere in your program) then you can just do what you want. And f you want to interact with FadeLed just check with led.done() and led.getCurrent() when to interact with FadeLed.

          And like I said, don’t use delay() anywhere in the code. That’s always a bad idea. delay() is like sitting in the corner and really do nothing at all, even if your house burns down you will just wait until the delay is over.

          Also, using a interrupt for a simple button is just over the top. That’s not what a interrupt is for. An interrupt is for fast (aka, millisecond rang) signals. For a button, just poll it. A library like Bounce2 can do all the heavy lifting for you. One of the examples even uses Bounce2.

          Timo

          1. Hi again Timo,

            Yes by pause i mean the different leds should “Freeze” from what they’re doing, so a little bit of code using .getCurrent() should do :)

            I got your point concerning the interrupts, i admit i got better reactivity compared to debouncing, (testing with a mechanical button for now, future will use a capacitive button), . Thanks a lot !

          2. To stop FadeLed led’s dead in there tracks you can call .stop() and they will stop fading and stay at there current level. But for a sequence using .getCurrent() is indeed more useful.

            And even a button connected to an interrupt needs debouncing. And because you see every transient that will take more process power then when you poll ;) If you use a IC for the capacitive button then you probably don’t need debouncing because the IC already does that for you. But again, no need for an interrupt.

            And out of curiosity, what are you making? When do I see pictures? 0:-)

            Timo

Leave a Comment

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