FastLED 3.9.15
Loading...
Searching...
No Matches
FireCylinder.ino
Go to the documentation of this file.
1
2/*
3This demo is best viewed using the FastLED compiler.
4Install: pip install fastled
5Run: fastled <this sketch directory>
6This will compile and preview the sketch in the browser, and enable
7all the UI elements you see below.
8
9OVERVIEW:
10This sketch creates a fire effect on a cylindrical LED display using Perlin noise.
11Unlike a flat matrix, this cylinder connects the left and right edges (x=0 and x=width-1),
12creating a seamless wrap-around effect. The fire appears to rise from the bottom,
13with colors transitioning from black to red/yellow/white (or other palettes).
14*/
15
16// Perlin noise fire procedure
17// 16x16 rgb led cylinder demo
18// Exactly the same as the FireMatrix example, but with a cylinder, meaning that the x=0
19// and x = len-1 are connected.
20// This also showcases the inoise16(x,y,z,t) function which handles 3D+time noise effects.
21// Keep in mind that a cylinder is embedded in a 3D space with time being used to add
22// additional noise to the effect.
23
24// HOW THE CYLINDRICAL FIRE EFFECT WORKS:
25// 1. We use sine and cosine to map the x-coordinate to a circle in 3D space
26// 2. This creates a cylindrical mapping where the left and right edges connect seamlessly
27// 3. We use 4D Perlin noise (x,y,z,t) to generate natural-looking fire patterns
28// 4. The height coordinate controls color fade-out to create the rising fire effect
29// 5. The time dimension adds continuous variation to make the fire look dynamic
30
31#include "FastLED.h" // Main FastLED library for controlling LEDs
32#include "fl/ui.h" // UI components for the FastLED web compiler (sliders, buttons, etc.)
33#include "fl/xymap.h" // Mapping between 1D LED array and 2D coordinates
34#include "fx/time.h" // Time manipulation utilities for animations
35
36using namespace fl; // Use the FastLED namespace for convenience
37
38// Cylinder dimensions - this defines the size of our virtual LED grid
39#define HEIGHT 100 // Number of rows in the cylinder (vertical dimension)
40#define WIDTH 100 // Number of columns in the cylinder (circumference)
41#define SERPENTINE true // Whether the LED strip zigzags back and forth (common in matrix layouts)
42#define BRIGHTNESS 255 // Maximum brightness level (0-255)
43
44// UI elements that appear in the FastLED web compiler interface:
45UITitle title("FireCylinder Demo"); // Title displayed in the UI
46UIDescription description("This Fire demo wraps around the cylinder. It uses Perlin noise to create a fire effect.");
47
48// TimeWarp helps control animation speed - it tracks time and allows speed adjustments
49TimeWarp timeScale(0, 1.0f); // Initialize with 0 starting time and 1.0 speed multiplier
50
51// UI Controls for adjusting the fire effect:
52UISlider scaleXY("Scale", 8, 1, 100, 1); // Controls the overall size of the fire pattern
53UISlider speedY("SpeedY", 1.3, 1, 6, .1); // Controls how fast the fire moves upward
54UISlider scaleX("ScaleX", .3, 0.1, 3, .01); // Controls the horizontal scale (affects the wrap-around)
55UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1); // Controls how fast the fire pattern changes over time (higher = slower)
56UISlider brightness("Brightness", 255, 0, 255, 1); // Controls overall brightness
57UINumberField palette("Palette", 0, 0, 2); // Selects which color palette to use (0=fire, 1=green, 2=blue)
58
59// Array to hold all LED color values - one CRGB struct per LED
61
62// Color palettes define the gradient of colors used for the fire effect
63// Each entry has the format: position (0-255), R, G, B
64
66 // Traditional fire palette - transitions from black to red to yellow to white
67 0, 0, 0, 0, // black (bottom of fire)
68 32, 255, 0, 0, // red (base of flames)
69 190, 255, 255, 0, // yellow (middle of flames)
70 255, 255, 255, 255 // white (hottest part/tips of flames)
71};
72
73DEFINE_GRADIENT_PALETTE(electricGreenFirePal){
74 // Green fire palette - for a toxic/alien look
75 0, 0, 0, 0, // black (bottom)
76 32, 0, 70, 0, // dark green (base)
77 190, 57, 255, 20, // electric neon green (middle)
78 255, 255, 255, 255 // white (hottest part)
79};
80
81DEFINE_GRADIENT_PALETTE(electricBlueFirePal){
82 // Blue fire palette - for a cold/ice fire look
83 0, 0, 0, 0, // Black (bottom)
84 32, 0, 0, 70, // Dark blue (base)
85 128, 20, 57, 255, // Electric blue (middle)
86 255, 255, 255, 255 // White (hottest part)
87};
88
89// Create a mapping between 1D array positions and 2D x,y coordinates
91
92void setup() {
93 Serial.begin(115200); // Initialize serial communication for debugging
94
95 // Initialize the LED strip:
96 // - NEOPIXEL is the LED type
97 // - 3 is the data pin number (for real hardware)
98 // - setScreenMap connects our 2D coordinate system to the 1D LED array
99 FastLED.addLeds<NEOPIXEL, 3>(leds, HEIGHT * WIDTH).setScreenMap(xyMap);
100
101 // Apply color correction for more accurate colors on LED strips
102 FastLED.setCorrection(TypicalLEDStrip);
103}
104
105uint8_t getPaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height,
106 uint32_t y_speed) {
107 // This function calculates which color to use from our palette for each LED
108
109 // Get the scale factor from the UI slider
110 uint16_t scale = scaleXY.as<uint16_t>();
111
112 // Convert width position to an angle (0-255 represents 0-360 degrees)
113 // This maps our flat coordinate to a position on a cylinder
114 float xf = (float)width / (float)max_width; // Normalized position (0.0 to 1.0)
115 uint8_t x = (uint8_t)(xf * 255); // Convert to 0-255 range for trig functions
116
117 // Calculate the sine and cosine of this angle to get 3D coordinates on the cylinder
118 uint32_t cosx = cos8(x); // cos8 returns a value 0-255 representing cosine
119 uint32_t sinx = sin8(x); // sin8 returns a value 0-255 representing sine
120
121 // Apply scaling to the sine/cosine values
122 // This controls how "wide" the noise pattern is around the cylinder
123 float trig_scale = scale * scaleX.value();
124 cosx *= trig_scale;
125 sinx *= trig_scale;
126
127 // Calculate Y coordinate (vertical position) with speed offset for movement
128 uint32_t y = height * scale + y_speed;
129
130 // Calculate Z coordinate (time dimension) - controls how the pattern changes over time
131 uint16_t z = millis32 / invSpeedZ.as<uint16_t>();
132
133 // Generate 16-bit Perlin noise using our 4D coordinates (x,y,z,t)
134 // The << 8 shifts values left by 8 bits (multiplies by 256) to use the full 16-bit range
135 // The last parameter (0) could be replaced with another time variable for more variation
136 uint16_t noise16 = inoise16(cosx << 8, sinx << 8, y << 8, 0);
137
138 // Convert 16-bit noise to 8-bit by taking the high byte
139 uint8_t noise_val = noise16 >> 8;
140
141 // Calculate how much to subtract based on vertical position (height)
142 // This creates the fade-out effect from bottom to top
143 // The formula maps height from 0 to max_height-1 to a value from 255 to 0
144 int8_t subtraction_factor = abs8(height - (max_height - 1)) * 255 /
145 (max_height - 1);
146
147 // Subtract the factor from the noise value (with underflow protection)
148 // qsub8 is a "saturating subtraction" - it won't go below 0
149 return qsub8(noise_val, subtraction_factor);
150}
151CRGBPalette16 getPalette() {
152 // This function returns the appropriate color palette based on the UI selection
153 switch (palette) {
154 case 0:
155 return firepal; // Traditional orange/red fire
156 case 1:
157 return electricGreenFirePal; // Green "toxic" fire
158 case 2:
159 return electricBlueFirePal; // Blue "cold" fire
160 default:
161 return firepal; // Default to traditional fire if invalid value
162 }
163}
164
165void loop() {
166 // The main program loop that runs continuously
167
168 // Set the overall brightness from the UI slider
169 FastLED.setBrightness(brightness);
170
171 // Get the selected color palette
172 CRGBPalette16 myPal = getPalette();
173
174 // Get the current time in milliseconds
175 uint32_t now = millis();
176
177 // Update the animation speed from the UI slider
178 timeScale.setSpeed(speedY);
179
180 // Calculate the current y-offset for animation (makes the fire move)
181 uint32_t y_speed = timeScale.update(now);
182
183 // Loop through every LED in our cylindrical matrix
184 for (int width = 0; width < WIDTH; width++) {
185 for (int height = 0; height < HEIGHT; height++) {
186 // Calculate which color to use from our palette for this LED
187 // This function handles the cylindrical mapping using sine/cosine
188 uint8_t palette_index =
189 getPaletteIndex(now, width, WIDTH, height, HEIGHT, y_speed);
190
191 // Get the actual RGB color from the palette
192 // BRIGHTNESS ensures we use the full brightness range
193 CRGB c = ColorFromPalette(myPal, palette_index, BRIGHTNESS);
194
195 // Convert our 2D coordinates to the 1D array index
196 // We use (WIDTH-1)-width and (HEIGHT-1)-height to flip the coordinates
197 // This makes the fire appear to rise from the bottom
198 int index = xyMap((WIDTH - 1) - width, (HEIGHT - 1) - height);
199
200 // Set the LED color in our array
201 leds[index] = c;
202 }
203 }
204
205 // Send the color data to the actual LEDs
206 FastLED.show();
207}
CRGB leds[NUM_LEDS]
Definition Apa102.ino:11
int y
Definition Audio.ino:72
#define WIDTH
Definition Audio.ino:33
int x
Definition Audio.ino:71
#define HEIGHT
Definition Audio.ino:32
XYMap xyMap(WIDTH, HEIGHT, false)
UISlider scale("Scale", 1.0f, 0.0f, 1.0f, 0.01f)
#define SERPENTINE
Definition Blur2d.ino:16
#define BRIGHTNESS
Definition Blur.ino:8
CFastLED FastLED
Global LED strip management instance.
central include file for FastLED, defines the CFastLED class/object
uint32_t z[NUM_LAYERS]
Definition Fire2023.ino:84
CRGBPalette16 getPalette()
UINumberField palette("Palette", 0, 0, 2)
UIDescription description("This Fire demo wraps around the cylinder. It uses Perlin noise to create a fire effect.")
UISlider speedY("SpeedY", 1.3, 1, 6,.1)
TimeWarp timeScale(0, 1.0f)
void setup()
XYMap xyMap(HEIGHT, WIDTH, SERPENTINE)
uint8_t getPaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height, uint32_t y_speed)
UISlider scaleXY("Scale", 8, 1, 100, 1)
UISlider invSpeedZ("Inverse SpeedZ", 20, 1, 100, 1)
UISlider scaleX("ScaleX",.3, 0.1, 3,.01)
UITitle title("FireCylinder Demo")
UISlider brightness("Brightness", 255, 0, 255, 1)
void loop()
int y_speed
LED controller for WS2812 LEDs with GRB color order.
Definition FastLED.h:155
#define DEFINE_GRADIENT_PALETTE(X)
Defines a static RGB palette very compactly using a series of connected color gradients.
Definition colorutils.h:112
@ TypicalLEDStrip
Typical values for SMD5050 LEDs.
Definition color.h:19
LIB8STATIC_ALWAYS_INLINE int8_t abs8(int8_t i)
Take the absolute value of a signed 8-bit uint8_t.
Definition math8.h:500
LIB8STATIC_ALWAYS_INLINE uint8_t qsub8(uint8_t i, uint8_t j)
Subtract one byte from another, saturating at 0x00.
Definition math8.h:103
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 uint8_t cos8(uint8_t theta)
Fast 8-bit approximation of cos(x).
Definition trig8.h:271
#define sin8
Platform-independent alias of the fast sin implementation.
Definition trig8.h:221
CRGB ColorFromPalette(const CRGBPalette16 &pal, uint8_t index, uint8_t brightness, TBlendType blendType)
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