Analizador de espectro de audio Arduino de 32 bandas – Visualización lineal y pseudo-logarítmica
Componentes y suministros
| Arduino Nano R3 | ×1 |
| Resistencia 10kΩ | ×1 |
| Resistencia 100kΩ | ×2 |
| Resistencia 4.75kΩ | ×3 |
| Cables jumper (genéricos) | ×1 |
| Protoboard (genérica) | ×1 |
| Cable USB-A a Mini-USB | ×1 |
| Interruptor táctil (actuación superior) | ×1 |
| Header macho 36 posiciones 1 fila (0.1") | ×1 |
Herramientas y máquinas necesarias
- Soldador (genérico)
Software y servicios online
- Arduino IDE
Sobre este proyecto
Este proyecto marca mi primera incursión en la electrónica de audio basada en Arduino. Inspirado por el visualizador de audio de Shajeeb, expandí la visualización para incluir un modo lineal de 32 bandas y un modo pseudo-logarítmico de 11 bandas. Construí tablas de mapeo logarítmico personalizadas en Excel e integré en el firmware para una respuesta de frecuencia más precisa.
Un botón táctil alterna entre los dos modos de visualización, permitiendo cambio rápido durante actuación o experimentación.
Siéntete libre de ajustar el firmware o hardware para adaptarlo a tus propios proyectos creativos.
Código fuente
32_Band_LED_Spectrum_Analyzer-009.ino (Arduino)
// Código modificado por Christian Suryanto, basado en (c) 2019 Shajeeb TM
// HAZI TECH
// Actualizado por Christian Suryanto
#include <arduinoFFT.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <EEPROM.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
#define SAMPLES 64
#define MAX_DEVICES 4
#define xres 32
#define yres 8
#define PREV 0xFF02FD
#define NEXT 0xFFC23D
#define PWR 0xFFA25D
int audio_response = 35;
double vReal[SAMPLES];
double vImag[SAMPLES];
char data_avgs[xres];
int yvalue;
int displaycolumn , displayvalue;
int peaks[xres];
const int buttonPin = 6;
int state = HIGH;
int previousState = LOW;
int displaymode;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
int MY_ARRAY[]={0, 128, 192, 224, 240, 248, 252, 254, 255};
bool EQ_ON = true;
byte eq1[32] = {40, 45, 50, 60, 65, 70, 75, 95, 110, 110, 110, 110, 110, 110, 110, 110, 130, 130, 130, 130, 130, 130, 130, 130, 145, 155, 170, 180, 215, 220, 245, 255};
byte eq2[11] = {40, 70, 75, 110, 110, 140, 145, 220, 220, 230, 250};
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
arduinoFFT FFT = arduinoFFT();
void setup() {
EEPROM.update(1,1);
displaymode = EEPROM.read(1);
ADCSRA = 0b11100101;
ADMUX = 0b00000000;
pinMode(buttonPin, INPUT);
mx.begin();
mx.control(MD_MAX72XX::INTENSITY, 0);
delay(50);
}
void loop() {
int numData;
double rSum;
for(int i=0; i<SAMPLES; i++) {
while(!(ADCSRA & 0x10));
ADCSRA = 0b11110101;
int value = ADC - 512;
value = value / 8;
vReal[i] = value;
vImag[i] = 0;
}
FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
int step = (SAMPLES)/xres;
switch (displaymode) {
case 1 : {
numData = 32;
for(int i=0; i<32; i++)
data_avgs[i] = (vReal[i] + vReal[SAMPLES-1-i]) / 2;
break;
}
case 2 : {
numData = 11;
data_avgs[0] = vReal[0];
data_avgs[1] = (vReal[0] + vReal[63] + vReal[1] + vReal[0]) / 4;
data_avgs[2] = (vReal[1] + vReal[63] + vReal[2] + vReal[62] + vReal[3] + vReal[61]) / 6;
data_avgs[3] = (vReal[2] + vReal[62] + vReal[3] + vReal[61] + vReal[4] + vReal[60]) / 6;
data_avgs[4] = (vReal[5] + vReal[59] + vReal[6] + vReal[58] + vReal[7] + vReal[57]) / 6;
data_avgs[5] = (vReal[8] + vReal[56] + vReal[9] + vReal[55] + vReal[10] + vReal[54] + vReal[11] + vReal[53]) / 8;
data_avgs[6] = (vReal[12] + vReal[52] + vReal[13] + vReal[51] + vReal[14] + vReal[50] + vReal[15] + vReal[49]) / 8;
data_avgs[7] = (vReal[16] + vReal[48] + vReal[17] + vReal[47] + vReal[18] + vReal[46]) / 6;
data_avgs[8] = (vReal[19] + vReal[45] + vReal[20] + vReal[44] + vReal[21] + vReal[43] + vReal[22] + vReal[42]) / 8;
data_avgs[9] = (vReal[23] + vReal[41] + vReal[24] + vReal[40] + vReal[25] + vReal[39] + vReal[26] + vReal[38] + vReal[27] + vReal[37]) / 10;
data_avgs[10] = (vReal[28] + vReal[36] + vReal[29] + vReal[35] + vReal[30] + vReal[34] + vReal[31] + vReal[33]) / 8;
break;
}
}
for(int i=0; i<numData; i++) {
data_avgs[i] = data_avgs[i] / 2;
if (EQ_ON) {
if (displaymode==1) data_avgs[i] = data_avgs[i] * eq1[i] / 100;
else data_avgs[i] = data_avgs[i] * eq2[i] / 100;
}
data_avgs[i] = constrain(data_avgs[i],0,audio_response);
data_avgs[i] = map(data_avgs[i], 0, audio_response, 0, yres);
yvalue = data_avgs[i];
peaks[i] = peaks[i]-1;
if (yvalue > peaks[i]) peaks[i] = yvalue;
yvalue = peaks[i];
displayvalue = MY_ARRAY[yvalue];
if (displaymode==1) {
displaycolumn = 31-i;
mx.setColumn(displaycolumn, displayvalue);
} else {
displaycolumn = 31-(3*i);
mx.setColumn(displaycolumn-1, displayvalue);
mx.setColumn(displaycolumn, displayvalue);
}
}
displayModeChange();
}
void displayModeChange() {
int reading = digitalRead(buttonPin);
if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) {
if (displaymode==1) {
displaymode = 2;
mx.clear();
delay(200);
EEPROM.update(1,2);
} else {
displaymode = 1;
mx.clear();
delay(200);
EEPROM.update(1,1);
}
lastDebounceTime = millis();
}
previousState = reading;
}
Esquemáticos
Proceso de manufactura
- Alerta de Sed Inteligente para Plantas: Sensor DIY para Riego Óptimo
- Reloj de Palabras en Italiano con Arduino Nano, NeoPixel, LCD y RTC
- Ahorra Pines en Arduino: Conecta Teclado 4x3 con Solo 3 Conexiones Analógicas
- Medidor kWh Sigfox Fiable con Arduino MKR Fox 1200
- Monitor de temperatura con Bluetooth usando Arduino Nano
- Medidor de Capacitancia Autoranging DIY (10 pF–10 µF) – Fácil Construcción con Arduino
- Cerradura por Gestos Sin Contacto: Acceso Seguro con APDS-9960 y Arduino
- Kit Compañero Arduino Nano: Componentes y Herramientas Esenciales para Electrónica DIY
- Kit Adaptador USB MIDI para Arduino Micro / Leonardo: Lista Completa de Componentes
- Circuito de entrada analógica aislada para Arduino
- Test de Precisión de Tiempo de Reacción con Arduino UNO