Array Setup Question!   Arrays continue to baffle me.  I'll get there.

Array Setup Question!

Arrays continue to baffle me. I’ll get there. Just need to quit with the headdesk banging and ask for help…

I want to tell FastLED to mirror my animation. I have 120 LEDs, and I want to start the animation on LED 59 and 60, and have it run forwards from 60-119, and backward from 59-0.

I need to set up an array for 0-59 and another for 60-119 and then mess with the modifiers to get it to run backwards on the first array. … right?

Code in the comments… any help is appreciated!

uint8_t LeftSide[NUM_SIDES] = {leds 0-59, how do I write this?};

uint8_t RightSide[NUM_SIDES] = {leds 60-119, how do I write this?};

void FireLeftSide()
{
random16_add_entropy( random());
static byte heat[60];
for( int i = 0; i < 60; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / 60) + 2));
}
for( int k= 60 - 3; k > 0; k–) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
if( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160,255) );
}
for( int j = 0; j < 60; j++) {
byte colorindex = scale8( heat[j], 240);
LeftSide[(FIRE_COUNT - 1) - j] = ColorFromPalette( currentPalette, colorindex);

}

}

void FireRightSide()
{
random16_add_entropy( random());
static byte heat[60];
for( int i = 0; i < 60; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / 60) + 2));
}
for( int k= 60 - 3; k > 0; k–) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
if( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160,255) );
}
for( int j = 0; j < 60; j++) {
byte colorindex = scale8( heat[j], 240);
RightSide[ j] = ColorFromPalette( currentPalette, colorindex);

}

}

Are you just having trouble initializing the array? You should be able to just go:

uint8_t LeftSide[NUM_SIDES];

for (int i=0; i< NUM_SIDES; i++) { LeftSide[i] = 0; } // Initialize…

If you want to mirror the array on two separate LED strips (I assume) - you can do this with a single array.

Are you not wanting to type all the numbers out? Maybe this is helpful?

uint8_t LeftSide[NUM_SIDES]; // define number of elements without specifically typing them all out
for(int x=0; x<60; x=x+1) { LeftSide[x]=x; } // this fills the array with range 0-59

uint8_t RightSide[NUM_SIDES]; // define number of elements without specifically typing them all out
for(int x=60; x<120; x=x+1) { RightSide[x]=x; } // this fills the array with numbers 60-119

They could also be filled in reverse order if that might be helpful.

for(int x=119; x>59; x=x-1) { RightSide[x]=x; } // this fills the array with numbers 119 down to 60

That’s super helpful. That was the first part of my problem. I’m still confused as to how to use that array to actually fill the leds. I defined

CRGB leds [120];

earlier in the code. How do I tell this function to fill LeftSide or RightSide (or both) instead of the “leds” array?

Hi Erin, I may not understand properly. But if the right side is a mirror of the left side then you don’t actually need a right side array.

You seem to be using Fire2012, so I’ve adjusted that for you. Basically, I pretend that you have half the number of LEDs that you really have (by changing all the “NUM_LEDS” to “(NUM_LEDS / 2)”

Then when it comes to setting the LEDs themselves I set the left half as normal (except with half the LEDs still), but then set the right half as the opposite.

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

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

// Step 2.  Heat from each cell drifts 'up' and diffuses a little
for( int k= (NUM_LEDS / 2) - 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 / 2); j++) {
    leds[j] = HeatColor( heat[j]);
	leds[NUM_LEDS - j - 1] = HeatColor( heat[j]); // right side mirrors the left
}

}

Good luck!!

Oh that is SO SUPER CLOSE… it’s working but it’s starting the fire animations at leds #0 nd #119 (at the edges). I want it to start in the middle, at leds #59 and #60. Is it even possible to have an int counting both up and down at the same time, or do I need a different variable?

Try the last ‘for’ as:

for( int j = (NUM_LEDS / 2) - 1; j > 0; j–) {

It’s telling me “stray ‘’ in program” when I change just that one line…?

weird copy/paste error maybe. I changed “(NUM_LEDS/2) - 1” to “59” and now it compiles. IT still starts the animation from the edges though…

Here’s the whole thing again…

If you want to thank me, and have an Android device - then would you mind giving my Xmas wallpaper a a good review (and +1 the store page)?

:slight_smile:

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

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

// Step 2.  Heat from each cell drifts 'up' and diffuses a little
for( int k= (NUM_LEDS / 2) - 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 = (NUM_LEDS / 2) - 1; j > 0; j--) {
    leds[j] = HeatColor( heat[j]);
	leds[NUM_LEDS - j - 1] = HeatColor( heat[j]); // right side mirrors the left
}

}

absolutely. (And I was one of the first to download that when you posted it, it’s cool!) Thanks for your help!

… but the animation still starts from the edges. MATH IS HARD. I will bang my head on it some more but not until after breakfast. Sigh.

Very kind! Remember to post a video when you’re up and running. Also if you need help converting other stuff to be mirrored, just ask here.

Ha Ha! Thanks very much!

Here’s where you can start using/abusing the fact that, in C, pointers and arrays are kind of the same thing under the hood. Also, there’s nothing that says animation functions have to work on the global led array object, instead you can pass in a pointer to where you want things to start and how many things you want it to affect:

// some defines because I am lazy
#define NUM_LEDS_PER_SIDE 60
#define NLPS NUM_LEDS_PER_SIDE

// here’s your “normal” array
CRBG leds[NLPS*2];

// We’ve set up two “pointers” to the leds, leftSide, starting at 0, and right side, starting at 60.
CRGB *leftSide = leds;
CRGB *rightSide = leds + NLPS;

// Now we also want to track heat outside of the fire function
byte leftHeat[NLPS];
byte rightHeat[NLPS];

// direction: -1 means go from high to low, 1 means low to high
void Fire(CRGB *fireleds, byte *heat, int numLeds, int direction) {
// Step 1 - cool
for(int i = 0; i < numLeds; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / numLeds) + 2));
}

for( int k= numLeds - 3; k > 0; k–) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
if( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160,255) );
}

// Split out into two clauses to be extra clear about what is going on.
// If direction is less than 0, then our heat array will fill from high led down
// if direction is greater than or equal to 0, then our heat array will fill from low led on up        
for( int j = 0; j < numLeds; j++) {
    byte colorindex = scale8( heat[j], 240);
    if(direction < 0) { 
      fireleds[(num_leds-1)-j] = ColorFromPalette( currentPalette, colorindex);
    } else {
      fireleds[j] = ColorFromPalette( currentPalette, colorindex);
    }
  }

}
}

// now, in loop, make your calls:
void loop() {
// yadda yadda yadda
Fire(leftSide, leftHeat, NLPS, -1);
Fire(rightSide, rightHeat, NLPS, 1);
// more yaddaing goes here
}

This also has the bonus of generating much more compact code (because you don’t have two copies of the fire function running around :slight_smile:

Daniel, There two issue with the code you posted.
1st) First this isn’t mirrored. This code will create two fire animation independently on each side.
2nd) I tried to run your Code and I found an error. When you setup the pointers for leftSide and rightSide, you should have the rightSide start at 0, else you will always try to fill in the flame starting at index 60 up to 119, vs wanting to go from 0 to 59. So you have to reverse the two cells.

I remove a lot of the comment i cut and past using the Fire_Pallet, but here my code that i got to run on my LED 116 LED infinity Mirror.

#include <FastLED.h>

#define LED_PIN 9
#define COLOR_ORDER GRB
#define CHIPSET WS2811
#define NUM_LEDS 116

#define NLPS 58
#define COOLING 55
#define SPARKING 120
#define BRIGHTNESS 100
#define FRAMES_PER_SECOND 60

CRGBPalette16 currentPalette;
// here’s your “normal” array
CRGB leds[NUM_LEDS];
// We’ve set up two “pointers” to the leds, rightSide, starting at 0, and leftSide, starting at 59.
CRGB *leftSide = leds + NLPS;
CRGB *rightSide = leds;
// Now we also want to track heat outside of the fire function
byte leftHeat[NLPS];
byte rightHeat[NLPS];

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

void loop() {
Fire(leftSide, leftHeat, NLPS, -1);
Fire(rightSide, rightHeat, NLPS, 1);
FastLED.show(); // display this frame
FastLED.delay(1000 / FRAMES_PER_SECOND);
}

// direction: -1 means go from high to low, 1 means low to high
void Fire(CRGB *fireleds, byte *heat, int numLeds, int direction) {
// Step 1 - cool
for(int i = 0; i < numLeds; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / numLeds) + 2));
}

for( int k= numLeds - 3; k > 0; k–) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
if( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160,255) );
}

// Split out into two clauses to be extra clear about what is going on.
// If direction is less than 0, then our heat array will fill from high led down
// if direction is greater than or equal to 0, then our heat array will fill from low led on up        
for( int j = 0; j < numLeds; j++) {
    byte colorindex = scale8( heat[j], 240);
    if(direction < 0) { 
      fireleds[(numLeds-1)-j] = ColorFromPalette( currentPalette, colorindex);
    } else {
      fireleds[j] = ColorFromPalette( currentPalette, colorindex);
    }
  }

}

Hi Daniel - this is a nice solution for two separate animations, not mirrored?

I’m no great coder - but if my two calls to HeatColor uses up resources - could I not use

leds[NUM_LEDS - j - 1] = leds[j];

for Erin’s second leds assignment? Would this use less resources? Thanks

I missed the request for mirrored in the original post (to be fair, I don’t think of fire mirrored even when fanning out from a single point :slight_smile:

If you just want a mirroring something like that would be fine.

We all still learned something :slight_smile: