FastLED 3.9.15
Loading...
Searching...
No Matches
FireMatrix.h
Go to the documentation of this file.
1/*
2This demo is best viewed using the FastLED compiler.
3
4Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
5
6Python
7
8Install: pip install fastled
9Run: fastled <this sketch directory>
10This will compile and preview the sketch in the browser, and enable
11all the UI elements you see below.
12
13OVERVIEW:
14This sketch creates a fire effect using Perlin noise on a matrix of LEDs.
15The fire appears to move upward with colors transitioning from white and yellow at the bottom,
16through orange in the middle, to red at the top, with black space above (for the default palette).
17*/
18
19// Perlin noise fire procedure
20// 16x16 rgb led matrix demo
21// Yaroslaw Turbin, 22.06.2020
22// https://vk.com/ldirko
23// https://www.reddit.com/user/ldirko/
24// https://www.reddit.com/r/FastLED/comments/hgu16i/my_fire_effect_implementation_based_on_perlin/
25// Based on the code found at: https://editor.soulmatelights.com/gallery/1229-
26
27// HOW THE FIRE EFFECT WORKS:
28// 1. We use Perlin noise with time offset for X and Z coordinates
29// to create a naturally scrolling fire pattern that changes over time
30// 2. We distort the fire noise to make it look more realistic
31// 3. We subtract a value based on Y coordinate to shift the fire color in the palette
32// (not just brightness). This creates a fade-out effect from the bottom of the matrix to the top
33// 4. The palette is carefully designed to give realistic fire colors
34
35#if defined(__AVR__)
36// Platform does not have enough memory
37void setup() {}
38void loop() {}
39#else
40
41#include "FastLED.h" // Main FastLED library for controlling LEDs
42#include "fl/ui/ui.h" // UI components for the FastLED web compiler (sliders, etc.)
43#include "fl/math/xymap.h" // Mapping between 1D LED array and 2D coordinates
44#include "fl/fx/time.h" // Time manipulation utilities
45
46// Use the FastLED namespace for convenience
47
48// Matrix dimensions - this defines the size of our virtual LED grid
49#define HEIGHT 100 // Number of rows in the matrix
50#define WIDTH 100 // Number of columns in the matrix
51#define SERPENTINE true // Whether the LED strip zigzags back and forth (common in matrix layouts)
52#define BRIGHTNESS 255 // Maximum brightness level (0-255)
53
54// fl::TimeWarp helps control animation speed - it tracks time and allows speed adjustments
55fl::TimeWarp timeScale(0, 1.0f); // Initialize with 0 starting time and 1.0 speed multiplier
56
57// UI Controls that appear in the FastLED web compiler interface:
58fl::UISlider scaleXY("Scale", 20, 1, 100, 1); // Controls the size of the fire pattern
59fl::UISlider speedY("SpeedY", 1, 1, 6, .1); // Controls how fast the fire moves upward
60fl::UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1); // Controls how fast the fire pattern changes over time (higher = slower)
61fl::UISlider brightness("Brightness", 255, 0, 255, 1); // Controls overall brightness
62UINumberField palette("Palette", 0, 0, 2); // Selects which color palette to use (0=fire, 1=green, 2=blue)
63
64// Array to hold all LED color values - one fl::CRGB struct per LED
66
67// Color palettes define the gradient of colors used for the fire effect
68// Each entry has the format: position (0-255), R, G, B
69
71 // Traditional fire palette - transitions from white to yellow to red
72 0, 0, 0, 0, // black (space above fire)
73 32, 255, 0, 0, // red (tips of flames)
74 190, 255, 255, 0, // yellow (middle of flames)
75 255, 255, 255, 255 // white (hottest part/base of flames)
76};
77
78DEFINE_GRADIENT_PALETTE(electricGreenFirePal){
79 // Green fire palette - for a toxic/alien look
80 0, 0, 0, 0, // black (space above fire)
81 32, 0, 70, 0, // dark green (tips of flames)
82 190, 57, 255, 20, // electric neon green (middle of flames)
83 255, 255, 255, 255 // white (hottest part/base of flames)
84};
85
86DEFINE_GRADIENT_PALETTE(electricBlueFirePal) {
87 // Blue fire palette - for a cold/ice fire look
88 0, 0, 0, 0, // Black (space above fire)
89 32, 0, 0, 70, // Dark blue (tips of flames)
90 128, 20, 57, 255, // Electric blue (middle of flames)
91 255, 255, 255, 255 // White (hottest part/base of flames)
92};
93
94// Create a mapping between 1D fl::array positions and 2D x,y coordinates
96
97void setup() {
98 Serial.begin(115200); // Initialize serial communication for debugging
99
100 // Initialize the LED strip:
101 // - NEOPIXEL is the LED type
102 // - 3 is the data pin number (for real hardware)
103 // - setScreenMap connects our 2D coordinate system to the 1D LED array
104
105 fl::ScreenMap screen_map = xyMap.toScreenMap();
106 screen_map.setDiameter(0.1f); // Set the diameter for the cylinder (0.2 cm per LED)
107 FastLED.addLeds<NEOPIXEL, 3>(leds, HEIGHT * WIDTH).setScreenMap(screen_map);
108
109 // Apply color correction for more accurate colors on LED strips
110 FastLED.setCorrection(TypicalLEDStrip);
111}
112
113uint8_t getPaletteIndex(uint32_t millis32, int i, int j, uint32_t y_speed) {
114 // This function calculates which color to use from our palette for each LED
115
116 // Get the scale factor from the UI slider (controls the "size" of the fire)
117 uint16_t scale = scaleXY.as<uint16_t>();
118
119 // Calculate 3D coordinates for the Perlin noise function:
120 uint16_t x = i * scale; // X position (horizontal in matrix)
121 uint32_t y = j * scale + y_speed; // Y position (vertical) + movement offset
122 uint16_t z = millis32 / invSpeedZ.as<uint16_t>(); // Z position (time dimension)
123
124 // Generate 16-bit Perlin noise value using these coordinates
125 // The << 8 shifts values left by 8 bits (multiplies by 256) to use the full 16-bit range
126 uint16_t noise16 = inoise16(x << 8, y << 8, z << 8);
127
128 // Convert 16-bit noise to 8-bit by taking the high byte (>> 8 shifts right by 8 bits)
129 uint8_t noise_val = noise16 >> 8;
130
131 // Calculate how much to subtract based on vertical position (j)
132 // This creates the fade-out effect from bottom to top
133 // abs8() ensures we get a positive value
134 // The formula maps j from 0 to HEIGHT-1 to a value from 255 to 0
135 int8_t subtraction_factor = abs8(j - (HEIGHT - 1)) * 255 / (HEIGHT - 1);
136
137 // Subtract the factor from the noise value (with underflow protection)
138 // qsub8 is a "saturating subtraction" - it won't go below 0
139 return qsub8(noise_val, subtraction_factor);
140}
141
142fl::CRGBPalette16 getPalette() {
143 // This function returns the appropriate color palette based on the UI selection
144 switch (palette) {
145 case 0:
146 return firepal; // Traditional orange/red fire
147 case 1:
148 return electricGreenFirePal; // Green "toxic" fire
149 case 2:
150 return electricBlueFirePal; // Blue "cold" fire
151 default:
152 return firepal; // Default to traditional fire if invalid value
153 }
154}
155
156void loop() {
157 // The main program loop that runs continuously
158
159 // Set the overall brightness from the UI slider
160 FastLED.setBrightness(brightness);
161
162 // Get the selected color palette
163 fl::CRGBPalette16 myPal = getPalette();
164
165 // Get the current time in milliseconds
166 uint32_t now = fl::millis();
167
168 // Update the animation speed from the UI slider
169 timeScale.setSpeed(speedY);
170
171 // Calculate the current y-offset for animation (makes the fire move)
172 uint32_t y_speed = timeScale.update(now);
173
174 // Loop through every LED in our matrix
175 for (int i = 0; i < WIDTH; i++) {
176 for (int j = 0; j < HEIGHT; j++) {
177 // Calculate which color to use from our palette for this LED
178 uint8_t palette_index = getPaletteIndex(now, i, j, y_speed);
179
180 // Get the actual RGB color from the palette
181 // BRIGHTNESS ensures we use the full brightness range
182 fl::CRGB c = ColorFromPalette(myPal, palette_index, BRIGHTNESS);
183
184 // Convert our 2D coordinates (i,j) to the 1D fl::array index
185 // We use (WIDTH-1)-i and (HEIGHT-1)-j to flip the coordinates
186 // This makes the fire appear to rise from the bottom
187 int index = xyMap((WIDTH - 1) - i, (HEIGHT - 1) - j);
188
189 // Set the LED color in our fl::array
190 leds[index] = c;
191 }
192 }
193
194 // Send the color data to the actual LEDs
195 FastLED.show();
196}
197
198#endif
fl::XYMap xyMap
fl::CRGB leds[NUM_LEDS]
fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255)
#define BRIGHTNESS
int y
Definition simple.h:93
int x
Definition simple.h:92
#define SERPENTINE
Definition Blur2d.ino:29
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
uint32_t z[NUM_LAYERS]
Definition Fire2023.h:93
fl::UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1)
UINumberField palette("Palette", 0, 0, 2)
fl::UISlider scaleXY("Scale", 8, 1, 100, 1)
fl::TimeWarp timeScale(0, 1.0f)
fl::UISlider speedY("SpeedY", 1.3, 1, 6,.1)
fl::UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1)
UINumberField palette("Palette", 0, 0, 2)
void setup()
Definition FireMatrix.h:97
uint8_t getPaletteIndex(uint32_t millis32, int i, int j, uint32_t y_speed)
Definition FireMatrix.h:113
fl::UISlider scaleXY("Scale", 20, 1, 100, 1)
fl::UISlider speedY("SpeedY", 1, 1, 6,.1)
fl::TimeWarp timeScale(0, 1.0f)
fl::CRGBPalette16 getPalette()
Definition FireMatrix.h:142
void loop()
Definition FireMatrix.h:156
fl::UISlider scale("Scale", 4,.1, 4,.1)
int y_speed
#define WIDTH
#define HEIGHT
void setDiameter(float diameter) FL_NOEXCEPT
#define DEFINE_GRADIENT_PALETTE(X)
CRGB ColorFromPalette(const CRGBPalette16 &pal, fl::u8 index, fl::u8 brightness, TBlendType blendType)
fl::u16 inoise16(fl::u32 x, fl::u32 y, fl::u32 z, fl::u32 t)
@ TypicalLEDStrip
Typical values for SMD5050 LEDs.
Definition color.h:15
fl::u32 millis()
Universal millisecond timer - returns milliseconds since system startup.
Representation of an 8-bit RGB pixel (Red, Green, Blue)
Definition crgb.h:38
#define Serial
Definition serial.h:304
Aggregator header for the fl/ui/ family of per-element UI types.