Last active
December 26, 2019 10:19
-
-
Save nortonw3/79d434aff886c131a484f5d07af56726 to your computer and use it in GitHub Desktop.
Stefan Petrick's fire2018 with individual LED strips
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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