Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!




Fade one color to a...
 
Share:
Notifications
Clear all

Fade one color to another color Wemos / NodeMCU

9 Posts
2 Users
0 Likes
40 Views
Joined: 53 years ago
Posts: 0
Topic starter  

Hi,
I am looking for a way to fade from one color eg.(255,120,0) to another color (0,200,255) in a given time eg. 30 sec. using FastLED and Wemos D1 Mini or NodeMCU

Thanks in advance


   
ReplyQuote
Topic Tags
 Hans
(@hans)
Famed Member Admin
Joined: 10 years ago
Posts: 2407
 

You're looking at two "challenges" ...

First one is fading from one color to another this can be surprisingly challenging (depending on how "accurate" you want the fade to be). 
I had to look for a function as well, and found one here:

#include <FastLED.h>

// fadeTowardColor example code.
//
// Sample code that includes a function for fading one RGB color toward a target RGB color
// Also includes a function for fading a whole array of pixels toward a given color
//
// Both of these functions _modify_ the existing color, in place.
//
// All fades are done in RGB color space.
//
// Mark Kriegsman
// December 2016


#define NUM_LEDS 50
#define LED_PIN 3
#define LED_TYPE WS2811
#define COLOR_ORDER GRB

CRGB leds[NUM_LEDS];

void setup() {
  delay(3000); // sanity delay
  FastLED.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,NUM_LEDS);
}




// Helper function that blends one uint8_t toward another by a given amount
void nblendU8TowardU8( uint8_t& cur, const uint8_t target, uint8_t amount)
{
  if( cur == target) return;
  
  if( cur < target ) {
    uint8_t delta = target - cur;
    delta = scale8_video( delta, amount);
    cur += delta;
  } else {
    uint8_t delta = cur - target;
    delta = scale8_video( delta, amount);
    cur -= delta;
  }
}

// Blend one CRGB color toward another CRGB color by a given amount.
// Blending is linear, and done in the RGB color space.
// This function modifies 'cur' in place.
CRGB fadeTowardColor( CRGB& cur, const CRGB& target, uint8_t amount)
{
  nblendU8TowardU8( cur.red,   target.red,   amount);
  nblendU8TowardU8( cur.green, target.green, amount);
  nblendU8TowardU8( cur.blue,  target.blue,  amount);
  return cur;
}

// Fade an entire array of CRGBs toward a given background color by a given amount
// This function modifies the pixel array in place.
void fadeTowardColor( CRGB* L, uint16_t N, const CRGB& bgColor, uint8_t fadeAmount)
{
  for( uint16_t i = 0; i < N; i++) {
    fadeTowardColor( L[i], bgColor, fadeAmount);
  }
}


void loop() 
{
  CRGB bgColor( 0, 15, 2); // pine green ?
  
  // fade all existing pixels toward bgColor by "5" (out of 255)
  fadeTowardColor( leds, NUM_LEDS, bgColor, 5);

  // periodically set random pixel to a random color, to show the fading
  EVERY_N_MILLISECONDS( 300 ) {
    uint16_t pos = random16( NUM_LEDS);
    CRGB color = CHSV( random8(), 255, 255);
    leds[ pos ] = color;
  }

  FastLED.show();
  FastLED.delay(10);
}

Looking at this code, especially the "void loop()"; we see that the developer uses "fadeTowardColor()" to fade from one color to another with steps of "5" (bigger steps = faster and less accurate).

You'll now have to tinker a little to see where we want to add some "delay()" statements to make sure the fade doesn't go too fast and staying in your 30 seconds window.

Hope this helps to get you started, and apologies for the late reply 😁 


   
ReplyQuote
Joined: 53 years ago
Posts: 0
Topic starter  

Thank you Hans, I am looking forward to try out your code. Hope I understand the code although C++ isn’t my favorite programming language.


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 10 years ago
Posts: 2407
 

Haha, yeah, it's not my favorite either ... 

Feel free to post questions 😊 

 

p.s. I do not think you'll need it, but just in case: I did write a small beginners course specifically for the Arduino - maybe its useful.


   
ReplyQuote
Joined: 53 years ago
Posts: 0
Topic starter  

Thank you for the Arduino Programming for Beginners. Maybe I can use some tips from it 🙂 

Regarding your code from above. It is working very well and I am implementing it in my Wemos project.
I havent fully testet it with my other code yet but I am confident that it wil work just fine.
One thing that surprises me is that I can't move the fadeTowardColor to a new tab. I get an error ('CRGB' does not name a type )


   
ReplyQuote


 Hans
(@hans)
Famed Member Admin
Joined: 10 years ago
Posts: 2407
 

@henrikl2000 Not sure what you mean with moving fadeTowardColor to a new tab? You mean copy the code into your code?

Can you post the offending code and full error message?

Note: CRGB is defined in the FastLED library, so make sure it is in one of the #include lines.


   
ReplyQuote
Joined: 53 years ago
Posts: 0
Topic starter  

I just tried it again this time no error. Hmm ....


   
ReplyQuote
Joined: 53 years ago
Posts: 0
Topic starter  

I don’t know if I should start a new thread or just post it here.

I have a problem which I am afraid I need your help to solve.

If I fade from one color to two colors no problem, but if I fade from 2 colors to 2 different colors the leds flickers. I guess it something to do with the function CRGB fadeTowardColor( CRGB& cur, const CRGB& target, uint8_t amount)

Would you please take a look.

Thank you in advance

 

void loop() {
  if (update1Color == true) {
    setBright(brightness);
    setAll(colorRed, colorGreen, colorBlue);
  }
  if (update2Color == true) {
    setBright(brightness);
    set2Color(colorRed, colorGreen, colorBlue, colorRed2, colorGreen2, colorBlue2);
  }
  if (updateFadeColors1 == true) {
    fadeTo(fadeRed, fadeGreen, fadeBlue, fadeDelay, fadeAmount);
  }

  if (updateFadeColors2 == true) {
    fadeTo2(fadeRed, fadeGreen, fadeBlue, fadeRed2, fadeGreen2, fadeBlue2, fadeDelay, fadeAmount);
  }
  
  // 1 farve
  if ((leds[1].r == fadeRed) && (leds[1].g == fadeGreen) && (leds[1].b == fadeBlue)) {
    updateFadeColors1 = false;
  }
  
  // 2 farver
  if ((leds[0].r == fadeRed) && (leds[0].g == fadeGreen) && (leds[0].b == fadeBlue) && (leds[1].r == fadeRed2) && (leds[1].g == fadeGreen2) && (leds[1].b == fadeBlue2)) {
    updateFadeColors2 = false;
  }
}

void nblendU8TowardU8( uint8_t& cur, const uint8_t target, uint8_t amount)
{
  if( cur == target) return;
  
  if( cur < target ) {
    uint8_t delta = target - cur;
    delta = scale8_video( delta, amount);
    cur += delta;
  } else {
    uint8_t delta = cur - target;
    delta = scale8_video( delta, amount);
    cur -= delta;
  }
}

// Blend one CRGB color toward another CRGB color by a given amount.
// Blending is linear, and done in the RGB color space.
// This function modifies 'cur' in place.
CRGB fadeTowardColor( CRGB& cur, const CRGB& target, uint8_t amount)
{
  nblendU8TowardU8( cur.red,   target.red,   amount);
  nblendU8TowardU8( cur.green, target.green, amount);
  nblendU8TowardU8( cur.blue,  target.blue,  amount);
  return cur;
}

// Fade an entire array of CRGBs toward a given background color by a given amount
// This function modifies the pixel array in place.
void fadeTowardColor( CRGB* L, uint16_t N, const CRGB& bgColor, uint8_t fadeAmount)
{
  for( uint16_t i = 0; i < N; i++) {
    fadeTowardColor( L[i], bgColor, fadeAmount);
  }
}

void fadeTowardColor2( CRGB* L, uint16_t N, const CRGB& bgColor, const CRGB& bgColor2, uint8_t fadeAmount)
{
  for( uint16_t i = 0; i < N; i++) {
    if ((i % 2) == 0) {
      fadeTowardColor( L[i], bgColor, fadeAmount);
    } else {
      fadeTowardColor( L[i], bgColor2, fadeAmount);
    }
  }
}

void fadeTo(byte toRed, byte toGreen, byte toBlue, int fadeDelay, byte fadeAmount) {       //byte red, byte green, byte blue, byte toRed, byte toGreen, byte toBlue, int fadeDelay, byte fadeAmount) {
  // Syntax: toRed, toGreen, toBlue, fade delay, how much to fade)
    
  CRGB bgColor(toRed, toGreen , toBlue);
  fadeTowardColor( leds, NUM_LEDS, bgColor, fadeAmount);

  FastLED.show();
  FastLED.delay(fadeDelay);  
}

void fadeTo2(byte toRed, byte toGreen, byte toBlue, byte toRed2, byte toGreen2, byte toBlue2, int fadeDelay, byte fadeAmount) {       //byte red, byte green, byte blue, byte toRed, byte toGreen, byte toBlue, int fadeDelay, byte fadeAmount) {
  // Syntax: toRed, toGreen, toBlue, toRed2, toGreen2, toBlue2, fade delay, how much to fade)
    
  CRGB bgColor(toRed, toGreen , toBlue);
  CRGB bgColor2(toRed2, toGreen2, toBlue2);
  fadeTowardColor2( leds, NUM_LEDS, bgColor, bgColor2, fadeAmount);

  FastLED.show();
  FastLED.delay(fadeDelay);  
}

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 10 years ago
Posts: 2407
 

I presume it flickers when calling fadeTo2? (sorry - took me quite a bit of reading to figure out what you meant and what the code may be doing)

Not sure why it would flicker, but I can image there is room for improvement to speed up things.

A few ideas ...

To reduce confusion when reading code maybe it is better we change the name of this functions.
The original fade-to-color developer used the same names as the other function, which is not incorrect, but I found this to be confusing at times when reading code.

So let's change this function

CRGB fadeTowardColor( CRGB& cur, const CRGB& target, uint8_t amount)
{
  nblendU8TowardU8( cur.red,   target.red,   amount);
  nblendU8TowardU8( cur.green, target.green, amount);
  nblendU8TowardU8( cur.blue,  target.blue,  amount);
  return cur;
}

to maybe this (or whatever name you prefer):

CRGB fadeOneColor( CRGB& cur, const CRGB& target, uint8_t amount)
{
  nblendU8TowardU8( cur.red,   target.red,   amount);
  nblendU8TowardU8( cur.green, target.green, amount);
  nblendU8TowardU8( cur.blue,  target.blue,  amount);
  return cur;
}

You will have to update these two functions (fadeTowardColor and fadeTowardColor2) to this, so it uses the new name:

// Fade an entire array of CRGBs toward a given background color by a given amount
// This function modifies the pixel array in place.
void fadeTowardColor( CRGB* L, uint16_t N, const CRGB& bgColor, uint8_t fadeAmount)
{
  for( uint16_t i = 0; i < N; i++) {
    fadeOneColor( L[i], bgColor, fadeAmount);
  }
}

void fadeTowardColor2( CRGB* L, uint16_t N, const CRGB& bgColor, const CRGB& bgColor2, uint8_t fadeAmount)
{
  for( uint16_t i = 0; i < N; i++) {
    if ((i % 2) == 0) {
      fadeOneColor( L[i], bgColor, fadeAmount);
    } else {
      fadeOneColor( L[i], bgColor2, fadeAmount);
    }
  }
}

 

 

Next, the entire strip is either one or two colors, so instead of recalculating the new color for each individual LED, we could calculate the new color only one time and copy it to the other LEDs. This would potentially be significantly faster.

Maybe something like this (calculate once, and copy it for all LEDs);

// Fade an entire array of CRGBs toward a given background color by a given amount
// This function modifies the pixel array in place.
void fadeTowardColor( CRGB* L, uint16_t N, const CRGB& bgColor, uint8_t fadeAmount)
{
  fadeOneColor( L[0], bgColor, fadeAmount); // first LED - calc new color

  for( uint16_t i = 0; i < N; i++) {
     L[i] = L[0]; // copy color from first LED
  }
}

void fadeTowardColor2( CRGB* L, uint16_t N, const CRGB& bgColor, const CRGB& bgColor2, uint8_t fadeAmount)
{
  fadeOneColor( L[0], bgColor, fadeAmount); // Calc new color first LED
  fadeOneColor( L[1], bgColor, fadeAmount); // and second LED

  for( uint16_t i = 0; i < N; i++) {
    if ((i % 2) == 0) {
      L[i] = L[0];  // copy 1st LED color
    } else {
      L[i] = L[1]; // copy seconde LED color
    }
  }
}

 

Next, I'd strip your code (in a copy of course) to just the 2 color fade related code ... just to make sure we get that to work first.
So remove as much as you can, just to stick to the barebones 2 color fade.


   
ReplyQuote

Like what you see and you'd like to help out? 

The best way to help is of course by assisting others with their questions here in the forum, but you can also help us out in other ways:

- Do your shopping at Amazon, it will not cost you anything extra but may generate a small commission for us,
- send a cup of coffee through PayPal ($5, $10, $20, or custom amount),
- become a Patreon,
- donate BitCoin (BTC), or BitCoinCash (BCH).

Share: