Skip to content

Instantly share code, notes, and snippets.

@StefanPetrick
Last active December 8, 2023 02:44
Show Gist options
  • Save StefanPetrick/819e873492f344ebebac5bcd2fdd8aa8 to your computer and use it in GitHub Desktop.
Save StefanPetrick/819e873492f344ebebac5bcd2fdd8aa8 to your computer and use it in GitHub Desktop.
Fire effect v2.0 for FastLED matrix
#include "FastLED.h"
// matrix size
uint8_t Width = 16;
uint8_t Height = 16;
uint8_t CentreX = (Width / 2) - 1;
uint8_t CentreY = (Height / 2) - 1;
// NUM_LEDS = Width * Height
#define NUM_LEDS 256
#define BRIGHTNESS 255
CRGB leds[NUM_LEDS];
// parameters and buffer for the noise array
#define NUM_LAYERS 2
uint32_t x[NUM_LAYERS];
uint32_t y[NUM_LAYERS];
uint32_t z[NUM_LAYERS];
uint32_t scale_x[NUM_LAYERS];
uint32_t scale_y[NUM_LAYERS];
uint8_t noise[NUM_LAYERS][16][16];
uint8_t noise2[NUM_LAYERS][16][16];
uint8_t heat[256];
void setup() {
Serial.begin(115200);
// Adjust this for you own setup. Use the hardware SPI pins if possible.
// On Teensy 3.1/3.2 the pins are 11 & 13
// Details here: https://github.com/FastLED/FastLED/wiki/SPI-Hardware-or-Bit-banging
// In case you see flickering / glitching leds, reduce the data rate to 12 MHZ or less
LEDS.addLeds<APA102, 11, 13, BGR, DATA_RATE_MHZ(12)>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
FastLED.setDither(DISABLE_DITHER);
}
void loop() {
Fire2018_2();
//show_fps();
}
// check the Serial Monitor for fps rate
void show_fps() {
EVERY_N_MILLIS(100) {
Serial.println(LEDS.getFPS());
}
}
// this finds the right index within a serpentine matrix
uint16_t XY( uint8_t x, uint8_t y) {
uint16_t i;
if ( y & 0x01) {
uint8_t reverseX = (Width - 1) - x;
i = (y * Width) + reverseX;
} else {
i = (y * Width) + x;
}
return i;
}
void Fire2018_2() {
// some changing values
uint16_t ctrl1 = inoise16(11 * millis(), 0, 0);
uint16_t ctrl2 = inoise16(13 * millis(), 100000, 100000);
uint16_t ctrl = ((ctrl1 + ctrl2) / 2);
// parameters for the heatmap
uint16_t speed = 25;
x[0] = 3 * ctrl * speed;
y[0] = 20 * millis() * speed;
z[0] = 5 * millis() * speed ;
scale_x[0] = ctrl1 / 2;
scale_y[0] = ctrl2 / 2;
//calculate the noise data
uint8_t layer = 0;
for (uint8_t i = 0; i < Width; i++) {
uint32_t ioffset = scale_x[layer] * (i - CentreX);
for (uint8_t j = 0; j < Height; j++) {
uint32_t joffset = scale_y[layer] * (j - CentreY);
uint16_t data = ((inoise16(x[layer] + ioffset, y[layer] + joffset, z[layer])) + 1);
noise[layer][i][j] = data >> 8;
}
}
// parameters for te brightness mask
speed = 20;
x[1] = 3 * ctrl * speed;
y[1] = 20 * millis() * speed;
z[1] = 5 * millis() * speed ;
scale_x[1] = ctrl1 / 2;
scale_y[1] = ctrl2 / 2;
//calculate the noise data
layer = 1;
for (uint8_t i = 0; i < Width; i++) {
uint32_t ioffset = scale_x[layer] * (i - CentreX);
for (uint8_t j = 0; j < Height; j++) {
uint32_t joffset = scale_y[layer] * (j - CentreY);
uint16_t data = ((inoise16(x[layer] + ioffset, y[layer] + joffset, z[layer])) + 1);
noise[layer][i][j] = data >> 8;
}
}
// draw lowest line - seed the fire
for (uint8_t x = 0; x < Width; x++) {
heat[XY(x, 15)] = noise[0][15 - x][7];
}
//copy everything one line up
for (uint8_t y = 0; y < Height - 1; y++) {
for (uint8_t x = 0; x < Width; x++) {
heat[XY(x, y)] = heat[XY(x, y + 1)];
}
}
//dim
for (uint8_t y = 0; y < Height - 1; y++) {
for (uint8_t x = 0; x < Width; x++) {
uint8_t dim = noise[0][x][y];
// high value = high flames
dim = dim / 1.7;
dim = 255 - dim;
heat[XY(x, y)] = scale8(heat[XY(x, y)] , dim);
}
}
for (uint8_t y = 0; y < Height; y++) {
for (uint8_t x = 0; x < Width; x++) {
// map the colors based on heatmap
leds[XY(x, y)] = CRGB( heat[XY(x, y)], 1 , 0);
// dim the result based on 2nd noise layer
leds[XY(x, y)].nscale8(noise[1][x][y]);
}
}
FastLED.show();
delay(8);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment