Sound Reactive Disco Speaker

by hkim219 in Craft > Art

209 Views, 2 Favorites, 0 Comments

Sound Reactive Disco Speaker

IMG_6487.jpg

This sound-reactive LED Bluetooth speaker is designed for someone who enjoys partying, music, and attention-grabbing on a tight budget. The beat and notes of the music will cause the LED lights to flash. The mirrored outer section functions similarly to a disco ball, saving the user from having to drill a hole in the ceiling. 

Parts, Tools, Supplies

IMG_5473.jpg
  • LED Strips
  • Breadboard
  • Arduino Uno
  • Wire Cutter
  • Sound Amplifier
  • Bluetooth Speaker
  • USB A-B Cable
  • Sharp utility knife
  • Hot melt glue gun
  • Soldering iron and Solder
  • Third hand tool
  • Tweezers
  • Small needlenose plier
  • Battery pack
  • Bluetooth speaker
  • Mirror acrylic sheet

Circuit Diagram and Code

Screenshot 2023-12-04 at 22.18.18.png

/*

LED VU meter for Arduino and Adafruit NeoPixel LEDs.


Hardware requirements:

- Most Arduino or Arduino-compatible boards (ATmega 328P or better).

- Adafruit Electret Microphone Amplifier (ID: 1063)

- Adafruit Flora RGB Smart Pixels (ID: 1260)

OR

- Adafruit NeoPixel Digital LED strip (ID: 1138)

- Optional: battery for portable use (else power through USB or adapter)

Software requirements:

- Adafruit NeoPixel library


Connections:

- 3.3V to mic amp +

- GND to mic amp -

- Analog pin to microphone output (configurable below)

- Digital pin to LED data input (configurable below)

See notes in setup() regarding 5V vs. 3.3V boards - there may be an

extra connection to make and one line of code to enable or disable.


Written by Adafruit Industries. Distributed under the BSD license.

This paragraph must be included in any redistribution.

*/


#include <Adafruit_NeoPixel.h>


#define N_PIXELS 4// Number of pixels in strand

#define MIC_PIN A1 // Microphone is attached to this analog pin

#define LED_PIN 1 // NeoPixel LED strand is connected to this pin

#define DC_OFFSET 0 // DC offset in mic signal - if unusure, leave 0

#define NOISE 20 // Noise/hum/interference in mic signal

#define SAMPLES 100 // Length of buffer for dynamic level adjustment

#define TOP (N_PIXELS + 2) // Allow dot to go slightly off scale

#define PEAK_FALL 8 // Rate of peak falling dot


byte

peak = 0, // Used for falling dot

dotCount = 0, // Frame counter for delaying dot-falling speed

volCount = 0; // Frame counter for storing past volume data

int

vol[SAMPLES], // Collection of prior volume samples

lvl = 10, // Current "dampened" audio level

minLvlAvg = 0, // For dynamic adjustment of graph low & high

maxLvlAvg = 512;

Adafruit_NeoPixel

strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);


void setup() {


// This is only needed on 5V Arduinos (Uno, Leonardo, etc.).

// Connect 3.3V to mic AND TO AREF ON ARDUINO and enable this

// line. Audio samples are 'cleaner' at 3.3V.

// COMMENT OUT THIS LINE FOR 3.3V ARDUINOS (FLORA, ETC.):

// analogReference(EXTERNAL);


memset(vol, 0, sizeof(vol));

strip.begin();

}


void loop() {

uint8_t i;

uint16_t minLvl, maxLvl;

int n, height;



n = analogRead(MIC_PIN); // Raw reading from mic

n = abs(n - 512 - DC_OFFSET); // Center on zero

n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum

lvl = ((lvl * 7) + n) >> 3; // "Dampened" reading (else looks twitchy)


// Calculate bar height based on dynamic min/max levels (fixed point):

height = TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);


if(height < 0L) height = 0; // Clip output

else if(height > TOP) height = TOP;

if(height > peak) peak = height; // Keep 'peak' dot at top



// Color pixels based on rainbow gradient

for(i=0; i<N_PIXELS; i++) {

if(i >= height) strip.setPixelColor(i, 0, 0, 0);

else strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));

}




// Draw peak dot

if(peak > 0 && peak <= N_PIXELS-1) strip.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,30,150)));

strip.show(); // Update strip


// Every few frames, make the peak pixel drop by 1:


if(++dotCount >= PEAK_FALL) { //fall rate

if(peak > 0) peak--;

dotCount = 0;

}




vol[volCount] = n; // Save sample for dynamic leveling

if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter


// Get volume range of prior frames

minLvl = maxLvl = vol[0];

for(i=1; i<SAMPLES; i++) {

if(vol[i] < minLvl) minLvl = vol[i];

else if(vol[i] > maxLvl) maxLvl = vol[i];

}

// minLvl and maxLvl indicate the volume range over prior frames, used

// for vertically scaling the output graph (so it looks interesting

// regardless of volume level). If they're too close together though

// (e.g. at very low volume levels) the graph becomes super coarse

// and 'jumpy'...so keep some minimum distance between them (this

// also lets the graph go to zero when no sound is playing):

if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;

minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels

maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)


}


// Input a value 0 to 255 to get a color value.

// The colors are a transition r - g - b - back to r.

uint32_t Wheel(byte WheelPos) {

if (WheelPos < 128) {

// Red to magenta

return strip.Color(255, 0, WheelPos * 2);

} else {

// Magenta to purple

return strip.Color(255 - (WheelPos - 128) * 2, 0, 255);

}

}


Circuit Construction From Prototype to Soldered

Form & Material

IMG_6251 2.jpg
IMG_6252.jpg
IMG_6453.jpg
  • Trim the LED strips to the appropriate size to ensure they fit within the outer casing.
  • Solder each part(GND, 5V, A1) and connect them all together.
  • Solder the connected LED strips with Gemma board and sound amplifier.
  • Attach everything inside of the outer casing.
  • Place the batteries into the battery pack and verify its functionality through testing.

Celebrate and Call to Action

IMG_6487.jpg

https://drive.google.com/file/d/1b0J80H7yXl5lyBAMUDXlnUuIZhlBik3v/view?usp=sharing