Project tutorial
Translightion Board (Controllable Music Visualizer)

Translightion Board (Controllable Music Visualizer) © GPL3+

Translate music to a dazzling light show with this customizable light controller project. Great for DJs, parties, and 1:1 shows!

  • 998 views
  • 0 comments
  • 10 respects

Components and supplies

Necessary tools and machines

Hy gluegun
Hot glue gun (generic)

Apps and online services

About this project

The idea behind this project was to create a controller to allows users to “play” light like it is an instrument with custom visuals, gesture control, and brightness/speed dials.

Considering how pricey consumer light controllers can be (often $100 bucks or more- not including the lights!) we decided to try to make a cheaper, more customizable solution!

One of the challenges with a project like this is the number of buttons it would have to include. Even in my more conservative designs, I wanted to have around 8 buttons to manage the different visual sequences, color palettes, and other mode selection. Wiring up that many buttons can be tedious and opens a lot of possibility for one connection to break and ruin the whole performance. Additionally the Arduino we are using (the UNO) only has so many digital inputs that can be used. Luckily by using the the Pmod KYPD we were able to circumvent both these issues!

The Pmod KYPD's small form-factor allows it to fit neatly onto any baseboard without taking up too much real estate. I am using a wood sample I got from my local hardware store for free as my mounting panel.

To wire up this project, first wire up the Pmod KYPD according to this diagram:

Then wire in your potentiometers to Analog Pins A5 (brightness) and A4 (speed).

Attach the LED Strips to Ground and 5V, then wire both signal pins into Digital Pin 11.

Wire up the sound sensor to power and ground, and the white wire to A1 and yellow wire to A0 (if you do not have the connecting cable as reference, the yellow wire is the outside one, and more documentation on the sensor is here.

For the Ping sensor/Ultrasonic rangefinder Trig is on Digital Pin 13 and Echo is on Digital Pin 12 (in addition to power and ground of course).

For the code you will need the FastLED and Keypad library (both found in the Arduino IDE library manager). Keypad is not listed first when you search for it, you will have to scroll down until you find the one by Mark Stanley and Alexander Brevig.

The rest of the code is here:

#include <FastLED.h>
#include <Keypad.h>
// --------- BEGIN CONFIGURABLE SETTINGS ---------
// PIN MAPPINGS                                  //
//                                               //
#define LED_PIN     11                            //
//                                               //
#define POT_PIN_01  A5 // Brightness             //
#define POT_PIN_02  A4 // Speed                  //
//                                               //
const int pinAdc = A0;
//                                               //
#define PING_PIN    13                            //
#define ECHO_PIN    12                            //
//                                               //
// SETUP CONSTANTS                               //
//                                               //
#define PING_MIN_RANGE 0                         //
#define PING_MAX_RANGE 12                        //
//                                               //
#define LED_MAX_SPEED 60                         //
//                                               //
#define NUM_LEDS    30                           //
#define LED_TYPE    WS2811                       //
#define COLOR_ORDER GRB                          //
//                                               //
#define SOUND_BUMP_THRESHOLD 20                  //
#define AUDIO_UPDATE_FREQ    10000                //
const byte LINE = 4; // 4 lines
const byte COLUMN = 4; // 4 columms
//Declaration of the key of the keypad
char hexaKeys[LINE][COLUMN] =
{
 {'1', '2', '3', 'A'},
 {'4', '5', '6', 'B'},
 {'7', '8', '9', 'C'},
 {'0', 'F', 'E', 'D'}
};
//Assignement of pin for the keypad
byte line_pin[LINE] = {2, 3, 4, 5};
byte column_pin[COLUMN] = {6, 7, 8, 9};
Keypad clavier = Keypad( makeKeymap(hexaKeys), line_pin, column_pin, LINE, COLUMN); // creation of object keypad
//                                               //
// ---------- END CONFIGURABLE SETTINGS ----------
// Define color offsets
// Basically we are taking the 16 color pallete and reducing it to 4
#define COLOR_01 0
#define COLOR_02 16
#define COLOR_03 32
#define COLOR_04 48
// GLOBAL VARIABLES
CRGB leds[NUM_LEDS];
CRGBPalette16 currentPalette;
uint8_t led_brightness = 100; // Default only, will be overwritten
uint8_t led_speed = 10;       // Default only, will be overwritten
uint8_t visual = 1;
uint8_t palette = 0;
bool btn_01_status = false;
bool btn_02_status = false;
bool btn_03_status = false;
bool btn_04_status = false;
bool btn_05_status = false;
bool btn_06_status = false;
bool btn_07_status = false;
bool btn_08_status = false;
bool btn_09_status = false;
bool btn_10_status = false;
bool btn_11_status = false;
bool btn_12_status = false;
// BEGIN CODE
void setup() {
 //Initialize LED Strip
 FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
 FastLED.setBrightness(led_brightness);
 //Set pin modes
 pinMode(PING_PIN, OUTPUT);
 pinMode(ECHO_PIN, INPUT);
 // Initialize pallete to gray
 currentPalette = CRGBPalette16(
                    CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100),
                    CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100),
                    CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100),
                    CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100) );
 Serial.begin(9600);
}
void loop()
{
 char key = clavier.getKey();
 Serial.print("Key: ");
 Serial.println(key);
 // Handle button presses
 if (key != 0x00) // if there is not any key, function getKey send NULL character (0x00)
 {
   if (key == '1') {
     if (btn_01_status == false) {
       btn_01_status = true;
       visual = 1;
     }
   } else {
     btn_01_status = false;
   }
   if (key == '2') {
     if (btn_02_status == false) {
       btn_02_status = true;
       visual = 2;
     }
   } else {
     btn_02_status = false;
   }
   if (key == '3') {
     if (btn_03_status == false) {
       btn_03_status = true;
       visual = 3;
     }
   } else {
     btn_03_status = false;
   }
   if (key == '4') {
     if (btn_04_status == false) {
       btn_04_status = true;
       visual = 4;
     }
   } else {
     btn_04_status = false;
   }
   if (key == '5') {
     if (btn_05_status == false) {
       btn_05_status = true;
       visual = 5;
     }
   } else {
     btn_05_status = false;
   }
   if (key == '6') {
     if (btn_06_status == false) {
       btn_06_status = true;
       palette = 1;
     }
   } else {
     btn_06_status = false;
   }
   if (key == '7') {
     if (btn_07_status == false) {
       btn_07_status = true;
       palette = 2;
     }
   } else {
     btn_07_status = false;
   }
   if (key == '8') {
     if (btn_08_status == false) {
       btn_08_status = true;
       palette = 3;
     }
   } else {
     btn_08_status = false;
   }
   if (key == '9') {
     if (btn_09_status == false) {
       btn_09_status = true;
       palette = 4;
     }
   } else {
     btn_09_status = false;
   }
    if (key == '0') {
     if (btn_10_status == false) {
       btn_10_status = true;
       visual = 6;
     }
   } else {
     btn_10_status = false;
   }
    if (key == 'C') {
     if (btn_11_status == false) {
       btn_11_status = true;
       palette = 5;
     }
   } else {
     btn_11_status = false;
   }
    if (key == 'F') {
     if (btn_12_status == false) {
       btn_12_status = true;
       palette = 6;
     }
   } else {
     btn_12_status = false;
   }
 }
 Serial.print("Visual: ");
 Serial.print(visual);
 Serial.print(" Palette: ");
 Serial.println(palette);
 // Update variables from potentiometers
 led_brightness = map(analogRead(POT_PIN_01), 0, 1023, 0, 255);
 led_speed = map(analogRead(POT_PIN_02), 0, 1023, 1, LED_MAX_SPEED);
 // Visualizers:
 // runVisualFlow();
 // runVisualPing();
 // runVisualPingBlob();
 // runVisualBounce();
 // runVisualDoubleBounce();
 // runVisualSegments();
 // runVisualSound();
 // Run visual based on visual id number
 // ---------- CHANGE THESE TO CHANGE SELECTED VISUALIZATION ----------
 switch (visual) {
   case 1:
     runVisualFlow();
     break;
   case 2:
     runVisualDoubleBounce();
     break;
   case 3:
     runVisualPing();
     break;
   case 4:
     runVisualPingBlob();
     break;
   case 5:
     runVisualSegments();
     break;
   case 6:
     runVisualSound();
     break;
   default:
     runVisualFlow();
     break;
 }
 // Palettes:
 // setPaletteFire(),
 // setPaletteSynth(),
 // setPaletteParty(),
 // setPaletteBlackWhite()
 // Map Palettes to visual id number
 // ---------- CHANGE THESE TO CHANGE SELECTED PALETTES ----------
 switch (palette) {
   case 1:
     setPaletteFire();
     break;
   case 2:
     setPaletteSynth();
     break;
   case 3:
     setPaletteParty();
     break;
   case 4:
     setPaletteBlackWhite();
     break;
    case 5:
     setChloePalette();
     break;
    case 6:
     setReggaePalette();
     break;
   default:
     break;
 }
 FastLED.show();
 FastLED.delay(1000 / led_speed);
}
// ---------- BEGIN VISUALIZERS ----------
// Turns on leds corresponding to the sound level compared to the last AUDIO_UPDATE_FREQ millisecond period
void runVisualSound() {
 Serial.print("VISUAL SOUND");
 long soundLevel_00 = 0;
 static long soundLevel_01 = 0;
 static long soundLevel_02 = 0;
 static long soundLevel_03 = 0;
 static long soundLevel_04 = 0;
 // Get current sound level
 for (int i = 0; i < 32; i++)
 {
   soundLevel_00 += analogRead(pinAdc);
 }
 soundLevel_00 >>= 5;
 long aveSound = (soundLevel_00 + soundLevel_01 + soundLevel_02 + soundLevel_03 + soundLevel_04) / 5;
 Serial.print("Current Sound: ");
 Serial.print(soundLevel_00);
 Serial.print(" Averaged Sound: ");
 Serial.println(aveSound);
 // Map sound level to a value 0 to NUM_LEDs based on long term min/max
 uint8_t ledRange = map(aveSound, 300, 500, 1, NUM_LEDS);
Serial.println(ledRange);
 // Light LEDs based on the sound level
 for ( int i = 0; i < NUM_LEDS; i++) {
   if (i < ledRange) {
     leds[i] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
   } else {
     leds[i] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
   }
 }
soundLevel_04 = soundLevel_03;
 soundLevel_03 = soundLevel_02;
 soundLevel_02 = soundLevel_01;
 soundLevel_01 = soundLevel_00;
}
// Creates sets of 7 LEDs colored in order from the palette and shifts them 1 each cycle
void runVisualFlow() {
 // Create static var to hand current position
 static uint8_t start_position = 0;
 // Update start position to "move" LEDs. In this case just a simple shift
 if (start_position > NUM_LEDS) {
   start_position = getSafeIndex(start_position);
 } else {
   start_position += 1;
 }
 uint8_t current_color = COLOR_01;
 // The visualizer logic goes here
 for ( int i = 0; i < NUM_LEDS; i += 7) {
   leds[getSafeIndex(i + start_position)] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_position + 1)] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_position + 2)] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_position + 3)] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_position + 4)] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_position + 5)] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_position + 6)] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
 }
}
// Sets a back drop of the "base" color 4 and moves an LED of "primary" color 1 up and down the string
void runVisualBounce() {
 // Create static var to hand current position
 static uint8_t start_position = 0;
 static bool move_direction = true;
 // Update start position to "move" LEDs, changing direction when we hit the ends
 if (move_direction) {
   if (++start_position == NUM_LEDS - 1) {
     move_direction = false;
   }
 } else {
   if (--start_position == 0) {
     move_direction = true;
   }
 }
 uint8_t current_color = COLOR_01;
 // Set all LEDs to "base" color 4
 for ( int i = 0; i < NUM_LEDS; i += 1) {
   // Added a bit of randomness to make it less static looking
   // Mostly makes it flash a bit
   leds[i] = ColorFromPalette( currentPalette, COLOR_04 + random(0, 5), led_brightness, LINEARBLEND);
 }
 // Set lead LED to primary color
 leds[start_position] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
 // Set first trailer LED
 if (move_direction) {
   if (start_position - 1 > 0) {
     leds[start_position - 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   }
 } else {
   if (start_position + 1 < NUM_LEDS) {
     leds[start_position + 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   }
 }
 // Set the second trailer LED
 if (move_direction) {
   if (start_position - 2 > 0) {
     leds[start_position - 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   }
 } else {
   if (start_position + 2 < NUM_LEDS) {
     leds[start_position + 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   }
 }
}
// Sets a back drop of the "base" color 4 and moves an LED of "primary" color 1 up and down the string
void runVisualDoubleBounce() {
 // Create static var to hand current position
 static uint8_t start_position_1 = 0;
 static bool move_direction_1 = true;
 static uint8_t start_position_2 = NUM_LEDS;
 static bool move_direction_2 = false;
 // Update start position to "move" LEDs, changing direction when we hit the ends
 if (move_direction_1) {
   if (++start_position_1 == NUM_LEDS - 1) {
     move_direction_1 = false;
   }
 } else {
   if (--start_position_1 == 0) {
     move_direction_1 = true;
   }
 }
 if (move_direction_2) {
   if (++start_position_2 == NUM_LEDS - 1) {
     move_direction_2 = false;
   }
 } else {
   if (--start_position_2 == 0) {
     move_direction_2 = true;
   }
 }
 uint8_t current_color = COLOR_01;
 // Set all LEDs to "base" color 4
 for ( int i = 0; i < NUM_LEDS; i += 1) {
   // Added a bit of randomness to make it less static looking
   // Mostly makes it flash a bit
   leds[i] = ColorFromPalette( currentPalette, COLOR_04 + random(0, 5), led_brightness, LINEARBLEND);
 }
 // Set lead LED to primary color
 leds[start_position_1] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
 leds[start_position_2] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
 // Set first trailer LED
 if (move_direction_1) {
   if (start_position_1 - 1 > 0) {
     leds[start_position_1 - 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   }
 } else {
   if (start_position_1 + 1 < NUM_LEDS) {
     leds[start_position_1 + 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   }
 }
 if (move_direction_2) {
   if (start_position_2 - 1 > 0) {
     leds[start_position_2 - 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   }
 } else {
   if (start_position_2 + 1 < NUM_LEDS) {
     leds[start_position_2 + 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
   }
 }
 // Set the second trailer LED
 if (move_direction_1) {
   if (start_position_1 - 2 > 0) {
     leds[start_position_1 - 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   }
 } else {
   if (start_position_1 + 2 < NUM_LEDS) {
     leds[start_position_1 + 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   }
 }
 if (move_direction_2) {
   if (start_position_2 - 2 > 0) {
     leds[start_position_2 - 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   }
 } else {
   if (start_position_2 + 2 < NUM_LEDS) {
     leds[start_position_2 + 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
   }
 }
}
// Creates segments of 6 LEDs color from the palette randomly and updates them (and their position) every cycle
void runVisualSegments() {
 // Create random start position to begin our segments at so they don't always appear in the same place
 uint8_t start_pos = random(0, NUM_LEDS + 1);
 for ( int i = 0; i < NUM_LEDS; i += 6) {
   // Pick a random color from our color palette
   // Remember we are effectively limiting it to 4 colors, which have a gap of 16
   uint8_t current_color_offset = random(0, 4) * 16;
   leds[getSafeIndex(i + start_pos)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_pos + 1)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_pos + 2)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_pos + 3)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_pos + 4)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
   leds[getSafeIndex(i + start_pos + 5)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
 }
}
// Sets the "base" color to palette color 4 and lights up all LEDs lower than the ping distance to the "primary" color 1
void runVisualPing() {
 digitalWrite(PING_PIN, LOW);
 delayMicroseconds(2);
 digitalWrite(PING_PIN, HIGH);
 delayMicroseconds(10);
 digitalWrite(PING_PIN, LOW);
 long inches = pulseIn(ECHO_PIN, HIGH) / 74 / 2;
 Serial.print("Distance: ");
 Serial.println(inches);
 // Translate distance to a value in the ping control range
 uint8_t ledRange = constrain(inches, PING_MIN_RANGE, PING_MAX_RANGE);
 ledRange = map(ledRange, PING_MIN_RANGE, PING_MAX_RANGE, 0, NUM_LEDS);
 for ( int i = 0; i < NUM_LEDS; i++) {
   if (i < ledRange) {
     leds[i] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
   } else {
     leds[i] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
   }
 }
}
// Sets the "base" color to palette color 4 and light up 5 LEDs around the location of the
void runVisualPingBlob() {
 digitalWrite(PING_PIN, LOW);
 delayMicroseconds(2);
 digitalWrite(PING_PIN, HIGH);
 delayMicroseconds(10);
 digitalWrite(PING_PIN, LOW);
 long inches = pulseIn(ECHO_PIN, HIGH) / 74 / 2;
 Serial.print("Distance: ");
 Serial.println(inches);
 // Translate distance to a value in the ping control range
 uint8_t ledRange = constrain(inches, PING_MIN_RANGE, PING_MAX_RANGE);
 ledRange = map(ledRange, PING_MIN_RANGE, PING_MAX_RANGE, 0, NUM_LEDS);
 for ( int i = 0; i < NUM_LEDS; i++) {
   if (i <= ledRange + 2 && i >= ledRange - 2) {
     leds[i] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
   } else {
     leds[i] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
   }
 }
}
// Gets an index we can safely assign to the led array, makes overflow "wrap" around
uint8_t getSafeIndex(uint8_t index) {
 return (index % NUM_LEDS);
}
// ---------- END VISUALIZERS ----------
// ---------- BEGIN PALETTES ----------
void setPaletteFire()
{
 CRGB color4 = CRGB(180, 0, 0);
 CRGB color3 = CRGB(255, 77, 0);
 CRGB color2 = CRGB(255, 116, 0);
 CRGB color1 = CRGB(255, 154, 0);
 currentPalette = CRGBPalette16(
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4);
}
void setPaletteSynth()
{
 CRGB color1 = CRGB(212, 0, 120);
 CRGB color2 = CRGB(146, 0, 117);
 CRGB color3 = CRGB(20, 75, 156);
 CRGB color4 = CRGB(0, 0, 0);
 currentPalette = CRGBPalette16(
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4);
}
void setPaletteParty()
{
 CRGB color1 = CRGB(255, 0, 102);
 CRGB color2 = CRGB(255, 235, 0);
 CRGB color3 = CRGB(0, 152, 195);
 CRGB color4 = CRGB(0, 220, 110);
 currentPalette = CRGBPalette16(
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4);
}
void setPaletteBlackWhite()
{
 CRGB color1 = CRGB(255, 255, 255);
 CRGB color2 = CRGB(200, 200, 200);
 CRGB color3 = CRGB(150, 150, 150);
 CRGB color4 = CRGB(0, 0, 0);
 currentPalette = CRGBPalette16(
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4);
}
void setChloePalette()
{
 CRGB color1 = CRGB(148, 0, 211);  //148, 0, 211
 CRGB color2 = CRGB(255, 105, 180);
 CRGB color3 = CRGB(160, 32, 240);
 CRGB color4 = CRGB(255, 69, 0); //255, 69, 0
 currentPalette = CRGBPalette16(
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4);
}
void setReggaePalette()
{
 CRGB color1 = CRGB(255, 0, 0);  //148, 0, 211
 CRGB color2 = CRGB(255, 215, 0);
 CRGB color3 = CRGB(255, 255, 0);
 CRGB color4 = CRGB(0, 128, 0); //255, 69, 0
 currentPalette = CRGBPalette16(
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4,
                    color1, color2, color3, color4);
}

Copy and paste the code into the Arduino IDE and click upload. Now it is time to play around with the board! Note- Buttons 3 and 4 are attached to the ping sensor so try putting your hand over the sensor when you activate those visualizers.

Have fun and feel free to expand this project to add more visualizers, sensors, ect!

Code

FinalLEDControllerWithChloePalette.inoArduino
#include <FastLED.h>
#include <Keypad.h>

// --------- BEGIN CONFIGURABLE SETTINGS ---------
// PIN MAPPINGS                                  //
//                                               //
#define LED_PIN     11                            //
//                                               //
#define POT_PIN_01  A5 // Brightness             //
#define POT_PIN_02  A4 // Speed                  //
//                                               //

const int pinAdc = A0;
                  
//                                               //
#define PING_PIN    13                            //
#define ECHO_PIN    12                            //
//                                               //
// SETUP CONSTANTS                               //
//                                               //
#define PING_MIN_RANGE 0                         //
#define PING_MAX_RANGE 12                        //
//                                               //
#define LED_MAX_SPEED 60                         //
//                                               //
#define NUM_LEDS    30                           //
#define LED_TYPE    WS2811                       //
#define COLOR_ORDER GRB                          //
//                                               //
#define SOUND_BUMP_THRESHOLD 20                  //
#define AUDIO_UPDATE_FREQ    10000                //

const byte LINE = 4; // 4 lines
const byte COLUMN = 4; // 4 columms

//Declaration of the key of the keypad
char hexaKeys[LINE][COLUMN] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'0', 'F', 'E', 'D'}
};
//Assignement of pin for the keypad
byte line_pin[LINE] = {2, 3, 4, 5};
byte column_pin[COLUMN] = {6, 7, 8, 9};

Keypad clavier = Keypad( makeKeymap(hexaKeys), line_pin, column_pin, LINE, COLUMN); // creation of object keypad
//                                               //
// ---------- END CONFIGURABLE SETTINGS ----------

// Define color offsets
// Basically we are taking the 16 color pallete and reducing it to 4
#define COLOR_01 0
#define COLOR_02 16
#define COLOR_03 32
#define COLOR_04 48

// GLOBAL VARIABLES

CRGB leds[NUM_LEDS];
CRGBPalette16 currentPalette;
uint8_t led_brightness = 100; // Default only, will be overwritten
uint8_t led_speed = 10;       // Default only, will be overwritten
uint8_t visual = 1;
uint8_t palette = 0;

bool btn_01_status = false;
bool btn_02_status = false;
bool btn_03_status = false;
bool btn_04_status = false;
bool btn_05_status = false;
bool btn_06_status = false;
bool btn_07_status = false;
bool btn_08_status = false;
bool btn_09_status = false;
bool btn_10_status = false;
bool btn_11_status = false;
bool btn_12_status = false;


// BEGIN CODE

void setup() {
  //Initialize LED Strip
  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness(led_brightness);

  //Set pin modes
  pinMode(PING_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  // Initialize pallete to gray
  currentPalette = CRGBPalette16(
                     CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100),
                     CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100),
                     CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100),
                     CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100), CRGB(100, 100, 100) );

  Serial.begin(9600);
}

void loop()
{
  char key = clavier.getKey();
  Serial.print("Key: ");
  Serial.println(key);
  // Handle button presses
  if (key != 0x00) // if there is not any key, function getKey send NULL character (0x00)
  {
    if (key == '1') {
      if (btn_01_status == false) {
        btn_01_status = true;
        visual = 1;
      }
    } else {
      btn_01_status = false;
    }
    if (key == '2') {
      if (btn_02_status == false) {
        btn_02_status = true;
        visual = 2;
      }
    } else {
      btn_02_status = false;
    }
    if (key == '3') {
      if (btn_03_status == false) {
        btn_03_status = true;
        visual = 3;
      }
    } else {
      btn_03_status = false;
    }
    if (key == '4') {
      if (btn_04_status == false) {
        btn_04_status = true;
        visual = 4;
      }
    } else {
      btn_04_status = false;
    }
    if (key == '5') {
      if (btn_05_status == false) {
        btn_05_status = true;
        visual = 5;
      }
    } else {
      btn_05_status = false;
    }
    if (key == '6') {
      if (btn_06_status == false) {
        btn_06_status = true;
        palette = 1;
      }
    } else {
      btn_06_status = false;
    }
    if (key == '7') {
      if (btn_07_status == false) {
        btn_07_status = true;
        palette = 2;
      }
    } else {
      btn_07_status = false;
    }
    if (key == '8') {
      if (btn_08_status == false) {
        btn_08_status = true;
        palette = 3;
      }
    } else {
      btn_08_status = false;
    }
    if (key == '9') {
      if (btn_09_status == false) {
        btn_09_status = true;
        palette = 4;
      }
    } else {
      btn_09_status = false;
    }
  
     if (key == '0') {
      if (btn_10_status == false) {
        btn_10_status = true;
        visual = 6;
      }
    } else {
      btn_10_status = false;
    }
  
     if (key == 'C') {
      if (btn_11_status == false) {
        btn_11_status = true;
        palette = 5;
      }
    } else {
      btn_11_status = false;
    }
  
     if (key == 'F') {
      if (btn_12_status == false) {
        btn_12_status = true;
        palette = 6;
      }
    } else {
      btn_12_status = false;
    }
  }
  

  Serial.print("Visual: ");
  Serial.print(visual);
  Serial.print(" Palette: ");
  Serial.println(palette);


  // Update variables from potentiometers
  led_brightness = map(analogRead(POT_PIN_01), 0, 1023, 0, 255);
  led_speed = map(analogRead(POT_PIN_02), 0, 1023, 1, LED_MAX_SPEED);

  // Visualizers:
  // runVisualFlow();
  // runVisualPing();
  // runVisualPingBlob();
  // runVisualBounce();
  // runVisualDoubleBounce();
  // runVisualSegments();
  // runVisualSound();

  // Run visual based on visual id number
  // ---------- CHANGE THESE TO CHANGE SELECTED VISUALIZATION ----------
  switch (visual) {
    case 1:
      runVisualFlow();
      break;
    case 2:
      runVisualDoubleBounce();
      break;
    case 3:
      runVisualPing();
      break;
    case 4:
      runVisualPingBlob();
      break;
    case 5:
      runVisualSegments();
      break;
    case 6:
      runVisualSound();
      break;
    default:
      runVisualFlow();
      break;
  }

  // Palettes:
  // setPaletteFire(),
  // setPaletteSynth(),
  // setPaletteParty(),
  // setPaletteBlackWhite()

  // Map Palettes to visual id number
  // ---------- CHANGE THESE TO CHANGE SELECTED PALETTES ----------
  switch (palette) {
    case 1:
      setPaletteFire();
      break;
    case 2:
      setPaletteSynth();
      break;
    case 3:
      setPaletteParty();
      break;
    case 4:
      setPaletteBlackWhite();
      break;
     case 5:
      setChloePalette();
      break;
     case 6:
      setReggaePalette();
      break;
    default:
      break;
  }

  FastLED.show();
  FastLED.delay(1000 / led_speed);
}

// ---------- BEGIN VISUALIZERS ----------

// Turns on leds corresponding to the sound level compared to the last AUDIO_UPDATE_FREQ millisecond period
void runVisualSound() {
  Serial.print("VISUAL SOUND");
  long soundLevel_00 = 0;
  static long soundLevel_01 = 0;
  static long soundLevel_02 = 0;
  static long soundLevel_03 = 0;
  static long soundLevel_04 = 0;

  // Get current sound level
  for (int i = 0; i < 32; i++)
  {
    soundLevel_00 += analogRead(pinAdc);
  }

  soundLevel_00 >>= 5;

  long aveSound = (soundLevel_00 + soundLevel_01 + soundLevel_02 + soundLevel_03 + soundLevel_04) / 5;
  Serial.print("Current Sound: ");
  Serial.print(soundLevel_00);
  Serial.print(" Averaged Sound: ");
  Serial.println(aveSound);
  

  // Map sound level to a value 0 to NUM_LEDs based on long term min/max
  uint8_t ledRange = map(aveSound, 300, 500, 1, NUM_LEDS);
Serial.println(ledRange);
  // Light LEDs based on the sound level
  for ( int i = 0; i < NUM_LEDS; i++) {
    if (i < ledRange) {
      leds[i] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
    } else {
      leds[i] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
    }
  }
 soundLevel_04 = soundLevel_03;
  soundLevel_03 = soundLevel_02;
  soundLevel_02 = soundLevel_01;
  soundLevel_01 = soundLevel_00;

}

// Creates sets of 7 LEDs colored in order from the palette and shifts them 1 each cycle
void runVisualFlow() {
  // Create static var to hand current position
  static uint8_t start_position = 0;

  // Update start position to "move" LEDs. In this case just a simple shift
  if (start_position > NUM_LEDS) {
    start_position = getSafeIndex(start_position);
  } else {
    start_position += 1;
  }
  uint8_t current_color = COLOR_01;

  // The visualizer logic goes here
  for ( int i = 0; i < NUM_LEDS; i += 7) {
    leds[getSafeIndex(i + start_position)] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_position + 1)] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_position + 2)] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_position + 3)] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_position + 4)] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_position + 5)] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_position + 6)] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
  }
}

// Sets a back drop of the "base" color 4 and moves an LED of "primary" color 1 up and down the string
void runVisualBounce() {
  // Create static var to hand current position
  static uint8_t start_position = 0;
  static bool move_direction = true;

  // Update start position to "move" LEDs, changing direction when we hit the ends
  if (move_direction) {
    if (++start_position == NUM_LEDS - 1) {
      move_direction = false;
    }
  } else {
    if (--start_position == 0) {
      move_direction = true;
    }
  }

  uint8_t current_color = COLOR_01;

  // Set all LEDs to "base" color 4
  for ( int i = 0; i < NUM_LEDS; i += 1) {
    // Added a bit of randomness to make it less static looking
    // Mostly makes it flash a bit
    leds[i] = ColorFromPalette( currentPalette, COLOR_04 + random(0, 5), led_brightness, LINEARBLEND);
  }

  // Set lead LED to primary color
  leds[start_position] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);

  // Set first trailer LED
  if (move_direction) {
    if (start_position - 1 > 0) {
      leds[start_position - 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    }
  } else {
    if (start_position + 1 < NUM_LEDS) {
      leds[start_position + 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    }
  }

  // Set the second trailer LED
  if (move_direction) {
    if (start_position - 2 > 0) {
      leds[start_position - 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    }
  } else {
    if (start_position + 2 < NUM_LEDS) {
      leds[start_position + 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    }
  }
}

// Sets a back drop of the "base" color 4 and moves an LED of "primary" color 1 up and down the string
void runVisualDoubleBounce() {
  // Create static var to hand current position
  static uint8_t start_position_1 = 0;
  static bool move_direction_1 = true;
  static uint8_t start_position_2 = NUM_LEDS;
  static bool move_direction_2 = false;

  // Update start position to "move" LEDs, changing direction when we hit the ends
  if (move_direction_1) {
    if (++start_position_1 == NUM_LEDS - 1) {
      move_direction_1 = false;
    }
  } else {
    if (--start_position_1 == 0) {
      move_direction_1 = true;
    }
  }
  if (move_direction_2) {
    if (++start_position_2 == NUM_LEDS - 1) {
      move_direction_2 = false;
    }
  } else {
    if (--start_position_2 == 0) {
      move_direction_2 = true;
    }
  }

  uint8_t current_color = COLOR_01;

  // Set all LEDs to "base" color 4
  for ( int i = 0; i < NUM_LEDS; i += 1) {
    // Added a bit of randomness to make it less static looking
    // Mostly makes it flash a bit
    leds[i] = ColorFromPalette( currentPalette, COLOR_04 + random(0, 5), led_brightness, LINEARBLEND);
  }

  // Set lead LED to primary color
  leds[start_position_1] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
  leds[start_position_2] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);

  // Set first trailer LED
  if (move_direction_1) {
    if (start_position_1 - 1 > 0) {
      leds[start_position_1 - 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    }
  } else {
    if (start_position_1 + 1 < NUM_LEDS) {
      leds[start_position_1 + 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    }
  }
  if (move_direction_2) {
    if (start_position_2 - 1 > 0) {
      leds[start_position_2 - 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    }
  } else {
    if (start_position_2 + 1 < NUM_LEDS) {
      leds[start_position_2 + 1] = ColorFromPalette( currentPalette, COLOR_02, led_brightness, LINEARBLEND);
    }
  }

  // Set the second trailer LED
  if (move_direction_1) {
    if (start_position_1 - 2 > 0) {
      leds[start_position_1 - 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    }
  } else {
    if (start_position_1 + 2 < NUM_LEDS) {
      leds[start_position_1 + 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    }
  }
  if (move_direction_2) {
    if (start_position_2 - 2 > 0) {
      leds[start_position_2 - 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    }
  } else {
    if (start_position_2 + 2 < NUM_LEDS) {
      leds[start_position_2 + 2] = ColorFromPalette( currentPalette, COLOR_03, led_brightness, LINEARBLEND);
    }
  }
}

// Creates segments of 6 LEDs color from the palette randomly and updates them (and their position) every cycle
void runVisualSegments() {

  // Create random start position to begin our segments at so they don't always appear in the same place
  uint8_t start_pos = random(0, NUM_LEDS + 1);

  for ( int i = 0; i < NUM_LEDS; i += 6) {
    // Pick a random color from our color palette
    // Remember we are effectively limiting it to 4 colors, which have a gap of 16
    uint8_t current_color_offset = random(0, 4) * 16;

    leds[getSafeIndex(i + start_pos)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_pos + 1)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_pos + 2)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_pos + 3)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_pos + 4)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);
    leds[getSafeIndex(i + start_pos + 5)] = ColorFromPalette( currentPalette, current_color_offset, led_brightness, LINEARBLEND);

  }
}

// Sets the "base" color to palette color 4 and lights up all LEDs lower than the ping distance to the "primary" color 1
void runVisualPing() {
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(PING_PIN, LOW);
  long inches = pulseIn(ECHO_PIN, HIGH) / 74 / 2;
  Serial.print("Distance: ");
  Serial.println(inches);

  // Translate distance to a value in the ping control range
  uint8_t ledRange = constrain(inches, PING_MIN_RANGE, PING_MAX_RANGE);
  ledRange = map(ledRange, PING_MIN_RANGE, PING_MAX_RANGE, 0, NUM_LEDS);

  for ( int i = 0; i < NUM_LEDS; i++) {

    if (i < ledRange) {
      leds[i] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
    } else {
      leds[i] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
    }
  }
}

// Sets the "base" color to palette color 4 and light up 5 LEDs around the location of the
void runVisualPingBlob() {
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(PING_PIN, LOW);
  long inches = pulseIn(ECHO_PIN, HIGH) / 74 / 2;
  Serial.print("Distance: ");
  Serial.println(inches);

  // Translate distance to a value in the ping control range
  uint8_t ledRange = constrain(inches, PING_MIN_RANGE, PING_MAX_RANGE);
  ledRange = map(ledRange, PING_MIN_RANGE, PING_MAX_RANGE, 0, NUM_LEDS);

  for ( int i = 0; i < NUM_LEDS; i++) {
    if (i <= ledRange + 2 && i >= ledRange - 2) {
      leds[i] = ColorFromPalette( currentPalette, COLOR_01, led_brightness, LINEARBLEND);
    } else {
      leds[i] = ColorFromPalette( currentPalette, COLOR_04, led_brightness, LINEARBLEND);
    }
  }
}

// Gets an index we can safely assign to the led array, makes overflow "wrap" around
uint8_t getSafeIndex(uint8_t index) {
  return (index % NUM_LEDS);
}
// ---------- END VISUALIZERS ----------


// ---------- BEGIN PALETTES ----------

void setPaletteFire()
{
  CRGB color4 = CRGB(180, 0, 0);
  CRGB color3 = CRGB(255, 77, 0);
  CRGB color2 = CRGB(255, 116, 0);
  CRGB color1 = CRGB(255, 154, 0);

  currentPalette = CRGBPalette16(
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4);
}
void setPaletteSynth()
{
  CRGB color1 = CRGB(212, 0, 120);
  CRGB color2 = CRGB(146, 0, 117);
  CRGB color3 = CRGB(20, 75, 156);
  CRGB color4 = CRGB(0, 0, 0);

  currentPalette = CRGBPalette16(
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4);
}
void setPaletteParty()
{
  CRGB color1 = CRGB(255, 0, 102);
  CRGB color2 = CRGB(255, 235, 0);
  CRGB color3 = CRGB(0, 152, 195);
  CRGB color4 = CRGB(0, 220, 110);

  currentPalette = CRGBPalette16(
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4);
}
void setPaletteBlackWhite()
{
  CRGB color1 = CRGB(255, 255, 255);
  CRGB color2 = CRGB(200, 200, 200);
  CRGB color3 = CRGB(150, 150, 150);
  CRGB color4 = CRGB(0, 0, 0);

  currentPalette = CRGBPalette16(
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4);
}

void setChloePalette()
{
  CRGB color1 = CRGB(148, 0, 211);  //148, 0, 211
  CRGB color2 = CRGB(255, 105, 180);
  CRGB color3 = CRGB(160, 32, 240);
  CRGB color4 = CRGB(255, 69, 0); //255, 69, 0

  currentPalette = CRGBPalette16(
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4);
}


void setReggaePalette()
{
  CRGB color1 = CRGB(255, 0, 0);  //148, 0, 211
  CRGB color2 = CRGB(255, 215, 0);
  CRGB color3 = CRGB(255, 255, 0);
  CRGB color4 = CRGB(0, 128, 0); //255, 69, 0

  currentPalette = CRGBPalette16(
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4,
                     color1, color2, color3, color4);
}
// ---------- END PALETTES ----------

Comments

Similar projects you might like

Newbie Music Player

Project in progress by Michael Marinis

  • 3,863 views
  • 2 comments
  • 12 respects

Interactive Toddler Music Box Toy

Project tutorial by Christopher Monreal and Nick Udell

  • 937 views
  • 0 comments
  • 2 respects

Control Music Volume and Ledbar Using Slider of 1Sheeld

Project tutorial by ahmed ismail

  • 1,655 views
  • 2 comments
  • 12 respects

Fingerscan: Music at Your Fingertips

Project showcase by touchmysound

  • 9,351 views
  • 6 comments
  • 29 respects

Play Music With Your Remote

Project tutorial by Simone Adobs

  • 6,618 views
  • 21 comments
  • 26 respects

How to make music with an Arduino

Project tutorial by Code_and_Make

  • 4,193 views
  • 0 comments
  • 10 respects
Add projectSign up / Login