I need a little help with Mark Kriegsman 's Fire2012 code.

I need a little help with @Mark_Kriegsman 's Fire2012 code. I’ve modified it so it’s got sort of a fire-and-ice thing going on - a blue flame and a red flame. I want it to run the blue flame for around 30 seconds and then switch to the red flame sequence, and then back again forever. Can anyone help me figure out how to do this? I’ve tried everything I can think of but had no success… the delay() function doesn’t work because the code repeats itself after one frame and so I can’t seem to get 30 seconds worth of frames. If that makes any sense…?

Here’s what I’ve got:

// Fire2012: a basic fire simulation for a one-dimensional string of LEDs
// Mark Kriegsman, July 2012.
//
// Compiled size for Arduino/AVR is about 3,968 bytes.

#include <FastLED.h>

#define LED_DT 12
#define COLOR_ORDER GBR
#define COLOR_ORDER_RED GRB
#define CHIPSET WS2811
#define LED_COUNT 28
#define max_bright 150
#define FRAMES_PER_SECOND 15

CRGB leds[LED_COUNT];

void setup() {
delay(3000); // sanity delay
FastLED.addLeds<CHIPSET, LED_DT, COLOR_ORDER>(leds, LED_COUNT);
FastLED.setBrightness( max_bright );
}

void loop() {
flame_red();
//would love this to run for 30 seconds
flame_blue();
//and then this to run for 30 seconds
}

void flame_red()
{
FastLED.addLeds<CHIPSET, LED_DT, COLOR_ORDER_RED>(leds, LED_COUNT);
// Add entropy to random number generator; we use a lot of it.
random16_add_entropy( random());
Fire2012(); // run simulation frame
FastLED.show(); // display this frame
delay(1000 / FRAMES_PER_SECOND);}

void flame_blue()
{
FastLED.addLeds<CHIPSET, LED_DT, COLOR_ORDER>(leds, LED_COUNT);
// Add entropy to random number generator; we use a lot of it.
random16_add_entropy( random());
Fire2012(); // run simulation frame
FastLED.show(); // display this frame
delay(1000 / FRAMES_PER_SECOND);}

// Fire2012 by Mark Kriegsman, July 2012
// as part of “Five Elements” shown here: "Five Elements" light sculpture (2nd installation) - YouTube
//
// 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 LED_COUNT; 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.
//
//
// 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 55, suggested range 20-100
#define COOLING 30

// 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 80

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

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

// Step 2.  Heat from each cell drifts 'up' and diffuses a little
for( int k= LED_COUNT - 3; k > 0; 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 < LED_COUNT; j++) {
    leds[j] = HeatColor( heat[j]);
}

}

// CRGB HeatColor( uint8_t temperature)
// [to be included in the forthcoming FastLED v2.1]
//
// Approximates a ‘black body radiation’ spectrum for
// a given ‘heat’ level. This is useful for animations of ‘fire’.
// Heat is specified as an arbitrary scale from 0 (cool) to 255 (hot).
// This is NOT a chromatically correct ‘black body radiation’
// spectrum, but it’s surprisingly close, and it’s extremely fast and small.
//
// On AVR/Arduino, this typically takes around 70 bytes of program memory,
// versus 768 bytes for a full 256-entry RGB lookup table.

CRGB HeatColor( uint8_t temperature)
{
CRGB heatcolor;

// Scale ‘heat’ down from 0-255 to 0-191,
// which can then be easily divided into three
// equal ‘thirds’ of 64 units each.
uint8_t t192 = scale8_video( temperature, 192);

// calculate a value that ramps up from
// zero to 255 in each ‘third’ of the scale.
uint8_t heatramp = t192 & 0x3F; // 0…63
heatramp <<= 2; // scale up to 0…252

// now figure out which third of the spectrum we’re in:
if( t192 & 0x80) {
// we’re in the hottest third
heatcolor.r = 255; // full red
heatcolor.g = 255; // full green
heatcolor.b = heatramp; // ramp up blue

} else if( t192 & 0x40 ) {
// we’re in the middle third
heatcolor.r = 255; // full red
heatcolor.g = heatramp; // ramp up green
heatcolor.b = 0; // no blue

} else {
// we’re in the coolest third
heatcolor.r = heatramp; // ramp up red
heatcolor.g = 0; // no green
heatcolor.b = 0; // no blue
}

return heatcolor;
}

Clever use of the Color Order thing there!
Give me a moment to think about how best to do this.

OK, here’s one approach, and while there are ‘better’ ways to do this, a little fish told me that you have a performance tonight, so this emphasizes simplicity of coding.

So start with what you have, and delete flame_red and flame_blue functions.

Use this for your loop():

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

// in each minute, the first 30 seconds are “red”
// and the second 30 seconds are “blue”, which we get by
// switching the R and B components.
uint32_t timeInSeconds = millis() / 1000;
int secondHand = timeInSeconds % 60;

// if we’re in the second half of the minute,
// swap all the red and blue values.
if( secondHand >= 30) {
for( int i = 0; i < LED_COUNT; i++) {
byte temp = leds[i].red;
leds[i].red = leds[i].blue;
leds[i].blue = temp;
}
}

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

How’s that?

“Ideally” we’d have two ‘HeatColor’, one red and one blue, functions and have the Fire2012 call one or the other. Or maybe have just one HeatColor function, which could produce red or blue ‘heat’. But… those are for another day when there’s not a performance coming up, and when I don’t have make dinner and check Eleanor’s math homework :smiley:

That said, I’m around to help tonight, off and on. Let me know how the code above works out!

You are amazing!!! I’ll post a video of the outfit in a bit. :slight_smile: Thank you so much! (it’s a memorial day gig and they insist I need to be in red, white, and blue and this is gonna blow them away)

That sounds great!
Can’t wait to see, and have a great performance!

can i ask where you got the cool thing around the lights?

It’s an Ikea “Rutbo” standing lamp, which has paper sides around a skeletal metal frame.
http://m.ikea.com/us/en/catalog/products/art/50131881/

I was gonna guess Ikea gonna have to buy one…

get the time at the start of the code, and compare it to the current time after each frame, then the difference is > then timeperiod make the switch, reset the initial time and start again?