Overview
Enhanced version of the FxNoiseRing example that automatically cycles through different noise effects and color palettes, providing dynamic visual variety with user controls for manual selection.
Featured Implementation: Plasma Waves - Advanced graphics technique showcasing sine wave interference with noise modulation, demonstrating sophisticated mathematical visualization on circular LED arrays.
Core Features
Automatic Cycling
User Interface Controls
- Variants Dropdown: "Noise Variants" - Manual selection of noise effects (0-9)
- Palettes Dropdown: "Color Palettes" - Manual selection of color schemes (0-4)
- Auto Cycle Checkbox: "Auto Cycle" - Enable/disable automatic rotation
- Existing Controls: Retain all current sliders (Brightness, Scale, Time Bitshift, Time Scale, PIR, Dither)
10 Noise Variations - Detailed Algorithmic Implementation
1. "Cosmic Swirl" - Enhanced Perlin Flow
- Description: Classic perlin noise with slow, flowing movements using multi-octave complexity
- Parameters: Base noise with moderate scale, gentle time progression
- Characteristics: Smooth gradients, organic flow patterns
Algorithm:
float time_factor = time_ms * 0.0008f;
float noise1 =
inoise16(coord.
x * 2000, coord.
y * 2000, time_factor * 1000) / 65536.0f;
float noise2 =
inoise16(coord.
x * 1000, coord.
y * 1000, time_factor * 2000) / 65536.0f * 0.5f;
float noise3 =
inoise16(coord.
x * 4000, coord.
y * 4000, time_factor * 500) / 65536.0f * 0.25f;
float combined_noise = noise1 +
noise2 + noise3;
uint8_t
hue = (uint8_t)((combined_noise + coord.
angle / (2*
M_PI)) * 255) % 256;
uint8_t sat = 220 + (uint8_t)(abs(
noise2) * 35);
uint8_t val = 180 + (uint8_t)(combined_noise * 75);
}
uint8_t noise2[NUM_LAYERS][WIDTH][HEIGHT]
CRGB drawCosmicSwirl(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
uint16_t inoise16(uint32_t x, uint32_t y, uint32_t z, uint32_t t)
16-bit, fixed point implementation of Perlin's noise.
Representation of an HSV pixel (hue, saturation, value (aka brightness)).
Representation of an RGB pixel (Red, Green, Blue)
2. "Electric Storm" - High-Frequency Chaos
- Description: High-frequency noise with rapid temporal changes creating lightning effects
- Parameters: 8x time acceleration, high spatial frequency, quantized thresholds
- Characteristics: Crackling, energetic, lightning-like patterns
Algorithm:
uint32_t fast_time = time_ms << 3;
float x_noise = coord.
x * 8000;
float y_noise = coord.
y * 8000;
uint16_t noise1 =
inoise16(x_noise, y_noise, fast_time);
uint16_t
noise2 =
inoise16(x_noise + 10000, y_noise + 10000, fast_time + 5000);
uint8_t threshold = 200;
bool lightning = (noise1 >> 8) > threshold || (
noise2 >> 8) > threshold;
if (lightning) {
uint8_t intensity = max((noise1 >> 8) - threshold, (
noise2 >> 8) - threshold) * 4;
return CRGB(intensity, intensity, 255);
} else {
uint8_t
hue = 160 + ((noise1 >> 10) % 32);
return CHSV(
hue, 255, (noise1 >> 8) / 4);
}
}
CRGB drawElectricStorm(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
3. "Lava Lamp" - Slow Blobby Movement
- Description: Slow, blobby movements with high contrast using low-frequency modulation
- Parameters: Ultra-low frequency, high amplitude, threshold-based blob creation
- Characteristics: Large, slow-moving color blobs with organic boundaries
Algorithm:
float slow_time = time_ms * 0.0002f;
float blob_scale = 800;
uint16_t primary_noise =
inoise16(coord.
x * blob_scale, coord.
y * blob_scale, slow_time * 1000);
uint16_t secondary_noise =
inoise16(coord.
x * blob_scale * 0.5f, coord.
y * blob_scale * 0.5f, slow_time * 1500);
float blob_value = (primary_noise + secondary_noise * 0.3f) / 65536.0f;
if (blob_value > 0.6f) {
uint8_t
hue = 0 + (uint8_t)((blob_value - 0.6f) * 400);
} else if (blob_value > 0.3f) {
float edge_factor = (blob_value - 0.3f) / 0.3f;
uint8_t
brightness = (uint8_t)(edge_factor * 255);
} else {
return CHSV(240, 100, 30);
}
}
CRGB drawLavaLamp(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
UISlider brightness("Brightness", 128, 0, 255, 1)
4. "Digital Rain" - Matrix Cascade
- Description: Matrix-style cascading effect using vertical noise mapping
- Parameters: Angle-to-vertical conversion, time-based cascade, stream segregation
- Characteristics: Vertical streams, binary-like transitions, matrix green
Algorithm:
float vertical_pos = sin(coord.
angle) * 0.5f + 0.5f;
float cascade_speed = 0.002f;
float time_offset = time_ms * cascade_speed;
int stream_id = (int)(coord.
angle * 10) % 8;
float stream_phase = fmod(vertical_pos + time_offset + stream_id * 0.125f, 1.0f);
uint16_t
noise =
inoise16(stream_id * 1000, stream_phase * 10000, time_ms / 4);
uint8_t digital_value = (
noise >> 8) > 128 ? 255 : 0;
uint8_t green_intensity = digital_value;
uint8_t trailing = max(0, green_intensity - (int)(stream_phase * 200));
return CRGB(0, green_intensity, trailing / 2);
}
uint8_t noise[NUM_LAYERS][WIDTH][HEIGHT]
CRGB drawDigitalRain(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
5. "Plasma Waves" - FEATURED IMPLEMENTATION
- Description: Multiple overlapping sine waves with noise modulation creating electromagnetic plasma effects
- Parameters: 4-source wave interference, noise modulation, dynamic color mapping
- Characteristics: Smooth wave interference patterns, flowing electromagnetic appearance
Algorithm:
private:
struct WaveSource {
};
{0.5f, 0.5f, 1.0f, 1.0f, 0.8f},
{0.0f, 0.0f, 1.5f, 0.8f, 1.2f},
{1.0f, 1.0f, 0.8f, 1.2f, 0.6f},
{0.5f, 0.0f, 1.2f, 0.9f, 1.0f}
};
public:
float time_scaled = time_ms * params.
time_scale * 0.001f;
float wave_sum = 0.0f;
for (int i = 0; i < 4; i++) {
float distance = sqrt(dx*dx + dy*dy);
float wave_phase = distance *
sources[i].frequency + time_scaled *
sources[i].phase_speed;
wave_sum += sin(wave_phase) *
sources[i].amplitude;
}
float noise_x = coord.
x * 0xffff * noise_scale;
float noise_y = coord.
y * 0xffff * noise_scale;
float noise_mod = (
inoise16(noise_x, noise_y, noise_time) - 32768) / 65536.0f;
}
private:
float normalized = (wave_value + 4.0f) / 8.0f;
normalized = constrain(normalized, 0.0f, 1.0f);
uint8_t
hue = (uint8_t)(normalized * 255.0f + params.
hue_offset) % 256;
float intensity = abs(wave_value);
uint8_t sat = (uint8_t)(192 + intensity * 63);
uint8_t val = (uint8_t)(normalized * 255.0f * params.
brightness);
return CHSV(
hue, sat, val);
}
};
};
CRGB calculatePlasmaPixel(const RingCoord &coord, uint32_t time_ms, const PlasmaParams ¶ms)
CRGB mapWaveToColor(float wave_value, const PlasmaParams ¶ms)
6. "Glitch City" - Chaotic Digital Artifacts
- Description: Chaotic, stuttering effects with quantized noise and bit manipulation
- Parameters: Time quantization, XOR operations, random bit shifts
- Characteristics: Harsh transitions, digital artifacts, strobe-like effects
Algorithm:
uint32_t glitch_time = (time_ms / 100) * 100;
uint16_t noise1 =
inoise16(coord.
x * 3000, coord.
y * 3000, glitch_time);
uint16_t glitch_value = noise1 ^
noise2;
uint8_t r = (glitch_value >> (time_ms % 8)) & 0xFF;
uint8_t g = (glitch_value << (time_ms % 5)) & 0xFF;
uint8_t b = ((noise1 |
noise2) >> 4) & 0xFF;
if ((glitch_value & 0xF000) == 0xF000) {
return CRGB(255, 255, 255);
}
}
CRGB drawGlitchCity(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
7. "Ocean Depths" - Underwater Currents
- Description: Slow, deep undulations mimicking underwater currents with blue-green bias
- Parameters: Ultra-low frequency, blue-green color bias, depth-based brightness
- Characteristics: Calm, flowing, deep water feel with gentle undulations
Algorithm:
float ocean_time = time_ms * 0.0005f;
float current1 =
inoise16(coord.
x * 1200, coord.
y * 1200, ocean_time * 800) / 65536.0f;
float current2 =
inoise16(coord.
x * 2400, coord.
y * 2400, ocean_time * 600) / 65536.0f * 0.5f;
float current3 =
inoise16(coord.
x * 600, coord.
y * 600, ocean_time * 1000) / 65536.0f * 0.3f;
float depth_factor = current1 + current2 + current3;
uint8_t base_hue = 140;
uint8_t hue_variation = (uint8_t)(abs(depth_factor) * 40);
uint8_t final_hue = (base_hue + hue_variation) % 256;
uint8_t depth_brightness = 120 + (uint8_t)(depth_factor * 135);
uint8_t saturation = 200 + (uint8_t)(abs(current2) * 55);
return CHSV(final_hue, saturation, depth_brightness);
}
CRGB drawOceanDepths(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
8. "Fire Dance" - Upward Flame Simulation
- Description: Flickering, flame-like patterns with upward bias and turbulent noise
- Parameters: Vertical gradient bias, turbulent noise, fire color palette
- Characteristics: Orange/red dominated, upward movement, flickering
Algorithm:
float vertical_component = sin(coord.
angle) * 0.5f + 0.5f;
float flame_x = coord.
x * 1500;
float flame_y = coord.
y * 1500 + time_ms * 0.003f;
uint16_t turbulence =
inoise16(flame_x, flame_y, time_ms);
float flame_intensity = (turbulence / 65536.0f) * (1.0f - vertical_component * 0.3f);
uint8_t base_hue = 0;
uint8_t hue_variation = (uint8_t)(flame_intensity * 45);
uint8_t final_hue = (base_hue + hue_variation) % 256;
uint8_t saturation = 255 - (uint8_t)(vertical_component * 100);
uint8_t
brightness = (uint8_t)(flame_intensity * 255);
}
CRGB drawFireDance(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
9. "Nebula Drift" - Cosmic Cloud Simulation
- Description: Slow cosmic clouds with starfield sparkles using multi-octave noise
- Parameters: Multiple noise octaves, sparse bright spots, cosmic color palette
- Characteristics: Misty backgrounds with occasional bright stars
Algorithm:
float nebula_time = time_ms * 0.0003f;
float cloud1 =
inoise16(coord.
x * 800, coord.
y * 800, nebula_time * 1000) / 65536.0f;
float cloud2 =
inoise16(coord.
x * 1600, coord.
y * 1600, nebula_time * 700) / 65536.0f * 0.5f;
float cloud3 =
inoise16(coord.
x * 400, coord.
y * 400, nebula_time * 1200) / 65536.0f * 0.25f;
float nebula_density = cloud1 + cloud2 + cloud3;
uint16_t star_noise =
inoise16(coord.
x * 4000, coord.
y * 4000, nebula_time * 200);
bool is_star = (star_noise > 60000);
if (is_star) {
uint8_t star_brightness = 200 + ((star_noise - 60000) / 256);
return CRGB(star_brightness, star_brightness, 255);
} else {
uint8_t nebula_hue = 200 + (uint8_t)(nebula_density * 80);
uint8_t nebula_sat = 150 + (uint8_t)(abs(cloud2) * 105);
uint8_t nebula_bright = 40 + (uint8_t)(nebula_density * 120);
return CHSV(nebula_hue, nebula_sat, nebula_bright);
}
}
CRGB drawNebulaDrift(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
10. "Binary Pulse" - Digital Heartbeat
- Description: Digital heartbeat with expanding/contracting rings using threshold-based noise
- Parameters: Concentric pattern generation, rhythmic pulsing, geometric thresholds
- Characteristics: Rhythmic, geometric, tech-inspired
Algorithm:
float pulse_period = 2000.0f;
float pulse_phase = fmod(time_ms, pulse_period) / pulse_period;
float distance_from_center = sqrt(coord.
x * coord.
x + coord.
y * coord.
y);
float ring_frequency = 5.0f;
float pulse_offset = pulse_phase * 2.0f;
float ring_value = sin((distance_from_center * ring_frequency - pulse_offset) * 2 *
M_PI);
float digital_mod = ((
noise >> 8) > 128) ? 1.0f : -0.5f;
float final_value = ring_value * digital_mod;
if (final_value > 0.3f) {
uint8_t intensity = (uint8_t)(final_value * 255);
return CRGB(intensity, 0, intensity);
} else if (final_value > -0.2f) {
uint8_t dim_intensity = (uint8_t)((final_value + 0.2f) * 500);
return CRGB(0, dim_intensity, 0);
} else {
}
}
CRGB drawBinaryPulse(const RingCoord &coord, uint32_t time_ms, ColorPaletteManager &palette)
5 Color Palettes
1. "Sunset Boulevard"
- Colors: Warm oranges, deep reds, golden yellows
- Description: Classic sunset gradient perfect for relaxing ambiance
- HSV Range: Hue 0-45, high saturation, varying brightness
2. "Ocean Breeze"
- Colors: Deep blues, aqua, seafoam green, white caps
- Description: Cool ocean palette for refreshing visual effects
- HSV Range: Hue 120-210, medium-high saturation
3. "Neon Nights"
- Colors: Electric pink, cyan, purple, lime green
- Description: Cyberpunk-inspired high-contrast palette
- HSV Range: Saturated primaries, high brightness contrasts
4. "Forest Whisper"
- Colors: Deep greens, earth browns, golden highlights
- Description: Natural woodland palette for organic feels
- HSV Range: Hue 60-150, natural saturation levels
5. "Galaxy Express"
- Colors: Deep purples, cosmic blues, silver stars, pink nebula
- Description: Space-themed palette for cosmic adventures
- HSV Range: Hue 200-300, with bright white accents
Implementation Strategy
Core Mathematical Framework
};
coord.
angle = (led_index * 2.0f *
M_PI / num_leds) + time_offset;
return coord;
}
private:
public:
}
}
RingCoord
fastRingCoord(
int led_index,
float time_offset = 0.0f) {
RingCoord coord;
return coord;
}
};
RingCoord calculateRingCoord(int led_index, int num_leds, float time_offset=0.0f)
float cos_table[NUM_LEDS]
RingCoord fastRingCoord(int led_index, float time_offset=0.0f)
float sin_table[NUM_LEDS]
Enhanced Control System with Smooth Transitions
private:
public:
void update(uint32_t now,
bool auto_cycle_enabled, uint8_t manual_variant) {
if (auto_cycle_enabled) {
}
}
}
}
}
CRGB
renderPixel(
const RingCoord& coord, uint32_t time_ms) {
} else {
}
}
private:
}
CRGB
renderVariant(uint8_t variant,
const RingCoord& coord, uint32_t time_ms) {
switch(variant) {
}
}
CRGB lerpCRGB(
const CRGB& a,
const CRGB& b,
float t) {
return CRGB(
a.r + (
int)((b.r - a.r) *
t),
a.g + (
int)((b.g - a.g) *
t),
a.b + (
int)((b.b - a.b) *
t)
);
}
};
float transition_progress
CRGB renderPixel(const RingCoord &coord, uint32_t time_ms)
PlasmaParams plasma_params
void startTransition(uint8_t new_variant, uint32_t now)
static const uint32_t TRANSITION_DURATION
uint32_t transition_start
void update(uint32_t now, bool auto_cycle_enabled, uint8_t manual_variant, const PlasmaParams ¶ms)
CRGB renderVariant(uint8_t variant, const RingCoord &coord, uint32_t time_ms)
PlasmaWaveGenerator plasma_gen
#define EVERY_N_MILLISECONDS(N)
Alias for EVERY_N_MILLIS.
@ Black
<div style='background:#000000;width:4em;height:4em;'></div>
Data Structures and UI Integration
"Cosmic Swirl", "Electric Storm", "Lava Lamp", "Digital Rain", "Plasma Waves",
"Glitch City", "Ocean Depths", "Fire Dance", "Nebula Drift", "Binary Pulse"
};
"Sunset Boulevard", "Ocean Breeze", "Neon Nights", "Forest Whisper", "Galaxy Express"
};
UICheckbox autoCycle("Auto Cycle Effects", true)
NoiseVariantManager variant_manager(palette_manager)
fl::string variant_names[10]
fl::string palette_names[5]
UIDropdown variants("Noise Variants", variant_names)
UIDropdown palettes("Color Palettes", palette_names)
Integration with Existing Framework
Serial.begin(115200);
}
void draw(uint32_t now) {
}
}
uint32_t now = millis();
uint8_t bri =
pir.transition(now);
}
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
CLEDController * controller
Pir pir(PIN_PIR, PIR_LATCH_MS, PIR_RISING_TIME, PIR_FALLING_TIME)
UICheckbox useDither("Use Binary Dither", true)
#define BINARY_DITHER
Enable dithering using binary dithering (only option)
#define DISABLE_DITHER
Disable dithering.
@ TypicalLEDStrip
Typical values for SMD5050 LEDs.
Technical Considerations
Performance Optimization
- Lookup Table Pre-computation: Pre-calculate trigonometric values for ring positions
- Fixed-Point Arithmetic: Use integer math where possible for embedded systems
- Noise Caching: Cache noise parameters between frames for consistent animation
- Memory-Efficient Algorithms: Optimize noise calculations for real-time performance
- Parallel Processing: Structure algorithms for potential multi-core optimization
Memory Management
- PROGMEM Storage: Store palettes and static data in program memory for Arduino compatibility
- Dynamic Allocation Avoidance: Minimize heap usage during effect transitions
- Stack Optimization: Use local variables efficiently in nested algorithm calls
- Buffer Management: Reuse coordinate calculation buffers where possible
Mathematical Precision
- 16-bit Noise Space: Maintain precision in noise calculations before 8-bit mapping
- Floating Point Efficiency: Balance precision vs. performance based on target platform
- Color Space Optimization: Use HSV for smooth transitions, RGB for final output
- Numerical Stability: Prevent overflow/underflow in wave interference calculations
User Experience
- Smooth Transitions: 1-second cross-fade between effects using linear interpolation
- Responsive Controls: Immediate override of automatic cycling via manual selection
- Visual Feedback: Clear indication of current variant and palette selection
- Performance Consistency: Maintain stable frame rate across all effect variants
First Pass Implementation: Plasma Waves
Why Start with Plasma Waves?
- Visual Impact: Most impressive demonstration of advanced graphics programming
- Mathematical Showcase: Demonstrates sine wave interference and noise modulation
- Building Foundation: Establishes the RingCoord system used by all other variants
- Performance Baseline: Tests the most computationally intensive algorithm first
Development Strategy
void setupPlasmaDemo() {
}
void drawPlasmaOnly(uint32_t now) {
}
}
void drawWithManualSelection(uint32_t now) {
uint8_t selected_variant =
variants.value();
switch(selected_variant) {
}
}
}
void drawFullSystem(uint32_t now) {
}
}
UISlider timescale("Time Scale", 1,.1, 10,.1)
Testing and Validation
- Plasma Waves Only: Verify smooth wave interference and noise modulation
- Parameter Responsiveness: Test all UI sliders affect plasma generation correctly
- Performance Metrics: Measure frame rate with plasma algorithm on target hardware
- Visual Quality: Confirm smooth color transitions and no artifacts
- Memory Usage: Monitor RAM consumption during plasma calculations
Incremental Development Plan
- Week 1: Implement Plasma Waves algorithm and RingCoord system
- Week 2: Add 2-3 simpler variants (Cosmic Swirl, Electric Storm, Fire Dance)
- Week 3: Implement transition system and automatic cycling
- Week 4: Add remaining variants and color palette system
- Week 5: Optimization, polish, and platform-specific tuning
Advanced Graphics Techniques Demonstrated
Wave Interference Mathematics
The plasma algorithm showcases classical physics simulation:
- Superposition Principle: Multiple wave sources combine linearly
- Phase Relationships: Time-varying phase creates animation
- Distance-Based Attenuation: Realistic wave propagation modeling
- Noise Modulation: Organic variation through Perlin noise overlay
Color Theory Implementation
- HSV Color Space: Smooth hue transitions for natural color flow
- Saturation Modulation: Dynamic saturation based on wave intensity
- Brightness Mapping: Normalized wave values to brightness curves
- Gamma Correction: Perceptually linear brightness progression
Performance Optimization Strategies
- Trigonometric Lookup: Pre-computed sine/cosine tables
- Fixed-Point Math: Integer approximations for embedded platforms
- Loop Unrolling: Minimize function call overhead in tight loops
- Memory Access Patterns: Cache-friendly coordinate calculations
Future Enhancements
Advanced Features
- Save/Load Configurations: User-defined effect combinations and parameters
- BPM Synchronization: Music-reactive timing for effect transitions
- Custom Palette Editor: User-defined color schemes with preview
- Effect Intensity Controls: Per-variant amplitude and speed modulation
- Multi-Ring Support: Expand to multiple concentric LED rings
Platform Extensions
- Multi-Core Optimization: Parallel processing for complex calculations
- GPU Acceleration: WebGL compute shaders for web platform
- Hardware Acceleration: Platform-specific optimizations (ESP32, Teensy)
- Memory Mapping: Direct hardware buffer access for maximum performance
Algorithm Enhancements
- Physically-Based Rendering: More realistic light simulation
- Particle Systems: Dynamic particle-based effects
- Fractal Algorithms: Mandelbrot and Julia set visualizations
- Audio Visualization: Spectrum analysis and reactive algorithms