FastLED 3.9.15
Loading...
Searching...
No Matches
Fire2023.ino
Go to the documentation of this file.
1/*This is a fire effect based on the famous Fire2012; but with various small improvements.
2Perlin noise is being used to make a fire layer and a smoke layer;
3and the overlay of both can make a quite realistic effect.
4
5The speed of both need to be adapted to the matrix size and width:
6* Super small matrices (like 3x3 led) don't need the smoke
7* medium sized matrices (8x8 for example) profit from fine tuning both Fire Speed/scale as well as Smoke speed/scale
8
9This code was adapted for a matrix with just four LED columns in 90° around a core and a height of 28.
10
11Right at the bottom of the code, you find a translation matrix that needs to be adapted to your set up. I included
12a link to a helpful page for this.
13
14@repo https://github.com/Anderas2/Fire2023
15@author https://github.com/Anderas2
16
17Demo: https://www.youtube.com/shorts/a_Wr0q9YQs4
18*/
19
20
21#include "FastLED.h"
22#include "fl/xymap.h"
23#include "fl/screenmap.h"
24#include "fl/vector.h"
25
26using namespace fl;
27
28
29// matrix size
30#define WIDTH 4
31#define HEIGHT 28
32#define CentreX (WIDTH / 2) - 1
33#define CentreY (HEIGHT / 2) - 1
34
35// NUM_LEDS = WIDTH * HEIGHT
36#define PIXELPIN 18
37#define NUM_LEDS 120
38#define LAST_VISIBLE_LED 119
39
40
41// Fire properties
42#define BRIGHTNESS 255
43#define FIRESPEED 17
44#define FLAMEHEIGHT 3.8 // the higher the value, the higher the flame
45#define FIRENOISESCALE 125 // small values, softer fire. Big values, blink fire. 0-255
46
47// Smoke screen properties
48// The smoke screen works best for big fire effects. It effectively cuts of a part of the flames
49// from the rest, sometimes; which looks very much fire-like. For small fire effects with low
50// LED count in the height, it doesn't help
51// speed must be a little different and faster from Firespeed, to be visible.
52// Dimmer should be somewhere in the middle for big fires, and low for small fires.
53#define SMOKESPEED 25 // how fast the perlin noise is parsed for the smoke
54#define SMOKENOISE_DIMMER 250 // thickness of smoke: the lower the value, the brighter the flames. 0-255
55#define SMOKENOISESCALE 125 // small values, softer smoke. Big values, blink smoke. 0-255
56
58
59// fire palette roughly like matlab "hot" colormap
60// This was one of the most important parts to improve - fire color makes fire impression.
61// position, r, g, b value.
62// max value for "position" is BRIGHTNESS
64 27, 0, 0, 0, // black
65 28, 140, 40, 0, // red
66 30, 205, 80, 0, // orange
67 155, 255, 100, 0,
68 210, 255, 200, 0, // yellow
69 255, 255, 255, 255 // white
70};
71CRGBPalette32 hotPalette = hot_gp;
72
73// Map XY coordinates to numbers on the LED strip
74uint8_t XY (uint8_t x, uint8_t y);
75
76
77// parameters and buffer for the noise array
78#define NUM_LAYERS 2
79// two layers of perlin noise make the fire effect
80#define FIRENOISE 0
81#define SMOKENOISE 1
82uint32_t x[NUM_LAYERS];
83uint32_t y[NUM_LAYERS];
84uint32_t z[NUM_LAYERS];
87
90
91uint8_t heat[NUM_LEDS];
92
93
95
96void setup() {
97
98 //Serial.begin(115200);
99 // Adjust this for you own setup. Use the hardware SPI pins if possible.
100 // On Teensy 3.1/3.2 the pins are 11 & 13
101 // Details here: https://github.com/FastLED/FastLED/wiki/SPI-Hardware-or-Bit-banging
102 // In case you see flickering / glitching leds, reduce the data rate to 12 MHZ or less
103 auto screenMap = makeScreenMap();
104 FastLED.addLeds<NEOPIXEL, PIXELPIN>(leds, NUM_LEDS).setScreenMap(screenMap); // Pin für Neopixel
105 FastLED.setBrightness(BRIGHTNESS);
106 FastLED.setDither(DISABLE_DITHER);
107}
108
109void Fire2023(uint32_t now);
110
111void loop() {
113 Fire2023(millis());
114 }
115 FastLED.show();
116}
117
120 for (uint16_t y = 0; y < WIDTH; y++) {
121 for (uint16_t x = 0; x < HEIGHT; x++) {
122 vec2f xy = {float(x) * 3, float(y) * 20};
123 lut.push_back(xy);
124 }
125 }
126 return ScreenMap(lut.data(), lut.size(), 1);
127}
128
129void Fire2023(uint32_t now) {
130 // some changing values
131 // these values are produced by perlin noise to add randomness and smooth transitions
132 uint16_t ctrl1 = inoise16(11 * now, 0, 0);
133 uint16_t ctrl2 = inoise16(13 * now, 100000, 100000);
134 uint16_t ctrl = ((ctrl1 + ctrl2) >> 1);
135
136 // parameters for the fire heat map
137 x[FIRENOISE] = 3 * ctrl * FIRESPEED;
138 y[FIRENOISE] = 20 * now * FIRESPEED;
139 z[FIRENOISE] = 5 * now * FIRESPEED;
142
143 //calculate the perlin noise data for the fire
144 for (uint8_t x_count = 0; x_count < WIDTH; x_count++) {
145 uint32_t xoffset = scale_x[FIRENOISE] * (x_count - CentreX);
146 for (uint8_t y_count = 0; y_count < HEIGHT; y_count++) {
147 uint32_t yoffset = scale_y[FIRENOISE] * (y_count - CentreY);
148 uint16_t data = ((inoise16(x[FIRENOISE] + xoffset, y[FIRENOISE] + yoffset, z[FIRENOISE])) + 1);
149 noise[FIRENOISE][x_count][y_count] = data >> 8;
150 }
151 }
152
153 // parameters for the smoke map
154 x[SMOKENOISE] = 3 * ctrl * SMOKESPEED;
155 y[SMOKENOISE] = 20 * now * SMOKESPEED;
156 z[SMOKENOISE] = 5 * now * SMOKESPEED;
159
160 //calculate the perlin noise data for the smoke
161 for (uint8_t x_count = 0; x_count < WIDTH; x_count++) {
162 uint32_t xoffset = scale_x[SMOKENOISE] * (x_count - CentreX);
163 for (uint8_t y_count = 0; y_count < HEIGHT; y_count++) {
164 uint32_t yoffset = scale_y[SMOKENOISE] * (y_count - CentreY);
165 uint16_t data = ((inoise16(x[SMOKENOISE] + xoffset, y[SMOKENOISE] + yoffset, z[SMOKENOISE])) + 1);
166 noise[SMOKENOISE][x_count][y_count] = data / SMOKENOISE_DIMMER;
167 }
168 }
169
170 //copy everything one line up
171 for (uint8_t y = 0; y < HEIGHT - 1; y++) {
172 for (uint8_t x = 0; x < WIDTH; x++) {
173 heat[XY(x, y)] = heat[XY(x, y + 1)];
174 }
175 }
176
177 // draw lowest line - seed the fire where it is brightest and hottest
178 for (uint8_t x = 0; x < WIDTH; x++) {
180 //if (heat[XY(x, HEIGHT-1)] < 200) heat[XY(x, HEIGHT-1)] = 150;
181 }
182
183 // dim the flames based on FIRENOISE noise.
184 // if the FIRENOISE noise is strong, the led goes out fast
185 // if the FIRENOISE noise is weak, the led stays on stronger.
186 // once the heat is gone, it stays dark.
187 for (uint8_t y = 0; y < HEIGHT - 1; y++) {
188 for (uint8_t x = 0; x < WIDTH; x++) {
189 uint8_t dim = noise[FIRENOISE][x][y];
190 // high value in FLAMEHEIGHT = less dimming = high flames
191 dim = dim / FLAMEHEIGHT;
192 dim = 255 - dim;
193 heat[XY(x, y)] = scale8(heat[XY(x, y)] , dim);
194
195 // map the colors based on heatmap
196 // use the heat map to set the color of the LED from the "hot" palette
197 // whichpalette position brightness blend or not
198 leds[XY(x, y)] = ColorFromPalette(hotPalette, heat[XY(x, y)], heat[XY(x, y)], LINEARBLEND);
199
200 // dim the result based on SMOKENOISE noise
201 // this is not saved in the heat map - the flame may dim away and come back
202 // next iteration.
203 leds[XY(x, y)].nscale8(noise[SMOKENOISE][x][y]);
204
205 }
206 }
207}
208
209/* Physical layout of LED strip ****************************/
210uint8_t XY (uint8_t x, uint8_t y) {
211 // any out of bounds address maps to the first hidden pixel
212 // https://macetech.github.io/FastLED-XY-Map-Generator/
213 if ( (x >= WIDTH) || (y >= HEIGHT) ) {
214 return (LAST_VISIBLE_LED + 1);
215 }
216 const uint8_t XYTable[] = {
217 25, 26, 81, 82,
218 25, 27, 81, 83,
219 25, 28, 80, 84,
220 24, 29, 79, 85,
221 23, 30, 78, 86,
222 22, 31, 77, 87,
223 21, 32, 76, 88,
224 20, 33, 75, 89,
225 19, 34, 74, 90,
226 18, 35, 73, 91,
227 17, 36, 72, 92,
228 16, 37, 71, 93,
229 15, 38, 70, 94,
230 14, 39, 69, 95,
231 13, 40, 68, 96,
232 12, 41, 67, 97,
233 11, 42, 66, 98,
234 10, 43, 65, 99,
235 9, 44, 64, 100,
236 8, 45, 63, 101,
237 7, 46, 62, 102,
238 6, 47, 61, 103,
239 5, 48, 60, 104,
240 4, 49, 59, 105,
241 3, 50, 58, 106,
242 2, 51, 57, 107,
243 1, 52, 56, 108,
244 0, 53, 55, 109
245 };
246
247 uint8_t i = (y * WIDTH) + x;
248 uint8_t j = XYTable[i];
249 return j;
250}
251
252
CRGB leds[NUM_LEDS]
Definition Apa102.ino:11
#define NUM_LEDS
Definition Apa102.ino:6
int y
Definition Audio.ino:72
#define WIDTH
Definition Audio.ino:33
int x
Definition Audio.ino:71
#define HEIGHT
Definition Audio.ino:32
#define BRIGHTNESS
Definition Blur.ino:8
CFastLED FastLED
Global LED strip management instance.
Definition FastLED.cpp:58
central include file for FastLED, defines the CFastLED class/object
fl::ScreenMap screenMap
#define SMOKENOISE
Definition Fire2023.ino:81
uint8_t noise[NUM_LAYERS][WIDTH][HEIGHT]
Definition Fire2023.ino:88
#define CentreX
Definition Fire2023.ino:32
#define FLAMEHEIGHT
Definition Fire2023.ino:44
#define SMOKENOISESCALE
Definition Fire2023.ino:55
uint32_t z[NUM_LAYERS]
Definition Fire2023.ino:84
void setup()
Definition Fire2023.ino:96
ScreenMap makeScreenMap()
Definition Fire2023.ino:118
uint8_t heat[NUM_LEDS]
Definition Fire2023.ino:91
CRGBPalette32 hotPalette
Definition Fire2023.ino:71
uint8_t noise2[NUM_LAYERS][WIDTH][HEIGHT]
Definition Fire2023.ino:89
#define SMOKESPEED
Definition Fire2023.ino:53
#define LAST_VISIBLE_LED
Definition Fire2023.ino:38
uint32_t scale_y[NUM_LAYERS]
Definition Fire2023.ino:86
#define PIXELPIN
Definition Fire2023.ino:36
#define FIRENOISE
Definition Fire2023.ino:80
#define FIRENOISESCALE
Definition Fire2023.ino:45
#define SMOKENOISE_DIMMER
Definition Fire2023.ino:54
#define FIRESPEED
Definition Fire2023.ino:43
void Fire2023(uint32_t now)
Definition Fire2023.ino:129
#define NUM_LAYERS
Definition Fire2023.ino:78
#define CentreY
Definition Fire2023.ino:33
uint32_t scale_x[NUM_LAYERS]
Definition Fire2023.ino:85
void loop()
Definition Fire2023.ino:111
unsigned int xy(unsigned int x, unsigned int y)
LED controller for WS2812 LEDs with GRB color order.
Definition FastLED.h:155
size_t size() const
Definition vector.h:435
void push_back(const T &value)
Definition vector.h:442
#define DEFINE_GRADIENT_PALETTE(X)
Defines a static RGB palette very compactly using a series of connected color gradients.
Definition colorutils.h:102
#define DISABLE_DITHER
Disable dithering.
Definition dither_mode.h:11
uint16_t inoise16(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
16-bit, fixed point implementation of Perlin's noise.
Definition noise.cpp:440
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:40
#define EVERY_N_MILLISECONDS(N)
Alias for EVERY_N_MILLIS.
Definition lib8tion.h:1341
uint16_t XY(uint8_t x, uint8_t y)
Definition blur.cpp:21
CRGB ColorFromPalette(const CRGBPalette16 &pal, uint8_t index, uint8_t brightness, TBlendType blendType)
vec2< float > vec2f
Definition geometry.h:301
HeapVector< T > vector
Definition vector.h:1028
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:55