Construimos el altavoz bluetooth definitivo
No se si los habrás visto pero hace 6 meses hicimos un proyecto de un altavoz bluetooth y hace un mes hicimos otro de un analizador de espectro. Bueno pues de esto que estábamos hablando y dijimos ¿oye y qué pasa si juntamos estos dos proyectos? Nos pareció buena idea así que es justo lo que hemos hecho.
Resumen del proyecto altavoz bluetooth definitivo
Hemos decidido mezclar dos proyectos que hicimos hace tiempo, el altavoz bluetooth casero y el analizador de espectro. La idea es construir un altavoz bluetooth bastante potente de un solo speaker y que además tenga integrado un pequeño analizador de espectro en su estructura.
Para poder escuchar los graves y los agudos con una buena calidad hemos escogido un speaker coaxial. Eso significa que tiene integrado tanto un Woofer, que sirve para reproducir los sonidos graves, como un Tweeter, que se encarga de reproducir los agudos.
En cuanto a los LEDs del analizador de espectro, hemos cogido una matriz WS2812B de 16×16 y la hemos cortado por la mitad. Así el analizador será de 8 filas (altura) y 16 columnas (longitud).
Por cierto, aquí te dejamos los archivos STL para que puedas imprimir en 3D las mismas piezas que hemos impreso nosotros: repositorio del proyecto.
Lista de materiales
Esquema eléctrico del altavoz bluetooth

Aquí tenemos el esquema eléctrico del altavoz bluetooth con analizador de espectro. Podemos dividirlo en dos partes. Por un lado la parte del altavoz y por el otro la parte del analizador de espectro.
En cuanto a la parte del altavoz, alimentamos el amplificador, al que hemos conectado el speaker, con una fuente de 12V. También tenemos que alimentar el receptor bluetooth, pero como este trabaja con un máximo de 5V, hemos puesto un transformador de voltaje. Por último, nos falta conectar el receptor bluetooth al amplificador para enviarle la señal de sonido. Entre medias hemos conectado un potenciómetro para poder ajustar el volumen manualmente.
Respecto a la parte del analizador de espectro, alimentamos tanto el microcontrolador ESP8266 como la matriz led con los 5V de salida del transformador de voltaje. El micrófono MAX9814 lo podemos alimentar directamente desde el microcontrolador. El pin de datos de la matriz hay que conectarlo a un pin digital de la ESP8266 y el pin de salida del micrófono a una entrada analógica.
Código del analizador de espectro
Aquí te dejamos el código del analizador de espectro del altavoz bluetooth. Si haces las conexiones siguiendo nuestro esquema eléctrico, no necesitas cambiar nada.
Si quieres aprender a modificar código y crearlo desde 0, puedes entrar a nuestro curso de programación y electrónica con Arduino.

Curso de Arduino desde Cero
Aprende programación y electrónica de forma rápida y sencilla con Arduino para que puedas montar tus proyectos tecnológicos lo antes posible.
#include //Librería para calcular la transformada de Fourier
#include
//SEÑAL DE AUDIO
#define SAMPLES 512 //Tiene que ser potencia de 2. Arduino Nano solo tiene memoria para guardar 128 muestras
#define SAMPLING_FREQ 40000 //Determina la frecuencia máxima que se puede analizar con FFT. Freq_max = sampling_freq/2
#define AMPLITUDE 500 //Can be used as a "sensitivity" control (1000)
#define AUDIO_IN_PIN A0 //Entrada analógica a la que se ha conectado el microfono
#define NOISE 500 //Los valores que estén por debajo de NOISE se ignoran
//******************************************************
#define NUM_BANDS 16
#define MAX_BAR_HEIGHT 8 //Número de leds por columna
//LEDS
#define NUM_LEDS NUM_BANDS*MAX_BAR_HEIGHT
#define LEDS_PIN 14 //D5 en la NodeMCU ESP8266
#define COLOR_ORDER GRB
#define MAX_BRIGHTNESS 30
#define LED_TYPE WS2812B
CRGB leds[NUM_LEDS];
unsigned int sampling_period_us;
unsigned long newTime;
double vReal[SAMPLES];
double vImag[SAMPLES];
arduinoFFT FFT = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);
//***********************************************************
int bandValues[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //Tenemos 16 bandas
//***********************************************************
int oldBarHeights[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//***********************************************************
int peak[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//HSV
byte base_hue = 0;
//Palettes
DEFINE_GRADIENT_PALETTE (ocean_palette){
0, 13, 4, 156,
75, 39, 142, 228,
145, 40, 160, 255,
255, 0, 255, 255
};
DEFINE_GRADIENT_PALETTE (fire_palette){
0, 255, 0, 0,
75, 255, 149, 0,
150, 255, 0, 100,
255, 255, 255, 255
};
CRGBPalette16 myPal;
void setup() {
// put your setup code here, to run once:
//Configuramos el ADC para obtener 58.6 KHz de velocidad de muestreo
Serial.begin(115200);
sampling_period_us = round(1000000 * (1.0/SAMPLING_FREQ));
FastLED.addLeds(leds, NUM_LEDS);
FastLED.setBrightness(MAX_BRIGHTNESS);
//Elegimos Palette
//myPal = ocean_palette;
myPal = fire_palette;
}
void loop() {
FastLED.clear();
Serial.println("0");
// Reset bandValues[]
for (int i = 0; i NOISE) { //Filtro de ruido
//16 bands, 80Hz a 20000KHz, 512 muestras
if (i<=1 ) bandValues[0] += (int)vReal[i];
if (i>1 && i<=2 ) bandValues[1] += (int)vReal[i];
if (i>2 && i<=3 ) bandValues[2] += (int)vReal[i];
if (i>3 && i<=4 ) bandValues[3] += (int)vReal[i];
if (i>4 && i<=6 ) bandValues[4] += (int)vReal[i];
if (i>6 && i<=9 ) bandValues[5] += (int)vReal[i];
if (i>9 && i<=13 ) bandValues[6] += (int)vReal[i];
if (i>13 && i<=18 ) bandValues[7] += (int)vReal[i];
if (i>18 && i<=26 ) bandValues[8] += (int)vReal[i];
if (i>26 && i<=37 ) bandValues[9] += (int)vReal[i];
if (i>37 && i<=53 ) bandValues[10] += (int)vReal[i];
if (i>53 && i<=76 ) bandValues[11] += (int)vReal[i];
if (i>76 && i<=108) bandValues[12] += (int)vReal[i];
if (i>108 && i<=153) bandValues[13] += (int)vReal[i];
if (i>153 && i<=218) bandValues[14] += (int)vReal[i];
if (i>218 ) bandValues[15] += (int)vReal[i];
}
}
for(int band=0; band MAX_BAR_HEIGHT) barHeight = MAX_BAR_HEIGHT;
//Hacemos promedio con el valor anterior
barHeight = round(((oldBarHeights[band] * 0.5) + 1.2* barHeight) / 2);
//Movemos la "cima"
if(barHeight > peak[band]){
peak[band] = min(MAX_BAR_HEIGHT, barHeight);
}
drawWithCHSV(band, barHeight, base_hue);
drawPeak(band, 255, 255, 255);
oldBarHeights[band] = barHeight;
}
//Bajamos la cima
EVERY_N_MILLISECONDS(120){
for (byte band = 0; band < NUM_BANDS; band++)
if (peak[band] > 0) peak[band] -= 1;
}
if(base_hue>245)base_hue = 0;
else base_hue +=10;
FastLED.show();
}
void drawWithCHSV(int num_band, int barHeight, byte hue){
int pos = num_band;
for(int i=0; i