Skip to content

Instantly share code, notes, and snippets.

@enwi
Forked from StefanPetrick/Fire2018-2.ino
Last active December 20, 2020 22:47
Show Gist options
  • Save enwi/0ce156eaf2e8b996d393df61b643c7da to your computer and use it in GitHub Desktop.
Save enwi/0ce156eaf2e8b996d393df61b643c7da to your computer and use it in GitHub Desktop.
Fire effect v2.0 for FastLED matrix
#include "FastLED.h"
const uint8_t BRIGHTNESS = 255;
// matrix size
const uint8_t WIDTH = 16;
const uint8_t HEIGHT = 16;
const uint16_t NUM_
= WIDTH * HEIGHT;
// parameters and buffer for the noise array
const uint8_t NUM_LAYERS = 2;
uint8_t noise[NUM_LAYERS][WIDTH][HEIGHT];
uint8_t noise2[NUM_LAYERS][WIDTH][HEIGHT];
uint8_t heat[WIDTH][HEIGHT];
// NUM_LEDS = Width * Height
CRGB pixels[NUM_LEDS];
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)>(pixels, 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
// This is for a strips that are aligned vertically, the first strip starts at the botttom right
uint16_t getSerpentineIndex(uint8_t x, uint8_t y)
{
uint16_t i;
if (x & 0x01)
{
i = (x * HEIGHT) + y;
}
else
{
uint8_t reverseY = (HEIGHT - 1) - y;
i = (x * HEIGHT) + reverseY;
}
return i;
}
template <size_t width, size_t height>
void calcNoise(uint8_t (&noise)[width][height], const uint32_t scaleX, const uint32_t scaleY, const uint32_t heatX,
const uint32_t heatY, const uint32_t heatZ)
{
const uint8_t centerX = (width / 2) - 1;
const uint8_t centerY = (height / 2) - 1;
for (uint8_t x = 0; x < width; x++)
{
uint32_t ioffset = scaleX * (x - centerX);
for (uint8_t y = 0; y < height; y++)
{
uint32_t joffset = scaleY * (y - centerY);
uint16_t data = ((inoise16(heatX + ioffset, heatY + joffset, heatZ)) + 1);
noise[x][y] = data >> 8;
}
}
}
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;
// calculate the noise data
calcNoise<WIDTH, HEIGHT>(
noise[0], ctrl1 / 2, ctrl2 / 2, 3 * ctrl * speed, 20 * millis() * speed, 5 * millis() * speed);
// parameters for te brightness mask
speed = 20;
// calculate the noise data
calcNoise<WIDTH, HEIGHT>(
noise[1], ctrl1 / 2, ctrl2 / 2, 3 * ctrl * speed, 20 * millis() * speed, 5 * millis() * speed);
// draw lowest line - seed the fire
for (uint8_t x = 0; x < WIDTH; x++)
{
heat[x][HEIGHT - 1] = noise[0][WIDTH - 1 - x][7]; // was HEIGHT / 2
}
// copy everything one line up
for (uint8_t y = 0; y < HEIGHT - 1; y++)
{
for (uint8_t x = 0; x < WIDTH; x++)
{
heat[x][y] = heat[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 = dim / 2;
dim = 255 - dim;
heat[x][y] = scale8(heat[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 and dim the result based on 2nd noise layer
// pixels[getSerpentineIndex(x, y)] = CRGB(heat[x][y], 1, 0).nscale8(noise[1][x][y]);
pixels[getSerpentineIndex(x, y)] = ColorFromPalette(HeatColors_p, heat[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