Skip to content

Instantly share code, notes, and snippets.

@nortonw3
Last active December 26, 2019 10:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nortonw3/79d434aff886c131a484f5d07af56726 to your computer and use it in GitHub Desktop.
Save nortonw3/79d434aff886c131a484f5d07af56726 to your computer and use it in GitHub Desktop.
Stefan Petrick's fire2018 with individual LED strips
#include <FastLED.h>
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define BRIGHTNESS 32
#define FRAMES_PER_SECOND 120
#define NUM_STRIPS 6
#define NUM_LEDS_PER_STRIP 72
#define NUM_LEDS NUM_LEDS_PER_STRIP * NUM_STRIPS
CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];
// the color palette
CRGBPalette16 Pal;
void setup() {
FastLED.addLeds<LED_TYPE, 2, COLOR_ORDER>(leds, 0, NUM_LEDS_PER_STRIP);
FastLED.addLeds<LED_TYPE, 14, COLOR_ORDER>(leds, NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
FastLED.addLeds<LED_TYPE, 7, COLOR_ORDER>(leds, 2 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
FastLED.addLeds<LED_TYPE, 8, COLOR_ORDER>(leds, 3 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
FastLED.addLeds<LED_TYPE, 6, COLOR_ORDER>(leds, 4 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
FastLED.addLeds<LED_TYPE, 20, COLOR_ORDER>(leds, 5 * NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);
//FastLED.setBrightness(BRIGHTNESS);
//FastLED.setDither(DISABLE_DITHER);
FastLED.setMaxPowerInVoltsAndMilliamps(5,2000);
Pal = HeatColors_p;
}
void loop() {
fire2019();
FastLED.show();
}
uint8_t Width = NUM_STRIPS;
uint8_t Height = NUM_LEDS_PER_STRIP;
uint8_t CentreX = (Width / 2) - 1;
uint8_t CentreY = (Height / 2) - 1;
// control parameters for the noise array
uint32_t x;
uint32_t y;
uint32_t z;
uint32_t scale_x;
uint32_t scale_y;
// storage for the noise data
// adjust the size to suit your setup
uint8_t noise[NUM_LEDS_PER_STRIP][NUM_STRIPS];
// heatmap data with the size matrix width * height
uint8_t heat[NUM_LEDS];
void show_fps() {
EVERY_N_MILLIS(100) {
Serial.println(LEDS.getFPS());
}
}
// finds the correct index within a non-serpentine matrix
uint16_t XY( uint8_t x, uint8_t y) {
uint16_t i;
i = (x * NUM_LEDS_PER_STRIP) + y;
// Print x, y locations and cooresponding LED #
return i;
}
void fire2019() {
// get one noise value out of a moving noise space
uint16_t ctrl1 = inoise16(11 * millis(), 0, 0);
// get another one
uint16_t ctrl2 = inoise16(13 * millis(), 100000, 100000);
// average of both to get a more unpredictable curve
uint16_t ctrl = ((ctrl1 + ctrl2) / 2);
// this factor defines the general speed of the heatmap movement
// high value = high speed
uint8_t speed = 27;
// here we define the impact of the wind
// high factor = a lot of movement to the sides
x = 5 * ctrl * speed;
// this is the speed of the upstream itself
// high factor = fast movement
y = 55 * millis() * speed;
// just for ever changing patterns we move through z as well
z = 3 * millis() * speed ;
// ...and dynamically scale the complete heatmap for some changes in the
// size of the heatspots.
// The speed of change is influenced by the factors in the calculation of ctrl1 & 2 above.
// The divisor sets the impact of the size-scaling.
scale_x = ctrl1 / 5;
scale_y = ctrl2 / 10;
// Calculate the noise array based on the control parameters.
uint8_t layer = 0;
for (uint8_t i = 0; i < Width; i++) {
uint32_t ioffset = scale_x * (i - CentreX);
for (uint8_t j = 0; j < Height; j++) {
uint32_t joffset = scale_y * (j - CentreY);
uint16_t data = ((inoise16(x + ioffset, y + joffset, z)) + 1);
noise[i][j] = data >> 8;
}
}
// Draw the first (lowest) line - seed the fire.
// It could be random pixels or anything else as well.
for (uint8_t x = 0; x < Width; x++) {
// draw
leds[XY(x, Height-1)] = ColorFromPalette( Pal, noise[x][0]);
// and fill the lowest line of the heatmap, too
heat[XY(x, Height-1)] = noise[x][0];
}
// Copy the heatmap one line up for the scrolling.
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)];
}
}
// Scale the heatmap values down based on the independent scrolling noise array.
for (uint8_t y = 0; y < Height - 1; y++) {
for (uint8_t x = 0; x < Width; x++) {
// get data from the calculated noise field
uint8_t dim = noise[x][y];
// This number is critical
// If it´s to low (like 1.1) the fire dosn´t go up far enough.
// If it´s to high (like 3) the fire goes up too high.
// It depends on the framerate which number is best.
// If the number is not right you loose the uplifting fire clouds
// which seperate themself while rising up.
dim = dim / 10;
dim = 255 - dim;
// here happens the scaling of the heatmap
heat[XY(x, y)] = scale8(heat[XY(x, y)] , dim);
}
}
// Now just map the colors based on the heatmap.
for (uint8_t y = 0; y < Height - 1; y++) {
for (uint8_t x = 0; x < Width; x++) {
leds[XY(x, y)] = ColorFromPalette( Pal, heat[XY(x, y)]);
}
}
// Done. Bring it on!
//FastLED.show();
// I hate this delay but with 8 bit scaling there is no way arround.
// If the framerate gets too high the frame by frame scaling doesn´s work anymore.
// Basically it does but it´s impossible to see then...
// If you change the framerate here you need to adjust the
// y speed and the dim divisor, too.
delay(10);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment