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*/
17
18
19#include "FastLED.h"
20#include "fl/xymap.h"
21#include "fl/screenmap.h"
22#include "fl/vector.h"
23
24using namespace fl;
25
26
27// matrix size
28#define WIDTH 4
29#define HEIGHT 28
30#define CentreX (WIDTH / 2) - 1
31#define CentreY (HEIGHT / 2) - 1
32
33// NUM_LEDS = WIDTH * HEIGHT
34#define PIXELPIN 18
35#define NUM_LEDS 120
36#define LAST_VISIBLE_LED 119
37
38
39// Fire properties
40#define BRIGHTNESS 255
41#define FIRESPEED 17
42#define FLAMEHEIGHT 3.8 // the higher the value, the higher the flame
43#define FIRENOISESCALE 125 // small values, softer fire. Big values, blink fire. 0-255
44
45// Smoke screen properties
46// The smoke screen works best for big fire effects. It effectively cuts of a part of the flames
47// from the rest, sometimes; which looks very much fire-like. For small fire effects with low
48// LED count in the height, it doesn't help
49// speed must be a little different and faster from Firespeed, to be visible.
50// Dimmer should be somewhere in the middle for big fires, and low for small fires.
51#define SMOKESPEED 25 // how fast the perlin noise is parsed for the smoke
52#define SMOKENOISE_DIMMER 250 // thickness of smoke: the lower the value, the brighter the flames. 0-255
53#define SMOKENOISESCALE 125 // small values, softer smoke. Big values, blink smoke. 0-255
54
56
57// fire palette roughly like matlab "hot" colormap
58// This was one of the most important parts to improve - fire color makes fire impression.
59// position, r, g, b value.
60// max value for "position" is BRIGHTNESS
62 27, 0, 0, 0, // black
63 28, 140, 40, 0, // red
64 30, 205, 80, 0, // orange
65 155, 255, 100, 0,
66 210, 255, 200, 0, // yellow
67 255, 255, 255, 255 // white
68};
70
71// Map XY coordinates to numbers on the LED strip
72uint8_t XY (uint8_t x, uint8_t y);
73
74
75// parameters and buffer for the noise array
76#define NUM_LAYERS 2
77// two layers of perlin noise make the fire effect
78#define FIRENOISE 0
79#define SMOKENOISE 1
80uint32_t x[NUM_LAYERS];
81uint32_t y[NUM_LAYERS];
82uint32_t z[NUM_LAYERS];
85
88
89uint8_t heat[NUM_LEDS];
90
91
93
94void setup() {
95
96 //Serial.begin(115200);
97 // Adjust this for you own setup. Use the hardware SPI pins if possible.
98 // On Teensy 3.1/3.2 the pins are 11 & 13
99 // Details here: https://github.com/FastLED/FastLED/wiki/SPI-Hardware-or-Bit-banging
100 // In case you see flickering / glitching leds, reduce the data rate to 12 MHZ or less
101 auto screenMap = makeScreenMap();
102 FastLED.addLeds<NEOPIXEL, PIXELPIN>(leds, NUM_LEDS).setScreenMap(screenMap); // Pin für Neopixel
103 FastLED.setBrightness(BRIGHTNESS);
104 FastLED.setDither(DISABLE_DITHER);
105}
106
107void Fire2023(uint32_t now);
108
109void loop() {
111 Fire2023(millis());
112 }
113 FastLED.show();
114}
115
118 for (uint16_t y = 0; y < WIDTH; y++) {
119 for (uint16_t x = 0; x < HEIGHT; x++) {
120 pair_xy_float xy = {float(x) * 3, float(y) * 20};
121 lut.push_back(xy);
122 }
123 }
124 return ScreenMap(lut.data(), lut.size(), 1);
125}
126
127void Fire2023(uint32_t now) {
128 // some changing values
129 // these values are produced by perlin noise to add randomness and smooth transitions
130 uint16_t ctrl1 = inoise16(11 * now, 0, 0);
131 uint16_t ctrl2 = inoise16(13 * now, 100000, 100000);
132 uint16_t ctrl = ((ctrl1 + ctrl2) >> 1);
133
134 // parameters for the fire heat map
135 x[FIRENOISE] = 3 * ctrl * FIRESPEED;
136 y[FIRENOISE] = 20 * now * FIRESPEED;
137 z[FIRENOISE] = 5 * now * FIRESPEED;
140
141 //calculate the perlin noise data for the fire
142 for (uint8_t x_count = 0; x_count < WIDTH; x_count++) {
143 uint32_t xoffset = scale_x[FIRENOISE] * (x_count - CentreX);
144 for (uint8_t y_count = 0; y_count < HEIGHT; y_count++) {
145 uint32_t yoffset = scale_y[FIRENOISE] * (y_count - CentreY);
146 uint16_t data = ((inoise16(x[FIRENOISE] + xoffset, y[FIRENOISE] + yoffset, z[FIRENOISE])) + 1);
147 noise[FIRENOISE][x_count][y_count] = data >> 8;
148 }
149 }
150
151 // parameters for the smoke map
152 x[SMOKENOISE] = 3 * ctrl * SMOKESPEED;
153 y[SMOKENOISE] = 20 * now * SMOKESPEED;
154 z[SMOKENOISE] = 5 * now * SMOKESPEED;
157
158 //calculate the perlin noise data for the smoke
159 for (uint8_t x_count = 0; x_count < WIDTH; x_count++) {
160 uint32_t xoffset = scale_x[SMOKENOISE] * (x_count - CentreX);
161 for (uint8_t y_count = 0; y_count < HEIGHT; y_count++) {
162 uint32_t yoffset = scale_y[SMOKENOISE] * (y_count - CentreY);
163 uint16_t data = ((inoise16(x[SMOKENOISE] + xoffset, y[SMOKENOISE] + yoffset, z[SMOKENOISE])) + 1);
164 noise[SMOKENOISE][x_count][y_count] = data / SMOKENOISE_DIMMER;
165 }
166 }
167
168 //copy everything one line up
169 for (uint8_t y = 0; y < HEIGHT - 1; y++) {
170 for (uint8_t x = 0; x < WIDTH; x++) {
171 heat[XY(x, y)] = heat[XY(x, y + 1)];
172 }
173 }
174
175 // draw lowest line - seed the fire where it is brightest and hottest
176 for (uint8_t x = 0; x < WIDTH; x++) {
178 //if (heat[XY(x, HEIGHT-1)] < 200) heat[XY(x, HEIGHT-1)] = 150;
179 }
180
181 // dim the flames based on FIRENOISE noise.
182 // if the FIRENOISE noise is strong, the led goes out fast
183 // if the FIRENOISE noise is weak, the led stays on stronger.
184 // once the heat is gone, it stays dark.
185 for (uint8_t y = 0; y < HEIGHT - 1; y++) {
186 for (uint8_t x = 0; x < WIDTH; x++) {
187 uint8_t dim = noise[FIRENOISE][x][y];
188 // high value in FLAMEHEIGHT = less dimming = high flames
189 dim = dim / FLAMEHEIGHT;
190 dim = 255 - dim;
191 heat[XY(x, y)] = scale8(heat[XY(x, y)] , dim);
192
193 // map the colors based on heatmap
194 // use the heat map to set the color of the LED from the "hot" palette
195 // whichpalette position brightness blend or not
197
198 // dim the result based on SMOKENOISE noise
199 // this is not saved in the heat map - the flame may dim away and come back
200 // next iteration.
201 leds[XY(x, y)].nscale8(noise[SMOKENOISE][x][y]);
202
203 }
204 }
205}
206
207/* Physical layout of LED strip ****************************/
208uint8_t XY (uint8_t x, uint8_t y) {
209 // any out of bounds address maps to the first hidden pixel
210 // https://macetech.github.io/FastLED-XY-Map-Generator/
211 if ( (x >= WIDTH) || (y >= HEIGHT) ) {
212 return (LAST_VISIBLE_LED + 1);
213 }
214 const uint8_t XYTable[] = {
215 25, 26, 81, 82,
216 25, 27, 81, 83,
217 25, 28, 80, 84,
218 24, 29, 79, 85,
219 23, 30, 78, 86,
220 22, 31, 77, 87,
221 21, 32, 76, 88,
222 20, 33, 75, 89,
223 19, 34, 74, 90,
224 18, 35, 73, 91,
225 17, 36, 72, 92,
226 16, 37, 71, 93,
227 15, 38, 70, 94,
228 14, 39, 69, 95,
229 13, 40, 68, 96,
230 12, 41, 67, 97,
231 11, 42, 66, 98,
232 10, 43, 65, 99,
233 9, 44, 64, 100,
234 8, 45, 63, 101,
235 7, 46, 62, 102,
236 6, 47, 61, 103,
237 5, 48, 60, 104,
238 4, 49, 59, 105,
239 3, 50, 58, 106,
240 2, 51, 57, 107,
241 1, 52, 56, 108,
242 0, 53, 55, 109
243 };
244
245 uint8_t i = (y * WIDTH) + x;
246 uint8_t j = XYTable[i];
247 return j;
248}
249
250
CRGB leds[NUM_LEDS]
Definition Apa102.ino:11
#define NUM_LEDS
Definition Apa102.ino:6
#define WIDTH
Definition Blur2d.ino:9
#define HEIGHT
Definition Blur2d.ino:10
#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
#define SMOKENOISE
Definition Fire2023.ino:79
uint8_t noise[NUM_LAYERS][WIDTH][HEIGHT]
Definition Fire2023.ino:86
#define CentreX
Definition Fire2023.ino:30
#define FLAMEHEIGHT
Definition Fire2023.ino:42
#define SMOKENOISESCALE
Definition Fire2023.ino:53
uint32_t z[NUM_LAYERS]
Definition Fire2023.ino:82
void setup()
Definition Fire2023.ino:94
ScreenMap makeScreenMap()
Definition Fire2023.ino:116
uint8_t XY(uint8_t x, uint8_t y)
Definition Fire2023.ino:208
uint32_t x[NUM_LAYERS]
Definition Fire2023.ino:80
uint8_t heat[NUM_LEDS]
Definition Fire2023.ino:89
CRGBPalette32 hotPalette
Definition Fire2023.ino:69
uint8_t noise2[NUM_LAYERS][WIDTH][HEIGHT]
Definition Fire2023.ino:87
#define SMOKESPEED
Definition Fire2023.ino:51
#define LAST_VISIBLE_LED
Definition Fire2023.ino:36
uint32_t scale_y[NUM_LAYERS]
Definition Fire2023.ino:84
#define PIXELPIN
Definition Fire2023.ino:34
#define FIRENOISE
Definition Fire2023.ino:78
#define FIRENOISESCALE
Definition Fire2023.ino:43
#define SMOKENOISE_DIMMER
Definition Fire2023.ino:52
uint32_t y[NUM_LAYERS]
Definition Fire2023.ino:81
#define FIRESPEED
Definition Fire2023.ino:41
void Fire2023(uint32_t now)
Definition Fire2023.ino:127
#define NUM_LAYERS
Definition Fire2023.ino:76
#define CentreY
Definition Fire2023.ino:31
uint32_t scale_x[NUM_LAYERS]
Definition Fire2023.ino:83
void loop()
Definition Fire2023.ino:109
ScreenMap screenMap
Definition FxSdCard.ino:60
unsigned int xy(unsigned int x, unsigned int y)
RGB color palette with 32 discrete values.
LED controller for WS2812 LEDs with GRB color order.
Definition FastLED.h:138
size_t size() const
Definition vector.h:311
void push_back(const T &value)
Definition vector.h:324
#define DEFINE_GRADIENT_PALETTE(X)
Defines a static RGB palette very compactly using a series of connected color gradients.
Definition colorutils.h:69
#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:466
@ LINEARBLEND
Linear interpolation between palette entries, with wrap-around from end to the beginning again.
CRGB ColorFromPalette(const CRGBPalette16 &pal, uint8_t index, uint8_t brightness, TBlendType blendType)
Get a color from a palette.
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:34
#define EVERY_N_MILLISECONDS(N)
Alias for EVERY_N_MILLIS.
Definition lib8tion.h:1359
pair_xy< float > pair_xy_float
Definition lut.h:24
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:54