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!



Looking for help co...
 
Share:
Notifications
Clear all

Looking for help combining Meteor Rain Sketch with another pattern

21 Posts
2 Users
1 Likes
541 Views
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2236
 

Oh my ... I have no idea what happened there. You're right, I missed something there - this time: thank you for your patience 😁 

Try this - it compiled, which is (again) zero guarantee that it will work 😜 

 

#include "FastLED.h"

#define NUM_LEDS 300
// CRGB leds[NUM_LEDS];
CRGBArray<NUM_LEDS> leds;
#define DATA_PIN 9

// Overall twinkle speed.
// 0 (VERY slow) to 8 (VERY fast).  
// 4, 5, and 6 are recommended, default is 4.
#define TWINKLE_SPEED 7

// Overall twinkle density.
// 0 (NONE lit) to 8 (ALL lit at once).  
// Default is 5.
#define TWINKLE_DENSITY 6

// How often to change color palettes.
#define SECONDS_PER_PALETTE  10
// Also: toward the bottom of the file is an array 
// called "ActivePaletteList" which controls which color
// palettes are used; you can add or remove color palettes
// from there freely.

// Background color for 'unlit' pixels
// Can be set to CRGB::Black if desired.
CRGB gBackgroundColor = CRGB::Black; 
// Example of dim incandescent fairy light background color
// CRGB gBackgroundColor = CRGB(CRGB::FairyLight).nscale8_video(16);

// If AUTO_SELECT_BACKGROUND_COLOR is set to 1,
// then for any palette where the first two entries 
// are the same, a dimmed version of that color will
// automatically be used as the background color.
#define AUTO_SELECT_BACKGROUND_COLOR 0

// If COOL_LIKE_INCANDESCENT is set to 1, colors will 
// fade out slighted 'reddened', similar to how
// incandescent bulbs change color as they get dim down.
#define COOL_LIKE_INCANDESCENT 1


CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;

void setup() {
  delay( 3000 ); //safety startup delay
//  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  //FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
   // .setCorrection(TypicalLEDStrip);
FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

  chooseNextColorPalette(gTargetPalette);
}


void loop()
{
  EVERY_N_SECONDS( SECONDS_PER_PALETTE ) { 
    chooseNextColorPalette( gTargetPalette ); 
  }
  
  EVERY_N_MILLISECONDS( 10 ) {
    nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 12);
  }
    
  meteorRain(250, 60, 0, 5, 85, true, 0);
}

//Starts at lowest number LED and goes to highest
void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  fill_solid( leds, NUM_LEDS, gBackgroundColor );
 
  for(int i = 0; i < NUM_LEDS; i++) {
   
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        leds[j].fadeToBlackBy( meteorTrailDecay );        
      }
    }
   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS) && (i-j>=0) ) {
        leds[i-j] = CRGB(red, green, blue);
      }
    }

    // draw twinkles up to led "i" (=tail)
    if( (i-meteorSize < NUM_LEDS) && ( i-meteorSize>=0) ) {
      drawTwinkles(leds, i-meteorSize);
    }
   
    FastLED.show();
    delay(SpeedDelay);
  }  
}


//  This function loops over each pixel, calculates the 
//  adjusted 'clock' that this pixel should use, and calls 
//  "CalculateOneTwinkle" on each pixel.  It then displays
//  either the twinkle color of the background color, 
//  whichever is brighter.
void drawTwinkles( CRGBSet& L, int maxLeds)
{
  // "PRNG16" is the pseudorandom number generator
  // It MUST be reset to the same starting value each time
  // this function is called, so that the sequence of 'random'
  // numbers that it generates is (paradoxically) stable.
  uint16_t PRNG16 = 11337;
  
  uint32_t clock32 = millis();

  // Set up the background color, "bg".
  // if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of
  // the current palette are identical, then a deeply faded version of
  // that color is used for the background color
  CRGB bg;
  if( (AUTO_SELECT_BACKGROUND_COLOR == 1) &&
      (gCurrentPalette[0] == gCurrentPalette[1] )) {
    bg = gCurrentPalette[0];
    uint8_t bglight = bg.getAverageLight();
    if( bglight > 64) {
      bg.nscale8_video( 16); // very bright, so scale to 1/16th
    } else if( bglight > 16) {
      bg.nscale8_video( 64); // not that bright, so scale to 1/4th
    } else {
      bg.nscale8_video( 86); // dim, scale to 1/3rd.
    }
  } else {
    bg = gBackgroundColor; // just use the explicitly defined background color
  }

  uint8_t backgroundBrightness = bg.getAverageLight();
  
  for(int i; i<maxLeds; i++) {     // <-- change this loop
     PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number
    uint16_t myclockoffset16= PRNG16; // use that number as clock offset
    PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number
    // use that number as clock speed adjustment factor (in 8ths, from 8/8ths to 23/8ths)
    uint8_t myspeedmultiplierQ5_3 =  ((((PRNG16 & 0xFF)>>4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08;
    uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16;
    uint8_t  myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel

    // We now have the adjusted 'clock' for this pixel, now we call
    // the function that computes what color the pixel should be based
    // on the "brightness = f( time )" idea.
    CRGB c = computeOneTwinkle( myclock30, myunique8);

    uint8_t cbright = c.getAverageLight();
    int16_t deltabright = cbright - backgroundBrightness;
    if( deltabright >= 32 || (!bg)) {
      // If the new pixel is significantly brighter than the background color, 
      // use the new color.
      leds[i] = c;  // <-- change this
    } else if( deltabright > 0 ) {
      // If the new pixel is just slightly brighter than the background color,
      // mix a blend of the new color and the background color
      leds[i] = blend( bg, c, deltabright * 8);// <-- change this
    } else { 
      // if the new pixel is not at all brighter than the background color,
      // just use the background color.
      leds[i] = bg;// <-- change this
    }
  }
}


//  This function takes a time in pseudo-milliseconds,
//  figures out brightness = f( time ), and also hue = f( time )
//  The 'low digits' of the millisecond time are used as 
//  input to the brightness wave function.  
//  The 'high digits' are used to select a color, so that the color
//  does not change over the course of the fade-in, fade-out
//  of one cycle of the brightness wave function.
//  The 'high digits' are also used to determine whether this pixel
//  should light at all during this cycle, based on the TWINKLE_DENSITY.
CRGB computeOneTwinkle( uint32_t ms, uint8_t salt)
{
  uint16_t ticks = ms >> (8-TWINKLE_SPEED);
  uint8_t fastcycle8 = ticks;
  uint16_t slowcycle16 = (ticks >> 8) + salt;
  slowcycle16 += sin8( slowcycle16);
  slowcycle16 =  (slowcycle16 * 2053) + 1384;
  uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8);
  
  uint8_t bright = 0;
  if( ((slowcycle8 & 0x0E)/2) < TWINKLE_DENSITY) {
    bright = attackDecayWave8( fastcycle8);
  }

  uint8_t hue = slowcycle8 - salt;
  CRGB c;
  if( bright > 0) {
    c = ColorFromPalette( gCurrentPalette, hue, bright, NOBLEND);
    if( COOL_LIKE_INCANDESCENT == 1 ) {
      coolLikeIncandescent( c, fastcycle8);
    }
  } else {
    c = CRGB::Black;
  }
  return c;
}


// This function is like 'triwave8', which produces a 
// symmetrical up-and-down triangle sawtooth waveform, except that this
// function produces a triangle wave with a faster attack and a slower decay:
//
//     / \ 
//    /     \ 
//   /         \ 
//  /             \ 
//

uint8_t attackDecayWave8( uint8_t i)
{
  if( i < 86) {
    return i * 3;
  } else {
    i -= 86;
    return 255 - (i + (i/2));
  }
}

// This function takes a pixel, and if its in the 'fading down'
// part of the cycle, it adjusts the color a little bit like the 
// way that incandescent bulbs fade toward 'red' as they dim.
void coolLikeIncandescent( CRGB& c, uint8_t phase)
{
  if( phase < 128) return;

  uint8_t cooling = (phase - 128) >> 4;
  c.g = qsub8( c.g, cooling);
  c.b = qsub8( c.b, cooling * 2);
}

// A mostly red palette with green accents and white trim.
// "CRGB::Gray" is used as white to keep the brightness more uniform.
const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM =
{  CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, 
   CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, 
   CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, 
   CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green };

// A mostly (dark) green palette with red berries.
#define Holly_Green 0x00580c
#define Holly_Red   0xB00402
const TProgmemRGBPalette16 Holly_p FL_PROGMEM =
{  Holly_Green, Holly_Green, Holly_Green, Holly_Green, 
   Holly_Green, Holly_Green, Holly_Green, Holly_Green, 
   Holly_Green, Holly_Green, Holly_Green, Holly_Green, 
   Holly_Green, Holly_Green, Holly_Green, Holly_Red 
};

// A red and white striped palette
// "CRGB::Gray" is used as white to keep the brightness more uniform.
const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM =
{  CRGB::Red,  CRGB::Red,  CRGB::Red,  CRGB::Red, 
   CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray,
   CRGB::Red,  CRGB::Red,  CRGB::Red,  CRGB::Red, 
   CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray };

// A mostly blue palette with white accents.
// "CRGB::Gray" is used as white to keep the brightness more uniform.
const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM =
{  CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 
   CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 
   CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 
   CRGB::Blue, CRGB::Gray, CRGB::Gray, CRGB::Gray };

// A pure "fairy light" palette with some brightness variations
#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2)
#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4)
const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM =
{  CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, 
   HALFFAIRY,        HALFFAIRY,        CRGB::FairyLight, CRGB::FairyLight, 
   QUARTERFAIRY,     QUARTERFAIRY,     CRGB::FairyLight, CRGB::FairyLight, 
   CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight };

// A palette of soft snowflakes with the occasional bright one
const TProgmemRGBPalette16 Snow_p FL_PROGMEM =
{  0x304048, 0x304048, 0x304048, 0x304048,
   0x304048, 0x304048, 0x304048, 0x304048,
   0x304048, 0x304048, 0x304048, 0x304048,
   0x304048, 0x304048, 0x304048, 0xE0F0FF };

// A palette reminiscent of large 'old-school' C9-size tree lights
// in the five classic colors: red, orange, green, blue, and white.
#define C9_Red    0xB80400
#define C9_Orange 0x902C02
#define C9_Green  0x046002
#define C9_Blue   0x070758
#define C9_White  0x606820
const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM =
{  C9_Red,    C9_Orange, C9_Red,    C9_Orange,
   C9_Orange, C9_Red,    C9_Orange, C9_Red,
   C9_Green,  C9_Green,  C9_Green,  C9_Green,
   C9_Blue,   C9_Blue,   C9_Blue,
   C9_White
};

// A cold, icy pale blue palette
#define Ice_Blue1 0x0C1040
#define Ice_Blue2 0x182080
#define Ice_Blue3 0x5080C0
const TProgmemRGBPalette16 Ice_p FL_PROGMEM =
{
  Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
  Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
  Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
  Ice_Blue2, Ice_Blue2, Ice_Blue2, Ice_Blue3
};


// Add or remove palette names from this list to control which color
// palettes are used, and in what order.
const TProgmemRGBPalette16* ActivePaletteList[] = {
  &RetroC9_p,
  &BlueWhite_p,
  &RainbowColors_p,
  &FairyLight_p,
  &RedGreenWhite_p,
  &PartyColors_p,
  &RedWhite_p,
  &Snow_p,
  &Holly_p,
  &Ice_p  
};


// Advance to the next color palette in the list (above).
void chooseNextColorPalette( CRGBPalette16& pal)
{
  const uint8_t numberOfPalettes = sizeof(ActivePaletteList) / sizeof(ActivePaletteList[0]);
  static uint8_t whichPalette = -1; 
  whichPalette = addmod8( whichPalette, 1, numberOfPalettes);

  pal = *(ActivePaletteList[whichPalette]);
}

ReplyQuote
 Kip
(@kip)
Active Member
Joined: 2 years ago
Posts: 11
Topic starter  

Hi Hans,

 Sorry for the delayed reply, but sadly this didn't work. Only the MeteorRain pattern shows up and runs. I was trying to wrap my head around the problem and I THINK it has something to do with the timing portion of of the TwinkleFox code. It may be too complex to combine with the MeteorRain to get the desired effect in looking for. 🤔 

Perhaps your earlier suggestion might work out, which is to boost the sparkle effect that comes after the meteor in the original MeteorRain code. That might get the burning embers after effect in trying to emulate. 


ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2236
 

Hi Kip,

Bummer... it's always a little messy when trying to combine code of two different developers. Now worries though, I'm sure we can get this to work somehow.
This is why I have had moments where I would abandon one of the two, and just would try to recreate the sparkle.

Do you happen to have a video of what the twinkle effect looks like?
I do not have a 300 LED strip laying around haha ... 😁 
If not: no worries, I'll dig up an old strip that I have laying around ... somewhere.


ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2236
 

Alright, so ... I couldn't resist and dug up my LED strip and such and tried the effect you had in mind.
At times, things appear more complicated than they might be - right 😉 
Maybe not 100% what you had in mind, but significantly less complex and maybe pretty close anyway?

First of all, I did remove all NeoPixel stuff and ... glued some twinkle code in the tail of the meteor ...

Few things to pay attention to:

Make sure I used the right LED count (NUM_LEDS 300) and PIN (9) number.
I could only test this with 60 LEDs, so I had to slow it down a little for my tests - looked pretty good!
Curious what your 300 LEDs will do.

Oh and I added a "SparkleBrightnessIntensity" parameter to the meteorRain function which determines how bright the sparkles can become.
100 seemed a nice value for it, but you can change that of course.

And I added "SparkleIntensity" which determines how intense the sparkles will appear - a value between 0 and 100.
I noticed that 10 looks pretty nice - but it depends on preference and application of course.
Higher number = more intense.

 

Let me know what you think 😊 

#include "FastLED.h"
#define NUM_LEDS 300
CRGB leds[NUM_LEDS];
#define PIN 9

void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  fill_solid(leds, NUM_LEDS, CRGB::Black);
}

void loop() 
{
  // my test with original meteorRain color for 60 LEDs
  //meteorRain(0xff,0xff,0xff,10, 64, true, 30, 100, 10);

  // my test with your meteorRain color for 60 LEDs
  //meteorRain(250, 60, 0, 5, 85, true, 30, 50, 10);

  // I hope this works well for you ... adapted to 300 LEDs 
  meteorRain(250, 60, 0, 5, 85, true, 0, 50, 10);
}

void meteorRain(byte red, byte green, byte blue, byte meteorSize, 
                byte meteorTrailDecay, boolean meteorRandomDecay, 
                int  SpeedDelay, 
                byte SparkleBrightnessIntensity,                  // 0 = darkest ... 255 = brightest
                byte SparkleIntensity )                           // value 0 (none) to 100 (always)
{  
  for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) 
  {
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) 
    {
      if( (!meteorRandomDecay) || (random(10)>5) ) 
      {
        leds[j].fadeToBlackBy( meteorTrailDecay );
      }
    }
   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) 
    {
      if( ( i-j <NUM_LEDS) && (i-j>=0) ) 
      {
        leds[i-j] = CRGB(red, green, blue);
      }
    }

    // Add twinkle random in tail
    for(int j=0; j< (i-meteorSize); j++) 
    {
      if( (random(100)<SparkleIntensity) ) 
      {
        leds[j] = CRGB( random(SparkleBrightnessIntensity), random(SparkleBrightnessIntensity), random(SparkleBrightnessIntensity) );
      }
    }
    
    FastLED.show();
    delay(SpeedDelay);
  }
}

 


ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2236
 

Not sure how ell this comes across ... but I tried to make a video of it (60 LEDS!). 😊 


ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2236
 

Small modification so it won't crash ...

The NUM_LEDS+NUM_LEDS was my dirty trick to make it so the entire strip would have a chance to fade to black.
The trail needed clearing. I was actually thinking about that and do have an alternative workaround for that.

However, this will cause the code to access an address in the array well beyond was is supposed to be used for that.

(I hope I got it this way)

#include "FastLED.h"
#define NUM_LEDS 300
CRGB leds[NUM_LEDS];
#define PIN 9

void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  fill_solid(leds, NUM_LEDS, CRGB::Black);
}

void loop() 
{
  // my test with original meteorRain color for 60 LEDs
  //meteorRain(0xff,0xff,0xff,10, 64, true, 30, 100, 10);

  // my test with your meteorRain color for 60 LEDs
  //meteorRain(250, 60, 0, 5, 85, true, 30, 50, 10);

  // I hope this works well for you ... adapted to 300 LEDs 
  meteorRain(250, 60, 0, 5, 85, true, 0, 50, 10);
}

void meteorRain(byte red, byte green, byte blue, byte meteorSize, 
                byte meteorTrailDecay, boolean meteorRandomDecay, 
                int  SpeedDelay, 
                byte SparkleBrightnessIntensity,                  // 0 = darkest ... 255 = brightest
                byte SparkleIntensity )                           // value 0 (none) to 100 (always)
{  
  for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) 
  {
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) 
    {
      if( (!meteorRandomDecay) || (random(10)>5) ) 
      {
        leds[j].fadeToBlackBy( meteorTrailDecay );
      }
    }
   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) 
    {
      if( (i-j<NUM_LEDS) && (i-j>=0) ) 
      {
        leds[i-j] = CRGB(red, green, blue);
      }
    }

    // Add twinkle random in tail
    for(int j=0; j<(i-meteorSize); j++) 
    {
      if( (j<NUM_LEDS) && (random(100)<SparkleIntensity) ) 
      {
        leds[j] = CRGB( random(SparkleBrightnessIntensity), random(SparkleBrightnessIntensity), random(SparkleBrightnessIntensity) );
      }
    }
    
    FastLED.show();
    delay(SpeedDelay);
  }
}

ReplyQuote
Page 2 / 2
Share: