03 - Lab Disco Light Master

Video

# Lab: Disco Light Master - Music-Synchronized LED Animations ## **Objective** Create a disco light show where the TK27 microphone detects music beats and the TK33 WS2812 LED strip dances to the rhythm. The system analyzes sound levels and creates dynamic visual patterns that synchronize with the music, creating an immersive audio-visual experience. ## **Required Components** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250723171514.png?v=1753857929) 1. **Lonely Binary UNO R3** - Main Arduino board 2. **TinkerBlock UNO R3 Shield** - Expansion shield that plugs onto the UNO R3 3. **TinkerBlock TK27** - Analog Microphone Module 4. **TinkerBlock TK33** - WS2812 LED Strip Module (5 LEDs) ## **Theory** ### **Sound-Activated Light Show** - **Beat Detection**: Analyze sound levels to detect musical beats - **Rhythm Analysis**: Identify patterns in audio input - **Visual Synchronization**: Match LED patterns to audio characteristics - **Dynamic Effects**: Create responsive light animations ### **Audio Analysis** - **Baseline Level**: Normal ambient sound around 500-600 - **Beat Threshold**: Minimum sound increase to trigger effects - **Frequency Response**: Different responses to various sound levels - **Pattern Recognition**: Identify rhythm and tempo patterns ### **Visual Effects** - **Color Mapping**: Map sound levels to specific colors - **Intensity Control**: Brightness varies with volume - **Pattern Generation**: Create dynamic light patterns - **Rhythm Synchronization**: Match light timing to beats ## **Wiring Instructions** ### **TK27 Analog Microphone Pinout** - **GND** → Arduino GND - **VCC** → Arduino 5V - **NC** → No Connection - **Signal** → Arduino Analog Pin A3 ### **TK33 WS2812 LED Strip Pinout** - **GND** → Arduino GND - **VCC** → Arduino 5V - **NC** → No Connection - **Signal** → Arduino Digital Pin D5 ### **Connection Diagram** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250723171535.png?v=1753857934) ``` UNO R3 + Shield ├── Analog Pin A3 ───→ TK27 Signal (Microphone) └── Digital Pin D5 ──→ TK33 Signal (WS2812 Data) ``` ## **Basic Sound-Activated Light Show** ```cpp // Basic Sound-Activated Light Show // Microphone detects beats and WS2812 LEDs respond #include <FastLED.h> // Pin definitions #define MIC_PIN A3 // TK27 Analog Microphone on A3 #define LED_PIN 5 // TK33 WS2812 LED Strip on D5 #define NUM_LEDS 5 // TK33 has 5 WS2812 LEDs // LED array CRGB leds[NUM_LEDS]; // Sound detection parameters #define BASELINE 500 // Normal ambient sound level (5xx) #define BEAT_THRESHOLD 20 // Minimum increase to detect beat #define SMOOTHING_SAMPLES 10 // Number of samples for smoothing #define UPDATE_RATE 50 // Update rate in milliseconds // Color definitions #define COLOR_QUIET CRGB(0, 0, 100) // Blue for quiet #define COLOR_NORMAL CRGB(0, 100, 0) // Green for normal #define COLOR_LOUD CRGB(100, 0, 0) // Red for loud #define COLOR_VERY_LOUD CRGB(255, 255, 0) // Yellow for very loud #define COLOR_EXTREME CRGB(255, 0, 255) // Purple for extreme // Variables int soundLevel = 0; int smoothedLevel = 0; int soundHistory[SMOOTHING_SAMPLES]; int historyIndex = 0; unsigned long lastBeatTime = 0; int beatCount = 0; bool beatDetected = false; void setup() { // Initialize serial communication Serial.begin(9600); Serial.println("Sound-Activated Light Show"); Serial.println("========================="); // Initialize WS2812 LED strip FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(100); // Set brightness (0-255) // Initialize microphone pin pinMode(MIC_PIN, INPUT); // Initialize sound history array for (int i = 0; i < SMOOTHING_SAMPLES; i++) { soundHistory[i] = BASELINE; } // Clear all LEDs FastLED.clear(); FastLED.show(); delay(1000); Serial.println("Light show initialized!"); Serial.println("TK27 Microphone: A3"); Serial.println("TK33 WS2812 LED Strip: D5"); Serial.println(); Serial.println("Baseline sound level: ~550"); Serial.println("Play music to see the light show!"); Serial.println(); } void loop() { // Read microphone input soundLevel = analogRead(MIC_PIN); // Smooth the sound level smoothedLevel = smoothSoundLevel(soundLevel); // Detect beats detectBeat(); // Update light show based on sound updateLightShow(); // Display sound info displaySoundInfo(); delay(UPDATE_RATE); } int smoothSoundLevel(int rawLevel) { // Add new reading to history soundHistory[historyIndex] = rawLevel; historyIndex = (historyIndex + 1) % SMOOTHING_SAMPLES; // Calculate average int sum = 0; for (int i = 0; i < SMOOTHING_SAMPLES; i++) { sum += soundHistory[i]; } return sum / SMOOTHING_SAMPLES; } void detectBeat() { // Calculate difference from baseline int soundDifference = abs(smoothedLevel - BASELINE); // Check if this is a beat if (soundDifference > BEAT_THRESHOLD) { if (!beatDetected) { beatDetected = true; beatCount++; lastBeatTime = millis(); Serial.print("Beat detected! #"); Serial.print(beatCount); Serial.print(" | Level: "); Serial.println(smoothedLevel); } } else { beatDetected = false; } } void updateLightShow() { // Calculate sound difference int soundDifference = abs(smoothedLevel - BASELINE); // Determine effect based on sound level if (soundDifference < BEAT_THRESHOLD) { // Quiet - gentle breathing effect breathingEffect(COLOR_QUIET); } else if (soundDifference < BEAT_THRESHOLD * 2) { // Normal - wave effect waveEffect(COLOR_NORMAL); } else if (soundDifference < BEAT_THRESHOLD * 3) { // Loud - pulse effect pulseEffect(COLOR_LOUD); } else if (soundDifference < BEAT_THRESHOLD * 4) { // Very loud - running lights runningLights(COLOR_VERY_LOUD); } else { // Extreme - rainbow effect rainbowEffect(); } // Beat accent effect if (beatDetected) { beatAccent(); } FastLED.show(); } void breathingEffect(CRGB color) { static int brightness = 0; static bool increasing = true; // Breathing animation if (increasing) { brightness += 5; if (brightness >= 255) { brightness = 255; increasing = false; } } else { brightness -= 5; if (brightness <= 0) { brightness = 0; increasing = true; } } // Apply to all LEDs for (int i = 0; i < NUM_LEDS; i++) { leds[i] = color; leds[i].fadeToBlackBy(255 - brightness); } } void waveEffect(CRGB color) { static uint8_t wavePos = 0; // Wave animation across LEDs for (int i = 0; i < NUM_LEDS; i++) { uint8_t brightness = sin8(i * 64 + wavePos) / 2; leds[i] = color; leds[i].fadeToBlackBy(255 - brightness); } wavePos += 8; } void pulseEffect(CRGB color) { static int pulseBrightness = 0; static bool pulseIncreasing = true; // Pulse animation if (pulseIncreasing) { pulseBrightness += 10; if (pulseBrightness >= 255) { pulseBrightness = 255; pulseIncreasing = false; } } else { pulseBrightness -= 10; if (pulseBrightness <= 0) { pulseBrightness = 0; pulseIncreasing = true; } } // Apply to all LEDs for (int i = 0; i < NUM_LEDS; i++) { leds[i] = color; leds[i].fadeToBlackBy(255 - pulseBrightness); } } void runningLights(CRGB color) { static int position = 0; // Clear all LEDs FastLED.clear(); // Set current position leds[position] = color; // Set adjacent LEDs with lower brightness if (position > 0) { leds[position - 1] = color; leds[position - 1].fadeToBlackBy(128); } if (position < NUM_LEDS - 1) { leds[position + 1] = color; leds[position + 1].fadeToBlackBy(128); } // Move to next position position = (position + 1) % NUM_LEDS; } void rainbowEffect() { static uint8_t hue = 0; // Rainbow animation for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(hue + i * 32, 255, 255); } hue += 8; } void beatAccent() { // Flash all LEDs white on beat for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CRGB::White; } // Show for a brief moment FastLED.show(); delay(50); // Return to normal effect FastLED.show(); } void displaySoundInfo() { static unsigned long lastDisplay = 0; if (millis() - lastDisplay > 1000) { int soundDifference = abs(smoothedLevel - BASELINE); Serial.print("Sound Level: "); Serial.print(smoothedLevel); Serial.print(" | Difference: "); Serial.print(soundDifference); Serial.print(" | Beats: "); Serial.println(beatCount); lastDisplay = millis(); } } ``` ## **Advanced Beat-Synchronized Light Show** ```cpp // Advanced Beat-Synchronized Light Show // More sophisticated beat detection and visual effects #include <FastLED.h> // Pin definitions #define MIC_PIN A3 // TK27 Analog Microphone on A3 #define LED_PIN 5 // TK33 WS2812 LED Strip on D5 #define NUM_LEDS 5 // TK33 has 5 WS2812 LEDs // LED array CRGB leds[NUM_LEDS]; // Advanced sound analysis parameters #define BASELINE 550 #define BEAT_THRESHOLD 40 #define BEAT_HISTORY_SIZE 20 #define TEMPO_ANALYSIS_SIZE 50 #define SMOOTHING_SAMPLES 15 // Beat detection variables int soundLevel = 0; int smoothedLevel = 0; int soundHistory[SMOOTHING_SAMPLES]; int beatHistory[BEAT_HISTORY_SIZE]; int beatHistoryIndex = 0; unsigned long beatTimes[TEMPO_ANALYSIS_SIZE]; int beatTimeIndex = 0; unsigned long lastBeatTime = 0; int beatCount = 0; bool beatDetected = false; int tempo = 0; // Visual effect variables int currentEffect = 0; unsigned long effectStartTime = 0; int effectDuration = 2000; void setup() { Serial.begin(9600); Serial.println("Advanced Beat-Synchronized Light Show"); Serial.println("====================================="); FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(100); pinMode(MIC_PIN, INPUT); // Initialize arrays for (int i = 0; i < SMOOTHING_SAMPLES; i++) { soundHistory[i] = BASELINE; } for (int i = 0; i < BEAT_HISTORY_SIZE; i++) { beatHistory[i] = 0; } for (int i = 0; i < TEMPO_ANALYSIS_SIZE; i++) { beatTimes[i] = 0; } FastLED.clear(); FastLED.show(); delay(1000); Serial.println("Advanced light show initialized!"); Serial.println("Analyzing music tempo and beats..."); Serial.println(); } void loop() { // Read and process sound soundLevel = analogRead(MIC_PIN); smoothedLevel = smoothSoundLevel(soundLevel); // Advanced beat detection detectAdvancedBeat(); // Analyze tempo analyzeTempo(); // Update visual effects updateAdvancedLightShow(); // Display analysis displayAdvancedInfo(); delay(30); } int smoothSoundLevel(int rawLevel) { soundHistory[historyIndex] = rawLevel; historyIndex = (historyIndex + 1) % SMOOTHING_SAMPLES; int sum = 0; for (int i = 0; i < SMOOTHING_SAMPLES; i++) { sum += soundHistory[i]; } return sum / SMOOTHING_SAMPLES; } void detectAdvancedBeat() { int soundDifference = abs(smoothedLevel - BASELINE); // Dynamic threshold based on recent history int dynamicThreshold = calculateDynamicThreshold(); if (soundDifference > dynamicThreshold) { if (!beatDetected && (millis() - lastBeatTime > 100)) { beatDetected = true; beatCount++; lastBeatTime = millis(); // Record beat time for tempo analysis beatTimes[beatTimeIndex] = millis(); beatTimeIndex = (beatTimeIndex + 1) % TEMPO_ANALYSIS_SIZE; // Record beat intensity beatHistory[beatHistoryIndex] = soundDifference; beatHistoryIndex = (beatHistoryIndex + 1) % BEAT_HISTORY_SIZE; Serial.print("Beat #"); Serial.print(beatCount); Serial.print(" | Intensity: "); Serial.println(soundDifference); } } else { beatDetected = false; } } int calculateDynamicThreshold() { // Calculate average beat intensity int sum = 0; int count = 0; for (int i = 0; i < BEAT_HISTORY_SIZE; i++) { if (beatHistory[i] > 0) { sum += beatHistory[i]; count++; } } if (count > 0) { int averageIntensity = sum / count; return max(BEAT_THRESHOLD, averageIntensity / 2); } return BEAT_THRESHOLD; } void analyzeTempo() { if (beatTimeIndex < 2) return; // Calculate average time between beats int totalTime = 0; int beatIntervals = 0; for (int i = 1; i < TEMPO_ANALYSIS_SIZE; i++) { int prevIndex = (beatTimeIndex - i + TEMPO_ANALYSIS_SIZE) % TEMPO_ANALYSIS_SIZE; int currIndex = (beatTimeIndex - i + 1 + TEMPO_ANALYSIS_SIZE) % TEMPO_ANALYSIS_SIZE; if (beatTimes[prevIndex] > 0 && beatTimes[currIndex] > 0) { totalTime += beatTimes[currIndex] - beatTimes[prevIndex]; beatIntervals++; } } if (beatIntervals > 0) { tempo = totalTime / beatIntervals; } } void updateAdvancedLightShow() { // Change effect based on tempo and intensity if (millis() - effectStartTime > effectDuration) { currentEffect = (currentEffect + 1) % 6; effectStartTime = millis(); // Adjust effect duration based on tempo if (tempo > 0) { effectDuration = max(500, min(3000, tempo * 2)); } } // Apply current effect switch (currentEffect) { case 0: tempoWaveEffect(); break; case 1: beatPulseEffect(); break; case 2: frequencySpectrumEffect(); break; case 3: rhythmChaseEffect(); break; case 4: beatExplosionEffect(); break; case 5: tempoRainbowEffect(); break; } // Beat accent if (beatDetected) { beatAccentEffect(); } FastLED.show(); } void tempoWaveEffect() { static uint8_t wavePos = 0; int speed = map(tempo, 0, 1000, 4, 16); for (int i = 0; i < NUM_LEDS; i++) { uint8_t brightness = sin8(i * 64 + wavePos) / 2; leds[i] = CHSV(160 + brightness / 4, 255, brightness); } wavePos += speed; } void beatPulseEffect() { static int pulseBrightness = 0; static bool pulseIncreasing = true; int speed = map(tempo, 0, 1000, 5, 20); if (pulseIncreasing) { pulseBrightness += speed; if (pulseBrightness >= 255) { pulseBrightness = 255; pulseIncreasing = false; } } else { pulseBrightness -= speed; if (pulseBrightness <= 0) { pulseBrightness = 0; pulseIncreasing = true; } } for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(0, 255, pulseBrightness); } } void frequencySpectrumEffect() { int soundDifference = abs(smoothedLevel - BASELINE); int intensity = map(soundDifference, 0, 200, 0, NUM_LEDS); FastLED.clear(); for (int i = 0; i < min(intensity, NUM_LEDS); i++) { leds[i] = CHSV(i * 32, 255, 255); } } void rhythmChaseEffect() { static int position = 0; int speed = map(tempo, 0, 1000, 50, 200); if (millis() % speed == 0) { FastLED.clear(); leds[position] = CHSV(beatCount * 32, 255, 255); position = (position + 1) % NUM_LEDS; } } void beatExplosionEffect() { if (beatDetected) { for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(random(255), 255, 255); } } else { // Fade out for (int i = 0; i < NUM_LEDS; i++) { leds[i].fadeToBlackBy(10); } } } void tempoRainbowEffect() { static uint8_t hue = 0; int speed = map(tempo, 0, 1000, 2, 8); for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(hue + i * 32, 255, 255); } hue += speed; } void beatAccentEffect() { // Flash white on beat for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CRGB::White; } FastLED.show(); delay(30); } void displayAdvancedInfo() { static unsigned long lastDisplay = 0; if (millis() - lastDisplay > 2000) { Serial.print("Tempo: "); Serial.print(tempo); Serial.print("ms | Beats: "); Serial.print(beatCount); Serial.print(" | Effect: "); Serial.print(currentEffect); Serial.print(" | Level: "); Serial.println(smoothedLevel); lastDisplay = millis(); } } ``` ## **Code Explanation** ### **Pin and Component Configuration** ```cpp #define MIC_PIN A3 // TK27 Analog Microphone on A3 #define LED_PIN 5 // TK33 WS2812 LED Strip on D5 #define NUM_LEDS 5 // TK33 has 5 WS2812 LEDs ``` - **Analog Pin A3**: Reads continuous sound levels from microphone (0-1023) - **Digital Pin D5**: Controls WS2812 LED strip data line - **5 LEDs**: TK33 module provides 5 individually addressable RGB LEDs - **FastLED Library**: Handles complex LED animations and color management ### **Sound Detection Parameters** ```cpp #define BASELINE 500 // Normal ambient sound level (5xx) #define BEAT_THRESHOLD 20 // Minimum increase to detect beat #define SMOOTHING_SAMPLES 10 // Number of samples for smoothing #define UPDATE_RATE 50 // Update rate in milliseconds ``` - **Baseline Calibration**: Establishes normal ambient sound level - **Beat Threshold**: Minimum sound increase to trigger beat detection - **Smoothing**: Reduces noise by averaging multiple samples - **Update Rate**: Controls animation smoothness and responsiveness ### **Color Mapping System** ```cpp #define COLOR_QUIET CRGB(0, 0, 100) // Blue for quiet #define COLOR_NORMAL CRGB(0, 100, 0) // Green for normal #define COLOR_LOUD CRGB(100, 0, 0) // Red for loud #define COLOR_VERY_LOUD CRGB(255, 255, 0) // Yellow for very loud #define COLOR_EXTREME CRGB(255, 0, 255) // Purple for extreme ``` - **Intensity-Based Colors**: Different colors for different sound levels - **Visual Feedback**: Immediate color indication of sound intensity - **Progressive Intensity**: Colors become more vibrant with louder sounds - **Psychological Impact**: Warm colors for loud, cool colors for quiet ### **Sound Processing System** ```cpp int smoothSoundLevel(int rawLevel) { // Add new reading to history soundHistory[historyIndex] = rawLevel; historyIndex = (historyIndex + 1) % SMOOTHING_SAMPLES; // Calculate average int sum = 0; for (int i = 0; i < SMOOTHING_SAMPLES; i++) { sum += soundHistory[i]; } return sum / SMOOTHING_SAMPLES; } ``` - **Circular Buffer**: Uses modulo operation for efficient memory usage - **Moving Average**: Smooths out noise and sudden spikes - **Real-time Processing**: Continuously updates with new readings - **Noise Reduction**: Eliminates false triggers from random noise ### **Beat Detection Algorithm** ```cpp void detectBeat() { // Calculate difference from baseline int soundDifference = abs(smoothedLevel - BASELINE); // Check if this is a beat if (soundDifference > BEAT_THRESHOLD) { if (!beatDetected) { beatDetected = true; beatCount++; lastBeatTime = millis(); Serial.print("Beat detected! #"); Serial.print(beatCount); Serial.print(" | Level: "); Serial.println(smoothedLevel); } } else { beatDetected = false; } } ``` - **Baseline Comparison**: Compares current level to ambient baseline - **Threshold Detection**: Only triggers on significant sound increases - **Debouncing**: Prevents multiple triggers for single beats - **Beat Counting**: Tracks total number of detected beats - **Timing Analysis**: Records beat timing for tempo calculation ### **Visual Effect System** #### **Breathing Effect** ```cpp void breathingEffect(CRGB color) { static int brightness = 0; static bool increasing = true; // Breathing animation if (increasing) { brightness += 5; if (brightness >= 255) { brightness = 255; increasing = false; } } else { brightness -= 5; if (brightness <= 0) { brightness = 0; increasing = true; } } // Apply to all LEDs for (int i = 0; i < NUM_LEDS; i++) { leds[i] = color; leds[i].fadeToBlackBy(255 - brightness); } } ``` - **Smooth Transitions**: Gradual brightness changes for organic feel - **Static Variables**: Maintains state between function calls - **Direction Control**: Alternates between increasing and decreasing - **Color Preservation**: Maintains base color while varying brightness #### **Wave Effect** ```cpp void waveEffect(CRGB color) { static uint8_t wavePos = 0; // Wave animation across LEDs for (int i = 0; i < NUM_LEDS; i++) { uint8_t brightness = sin8(i * 64 + wavePos) / 2; leds[i] = color; leds[i].fadeToBlackBy(255 - brightness); } wavePos += 8; } ``` - **Sine Wave Animation**: Uses trigonometric functions for smooth waves - **Position Tracking**: Moves wave position across LED strip - **Spatial Distribution**: Different brightness for each LED position - **Continuous Motion**: Endless wave animation #### **Running Lights Effect** ```cpp void runningLights(CRGB color) { static int position = 0; // Clear all LEDs FastLED.clear(); // Set current position leds[position] = color; // Set adjacent LEDs with lower brightness if (position > 0) { leds[position - 1] = color; leds[position - 1].fadeToBlackBy(128); } if (position < NUM_LEDS - 1) { leds[position + 1] = color; leds[position + 1].fadeToBlackBy(128); } // Move to next position position = (position + 1) % NUM_LEDS; } ``` - **Position Tracking**: Moves light position along LED strip - **Trail Effect**: Creates trailing effect with adjacent LEDs - **Boundary Handling**: Checks array bounds before accessing - **Circular Movement**: Wraps around using modulo operation ### **Advanced Beat Analysis** #### **Dynamic Threshold Calculation** ```cpp int calculateDynamicThreshold() { // Calculate average beat intensity int sum = 0; int count = 0; for (int i = 0; i < BEAT_HISTORY_SIZE; i++) { if (beatHistory[i] > 0) { sum += beatHistory[i]; count++; } } if (count > 0) { int averageIntensity = sum / count; return max(BEAT_THRESHOLD, averageIntensity / 2); } return BEAT_THRESHOLD; } ``` - **Adaptive Detection**: Adjusts threshold based on recent beat history - **Intensity Analysis**: Calculates average beat intensity - **Minimum Threshold**: Ensures detection doesn't become too sensitive - **Historical Data**: Uses past beats to predict future patterns #### **Tempo Analysis** ```cpp void analyzeTempo() { if (beatTimeIndex < 2) return; // Calculate average time between beats int totalTime = 0; int beatIntervals = 0; for (int i = 1; i < TEMPO_ANALYSIS_SIZE; i++) { int prevIndex = (beatTimeIndex - i + TEMPO_ANALYSIS_SIZE) % TEMPO_ANALYSIS_SIZE; int currIndex = (beatTimeIndex - i + 1 + TEMPO_ANALYSIS_SIZE) % TEMPO_ANALYSIS_SIZE; if (beatTimes[prevIndex] > 0 && beatTimes[currIndex] > 0) { totalTime += beatTimes[currIndex] - beatTimes[prevIndex]; beatIntervals++; } } if (beatIntervals > 0) { tempo = totalTime / beatIntervals; } } ``` - **Beat Timing**: Records precise timing of each beat - **Interval Calculation**: Measures time between consecutive beats - **Average Tempo**: Calculates overall tempo from multiple intervals - **Circular Buffer**: Efficiently manages timing data ### **Effect Selection System** ```cpp void updateAdvancedLightShow() { // Change effect based on tempo and intensity if (millis() - effectStartTime > effectDuration) { currentEffect = (currentEffect + 1) % 6; effectStartTime = millis(); // Adjust effect duration based on tempo if (tempo > 0) { effectDuration = max(500, min(3000, tempo * 2)); } } // Apply current effect switch (currentEffect) { case 0: tempoWaveEffect(); break; case 1: beatPulseEffect(); break; case 2: frequencySpectrumEffect(); break; case 3: rhythmChaseEffect(); break; case 4: beatExplosionEffect(); break; case 5: tempoRainbowEffect(); break; } } ``` - **Automatic Cycling**: Changes effects automatically over time - **Tempo Synchronization**: Adjusts effect duration based on music tempo - **Effect Variety**: Provides 6 different visual effects - **Dynamic Timing**: Effect changes match musical rhythm ### **Key Programming Concepts** #### **Real-time Audio Processing** - **Continuous Sampling**: Constant microphone monitoring - **Signal Smoothing**: Noise reduction through averaging - **Threshold Detection**: Reliable beat identification - **Dynamic Adaptation**: System adjusts to different music styles #### **Visual Synchronization** - **Audio-Visual Mapping**: Direct correlation between sound and light - **Effect Selection**: Different effects for different sound levels - **Beat Accent**: Special effects triggered by beat detection - **Tempo Matching**: Visual timing matches musical rhythm #### **Memory and Performance Optimization** - **Circular Buffers**: Efficient memory usage for historical data - **Static Variables**: Maintains state without global variables - **Timed Updates**: Controls processing frequency for stability - **Effect Cycling**: Prevents memory overflow from long effects #### **User Experience Design** - **Immediate Response**: Visual feedback matches audio input - **Effect Variety**: Multiple effects prevent visual boredom - **Intensity Scaling**: Visual intensity matches audio intensity - **Beat Synchronization**: Creates immersive audio-visual experience ## **Expected Output** ### **Serial Monitor Output** ``` Sound-Activated Light Show ========================= Light show initialized! TK27 Microphone: A3 TK33 WS2812 LED Strip: D5 Baseline sound level: ~550 Play music to see the light show! Beat detected! #1 | Level: 580 Beat detected! #2 | Level: 620 Beat detected! #3 | Level: 590 Sound Level: 575 | Difference: 25 | Beats: 3 ``` ### **Visual Output** - **Breathing Effect**: Gentle blue pulsing for quiet sounds - **Wave Effect**: Green wave animation for normal sounds - **Pulse Effect**: Red pulsing for loud sounds - **Running Lights**: Yellow moving lights for very loud sounds - **Rainbow Effect**: Colorful rainbow for extreme sounds - **Beat Accent**: White flash on beat detection ### **Behavior Patterns** - **Quiet Music**: Gentle breathing and wave effects - **Moderate Music**: Regular beat detection with pulse effects - **Loud Music**: Frequent beats with running lights and rainbow - **Beat Synchronization**: Visual effects match musical rhythm - **Dynamic Adaptation**: System adjusts to different music styles ## **Troubleshooting** ### **Sound Detection Issues:** - **No Beat Detection**: Adjust BASELINE and BEAT_THRESHOLD values - **False Triggers**: Increase smoothing samples or threshold - **Poor Sensitivity**: Decrease threshold or check microphone placement - **Erratic Behavior**: Ensure stable power and proper grounding ### **Visual Effect Problems:** - **Dim Effects**: Increase brightness or check LED connections - **Effect Not Changing**: Verify effect cycling logic and timing - **Color Problems**: Check FastLED configuration and color definitions - **Animation Issues**: Verify update rate and timing functions ### **Performance Issues:** - **Slow Response**: Reduce UPDATE_RATE for faster response - **Memory Problems**: Check array sizes and variable usage - **Power Issues**: Ensure adequate power for LED animations - **Processing Overload**: Optimize effect complexity and timing ### **Calibration Problems:** - **Wrong Baseline**: Test in your specific environment - **Poor Threshold**: Fine-tune for your music and environment - **Effect Timing**: Adjust effect duration for your preferences - **Color Preferences**: Modify color definitions for desired appearance