user38798: I am trying to simulate 4 flickering flames on a single LED strip.
The ws2812b strip has 60 LEDs. I cut and chained it into 4 chunks of 15 LEDs. Each chunk has a random Fire2012 sequence, however the entire sequence seems to start and stop at the same time, and therefore they all look extremely similar.
What is the best way to overlap the fire sequences so that timing looks different for each chunk?
Here is my code so far...
#include <FastLED.h>

#define LED_PIN     5
#define COLOR_ORDER GRB
#define CHIPSET     WS2812B

#define NUM_CHUNKS           4
#define NUM_LEDS_PER_CHUNK   15
#define NUM_LEDS NUM_CHUNKS * NUM_LEDS_PER_CHUNK

#define BRIGHTNESS  80
#define FRAMES_PER_SECOND  30

#define gReverseDirection false

CRGB leds[NUM_LEDS];

void setup() {
  delay(3000); // sanity delay
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness( BRIGHTNESS );
}

void loop()
{
  // Add entropy to random number generator; we use a lot of it.
  // random16_add_entropy( random());

  // Get LED Chunks
  for(int i = 0; i < NUM_CHUNKS; i++){
    //random16_add_entropy( random());
    Fire2012(i); // run simulation frame
  }

  FastLED.show(); // display this frame
  FastLED.delay(1000 / FRAMES_PER_SECOND);
}


// Fire2012 by Mark Kriegsman, July 2012
// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
//// 
// This basic one-dimensional 'fire' simulation works roughly as follows:
// There's a underlying array of 'heat' cells, that model the temperature
// at each point along the line.  Every cycle through the simulation, 
// four steps are performed:
//  1) All cells cool down a little bit, losing heat to the air
//  2) The heat from each cell drifts 'up' and diffuses a little
//  3) Sometimes randomly new 'sparks' of heat are added at the bottom
//  4) The heat from each cell is rendered as a color into the leds array
//     The heat-to-color mapping uses a black-body radiation approximation.
//
// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
//
// This simulation scales it self a bit depending on NUM_LEDS; it should look
// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. 
//
// I recommend running this simulation at anywhere from 30-100 frames per second,
// meaning an interframe delay of about 10-35 milliseconds.
//
// Looks best on a high-density LED setup (60+ pixels/meter).
//
//
// There are two main parameters you can play with to control the look and
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
// in step 3 above).
//
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames.  More cooling = shorter flames.
// Default 50, suggested range 20-100 
#define COOLING  55

// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire.  Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
#define SPARKING 60


void Fire2012(int chunk)
{
// Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS_PER_CHUNK];

  int startLed = NUM_LEDS_PER_CHUNK * chunk;
  int endLed = NUM_LEDS_PER_CHUNK * chunk + NUM_LEDS_PER_CHUNK;

  // Step 1.  Cool down every cell a little
    for( int i = 0; i < NUM_LEDS_PER_CHUNK; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS_PER_CHUNK) + 2));
    }

    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= NUM_LEDS_PER_CHUNK - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }

    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom

    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS_PER_CHUNK; j++) {
      CRGB color = HeatColor( heat[j]);
      int pixelnumber;
      if(gReverseDirection) {
        pixelnumber = (endLed - 1) - j;
      } else { //0 15
        pixelnumber = startLed + j;
      }
      leds[pixelnumber] = color;
    }
}


user38850: #include <FastLED.h>


 #define LED_PIN     5
 #define COLOR_ORDER GRB
 #define CHIPSET     WS2811
 #define NUM_LEDS    (kMatrixWidth * kMatrixHeight)
 #define FRAMES_PER_SECOND 60
 //////////////////////////////////////////////////////
 const uint8_t kMatrixWidth  = 15;
 const uint8_t kMatrixHeight = 4;
 const bool    kMatrixSerpentineLayout = true;
 //////////////////
 int BRIGHTNESS = 250;

//////////////////////////////////////////////////
bool gReverseDirection = false;

CRGB leds[NUM_LEDS];

void setup() {
Serial.begin(115200);
Serial.println("*** Inicialization");
///////////////////////////////////////////////
delay(3000); // sanity delay
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness( BRIGHTNESS );
}
/////////////////////////////////// end setup

void loop()
{

 Fire2012();
 FastLED.show(); // display this frame
 FastLED.delay(1000 / FRAMES_PER_SECOND);
 FastLED.setBrightness( BRIGHTNESS );
 }


 void Fire2012()
 {
  int COOLING = 90;
  int SPARKING = 100;
   // Array of temperature readings at each simulation cell

    static byte heat[kMatrixWidth] [kMatrixHeight];

    // Step 1.  Cool down every cell a little
    for (int n = 0; n< kMatrixHeight; n++)
   {

     for ( int i = 0; i < kMatrixWidth; i++) {
       heat[i][n] = qsub8( heat[i][n],  random8(0, 
       ((COOLING * 10) / (kMatrixWidth)) + 2));
       }

       // Step 2. 
      for ( int k = (kMatrixWidth- 1); k >= 2; k--) {
      heat[k][n] = (heat[k - 1][n] + heat[k - 2][n] + 
      heat[k - 2][n] ) / 3;
      }

       // Step 3. 
      if ( random8() < SPARKING ) {
       int y = random8(3);
       heat[y][n] = qadd8( heat[y][n], random8(160, 255) );
      }
     }

  // Step 4.  Map from heat cells to LED colors

for ( int i= 0; i < kMatrixWidth; i++) {
  for (int j = 0; j < kMatrixHeight; j++) {

    CRGB color = HeatColor(heat[i][j]);
    leds[XY(i, j)] = color;

     }
   }

 }

   /////////////
    uint16_t XY( uint8_t x, uint8_t y)
    {
    uint16_t i;
    if ( kMatrixSerpentineLayout == false) {
    i = (y * kMatrixWidth) + x;
    }
    if ( kMatrixSerpentineLayout == true) {
    if ( y & 0x01) {
     // Odd rows run backwards
     uint8_t reverseX = (kMatrixWidth - 1) - x;
     i = (y * kMatrixWidth) + reverseX;
     } else {
    // Even rows run forwards
      i = (y * kMatrixWidth) + x;
     }
    }

    return i;

   }/////


38798: <p>I am trying to simulate 4 flickering flames on a single LED strip.</p>

<p>The ws2812b strip has 60 LEDs. I cut and chained it into 4 chunks of 15 LEDs. Each chunk has a random Fire2012 sequence, however the entire sequence seems to start and stop at the same time, and therefore they all look extremely similar.</p>

<p>What is the best way to overlap the fire sequences so that timing looks different for each chunk?</p>

<p>Here is my code so far...</p>

<pre><code>#include &lt;FastLED.h&gt;

#define LED_PIN     5
#define COLOR_ORDER GRB
#define CHIPSET     WS2812B

#define NUM_CHUNKS           4
#define NUM_LEDS_PER_CHUNK   15
#define NUM_LEDS NUM_CHUNKS * NUM_LEDS_PER_CHUNK

#define BRIGHTNESS  80
#define FRAMES_PER_SECOND  30

#define gReverseDirection false

CRGB leds[NUM_LEDS];

void setup() {
  delay(3000); // sanity delay
  FastLED.addLeds&lt;CHIPSET, LED_PIN, COLOR_ORDER&gt;(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness( BRIGHTNESS );
}

void loop()
{
  // Add entropy to random number generator; we use a lot of it.
  // random16_add_entropy( random());

  // Get LED Chunks
  for(int i = 0; i &lt; NUM_CHUNKS; i++){
    //random16_add_entropy( random());
    Fire2012(i); // run simulation frame
  }

  FastLED.show(); // display this frame
  FastLED.delay(1000 / FRAMES_PER_SECOND);
}


// Fire2012 by Mark Kriegsman, July 2012
// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
//// 
// This basic one-dimensional 'fire' simulation works roughly as follows:
// There's a underlying array of 'heat' cells, that model the temperature
// at each point along the line.  Every cycle through the simulation, 
// four steps are performed:
//  1) All cells cool down a little bit, losing heat to the air
//  2) The heat from each cell drifts 'up' and diffuses a little
//  3) Sometimes randomly new 'sparks' of heat are added at the bottom
//  4) The heat from each cell is rendered as a color into the leds array
//     The heat-to-color mapping uses a black-body radiation approximation.
//
// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
//
// This simulation scales it self a bit depending on NUM_LEDS; it should look
// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. 
//
// I recommend running this simulation at anywhere from 30-100 frames per second,
// meaning an interframe delay of about 10-35 milliseconds.
//
// Looks best on a high-density LED setup (60+ pixels/meter).
//
//
// There are two main parameters you can play with to control the look and
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
// in step 3 above).
//
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames.  More cooling = shorter flames.
// Default 50, suggested range 20-100 
#define COOLING  55

// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire.  Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
#define SPARKING 60


void Fire2012(int chunk)
{
// Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS_PER_CHUNK];

  int startLed = NUM_LEDS_PER_CHUNK * chunk;
  int endLed = NUM_LEDS_PER_CHUNK * chunk + NUM_LEDS_PER_CHUNK;

  // Step 1.  Cool down every cell a little
    for( int i = 0; i &lt; NUM_LEDS_PER_CHUNK; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS_PER_CHUNK) + 2));
    }

    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= NUM_LEDS_PER_CHUNK - 1; k &gt;= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }

    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom

    if( random8() &lt; SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j &lt; NUM_LEDS_PER_CHUNK; j++) {
      CRGB color = HeatColor( heat[j]);
      int pixelnumber;
      if(gReverseDirection) {
        pixelnumber = (endLed - 1) - j;
      } else { //0 15
        pixelnumber = startLed + j;
      }
      leds[pixelnumber] = color;
    }
}
</code></pre>
 38850: <pre><code>#include &lt;FastLED.h&gt;


 #define LED_PIN     5
 #define COLOR_ORDER GRB
 #define CHIPSET     WS2811
 #define NUM_LEDS    (kMatrixWidth * kMatrixHeight)
 #define FRAMES_PER_SECOND 60
 //////////////////////////////////////////////////////
 const uint8_t kMatrixWidth  = 15;
 const uint8_t kMatrixHeight = 4;
 const bool    kMatrixSerpentineLayout = true;
 //////////////////
 int BRIGHTNESS = 250;

//////////////////////////////////////////////////
bool gReverseDirection = false;

CRGB leds[NUM_LEDS];

void setup() {
Serial.begin(115200);
Serial.println("*** Inicialization");
///////////////////////////////////////////////
delay(3000); // sanity delay
FastLED.addLeds&lt;CHIPSET, LED_PIN, COLOR_ORDER&gt;(leds, NUM_LEDS);
FastLED.setBrightness( BRIGHTNESS );
}
/////////////////////////////////// end setup

void loop()
{

 Fire2012();
 FastLED.show(); // display this frame
 FastLED.delay(1000 / FRAMES_PER_SECOND);
 FastLED.setBrightness( BRIGHTNESS );
 }


 void Fire2012()
 {
  int COOLING = 90;
  int SPARKING = 100;
   // Array of temperature readings at each simulation cell

    static byte heat[kMatrixWidth] [kMatrixHeight];

    // Step 1.  Cool down every cell a little
    for (int n = 0; n&lt; kMatrixHeight; n++)
   {

     for ( int i = 0; i &lt; kMatrixWidth; i++) {
       heat[i][n] = qsub8( heat[i][n],  random8(0, 
       ((COOLING * 10) / (kMatrixWidth)) + 2));
       }

       // Step 2. 
      for ( int k = (kMatrixWidth- 1); k &gt;= 2; k--) {
      heat[k][n] = (heat[k - 1][n] + heat[k - 2][n] + 
      heat[k - 2][n] ) / 3;
      }

       // Step 3. 
      if ( random8() &lt; SPARKING ) {
       int y = random8(3);
       heat[y][n] = qadd8( heat[y][n], random8(160, 255) );
      }
     }

  // Step 4.  Map from heat cells to LED colors

for ( int i= 0; i &lt; kMatrixWidth; i++) {
  for (int j = 0; j &lt; kMatrixHeight; j++) {

    CRGB color = HeatColor(heat[i][j]);
    leds[XY(i, j)] = color;

     }
   }

 }

   /////////////
    uint16_t XY( uint8_t x, uint8_t y)
    {
    uint16_t i;
    if ( kMatrixSerpentineLayout == false) {
    i = (y * kMatrixWidth) + x;
    }
    if ( kMatrixSerpentineLayout == true) {
    if ( y &amp; 0x01) {
     // Odd rows run backwards
     uint8_t reverseX = (kMatrixWidth - 1) - x;
     i = (y * kMatrixWidth) + reverseX;
     } else {
    // Even rows run forwards
      i = (y * kMatrixWidth) + x;
     }
    }

    return i;

   }/////
</code></pre>
