Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Visualizador Espectro Audio RGB 32 Bandas - Matriz LED Arduino

Componentes y suministros

Arduino Nano R3 1
Matriz RGB WS2812B 8x32 1
Resistencia 4.75k ohm 3
Resistencia 100k ohm 2
Resistencia 10k ohm 1
Resistencia 390 ohm (agujero pasante) 1
Condensador 100 nF 2
Condensador 1000 µF 1
Pulsador SparkFun 12mm 1
Placa prototipo 4x6 cm multihoyos 1

Herramientas y máquinas necesarias

Sobre este proyecto

El Proyecto

Proyecto para hacer un visualizador de espectro de frecuencia de audio (música) RGB 32 bandas usando Arduino Nano y matriz LED WS2812B 8x32 RGB.

Proyecto Original que Inspira Este

Gran agradecimiento a Shajeeb autor del proyecto original basado en matriz MAX72xx. Solo modifiqué la parte de control de la matriz LED para adaptarla a matriz RGB WS2812B.

Enlace original: 32-Band Audio Spectrum Visualizer Analyzer

La Matriz LED RGB WS2812B

Usando matriz RGB basada en LEDs SMD 5050 alto brillo, es necesario fuente externa porque la matriz puede consumir >10mA por LED, así que con todos los LEDs a brillo máximo podría consumir >2.5 Amperios.

Por eso puse un diodo en serie en +5V para poder alimentar Arduino en modo standalone (sin USB) y evitar que Arduino alimente la matriz RGB, evitando sobrecargar sus circuitos internos.

Además del diodo de entrada, para proteger entrada matriz de picos de tensión, añadí resistencia 390 ohm en serie entre pin D6 Arduino y entrada Data, y condensador 1000 µF 12V para mejorar estabilidad alimentación Arduino.

Montaje Hardware

Como se ve en foto principal, hice primer prototipo en placa multihoyos 4x6 cm usando dos zócalos RCA (soldados directo) que pueden reemplazarse por jack hembra 3.5 mm. Importante: evitar zumbido usando cable blindado entre fuente audio y entrada. Mantener conexión Arduino-matriz lo más corta posible.

El Código

Todo el software se basa en el gran trabajo del autor del muestreo mediante librería FFT y la realización definitiva de Shajeeb.

Añadí dos funciones:

  1. GetLedFromMatrix(...) para mapear matriz en filas/columnas y direccionar cada uno de los 256 LEDs por coordenadas fila/columna.
  2. SetColumn(...) que enciende LEDs de cada columna según valor pico de digitalización audio (0-7) y colores predefinidos en array 2D. Puedes cambiar valores y colores a gusto. Simplifiqué usando subrutina Wheel() (de demo librería Adafruit Neopixel) que de valor 0-255 devuelve unsigned long 32-bit para setPixelColor. Juega con esto, teniendo en cuenta limitaciones memoria Arduino evitando variables 32-bit para colores donde sea posible.

Ecualización Audio

Como probé con audio de tarjeta sonido integrada en placa base PC, para mejorar respuesta frecuencia añadí array byte 32 valores que constituyen curva ecualización para atenuar graves y realzar agudos. Si no necesitas, pon EQ_ON = false o cambia atenuación modificando 32 valores de eq[32]. Valor 100 = sin cambio, <100 atenúa, >100 realza banda.

Brillo LEDs

Brillo matriz predefinido en código a 32 (const BRIGHTNESS). Máximo teórico WS2812B es 255 pero ya con >100 la luz blanca se vuelve amarilla pálida, probablemente necesite alimentar matriz por cables centrales rojo/negro en vez de conector lateral.

Sigo probando... Con brillo 64, fuente 1A basta; si no, 2A esencial.

Actualización Futura

Trabajando en nueva versión usando librería OpenMusicLabs FHT que es muchas veces más rápida que Arduino FFT.

¡Pendientes! :)

Disculpen mi mal inglés, usé traductor Google.

Código

Spectrum_Analyzer_WS2812B.ino

/* Copyright (c) 2019 Shajeeb TM. Licencia MIT.
 * Versión matriz WS2812B por Janux
 */
#include <arduinoFFT.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>

#define SAMPLES 64          // Potencia de 2
#define xres 32             // Columnas display (<= SAMPLES/2)
#define yres 8              // Filas display
#define ledPIN 6            // Pin control matriz LED
#define NUM_LEDS (xres * yres)
#define BRIGHTNESS 32
#define buttonPin 5         // Pin pulsador cambio color

byte yvalue, displaycolumn, displayvalue;
int peaks[xres];
byte state = HIGH, previousState = LOW;
byte displaycolor = 0;

double vReal[SAMPLES];
double vImag[SAMPLES];
byte data_avgs[xres];
arduinoFFT FFT = arduinoFFT();

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 100;

Adafruit_NeoPixel pixel = Adafruit_NeoPixel(NUM_LEDS, ledPIN, NEO_GRB + NEO_KHZ800);

// Ecualizador: atenúa graves, mejora agudos (útil en tarjeta sonido PC)
bool EQ_ON = true;
byte eq[32] = {50, 55, 60, 70, 75, 80, 85, 95, 100, 100, 100, 100, 100, 100, 100, 100, 
               100, 100, 100, 100, 100, 100, 100, 100, 115, 125, 140, 160, 185, 200, 225, 255 };

// Colores por fila para cada modo displaycolor (0=personalizado)
byte colors[][8] = {
  {170, 160, 150, 140, 130, 120, 1, 1},
  {1, 5, 10, 15, 20, 25, 90, 90},
  {90, 85, 80, 75, 70, 65, 1, 1},
  {90, 90, 90, 30, 30, 30, 1, 1},
  {170, 160, 150, 140, 130, 120, 0, 0},
  {170, 160, 150, 140, 130, 120, 1, 1},
  {170, 160, 150, 140, 130, 120, 1, 1}
};

void setup() {
  pixel.begin();
  pixel.setBrightness(BRIGHTNESS);
  // Config ADC free-running, prescaler 32
  ADCSRA = 0b11100101; // 0xE5
  ADMUX = 0b00000000;  // Pin A0, ref externa
}

void loop() {
  // Muestreo
  for (int i = 0; i < SAMPLES; i++) {
    while (!(ADCSRA & 0x10)); // Espera fin conversión (ADIF)
    ADCSRA = 0b11110101;      // Limpia ADIF (0xF5)
    int value = ADC - 512;    // Lee ADC y quita offset DC
    vReal[i] = value / 8;     // Comprime
    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);
  
  // Reorganizar FFT para coincidir columnas display (xres)
  int step = (SAMPLES / 2) / xres;
  int c = 0;
  for (int i = 0; i < (SAMPLES / 2); i += step) {
    data_avgs[c] = 0;
    for (int k = 0; k < step; k++) 
      data_avgs[c] += vReal[i + k];
    data_avgs[c] /= step;
    c++;
  }
  
  // Enviar a display según valor medido
  for (int i = 0; i < xres; i++) {
    if (EQ_ON) data_avgs[i] = data_avgs[i] * (float)eq[i] / 100;
    data_avgs[i] = constrain(data_avgs[i], 0, 80);
    data_avgs[i] = map(data_avgs[i], 0, 80, 0, yres);
    
    yvalue = data_avgs[i];
    peaks[i]--; // Decaimiento
    if (yvalue > peaks[i]) peaks[i] = yvalue;
    yvalue = peaks[i];
    
    displaycolumn = i;
    displayvalue = yvalue;
    setColumn(displaycolumn, displayvalue);
  }
  pixel.show();
  displaycolorChange();
}

// Enciende LEDs columna x según valor y
void setColumn(byte x, byte y) {
  byte led, i;
  for (i = 0; i < yres; i++) {
    led = GetLedFromMatrix(x, i);
    if (peaks[x] > i) {
      switch (displaycolor) {
        case 4: // 0 en array = color personalizado picos
          if (colors[displaycolor][i] > 0)
            pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
          else
            pixel.setPixelColor(led, 255, 255, 255); // Blanco picos
          break;
        case 5: // Color por columna
          pixel.setPixelColor(led, Wheel(x * 16));
          break;
        case 6: // Color por fila
          pixel.setPixelColor(led, Wheel(i * 36));
          break;
        default: // Modos 0-3: colores array
          pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
      }
    } else {
      pixel.setPixelColor(led, 0);
    }
  }
}

// Calcula número LED por coordenadas x,y
// Válido para WS2812B layout serpentina horizontal, LED 0 en esquina inf der (conector derecha)
byte GetLedFromMatrix(byte x, byte y) {
  x = xres - x - 1;
  if (x & 0x01) { // Columnas impares aumentan hacia atrás
    return ((x + 1) * yres - y - 1);
  } else { // Columnas pares aumentan normalmente
    return ((x + 1) * yres - yres + y);
  }
}

void displaycolorChange() {
  int reading = digitalRead(buttonPin);
  if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) {
    displaycolor++;
    if (displaycolor > 6) displaycolor = 0;
    lastDebounceTime = millis();
  }
  previousState = reading;
}

// Utilidad Adafruit Neopixel: 0-255 → valor color (transición R-G-B-R)
unsigned long Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) 
    return pixel.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  if (WheelPos < 170) {
    WheelPos -= 85;
    return pixel.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return pixel.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Piezas personalizadas y cajas

Esquemáticos

Esquema del circuito disponible en el proyecto.

Proceso de manufactura

  1. Analizador de espectro de audio Arduino de 32 bandas – Visualización lineal y pseudo-logarítmica
  2. Alerta de Sed Inteligente para Plantas: Sensor DIY para Riego Óptimo
  3. Reloj de Palabras en Italiano con Arduino Nano, NeoPixel, LCD y RTC
  4. Medidor kWh Sigfox Fiable con Arduino MKR Fox 1200
  5. Monitor de temperatura con Bluetooth usando Arduino Nano
  6. Cerradura por Gestos Sin Contacto: Acceso Seguro con APDS-9960 y Arduino
  7. Kit Compañero Arduino Nano: Componentes y Herramientas Esenciales para Electrónica DIY
  8. Kit Adaptador USB MIDI para Arduino Micro / Leonardo: Lista Completa de Componentes
  9. Circuito de entrada analógica aislada para Arduino
  10. Construye un cable de salida TV para Arduino UNO con solo dos resistencias
  11. Test de Precisión de Tiempo de Reacción con Arduino UNO