Christmas Flies error

So, I have two 15m strips of WS2812B (60 leds per/m) on my house so far. Christmas Flies is one of my favorite patterns, but when i put PB settings to more than 500 leds, I get this error. :frowning:

Is there any kind of fix for this?

You’re out of memory – it’s allocating 4x500+ element arrays, plus a few smaller ones here and there. If I remember right, the maximum number of array elements is something like 2k.

The only cure for this is to rewrite the pattern in a more wave-oriented, less array intensive way. I’ve been thinking about doing this for fireflies too, after the holiday festivities settle down a bit.

Yep, memory limits.

One way to handle this would be to wrap or repeat the pattern. Modify it so it uses half (or some portion) of pixelCount and then in render remap the index to wrap or mirror the real pixels onto the subset.

@Mebejedi,
I don’t see that pattern on the site, is that one of yours? I’d love to check it out, and if you post the code I can make some more specific recommendations :slight_smile:

I think it might be related to XmasFlies (bottom of page 3 at time of posting).

I like that one a lot too!

2 Likes

Sorry, yes. It’s XmasFlies. I forgot that I renamed it.

That’s a good idea. It’s pretty random, so sending the same pattern to each strip shouldn’t be too noticeable.

1 Like

Got it!
So just eyeballing it, looks like it splits the sparks into 4 groups, each with their own fading pixel layer, then on render picks the brightest one out of the 4 that share that index and uses that for color.

I think something very similar could be done with 2 pieces of data per pixel: current value, and hue. When drawing a spark, check if the spark value is higher than the pixel value, if so change the hue, otherwise don’t draw the spark. It would render slightly differently, but should be close to what is intended.


I talked about a quick hack to repeat within some subset of the strip, a smaller world for the flies to buzz around in. Since the flies wrap from the end to the beginning when moving, this pattern can be repeated seamlessly!

Here’s a quick modification to repeat a smaller world, plus a few small tweaks. Just change the world size fraction until it fits in memory.

worldFraction = 1/2 // even multiples of 1 will repeat seamlessly

XmasFlies small world.epe (9.0 KB)

// This is a fork of Sparks, 
//  - modified to slow down the sparks
//  - gave them a longer lifetime 
//  - allowed them to loop from one ned to the other

// modified 2020-12-25 by wizard on to allow repeating within some fraction of 
//    the strip to save memory. floor numSparks to integers
//    and small optimizations in render

worldFraction = 1/2 // even multiples of 1 will repeat seamlessly
worldSize = floor(pixelCount * worldFraction)

sparkHue = .0;
sparkHue2 = .3;
sparkHue3 = .6;
sparkHue4 = .1;
sparkSaturation = 1;
numSparks = 1 + floor(worldSize / 5);
decay = 0.98;
pixelDecay = 0.99
maxSpeed = 0.4
newThreshhold = 0.01

sparks = array(numSparks);
sparkX = array(numSparks);
pixels = array(worldSize);
pixels2 = array(worldSize);
pixels3 = array(worldSize);
pixels4 = array(worldSize);

export function beforeRender(delta) {
  delta *= .13;
  
  for (i = 0; i < worldSize; i++) {
    pixels[i] = pixels[i] * pixelDecay;
    pixels2[i] = pixels2[i] * pixelDecay;
    pixels3[i] = pixels3[i] * pixelDecay;
    pixels4[i] = pixels4[i] * pixelDecay;
  }
  
  for (i = 0; i < numSparks; i++) {
    if (sparks[i] >= -newThreshhold && sparks[i] <= newThreshhold) {
      sparks[i] = (maxSpeed/2) - random(maxSpeed);
      sparkX[i] = random(worldSize);
    }
    
    sparks[i] *= decay;
    sparkX[i] += sparks[i] *  delta;
    
    if (sparkX[i] >= worldSize) {
      sparkX[i] = 0;
    }
    
    if (sparkX[i] < 0) {
      sparkX[i] = worldSize - 1;
    }
    if (i % 4 == 0) {
      pixels[(sparkX[i])] += sparks[i];
    } else if (i % 4 == 1) {
      pixels2[(sparkX[i])] += sparks[i];
    } else if (i % 4 == 2) {
      pixels3[(sparkX[i])] += sparks[i];
    } else {
      pixels4[(sparkX[i])] += sparks[i];
    }
  }
}

export function render(index) {
  index = index % worldSize //"wrap" index within the world size
  v = pixels[index];
  v2 = pixels2[index];
  v3 = pixels3[index];
  v4 = pixels4[index];
  var brightnest = max(max(max(v, v2), v3), v4)
  if (brightnest == v) {
    hue = sparkHue;
  } else if (brightnest == v2) {
    hue = sparkHue2;
  } else if (brightnest == v3) {
    hue = sparkHue3;
  } else {
    hue = sparkHue4;
  }
  value = brightnest * brightnest;
  
  //the original didn't use the brightest value and didn't fade much
  //uncomment the next line to use the original:
  // value = (v * v + v2 * v2) * 128
  hsv(hue, sparkSaturation, value);
}
4 Likes