Analizador del espectro sonoro de 32 bandas

Ilustración 1. Display matricial

Este proyecto ha sido desarrollado por el grupo 7 de la asignatura Diseño de Sistemas Empotrados, conformado por Eric Martínez Gamero, durante el primer cuatrimestre del curso 2021-2022.

INTRODUCCIÓN

El analizador LED del espectro de audio de 32 bandas permite visualizar las fluctuaciones de frecuencia de una señal analógica de, por ejemplo, una canción.

El display está compuesto por cuatro módulos de 8×8 LEDs rojos, que se iluminan en función de dichas fluctuaciones y siguen un patrón determinado por el modo de visualización seleccionado.

La idea original proviene de la entrada del blog oficial de Arduino publicada por el usuario shajeeb en 2019: https://create.arduino.cc/projecthub/shajeeb/32-band-audio-spectrum-visualizer-analyzer-902f51?ref=platform&ref_id=424_trending___&offset=22

COMPONENTES

ComponenteNúmeroPrecio
Placa Arduino Uno1Provista por la URJC
Placa de inserción1Provista por la URJC
Cable de audio estéreo2En propiedad
Cables DuPont178 €
Matriz LED 8×32 MAX7219110 €
Socket hembra para jack de 3.5»11.37 €
Splitter de audio 1 a 2 para jack de 3.5»10.50 €
Resistencias de 4.7k ohm34.33 €
Resistencias de 100k ohm24.33 €
Resistencia de 10k ohm14.33 €
Condensador cerámico 100nF20.61 €
Botón1Provisto por la URJC
Conector pila 9V15 €
Pila alcalina 9V13 €

HERRAMIENTAS

HerramientaNúmeroPrecio
Soldador de estaño124 €
Polímetro1En propiedad

HARDWARE

El sistema recibe la señal analógica de un dispositivo móvil gracias a un cable de audio estéreo. Este cable está conectado a un socket hembra que separa los canales izquierdo, derecho y tierra. Con el soldador de estaño se fijaron los pines del socket a tres cables que van a la placa de inserción.

Por otro lado, se instaló en la placa un botón para posibilitar el cambio entre los tres modos de visualización del display.

Respecto a la salida del sistema, esta se visualiza a través de una matriz LED 8×32 conectada mediante cables jumper a la placa Arduino Uno y constituida por cuatro módulos 8×8.

En cuanto a la fuente de alimentación, se optó por utilizar el jack de alimentación con adaptador DCAC para conectar una batería de 9V.

Ilustración 2. Sistema completo
Ilustración 3. Sistema completo

ESQUEMA DE CONEXIONES

Ilustración 4. Esquema de conexiones fritzing

SOFTWARE

Para la implementación del proyecto a nivel software se han utilizado las librerías de Arduino MD_MAX72xx (https://www.arduino.cc/reference/en/libraries/md_max72xx/) y arduinoFFT (https://www.arduino.cc/reference/en/libraries/arduinofft/).

La librería arduinoFFT permite calcular la frecuencia de una señal muestrea implementando el algoritmo de la transformada rápida de Fourier en coma flotante. Esto permite el tratamiento digital de señales de audio.

Por otro lado, la librería MD_MAX72XX implementa funciones para trabajar con matrices LED 8×8. Es necesario realizar un test inicial sobre la matriz comprada para conocer el tipo de hardware y poder especificarlo para la librería.

En cuanto a los modos de visualización del display, estos se encuentran codificados en binario en arrays de 9 elementos. El primer modo de visualización, por ejemplo, se podría ilustrar como:

Ilustración 5. Modo de visualización 1

La primera línea de setup() es importante, ya que pone el conversor analógico digital de la Arduino Uno en free running mode. Así se permite que el ADC se mantenga realizando conversiones consecutivas, reduciendo latencias.

Sobre loop(), el siguiente esquema representa el proceso que se lleva a cabo cada iteración:

Ilustración 6. Esquema del bucle principal

Como se puede ver, antes de volver al inicio hay que comprobar si se ha pulsado el botón para cambiar de modo. La función cambioModo() implementa esta funcionalidad.

CÓDIGO

#include <arduinoFFT.h> // librería que permite calcular la frecuencia de una señal muestreada
#include <MD_MAX72xx.h> // librería que permite utilizar una matriz LED como pantalla direccionable por píxeles

#define MUESTRAS 64            // debe ser potencia de dos para el algoritmo de muestreo
#define TIPO_HARDWARE MD_MAX72XX::ICSTATION_HW   // tipo de display para que la librería MD_MAX72XX lo reconozca
#define MODULOS  4   // número de módulos LED independientes
#define CLK_PIN   13  // pin CLOCK del display
#define DATA_PIN  11  // pin DATA del display
#define CS_PIN    10  // pin CONTROL del display

#define COLUMNAS 32      // número de columnas en el display (muestras / 2)
#define FILAS 8       // número de filas en el display

// modos de visualización - cada LED puesto a 1 en binario se iluminará
int MODO[]= {0, 128, 192, 224, 240, 248, 252, 254, 255}; // por defecto será el patrón estándar
int MODO_1[]= {0, 128, 192, 224, 240, 248, 252, 254, 255}; // patrón estándar
int MODO_2[]= {0, 128, 64, 32, 16, 8, 4, 2, 1}; // solo parte superior
int MODO_3[]= {0, 1, 3, 7, 15, 31, 63, 127, 255}; // patrón estándar del revés
int MODO_4[]= {0, 1, 2, 4, 8, 16, 32, 64, 128}; // solo parte superior del revés

 
double vReal[MUESTRAS];
double vImag[MUESTRAS];
char val[COLUMNAS];
                      
int columnaDisplay, valorDisplay; 

const int BOTON_PIN = 5;    // pin del botón
int estado = HIGH;             // el valor actual leído del pin
int estadoPrevio = LOW;   // el valor previo leído del pin
int modo = 1;

MD_MAX72XX mx = MD_MAX72XX(TIPO_HARDWARE, CS_PIN, MODULOS);   // objeto display
arduinoFFT FFT = arduinoFFT();                                // objeto fft


void setup() {
    
    ADCSRA = 0b11100101;      // poner conversor analógico digital en modo de funcionamiento libre y poner prescaler a 32
    ADMUX = 0b00000000;       // usar el pin A0 y referencia de voltaje externa
    pinMode(BOTON_PIN, INPUT);
    mx.begin();               // inicialización del display
    delay(50);                // espera para obtener voltaje de referencia estable
}
 
void loop() {
   // muestreo
   for(int i=0; i<MUESTRAS; i++)
    {
      while(!(ADCSRA & 0x10));        // esperar que ADC termine la conversión actual
      ADCSRA = 0b11110101 ;           // limpiar registro ADCSRA para que ADC pueda realizar la siguiente conversión (0xf5)
      int valor = ADC - 512 ;         // leer del ADC
      vReal[i] = valor/8;
      vImag[i] = 0;                         
    }

 
    // configuración de FFT
    FFT.Windowing(vReal, MUESTRAS, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
    FFT.Compute(vReal, vImag, MUESTRAS, FFT_FORWARD);
    FFT.ComplexToMagnitude(vReal, vImag, MUESTRAS);

    
    // reorganizar resultado FFT para adaptarse al número de columnas
    int step = (MUESTRAS/2) / COLUMNAS; 
    int c = 0;
    for(int i=0; i < (MUESTRAS/2); i++)  
    {
      val[c] = 0;
      for (int k = 0 ; k < step ; k++)
          val[c] = val[c] + vReal[i+k];
      val[c] = val[c]/step; 
      c++;
    }

    
    // enviar el valor medido a cada columna del display
    for(int i=0; i < COLUMNAS; i++)
    {
      val[i] = constrain(val[i],0,80);            // restringir valor entre 0 y 80
      val[i] = map(val[i], 0, 80, 0, FILAS);      // mapear el valor entre 0 y número de filas
 
      valorDisplay = MODO[val[i]];
      columnaDisplay = 31-i;
      mx.setColumn(columnaDisplay, valorDisplay);              // poner todos los LEDs de la columna en el nuevo estado
    }
     
    cambioModo ();         // comprueba si el botón se ha presionado para cambiar de modo
} 

void cambioModo() {
  int leido = digitalRead(BOTON_PIN); 
  if (leido == HIGH && estadoPrevio == LOW) // al presionar el botón cambiar de modo
  {
   switch (modo) {
    case 1:    // del modo 1 al 2
      modo = 2;
      for (int i=0 ; i<=8 ; i++ ) {
        MODO[i] = MODO_2[i];
      }
      break;
    case 2:    // del modo 2 al 3
      modo = 3;
      for (int i=0 ; i<=8 ; i++ ) {
        MODO[i] = MODO_3[i];
      }
      break;
    case 3:    // del modo 3 al 4
      modo = 4;
      for (int i=0 ; i<=8 ; i++ ) {
        MODO[i] = MODO_4[i];
      }
      break;
    case 4:    // del modo 4 al 1
      modo = 1;
      for (int i=0 ; i<=8 ; i++ ) {
        MODO[i] = MODO_1[i];
      }
      break;
    }
  }
  estadoPrevio = leido;
}

VÍDEO DE DEMOSTRACIÓN

MEMORIA

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *