Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

RGB 32-Band Audio-Spektrum-Visualisierer: Arduino Nano & WS2812B LED-Matrix

Komponenten und Zubehör

Arduino Nano R3 1
WS2812B 8×32 RGB LED-Matrix (256 LEDs) 1
Widerstand 4,75 kΩ 3
Widerstand 100 kΩ 2
Widerstand 10 kΩ 1
Widerstand 390 Ω (Durchsteck) 1
Keramikkondensator 100 nF 2
Elko 1000 µF / 12 V 1
Taster 12 mm 1
Lochrasterplatine 4×6 cm 1

Benötigte Werkzeuge

Projektbeschreibung

Das Projekt

Ein 32-Band-Audiofrequenz-Spektrum-Visualisierer (Musik-Analyzer) mit Arduino Nano und 8×32 WS2812B-RGB-LED-Matrix (256 LEDs).

Ursprungsprojekt

Basiert auf der Arbeit von Shajeeb (MAX72xx-Matrix-Version). Ich habe nur den LED-Matrix-Treiberteil für WS2812B angepasst. Original: „32-Band Audio Spectrum Visualizer Analyzer“.

Die WS2812B-RGB-LED-Matrix

Jede 5050-SMD-LED kann >10 mA ziehen → bei voller Helligkeit alle LEDs: >2,5 A. Externes Netzteil zwingend!

Schutzmaßnahmen:

Hardware-Aufbau

Erster Prototyp auf 4×6-cm-Lochraster mit zwei CINCH-Buchsen (oder 3,5-mm-Klinke). Wichtig: Geschirmtes Kabel für Audio-Eingang gegen Brummen. Verbindung Arduino → Matrix so kurz wie möglich halten.

Der Code

Basiert auf Shajeebs FFT-Sampling und Visualisierung. Zwei Erweiterungen:

  1. GetLedFromMatrix(x, y): Mappt serpentinenförmige Matrix (Eingangsstecker rechts, horizontale Ausrichtung) auf Zeile/Spalte → LED-Index 0–255.
  2. SetColumn(x, y): Setzt LEDs einer Spalte basierend auf Peak-Wert (0–7) und Farbpalette. Nutzt Wheel() (Adafruit NeoPixel Demo) für HSV-ähnliche Farbübergänge.

Audio-Equalisierung: Byte-Array eq[32] dämpft Bässe, hebt Höhen an (PC-Onboard-Sound oft basslastig). EQ_ON = true aktiviert; Wert 100 = neutral, <100 = Dämpfung, >100 = Anhebung.

Helligkeit: Konstant BRIGHTNESS = 32 (max. 255). Ab ~100 wird Weiß gelblich – wahrscheinlich Spannungseinbruch am Stecker. Empfehlung: Matrix mittig einspeisen (rote/schwarze Mittelkabel). Bei 64 Helligkeit reicht 1 A, sonst 2 A Netzteil.

Zukünftige Erweiterung

Arbeit an Version mit OpenMusicLabs FHT (Fast Hartley Transform) – vielfach schneller als Arduino-FFT.

Quellcode: Spectrum_Analyzer_WS2812B.ino

/* Copyright (c) 2019 Shajeeb TM, MIT License
 * WS2812B Version by Janux
 */
#include <arduinoFFT.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h>

#define SAMPLES 64        // 2er-Potenz
#define xres 32           // Spalten (≤ SAMPLES/2)
#define yres 8            // Zeilen
#define ledPIN 6          // Data-Pin Matrix
#define NUM_LEDS (xres * yres)
#define BRIGHTNESS 32
#define buttonPin 5       // Farbmodus-Wechsel

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

// EQ-Filter: Bässe dämpfen, Höhen anheben
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
};

// Farbpaletten [Modus][Zeile] – 0 = benutzerdefinierte Peak-Farbe (weiß)
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);
  // ADC Free-Running, Prescaler 32, A0, externe Referenz
  ADCSRA = 0b11100101; // 0xE5
  ADMUX  = 0b00000000;
}

void loop() {
  // Sampling
  for (int i = 0; i < SAMPLES; i++) {
    while (!(ADCSRA & 0x10)); // ADIF warten
    ADCSRA = 0b11110101;      // ADIF clear (0xF5)
    int value = ADC - 512;    // DC-Offset entfernen
    vReal[i] = value / 8;     // Komprimieren
    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);

  // FFT-Bins auf 32 Spalten mappen
  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++;
  }

  // Anzeige
  for (int i = 0; i < xres; i++) {
    if (EQ_ON) data_avgs[i] = data_avgs[i] * 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] = max(peaks[i] - 1, 0); // Decay
    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) {
  for (byte i = 0; i < yres; i++) {
    byte led = GetLedFromMatrix(x, i);
    if (peaks[x] > i) {
      switch (displaycolor) {
        case 4: // Peak-Farbe anpassbar (0 im Array = weiß)
          if (colors[displaycolor][i] > 0)
            pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
          else
            pixel.setPixelColor(led, 255, 255, 255);
          break;
        case 5: // Farbe nach Spalte
          pixel.setPixelColor(led, Wheel(x * 16));
          break;
        case 6: // Farbe nach Zeile
          pixel.setPixelColor(led, Wheel(i * 36));
          break;
        default: // Modi 0–3: feste Paletten
          pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
      }
    } else {
      pixel.setPixelColor(led, 0);
    }
  }
}

byte GetLedFromMatrix(byte x, byte y) {
  x = xres - x - 1; // Spiegelung (Eingang rechts)
  if (x & 0x01) // Ungerade Spalten: rückwärts
    return ((x + 1) * yres - y - 1);
  else        // Gerade Spalten: vorwärts
    return ((x + 1) * yres - yres + y);
}

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

// Adafruit Wheel: 0–255 → RGB-Farbkreis
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);
}

3D-Druck & Gehäuse

STL-Dateien im Originalprojekt: arduino_rgb_audio_analyzer_lX4Dv4Pta2.zip.

Schaltplan

Siehe Originalprojekt (Bilddatei).

Herstellungsprozess

  1. 32-Band Arduino Audio-Spektrumanalysator – Linear & Pseudo-Log Darstellung
  2. Smart Thirst Alert: DIY Pflanzen-Alarm für optimale Bewässerung
  3. Italienische Word Clock mit Arduino Nano, NeoPixel, LCD & RTC
  4. Zuverlässiger Sigfox-kWh-Zähler mit Arduino MKR Fox 1200
  5. Bluetooth-Temperaturmonitor mit Arduino Nano
  6. Berührungsloses Gesten-Schloss: Sicherer Zugang mit APDS-9960 & Arduino
  7. Arduino Nano Begleiter-Set – Essentielle Bauteile & Werkzeuge für DIY-Elektronik
  8. USB-MIDI-Adapter für Arduino Micro / Leonardo – Komplettes Bauteil-Kit & Code
  9. Isolierter Analogeingang für Arduino: Spannung/Strom galvanisch trennen
  10. Präziser Reaktionszeit-Test mit Arduino UNO