Pages: [1]   Go Down
Author Topic: RGB strip high end crossfading for improving your project (edited)  (Read 784 times)
0 Members and 1 Guest are viewing this topic.
Europe / Germany
Offline Offline
Sr. Member
****
Karma: 11
Posts: 334
keep it simple
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I proudly present a fine working concept, how to fade very smoothly (and fast, if you like) between 2 different contents on an adressable RGB strip. It softens the difference between 2  frames by calculating a crossfade - with as many frames in between as you wish - for example 64 frames with 10 ms delay works pretty fine to smooth dynamic animations.

You can use it for all kinds of projects based on the FastSPI library: RGB strips, 2D and 3D Matrix stuff, whatever.

You just use your own code - but instead of switching between the frames you crossfade them.

Instead of writing directly into the array, FastSPI provides, you write your content into the
Code:
byte new_frame[NUM_LEDS][3];
array.

When ready, you save the current picture by calling
Code:
copy_led_array_to_old_frame();
and then crossfade from the old to the new picture with
Code:
fade_from_old_to_new_frame(128,0);

The first number defines the the number of steps, the second the delay between them. Because in general you waste the most time with writing to the PWM chips, you decrease the delay between the frames when working with longer strips, if you ended at 0 and need it even faster you decrease the numer of steps. Even with just 16 steps it appears way better, than with only brutal switching between different colors...

The little demonstartion program shows a fade from a linear colorchange to another one to a random dot pattern and back. There could be your content or formula...it crossfades to anything you placed in the new_frame array.

Explore it, play with it, use it for your moodlights, coffeetables, decoration, whatever...

I hope the comments in the code are clear and helpful, if there are unaswered questions left, you´re welcome to contact me.

Any remarks and suggestions from you are highly welcome.

What? A function like this exists since ages? You can do it yourself way better? I just bored you?
Sorry, if so.

I just saw so many youtube videos about Arduino light projects which could be highly improved by using that, that I couln´t resist to publish it...

I appreciate your feedback - what you think about it, and of course, what you do with it!

If you cannot use it, because it needs to much RAM it is possible to work just with 2 arrays and in-/dercease the single colorvalues by a fixed step width - that looks not so nice then but for fast fades it´s maybe acceptable. Let me know in case you need support for that hack.

With best wishes,

Helmuth.

Here the complete code:
Code:
// FadeConcept by arduino.loeter@gmx.de
//
// A concept of a smooth and fast crossfade between
// 2 different pictures on an adressable RGB strip.
//
// Thanks to DanielGarcia@gmail.com for the FastSPI library
// and thanks to the support from all the guys in the
// german Arduino forum!
//
// Do with it whatever you like, but make it awesome!
//
// If you´d like to use it right away, select your
// chipset and striplength first. Wiring: DATA 11, CLOCK 13
// Tested @ Arduino Uno r3. It works because of limited RAM
// up to a lenght of 210 LEDs on an UNO with no other code
// arround.
// Yes, it eats loads of RAM, because it needs the complete
// memory for storing the stripcontent itself x3.
// But it´s worth the quality of the effect i think. :-)

#include <FastSPI_LED.h>

// That is the length of your strip.
#define NUM_LEDS 20

// Change the order of your rgb here.
struct CRGB { unsigned char r; unsigned char g; unsigned char b; };
struct CRGB *leds;

// to save, what you see right now on the strip (current frame)
byte old_frame[NUM_LEDS][3];

// the place for the stuff you want to see in future (next frame)
byte new_frame[NUM_LEDS][3];

// save what you see right now to old_frame for fading away from it later
void copy_led_array_to_old_frame(){
  for(int i = 0; i < NUM_LEDS; i++ ) {
    old_frame[i][0] = leds[i].r;
    old_frame[i][1] = leds[i].g;
    old_frame[i][2] = leds[i].b;
  }  
}

// fade to new content over a number of steps with wait_ms delay between the steps
void fade_from_old_to_new_frame(int steps, int wait_ms){
  for(int a=0; a < steps; a++){ // over the steps
    for(int b=0; b < NUM_LEDS; b++){ // over the whole lenght
      leds[b].r = (int)old_frame[b][0] + ((int)new_frame[b][0] - (int)old_frame[b][0]) * a / steps; //over the red
      leds[b].g = (int)old_frame[b][1] + ((int)new_frame[b][1] - (int)old_frame[b][1]) * a / steps; //the green
      leds[b].b = (int)old_frame[b][2] + ((int)new_frame[b][2] - (int)old_frame[b][2]) * a / steps; //and the blue LEDs
    }
    FastSPI_LED.show();
    delay(wait_ms);  
  }
}

/*
//some stuff you don´t really need, execpt for understanding and playing
//(and maybe for debugging your project...)

//set color of a single LED, don´t show
void set_color_led(int adex, int cred, int cgrn, int cblu) {  
  leds[adex].r = cred;
  leds[adex].g = cgrn;
  leds[adex].b = cblu;  
  }
  
//create and show something unique
void create_random_pixels(){
  for(int i = 0 ; i < NUM_LEDS; i++ ) {
    set_color_led(i, random(255), random(5), random(255));
  }
  FastSPI_LED.show();
}

//make the content of the new_frame visible immediately
void show_new_frame(){
  for(int i = 0 ; i < NUM_LEDS; i++ ) {
    leds[i].r = new_frame[i][0];
    leds[i].g = new_frame[i][1];
    leds[i].b = new_frame[i][2];
  }
  FastSPI_LED.show();
}

//just to compare: show the saved old_frame you started with again
void show_old_frame(){
  for(int i = 0 ; i < NUM_LEDS; i++ ) {
    leds[i].r = old_frame[i][0];
    leds[i].g = old_frame[i][1];
    leds[i].b = old_frame[i][2];
  }
  FastSPI_LED.show();
}

*/

// Here is the place for your own creativity.
// Put in the stuff you want to see in the next frame.
// Formulas, precalculated or saved images, whatever.
// Some very simple examples:

// fill new_frame with some linear color fade
void fill_new_frame_with_content(){
  for(int i = 0 ; i < NUM_LEDS; i++ ) {
    new_frame[i][0] = (i*255)/NUM_LEDS;
    new_frame[i][1] = 255-((i*255)/NUM_LEDS);
    new_frame[i][2] = 0;
  }
}

// ...with a different color fade
void fill_new_frame_with_different_content(){
  for(int i = 0 ; i < NUM_LEDS; i++ ) {
    new_frame[i][1] = (i*255)/NUM_LEDS;
    new_frame[i][2] = 255-((i*255)/NUM_LEDS);
    new_frame[i][0] = 0;
  }
}

//  ...just with some random dots
void fill_new_frame_with_random_content(){
  for(int i = 0 ; i < NUM_LEDS; i++ ) {
  new_frame[i][1] = random(255);
  new_frame[i][2] = random(255);
  new_frame[i][0] = random(255);
  }
}
  
void setup(){
  FastSPI_LED.setLeds(NUM_LEDS);
  // Select your chipset according to your strip type here - have a look at FastSPI documentation.
  // I´m using a LPD1101 right now who behaves like a LPD6803.
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  FastSPI_LED.init();
  FastSPI_LED.start();
  leds = (struct CRGB*)FastSPI_LED.getRGBData();
}

void loop() {
  // I hope, the names speak for themself.
  copy_led_array_to_old_frame();
  fill_new_frame_with_content();
  // Try it with differnt delays (second number)
  // and with different numer of frames (first one)
  // in case you´re using very long strips
  fade_from_old_to_new_frame(128,5);  
  delay(1000);
  
  copy_led_array_to_old_frame();  
  fill_new_frame_with_different_content();
  fade_from_old_to_new_frame(128,5);  
  delay(1000);
  
  copy_led_array_to_old_frame();  
  fill_new_frame_with_random_content();
  fade_from_old_to_new_frame(128,5);  
  delay(1000);
}

P.S. Massive edit and I asked the moderator, to move this thread from Project Guidance to Exhibition / Gallery.

« Last Edit: March 02, 2013, 11:17:29 am by Helmuth » Logged

Europe / Germany
Offline Offline
Sr. Member
****
Karma: 11
Posts: 334
keep it simple
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys, please, don´t let me die stupid and dont´t force me to cross post:

Wrong forum category or simply uninteresting for all of you?

Thanks for an answer, Helmuth
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 199
Posts: 12767
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wrong forum category or simply uninteresting for all of you?

What is that ... about 20 hours between your post and your bump?  The more likely reason you haven't had any replies is that people need time to: work, eat, sleep and then digest your code and formulate a reply.  In other words, try to show some patience.

Quote
...and dont´t force me to cross post...

Don't force me to censor.

If you want want your thread moved, use Report to moderator.  It's in the lower-right corner of each post.
Logged

Europe / Germany
Offline Offline
Sr. Member
****
Karma: 11
Posts: 334
keep it simple
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Coding Badly,

thanks for your helpful answer, I´ll relax. It was not my intention to offence you guys, sorry for the bump.

With best wishes,

Helmuth.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 199
Posts: 12767
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It was not my intention to offence you guys, sorry for the bump.

I'm not offended.  Just offering a potential explanation.

Quote
With best wishes,

Back at ya!
Logged

Europe / Germany
Offline Offline
Sr. Member
****
Karma: 11
Posts: 334
keep it simple
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Coding Badly,

i tried to use the "Report to Moderator" link as recommended to ask you, to move these thread into the Exhibiton / Gallery folder, but I´m not allowed to report my own thread.   smiley-red

Thanks for your support,

Helmuth.
« Last Edit: March 02, 2013, 06:47:09 am by Helmuth » Logged

Pages: [1]   Go Up
Jump to: