Jonathan Thomson's web journal

A smooth breathing effect while using FastLED’s power management February 6, 2019

Filed under: Electronics — jethomson @ 9:01 pm
Tags: , , , ,

If using a FastLED function (e.g. FastLED.setMaxPowerInVoltsAndMilliamps()) to manage how much power your LEDs use FastLED limits the maximum brightness that can be set to a value that does not exceed the requested power draw. So if FastLED determines your power limited maximum brightness is M then calling setBrightness() with a value greater than M will result in FastLED setting the brightness to exactly M.

A breathing effect ramps the brightness up until it reaches the maximum brightness then ramps the brightness back down to a minimum brightness then starts the whole cycle over again. A naive approach would be to use a triangle wave that goes from 0 to 255 and back down to 0 as the input for setBrightness(), but if the power limited maximum brightness M is less than 255 then the brightness will plateau at M, and the brightness will remain fixed until the triangle wave input falls below M again. My breathing() function achieves a continually changing brightness by setting the peak of the triangle wave to M. However, M changes based on the number of LEDs currently lit and their colors, so breathing() recalculates M before setting a new brightness value.

Snippet from the breathing code example available on GitHub:

void breathing(uint16_t interval) {
    const uint8_t min_brightness = 2;
    static uint8_t delta = 0; // goes up to 255 then overflows back to 0

    static uint32_t pm = 0; // previous millis
    if ( (millis() - pm) > interval ) {
        pm = millis();

        // for the LEDs in the current state setting the brightness higher than max_brightness will not actually increase the brightness displayed
        uint8_t max_brightness = calculate_max_brightness_for_power_vmA(leds, NUM_LEDS, 255, LED_STRIP_VOLTAGE, LED_STRIP_MILLIAMPS);
        uint8_t b = scale8(triwave8(delta), max_brightness-min_brightness)+min_brightness;



You may have read that you need to apply gamma correction or convert luminance to brightness so that the LEDs have a linear response. That is what I tried first, I never had success with that approach because of the clamping effect FastLED’s power management. After I figured out I had to determine the maximum brightness possible under power management conditions I found that the output of the LEDs looked linear to me using just a triangle wave, so I didn’t try to apply a correction curve. A point that confuses me is whether setBrightness() is actually controlling the brightness or the luminance. I couldn’t find a correction curve being applied when looking through the FastLED code.


The function calculate_max_brightness_for_power_mW returns the same value as calculate_max_brightness_for_power_vmA so I’m mentioning it in this write-up to help people find info on it too.
My example breathing code on GitHub
FastLED’s notes on power management
Power management functions documentation
LED Brightness to your eye, Gamma correction – No!


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