05 - DJ Controller

Video

# Lab: DJ Controller ## **Objective** Create an interactive LED controller where the TK04 button generates random colors for all 5 LEDs of the TK33 WS2812 LED strip, and the TK07 potentiometer adjusts the brightness from 0% to 100%. This lab demonstrates digital input, analog input, and advanced LED control. ## **Required Components** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250723121631.png?v=1753856118) 1. **Lonely Binary UNO R3** - Main Arduino board 2. **TinkerBlock UNO R3 Shield** - Expansion shield that plugs onto the UNO R3 3. **TinkerBlock TK33** - WS2812 LED Strip Module (5 LEDs) 4. **TinkerBlock TK07** - Potentiometer Module 5. **TinkerBlock TK04** - Button Module ## **Theory** ### **Color and Brightness Control** - **Random Color Generation**: Generate random RGB values for visual variety - **Brightness Control**: Use potentiometer to control overall LED brightness - **Button Debouncing**: Prevent multiple triggers from single button press - **Analog Mapping**: Convert potentiometer reading to brightness percentage ### **WS2812 LED Control** - **Individual LED Control**: Set each LED to the same color - **Brightness Scaling**: Apply brightness percentage to all LEDs - **Color Consistency**: Maintain color while adjusting brightness - **Real-time Updates**: Update display immediately on input changes ### **Input Processing** - **Digital Input**: Button state detection with debouncing - **Analog Input**: Potentiometer reading for brightness control - **Input Mapping**: Convert analog values to useful ranges - **State Management**: Track button and potentiometer states ## **Wiring Instructions** ### **TK33 WS2812 LED Strip Pinout** - **GND** → Arduino GND - **VCC** → Arduino 5V - **NC** → No Connection - **Signal** → Arduino Digital Pin D5 ### **TK07 Potentiometer Pinout** - **GND** → Arduino GND - **VCC** → Arduino 5V - **NC** → No Connection - **Signal** → Arduino Analog Pin A3 ### **TK04 Button Pinout** - **GND** → Arduino GND - **VCC** → Arduino 5V - **NC** → No Connection - **Signal** → Arduino Digital Pin D3 ### **Connection Diagram** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250723121653.png?v=1753856123) ``` UNO R3 + Shield ├── Digital Pin D5 ──→ TK33 Signal (WS2812 Data) ├── Analog Pin A3 ───→ TK07 Signal (Potentiometer) └── Digital Pin D3 ──→ TK04 Signal (Button) ``` ## **Basic Color and Brightness Controller** ```cpp // Basic Color and Brightness Controller // TK04 button generates random colors, TK07 potentiometer controls brightness #include <FastLED.h> // Pin definitions #define LED_PIN 5 // TK33 WS2812 LED Strip on D5 #define POT_PIN A3 // TK07 Potentiometer on A3 #define BUTTON_PIN 3 // TK04 Button on D3 #define NUM_LEDS 5 // TK33 has 5 WS2812 LEDs // LED array CRGB leds[NUM_LEDS]; // Button debouncing variables #define DEBOUNCE_DELAY 50 // Debounce time in milliseconds unsigned long lastButtonPress = 0; bool lastButtonState = HIGH; bool buttonPressed = false; // Color and brightness variables CRGB currentColor = CRGB::Red; int currentBrightness = 100; // 0-255 int brightnessPercentage = 100; // 0-100 void setup() { // Initialize serial communication Serial.begin(9600); Serial.println("Color and Brightness Controller"); Serial.println("==============================="); // Initialize WS2812 LED strip FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(currentBrightness); // Initialize input pins pinMode(POT_PIN, INPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); // Internal pull-up resistor // Clear all LEDs FastLED.clear(); FastLED.show(); delay(1000); Serial.println("Controller initialized!"); Serial.println("TK33 WS2812 LED Strip: D5"); Serial.println("TK07 Potentiometer: A3"); Serial.println("TK04 Button: D3"); Serial.println(); Serial.println("Press button to change color"); Serial.println("Turn potentiometer to adjust brightness"); Serial.println(); // Set initial color setAllLEDs(currentColor); FastLED.show(); } void loop() { // Read potentiometer for brightness control readPotentiometer(); // Read button for color change readButton(); // Update display updateDisplay(); // Display status displayStatus(); delay(100); } void readPotentiometer() { // Read potentiometer value (0-1023) int potValue = analogRead(POT_PIN); // Map to brightness percentage (0-100) int newBrightnessPercentage = map(potValue, 0, 1023, 0, 100); // Map percentage to LED brightness (0-255) int newBrightness = map(newBrightnessPercentage, 0, 100, 0, 255); // Update if changed if (newBrightnessPercentage != brightnessPercentage) { brightnessPercentage = newBrightnessPercentage; currentBrightness = newBrightness; Serial.print("Brightness: "); Serial.print(brightnessPercentage); Serial.println("%"); } } void readButton() { // Read button state (LOW when pressed due to pull-up) bool buttonState = digitalRead(BUTTON_PIN); // Check for button press with debouncing if (buttonState == LOW && lastButtonState == HIGH) { if (millis() - lastButtonPress > DEBOUNCE_DELAY) { buttonPressed = true; lastButtonPress = millis(); // Generate random color generateRandomColor(); Serial.print("New color: R="); Serial.print(currentColor.r); Serial.print(" G="); Serial.print(currentColor.g); Serial.print(" B="); Serial.println(currentColor.b); } } lastButtonState = buttonState; } void generateRandomColor() { // Generate random RGB values currentColor.r = random(256); currentColor.g = random(256); currentColor.b = random(256); // Ensure minimum brightness for visibility if (currentColor.r == 0 && currentColor.g == 0 && currentColor.b == 0) { currentColor.r = random(50, 256); } } void setAllLEDs(CRGB color) { // Set all LEDs to the same color for (int i = 0; i < NUM_LEDS; i++) { leds[i] = color; } } void updateDisplay() { // Set all LEDs to current color setAllLEDs(currentColor); // Apply brightness FastLED.setBrightness(currentBrightness); // Update display FastLED.show(); } void displayStatus() { static unsigned long lastDisplay = 0; if (millis() - lastDisplay > 2000) { Serial.println("=== STATUS ==="); Serial.print("Color: R="); Serial.print(currentColor.r); Serial.print(" G="); Serial.print(currentColor.g); Serial.print(" B="); Serial.println(currentColor.b); Serial.print("Brightness: "); Serial.print(brightnessPercentage); Serial.println("%"); Serial.print("Potentiometer: "); Serial.println(analogRead(POT_PIN)); Serial.println(); lastDisplay = millis(); } } ``` ## **Advanced Color and Brightness Controller** ```cpp // Advanced Color and Brightness Controller // Enhanced features with color presets and smooth transitions #include <FastLED.h> // Pin definitions #define LED_PIN 5 // TK33 WS2812 LED Strip on D5 #define POT_PIN A3 // TK07 Potentiometer on A3 #define BUTTON_PIN 3 // TK04 Button on D3 #define NUM_LEDS 5 // TK33 has 5 WS2812 LEDs // LED array CRGB leds[NUM_LEDS]; // Button variables #define DEBOUNCE_DELAY 50 #define LONG_PRESS_TIME 1000 unsigned long lastButtonPress = 0; unsigned long buttonPressStart = 0; bool lastButtonState = HIGH; bool buttonPressed = false; bool longPressDetected = false; // Color and brightness variables CRGB currentColor = CRGB::Red; CRGB targetColor = CRGB::Red; int currentBrightness = 100; int targetBrightness = 100; int brightnessPercentage = 100; // Color presets CRGB colorPresets[] = { CRGB::Red, CRGB::Green, CRGB::Blue, CRGB::Yellow, CRGB::Purple, CRGB::Cyan, CRGB::Orange, CRGB::Pink, CRGB::White, CRGB::WarmWhite }; int numPresets = sizeof(colorPresets) / sizeof(colorPresets[0]); int currentPreset = 0; // Transition variables bool transitioning = false; unsigned long transitionStart = 0; #define TRANSITION_DURATION 500 // milliseconds void setup() { Serial.begin(9600); Serial.println("Advanced Color and Brightness Controller"); Serial.println("======================================="); FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(currentBrightness); pinMode(POT_PIN, INPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); FastLED.clear(); FastLED.show(); delay(1000); Serial.println("Advanced controller initialized!"); Serial.println("Short press: Random color"); Serial.println("Long press: Cycle through presets"); Serial.println("Potentiometer: Adjust brightness"); Serial.println(); // Set initial color setAllLEDs(currentColor); FastLED.show(); } void loop() { // Read inputs readPotentiometer(); readAdvancedButton(); // Handle transitions handleTransitions(); // Update display updateAdvancedDisplay(); // Display status displayAdvancedStatus(); delay(20); // Faster updates for smooth transitions } void readPotentiometer() { int potValue = analogRead(POT_PIN); int newBrightnessPercentage = map(potValue, 0, 1023, 0, 100); int newBrightness = map(newBrightnessPercentage, 0, 100, 0, 255); if (newBrightnessPercentage != brightnessPercentage) { brightnessPercentage = newBrightnessPercentage; targetBrightness = newBrightness; if (!transitioning) { currentBrightness = targetBrightness; } Serial.print("Brightness: "); Serial.print(brightnessPercentage); Serial.println("%"); } } void readAdvancedButton() { bool buttonState = digitalRead(BUTTON_PIN); // Button press detection if (buttonState == LOW && lastButtonState == HIGH) { buttonPressStart = millis(); lastButtonPress = millis(); } // Button release detection if (buttonState == HIGH && lastButtonState == LOW) { unsigned long pressDuration = millis() - buttonPressStart; if (pressDuration > DEBOUNCE_DELAY && pressDuration < LONG_PRESS_TIME) { // Short press - random color generateRandomColor(); Serial.println("Short press: Random color generated"); } else if (pressDuration >= LONG_PRESS_TIME) { // Long press - cycle preset cycleColorPreset(); Serial.println("Long press: Color preset cycled"); } } lastButtonState = buttonState; } void generateRandomColor() { targetColor.r = random(256); targetColor.g = random(256); targetColor.b = random(256); // Ensure minimum brightness if (targetColor.r == 0 && targetColor.g == 0 && targetColor.b == 0) { targetColor.r = random(50, 256); } startTransition(); } void cycleColorPreset() { currentPreset = (currentPreset + 1) % numPresets; targetColor = colorPresets[currentPreset]; Serial.print("Preset "); Serial.print(currentPreset); Serial.print(": "); printColorName(targetColor); Serial.println(); startTransition(); } void startTransition() { transitioning = true; transitionStart = millis(); } void handleTransitions() { if (transitioning) { unsigned long elapsed = millis() - transitionStart; float progress = (float)elapsed / TRANSITION_DURATION; if (progress >= 1.0) { // Transition complete currentColor = targetColor; currentBrightness = targetBrightness; transitioning = false; } else { // Smooth transition currentColor.r = lerp8(currentColor.r, targetColor.r, progress * 255); currentColor.g = lerp8(currentColor.g, targetColor.g, progress * 255); currentColor.b = lerp8(currentColor.b, targetColor.b, progress * 255); currentBrightness = lerp8(currentBrightness, targetBrightness, progress * 255); } } } void setAllLEDs(CRGB color) { for (int i = 0; i < NUM_LEDS; i++) { leds[i] = color; } } void updateAdvancedDisplay() { setAllLEDs(currentColor); FastLED.setBrightness(currentBrightness); FastLED.show(); } void displayAdvancedStatus() { static unsigned long lastDisplay = 0; if (millis() - lastDisplay > 3000) { Serial.println("=== ADVANCED STATUS ==="); Serial.print("Color: R="); Serial.print(currentColor.r); Serial.print(" G="); Serial.print(currentColor.g); Serial.print(" B="); Serial.println(currentColor.b); Serial.print("Brightness: "); Serial.print(brightnessPercentage); Serial.println("%"); Serial.print("Preset: "); Serial.print(currentPreset); Serial.print("/"); Serial.println(numPresets - 1); Serial.print("Transitioning: "); Serial.println(transitioning ? "Yes" : "No"); Serial.println(); lastDisplay = millis(); } } void printColorName(CRGB color) { if (color == CRGB::Red) Serial.print("Red"); else if (color == CRGB::Green) Serial.print("Green"); else if (color == CRGB::Blue) Serial.print("Blue"); else if (color == CRGB::Yellow) Serial.print("Yellow"); else if (color == CRGB::Purple) Serial.print("Purple"); else if (color == CRGB::Cyan) Serial.print("Cyan"); else if (color == CRGB::Orange) Serial.print("Orange"); else if (color == CRGB::Pink) Serial.print("Pink"); else if (color == CRGB::White) Serial.print("White"); else if (color == CRGB::WarmWhite) Serial.print("Warm White"); else Serial.print("Custom"); } ``` ## **Interactive Color and Brightness Controller** ```cpp // Interactive Color and Brightness Controller // Serial commands and advanced features #include <FastLED.h> // Pin definitions #define LED_PIN 5 // TK33 WS2812 LED Strip on D5 #define POT_PIN A3 // TK07 Potentiometer on A3 #define BUTTON_PIN 3 // TK04 Button on D3 #define NUM_LEDS 5 // TK33 has 5 WS2812 LEDs // LED array CRGB leds[NUM_LEDS]; // Button variables #define DEBOUNCE_DELAY 50 unsigned long lastButtonPress = 0; bool lastButtonState = HIGH; // Color and brightness variables CRGB currentColor = CRGB::Red; int currentBrightness = 100; int brightnessPercentage = 100; bool autoMode = true; // Color modes enum ColorMode { MODE_RANDOM, MODE_RAINBOW, MODE_WARM_COLORS, MODE_COOL_COLORS, MODE_PRESET }; ColorMode currentMode = MODE_RANDOM; // Rainbow variables uint8_t rainbowHue = 0; void setup() { Serial.begin(9600); Serial.println("Interactive Color and Brightness Controller"); Serial.println("==========================================="); FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(currentBrightness); pinMode(POT_PIN, INPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); FastLED.clear(); FastLED.show(); delay(1000); Serial.println("Interactive controller ready!"); Serial.println("Commands: random, rainbow, warm, cool, preset, auto, manual, status, help"); Serial.println(); setAllLEDs(currentColor); FastLED.show(); } void loop() { // Handle serial commands handleSerialCommands(); // Read inputs readPotentiometer(); readButton(); // Update display based on mode updateInteractiveDisplay(); delay(50); } void handleSerialCommands() { if (Serial.available()) { String command = Serial.readStringUntil('\n'); command.trim(); command.toLowerCase(); if (command == "random") { currentMode = MODE_RANDOM; generateRandomColor(); Serial.println("Mode: Random colors"); } else if (command == "rainbow") { currentMode = MODE_RAINBOW; Serial.println("Mode: Rainbow cycle"); } else if (command == "warm") { currentMode = MODE_WARM_COLORS; generateWarmColor(); Serial.println("Mode: Warm colors"); } else if (command == "cool") { currentMode = MODE_COOL_COLORS; generateCoolColor(); Serial.println("Mode: Cool colors"); } else if (command == "preset") { currentMode = MODE_PRESET; cyclePreset(); Serial.println("Mode: Color presets"); } else if (command == "auto") { autoMode = true; Serial.println("Auto mode enabled"); } else if (command == "manual") { autoMode = false; Serial.println("Manual mode enabled"); } else if (command == "status") { displayInteractiveStatus(); } else if (command == "help") { displayHelp(); } else { Serial.println("Unknown command. Type 'help' for available commands."); } } } void readPotentiometer() { int potValue = analogRead(POT_PIN); int newBrightnessPercentage = map(potValue, 0, 1023, 0, 100); int newBrightness = map(newBrightnessPercentage, 0, 100, 0, 255); if (newBrightnessPercentage != brightnessPercentage) { brightnessPercentage = newBrightnessPercentage; currentBrightness = newBrightness; if (!autoMode) { Serial.print("Brightness: "); Serial.print(brightnessPercentage); Serial.println("%"); } } } void readButton() { bool buttonState = digitalRead(BUTTON_PIN); if (buttonState == LOW && lastButtonState == HIGH) { if (millis() - lastButtonPress > DEBOUNCE_DELAY) { lastButtonPress = millis(); if (autoMode) { // Auto mode - change color based on current mode switch (currentMode) { case MODE_RANDOM: generateRandomColor(); break; case MODE_RAINBOW: // Rainbow mode doesn't change on button press break; case MODE_WARM_COLORS: generateWarmColor(); break; case MODE_COOL_COLORS: generateCoolColor(); break; case MODE_PRESET: cyclePreset(); break; } } else { // Manual mode - always random generateRandomColor(); } } } lastButtonState = buttonState; } void generateRandomColor() { currentColor.r = random(256); currentColor.g = random(256); currentColor.b = random(256); if (currentColor.r == 0 && currentColor.g == 0 && currentColor.b == 0) { currentColor.r = random(50, 256); } if (!autoMode) { Serial.print("Random color: R="); Serial.print(currentColor.r); Serial.print(" G="); Serial.print(currentColor.g); Serial.print(" B="); Serial.println(currentColor.b); } } void generateWarmColor() { // Warm colors: red, orange, yellow, warm white int colorType = random(4); switch (colorType) { case 0: currentColor = CRGB::Red; break; case 1: currentColor = CRGB::Orange; break; case 2: currentColor = CRGB::Yellow; break; case 3: currentColor = CRGB::WarmWhite; break; } } void generateCoolColor() { // Cool colors: blue, green, cyan, purple int colorType = random(4); switch (colorType) { case 0: currentColor = CRGB::Blue; break; case 1: currentColor = CRGB::Green; break; case 2: currentColor = CRGB::Cyan; break; case 3: currentColor = CRGB::Purple; break; } } void cyclePreset() { static int presetIndex = 0; CRGB presets[] = {CRGB::Red, CRGB::Green, CRGB::Blue, CRGB::Yellow, CRGB::Purple, CRGB::Cyan, CRGB::Orange, CRGB::Pink, CRGB::White, CRGB::WarmWhite}; int numPresets = sizeof(presets) / sizeof(presets[0]); presetIndex = (presetIndex + 1) % numPresets; currentColor = presets[presetIndex]; if (!autoMode) { Serial.print("Preset "); Serial.print(presetIndex); Serial.println(" selected"); } } void setAllLEDs(CRGB color) { for (int i = 0; i < NUM_LEDS; i++) { leds[i] = color; } } void updateInteractiveDisplay() { if (currentMode == MODE_RAINBOW) { // Rainbow cycle effect for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(rainbowHue + i * 32, 255, 255); } rainbowHue += 2; } else { // Solid color mode setAllLEDs(currentColor); } FastLED.setBrightness(currentBrightness); FastLED.show(); } void displayInteractiveStatus() { Serial.println("=== INTERACTIVE STATUS ==="); Serial.print("Mode: "); switch (currentMode) { case MODE_RANDOM: Serial.println("Random"); break; case MODE_RAINBOW: Serial.println("Rainbow"); break; case MODE_WARM_COLORS: Serial.println("Warm Colors"); break; case MODE_COOL_COLORS: Serial.println("Cool Colors"); break; case MODE_PRESET: Serial.println("Preset"); break; } Serial.print("Auto Mode: "); Serial.println(autoMode ? "Yes" : "No"); Serial.print("Color: R="); Serial.print(currentColor.r); Serial.print(" G="); Serial.print(currentColor.g); Serial.print(" B="); Serial.println(currentColor.b); Serial.print("Brightness: "); Serial.print(brightnessPercentage); Serial.println("%"); Serial.println(); } void displayHelp() { Serial.println("=== AVAILABLE COMMANDS ==="); Serial.println("random - Random color mode"); Serial.println("rainbow - Rainbow cycle mode"); Serial.println("warm - Warm colors mode"); Serial.println("cool - Cool colors mode"); Serial.println("preset - Color preset mode"); Serial.println("auto - Enable auto mode"); Serial.println("manual - Enable manual mode"); Serial.println("status - Display current status"); Serial.println("help - Show this help"); Serial.println(); } ``` ## **Code Explanation** ### **Basic Version Features** - **Button Control**: Press TK04 to generate random colors - **Potentiometer Control**: Turn TK07 to adjust brightness (0-100%) - **Debouncing**: Prevents multiple triggers from single button press - **Real-time Updates**: Immediate response to input changes ### **Advanced Version Features** - **Smooth Transitions**: Gradual color and brightness changes - **Color Presets**: Predefined color options - **Long Press Detection**: Different actions for short/long button press - **Enhanced Feedback**: Detailed serial output ### **Interactive Version Features** - **Serial Commands**: Remote control via serial interface - **Multiple Modes**: Random, rainbow, warm, cool, preset modes - **Auto/Manual Mode**: Automatic or manual color changes - **Advanced Color Generation**: Themed color palettes ### **Key Functions** #### **Button Handling:** - **Debouncing**: Prevents false triggers - **Press Detection**: Short and long press recognition - **State Management**: Tracks button state changes #### **Potentiometer Processing:** - **Analog Reading**: Reads 0-1023 range - **Mapping**: Converts to 0-100% brightness - **Real-time Control**: Immediate brightness adjustment #### **Color Generation:** - **Random Colors**: Full RGB spectrum - **Preset Colors**: Predefined color options - **Themed Colors**: Warm and cool color palettes #### **LED Control:** - **Individual Control**: Set each LED independently - **Brightness Scaling**: Apply brightness to all LEDs - **Color Consistency**: Maintain color while adjusting brightness ## **Expected Output** ### **Basic Version:** ``` Color and Brightness Controller =============================== Controller initialized! TK33 WS2812 LED Strip: D5 TK07 Potentiometer: A3 TK04 Button: D3 Press button to change color Turn potentiometer to adjust brightness New color: R=255 G=128 B=64 Brightness: 75% === STATUS === Color: R=255 G=128 B=64 Brightness: 75% Potentiometer: 768 ``` ### **Advanced Version:** ``` Advanced Color and Brightness Controller ======================================= Advanced controller initialized! Short press: Random color Long press: Cycle through presets Potentiometer: Adjust brightness Short press: Random color generated Brightness: 60% Long press: Color preset cycled Preset 1: Green === ADVANCED STATUS === Color: R=0 G=255 B=0 Brightness: 60% Preset: 1/9 Transitioning: No ``` ### **Interactive Version:** ``` Interactive Color and Brightness Controller =========================================== Interactive controller ready! Commands: random, rainbow, warm, cool, preset, auto, manual, status, help random Mode: Random colors Random color: R=128 G=255 B=64 rainbow Mode: Rainbow cycle status === INTERACTIVE STATUS === Mode: Rainbow Auto Mode: Yes Color: R=255 G=0 B=255 Brightness: 80% ``` ## **Troubleshooting** ### **Button Issues:** - Check TK04 wiring (D3 pin) - Verify internal pull-up resistor - Test button state with Serial output - Check for loose connections ### **Potentiometer Issues:** - Check TK07 wiring (A3 pin) - Verify voltage supply (5V) - Test analog reading range - Check for noise in readings ### **LED Strip Issues:** - Check TK33 wiring (D5 pin) - Verify power supply (5V, sufficient current) - Test with simple color setting - Check FastLED library installation ### **Color Issues:** - Verify random number generation - Check color mapping functions - Test individual RGB components - Verify brightness scaling ## **Applications** ### **Home Automation** - **Mood Lighting**: Create different atmospheres - **Smart Home**: Integrate with home automation systems - **Ambient Lighting**: Background lighting control - **Party Lighting**: Dynamic event lighting ### **Educational** - **Color Theory**: Learn RGB color mixing - **Analog Input**: Practice potentiometer control - **Digital Input**: Learn button interfacing - **Real-time Systems**: Practice responsive programming ### **Commercial** - **Display Lighting**: Product showcase lighting - **Retail Ambiance**: Store atmosphere control - **Event Lighting**: Dynamic venue lighting - **Signage**: Interactive advertising displays ### **Art & Design** - **Color Testing**: Test color combinations - **Lighting Design**: Prototype lighting effects - **Interactive Art**: User-controlled installations - **Color Palettes**: Develop color schemes ## **Next Steps** - Add wireless control capabilities - Implement color temperature control - Create scheduling features - Add music-reactive modes ## **Resources** - **FastLED Library**: https://github.com/FastLED/FastLED - **Color Theory**: RGB color space and mixing - **Analog Input**: Potentiometer interfacing - **Digital Input**: Button debouncing techniques