🏠 FabLab Startseite | Nutzungsbedingungen | Impressum | Wiki

Equalizer LED-Wanddisplay

Bau eines Equalizer Wanddisplay’s
oder präzieser gesagt eines Spektrumanalysators mit großfomratigen Wansdisplay aus einer LED-Matrix

Ich möchte euch gerne mein aktuelles Winter-Projekt vorstellen. Worum es grob gesagt geht ist ja aus dem Titel ersichtlich. Etwas genauer gesagt geht es um folgendes:

Da der Platz zwischen meinen beiden HiFi boxen an der Wand noch leblos und kahl aussieht, bin ich auf die Iddee gekommen dort etwas „lebendiges“, zur Musik passendes, zu plazieren. Da mir zufällig zwei Tage vorher ein paar ungenutzte Neopixel in die Hände gefallen sind, war eins und eins recht schnell kombiniert: Ein großformatiges LED-Display das die über ein Mikrofon eingefangene Musik im form einer oldschool „Equalizier-Anzeige“ visualisiert.

Da ich ebenfalls noch einiges aus dem Arduino-Universum zur Hand hatte war auch schnell klar auf welchem System das ganze basieren soll. Nach kurzer Internetsuche konnte ich auch ein recht ähnliches Projekt bei Adafruit finden:

Adafruit Tiny Arduino Music Visualizer

Das ganze verdeutlich ziemlich gut, wo die Reise hin gehen soll, mit zwei entscheidenden Unterschieden:

  • Mein Display soll 1200mm x 768mm groß werden und eine Auflösung von 25px x 16px haben

  • Die einzelnen Pixel sollen aus SK6812 RGBW LED’s im 5050-Format bestehen (aka "Neopixel)

Ob die einzeln adressierebaren LED’s tatsächlichen irgendeinen praktischen nutzen haben weiß ich nicht, aber verwenden will ich die trotzdem - sind nämlich ziemlich cool!

Also hab ich mir zunächste eine weiß beschichtete 3mm HDF Platte besorgt, mein beabsichtiges Rasta aufgezeichnet (1 px=48x48mm) und ein paar Löcher gebohrt (an alles CNC-Nutzer: ja - 400 Löcher per Hand)

Das sah dann ungefähr so aus:

Als nächstes habe ich die einzelnen Pixel per Heißkleber eingeklebt, wobei ich mich zunächst auf die Hälfte des Display beschränken will, da ich mir nicht sicher bin, ob der Datenbus der SK 6812 die dann noch recht stattliche Leitungslänger vom px1 zu px400 störungsfrei mitmachen wird. Also erstmal einen Meilenstein bei der Hälfte zum Laufen bringen.

Verdrahtete sieht das dann so aus:

bzw. so:

Nach den ersten 48px habe ich mich dazu entschlossen die Verdrahtungsart zu ändern: mit einzelnen Kabelstücken ist der Aufwand durch das Zuschneiden und Abisolieren einfach zu groß. Der verzinnte Kupferdraht mit 0,6mm Stärke tuts genauso.

Inzwischen habe ich auch einen - wie ich denken - ganz ansehnlichen Rahmen gebaut und das ganze mal probehalber an die Wand gehängt:

Soweit ist erstmal der Stand der Dinge. Noch auf meiner ToDo-Liste stehen:

  • Innenliegendes Kreuzgitter bauen, um aus den Punkten rechteckige Pixel zu zaubern

  • Mattscheibe aus 2mm milchigen Acrylglas bauen und einsetzen

  • Den Programmcode von 8x8 px auf 25x8 px umschreiben

  • Wenn das klappt, die anderen 200 px anbauen und verdrahten

Wobei der vorletzte Punkt im Moment das größte Problem ist: Da ich maximal belesener Laie bin im programmieren, ist es mir bis jetzt nicht gelungen den vorhandenen Code aus dem Adafruit-Projket auf 25 x 8 px zu ändern.

Von daher an dieser Stelle meine Bitte um Unterstützung: Wenn einer von euch eine Idee hat, wie man den Code auf mein Display adaptieren kann, immer gerne her damit! Die Adaptierung auf Neopixel ist mir schon gelungen.
Adafruit-Code auf GitHub

Ich halte euch auf dem Laufenden und freu mich über Hilfe, Lob und auch Kritik (aber lieber Hilfe und Lob :wink: )

23/12/2016 Nachtrag 1

Damit das Trum nicht ganz unnütz an der Wand hängt wärend ich auf Teile und Geistesblitze warte hab ich schnell mal ein Uhr draus gebaut:

Zur Info: der schwache rote Balken unter der Zeit ist ein Sekundenbalken der mitläuft und kein Pixelfehler :wink:

6 „Gefällt mir“

Hey, sehr cooles Projekt :slight_smile:
Sieht echt gut aus. Wielange hast du denn daran gesessen sie alle einzeln zu verkabeln :-o
Ich habe das damals für meinen Snake
Wohnzimmertisch gemacht und war echt froh, dass ich nur 10 Reihen aneinanderlöten musste. Von diesem Projekt habe ich übrigens noch ein komplett anpassbares Steckgitter in Fusion360 um die Pixel viereckig anzuzeigen. Ich bin gerade unterwegs kann die Datei aber gerne nachher einmal hochladen. Ich kann das Gitter auch in Fusion anpassen und dir die dxf hochladen wenn du mir die Maße gibst.
Wirklich ein sehr schönes Projekt :+1:

Na da hast du dir ja was ausgedacht… nächstes mal denn am Lasercutter schneiden :wink:
Schönes Projekt! Zu deiner Frage: [quote=“Hunzi, post:1, topic:1580”]
Von daher an dieser Stelle meine Bitte um Unterstützung: Wenn einer von euch eine Idee hat, wie man den Code auf mein Display adaptieren kann, immer gerne her damit! Die Adaptierung auf Neopixel ist mir schon gelungen.Adafruit-Code auf GitHub
[/quote]

@janis: Kennst du dich nicht damit aus?

Hey, wirklich sehr cool!

Bin mal gespannt, wie das am Ende aussieht :smiley:
Der Code sieht tatsächlich etwas komplexer aus, aber ich denke ich habe eine grobe Ahnung wie das funktioniert. Falls du Fragen hast kann ich gerne versuchen dir zu helfen. Hast du deinen Code auch schon auf Github oder so?

Hi Natascha! Ich war letzte Woche krank geschrieben und hab so circa 2 Tage zum verkabeln gebraucht ^^ Vielen Dank für das Angebot mit dem Steckgitter, aber ich hab’s selbst schon konstruiert. Aber mich würde interessieren welches Material du für deins genommen hast?

@Janis

Dankeschön! Und ja, das bin ich auch :wink:

Also meine einizge Leistung im Code war bisher ihn auf die Neopixel-Matrix umzuschreiben und die Idee dahinter zu verstehen: im Hintergund läuft die FFT, die 256 bin’s mit Ergebnissen der Spektrumanalyse füllt. Der Code fasst diese selektiv in 8 bin’s zusammen und errechnet dann denn jeweiligen peakt-to-peak Wert. Tortz mehrtägiger Suche hab ich nicht herausfinden können, wie man auf die bin’s zugreift und vor allem, wie man statt 8 bin’s die FFT-Ergebnisse auf 25 bin’s aufteilt.

Ich hab gerade mal ein GitHub Repository angelegt (ich hoffe das hat geklappt):
GitHub Repository

Falls du ne Idee hast, wie die Verteilung der 256 bin’s funktioniert, und mir da einen Denkanstöß geben könntest, wäre das schon ne ziemliche Hilfe für mich :slight_smile:

Ah super, das sieht doch schon gut aus. Ich glaube die Erweiterung auf 25 Spalten wird doch nicht soo schwer. Es sei denn ich übersehe was :sweat_smile:

Wenn ich das richtig verstehe, landet das Ergebnis der Spektrumanalyse in dem spectrum Array (Z. 135) Sieht so aus als wären das dann nur 64 bins, aber das reicht ja :wink:

Die bins werden dann in Z. 149-156 auf die 8 LED-Spalten verteilt. Dafür sind vorher (Z. 53 - 74) diese colData Arrays definiert worden. In denen steht drin, welche bins mit welchem Gewicht zu welcher Spalte hinzugefügt werden. Der Code dafür scheint aber ganz gut von der Spaltenanzahl getrennt zu sein. Im Prinzip müsste man also nur die Arraygrößen und Schleifengrenzen anpassen, um von 8 auf 25 Spalten zu wechseln. Und natürlich die Zuordungen der bins zu den neuen Spalten definieren.

Nochmal genauer:

  • Die Arraygrößen von 8 auf 25 ändern (Z. 18-26: peak, col, minLvlAvg,
    maxLvlAvg, colDiv)
  • Die neuen Zeilenzuordungen definieren (wie Z. 53-74 nur halt für die Spalten 8-24).
  • Die neuen Zuordnungen in colData (Z. 77) einfügen
  • Schleifengrenzen von 8 auf 25 ändern (Z. 94, 150 und 204)
  • Hoffen das es so klappt :grin:

Viel Erfolg :smiley:

@Janis

Zuerst mal: Frohe Weihnachten :slight_smile:

Ich kann einen Teilfortschritt vermelden: den fallenden Punkt in der neuen Spalte (ich hab erstmal nur eine 9. hinzugefügt) gibt es jetzt schon. Aber ich glaube ich hab den Teil mit der Gewichtung (z. 53-74) noch nicht richtig gemacht: Ich hab einfach col5data kopiert und als col8date eingefügt. Das schein so aber nicht zu gehen (ich dachte ich kopiere erstmal die 5 zum ausprobieren). Kannst du mir nochmal einen Tipp geben was in colXdata passiert? So wie ich das verstehe wird da ein array undefinierter Größe angelegt und mit Indizies befüllt!? aber wofür diese stehen ist mir noch ein Rätsel :confused:

Ich habe meins aus 4mm Birken Sperrholz ausgelasert und anschließend weiß angesprüht um das Licht besser zu reflektieren. Hier ist natürlich die Höhe besonders wichtig. Je nachdem wie gestreut das Licht an der Oberfläche ankommen soll.

Hmm, hätte eigentlich klappen müssen :confused: Hast du dran gedacht dein col8data darunter in den colData-Array hinzuzufügen?

Die Arrays geben die Verteilung in der bins in die Spalten an. Die erste Zahl ist die Anzahl der bins, die zweite der index des ersten bins und danach die Gewichtung der Einzelnen bins.

Also zum Beispiel:
{2,3,1,1}
für jeweils 50% aus bin 3 und bin 4
{3,5,1,2,1}
für 25% aus bins 5 und 7 und 50% aus bin 6

@Janis
Ja, hab ich. Hab den Code gerade nochmal bei GitHub hochgeladen. D.h. die “Zahlen” beim array weight die der Autor verwendet sind im weitesten Sinne willkürlich und verstehen sich als relativ zueinander, ohne absolutuen Bezug? Da muss man erstmal drauf kommen :sweat_smile:
Ich versuch gleich mal ein Video hochzuladen auf dem man vll. sieht was im Moment das Problem ist…man schauen ob das klappt…
YouTube Video

Ah, alles klar. Ich hatte drüber nachgedacht mir weißen, besonder dicken Pappkarton zu besorgen. Oder alternativ 2mm dünnes weißes Plexiglas. Aber vll. ist das auch Perlen vor die Säue. Na mal schauen…

Was hast du als Abdeckung für die LEDs verwendet? Dadurch siehst du ja das Gitter sowieso nicht so genau, da es ja auch milchig ist. Aber Pappe sollte natürlich auch gehen. Die Uhr sieht echt genial aus :heart_eyes:

Ich glaub ich habs :smiley:
Ab Z.149, die Achten
matrix.fillRect(0, 0, 8, 3, RED); // Upper section matrix.fillRect(0, 3, 8, 2, YELLOW); // Mid matrix.fillRect(0, 5, 8, 3, GREEN); // Lower section

Außerdem müssen die Arrays oben glaub ich noch angepasst werden.
Ab Z. 19, ich würde hier auch alle Achten ersetzen
byte peak[8], // Peak level of each column; used for falling dots dotCount = 0, // Frame counter for delaying dot-falling speed colCount = 0; // Frame counter for storing past column data int col[9][10], // Column levels for the prior 10 frames minLvlAvg[8], // For dynamic adjustment of low & high ends of graph, maxLvlAvg[8], // pseudo rolling averages for the prior few frames. colDiv[9]; // Used when filtering FFT output to 8 columns

Im Zweifelsfall ist ein zu großer Array nicht schlimm, ein zu kleiner aber schon :wink:

@Janis
Ja, du hattest natürlich recht: ich habe vergessen die neue Spalte auch mit Farbe zu füllen. Mir fehlt allerdings noch die Erklärung warum die erste und letzte spalte jetzt viel sensibler reagiert als die anderen.
Aber leider musste ich feststellen, das mein UNO schon mit 16x8 vom Speicher her überfordert ist. Ich denke ich muss nochmal vorne anfangen und das ganze mit einem teensy 3.2 aufziehen. Der kann wohl “von haus aus” FFT und ist ja sowieso wesentlich leistungsstärker…