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**

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**

```
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