Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Visualizador de Espectro de Áudio RGB 32 Bandas – Projeto Matriz LED Arduino

Componentes e Materiais

Ferramentas e Máquinas Necessárias

Sobre o Projeto

O Projeto

Visualizador de espectro de frequência de áudio (música) RGB 32-bandas usando Arduino Nano e matriz LED WS2812B 8x32.

Projeto Original que Inspirou Este

Agradecimentos a Shajeeb, autor do projeto original baseado em matriz MAX72xx. Modifiquei apenas a parte de pilotagem da matriz para adaptar à matriz RGB WS2812B.

Link original: 32-Band Audio Spectrum Visualizer Analyzer

A Matriz RGB WS2812B

Usando matriz LED RGB baseada em LEDs SMD 5050 alto brilho, fonte de alimentação externa é necessária: cada LED pode consumir >10mA, totalizando >2.5A com todos acesos no brilho máximo.

Inseri diodo em série no +5V para permitir alimentar Arduino standalone (sem cabo USB) e evitar que Arduino alimente a matriz RGB, sobrecarregando seus circuitos internos.

Adicionei também: resistor 390Ω em série entre pino D6 do Arduino e entrada Data (proteção contra picos), e capacitor 1000µF 12V para estabilizar tensão de alimentação do Arduino.

Montagem do Hardware

Primeiro protótipo em placa multi-furos 4x6cm com dois soquetes RCA (soldados direto na placa), substituíveis por jack 3.5mm fêmea. Importante: Use cabo blindado entre fonte de áudio e entrada da placa para evitar ruído. Mantenha conexão Arduino-matriz o mais curta possível.

O Código

Software baseado no excelente trabalho do autor do procedimento de amostragem via biblioteca FFT e realização final de Shajeeb.

Adicionei duas funções:

Usei sub-rotina Wheel() (do demo Adafruit Neopixel) que converte valor 0-255 em cor 32-bit para setPixelColor. Evite variáveis 32-bit para economizar memória.

Equalização de Áudio

Testei com áudio de placa-mãe de PC. Para melhorar resposta em frequência, adicionei array eq[32] com curva de equalização: atenua graves, realça agudos. Defina EQ_ON = false para desabilitar ou altere valores do array (100 = inalterado, <100 atenua, >100 realça).

Brilho dos LEDs

Brilho pré-definido no código: BRIGHTNESS = 32. Máximo teórico WS2812B é 255, mas >100 a luz branca fica amarelada (provavelmente precisa alimentar pela fiação central vermelha/preta, não conector lateral). Ainda testando...

Com brilho 64, fonte 1A provavelmente basta; caso contrário, 2A essencial.

Atualização Futura

Trabalhando em nova versão com biblioteca OpenMusicLabs FHT, muito mais rápida que Arduino FFT. Aguardem!

Peço desculpas pelo inglês ruim, usei tradutor automático.

Código

Spectrum_Analyzer_WS2812B.ino

/* Copyright (c) 2019 Shajeeb TM
 * Licença MIT
 * Versão WS2812B por Janux
 */
#include <arduinoFFT.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>

#define SAMPLES 64           // Potência de 2
#define xres 32              // Colunas no display (<= SAMPLES/2)
#define yres 8               // Linhas no display
#define ledPIN 6             // Pino controle matriz LED
#define NUM_LEDS (xres * yres)
#define BRIGHTNESS 32
#define buttonPin 5          // Botão para mudar modo de cor

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

double vReal[SAMPLES], 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);

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};

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);
  ADCSRA = 0b11100101; // ADC free running, prescaler 32
  ADMUX = 0b00000000;  // Pino A0, referência externa
}

void loop() {
  // Amostragem
  for (int i = 0; i < SAMPLES; i++) {
    while (!(ADCSRA & 0x10)); // espera ADIF
    ADCSRA = 0b11110101; // limpa ADIF
    int value = ADC - 512; // remove offset DC
    vReal[i] = value / 8;  // compressão
    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);
  
  // Rearranja FFT para colunas do display
  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++;
  }
  
  // Envia para display
  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] = peaks[i] - 1; // decaimento
    if (yvalue > peaks[i]) peaks[i] = yvalue;
    yvalue = peaks[i];
    displaycolumn = i; displayvalue = yvalue;
    setColumn(displaycolumn, displayvalue);
  }
  pixel.show();
  displaycolorChange();
}

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 no array = cor personalizada para pico
          if (colors[displaycolor][i] > 0)
            pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
          else
            pixel.setPixelColor(led, 255, 255, 255); // branco para pico
          break;
        case 5: // cor por coluna
          pixel.setPixelColor(led, Wheel(x * 16)); break;
        case 6: // cor por linha
          pixel.setPixelColor(led, Wheel(i * 36)); break;
        default: // modos 0-3: cores do array
          pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
      }
    } else pixel.setPixelColor(led, 0);
  }
}

byte GetLedFromMatrix(byte x, byte y) {
  x = xres - x - 1;
  if (x & 0x01) // colunas ímpares: sentido inverso
    return ((x + 1) * yres - y - 1);
  else // colunas pares: sentido normal
    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;
}

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);
}

Peças Personalizadas e Gabinetes

Imagens do projeto e arquivo para download: arduino_rgb_audio_analyzer_lX4Dv4Pta2.zip

Esquemáticos

Esquemático do circuito.

Processo de manufatura

  1. Analisador de Espectro de Áudio Arduino 32 Bandas — Display Linear e Pseudo-Log
  2. Alerta Inteligente de Sede para Plantas – Sensor DIY para Hidratação Ideal
  3. Relógio de Palavras em Italiano com Arduino Nano, NeoPixel, LCD e RTC
  4. Medidor kWh Confiável com Sigfox e Arduino MKR Fox 1200
  5. Monitor de Temperatura com Bluetooth usando Arduino Nano
  6. Fechadura por Gestos Sem Toque: Acesso Seguro com APDS-9960 e Arduino
  7. Companion IC: Relógio, Ohmímetro, Capacímetro e Testador de Diodos com Arduino Nano
  8. Kit Adaptador USB-MIDI para Arduino Micro/Leonardo – Lista Completa de Peças
  9. Circuito de Entrada Analógica Isolada para Arduino
  10. Teste de Tempo de Reação Preciso com Arduino UNO