Musiclight

Aus bytewerk-Wiki
Zur Navigation springen Zur Suche springen

Über dieses Projekt

Musiclight ist ein Langzeitprojekt von cfr34k, das zum Ziel hat, Audio möglichst cool und generisch auf LED-Strips in Echtzeit zu visualisieren.

Im Juni 2018 steigt xor mit ein und fängt an, vernünftige Mechanik drum herum zu bauen.

Verantwortlich

Umsetzung und Funktionsweise

Das Projekt hat mittlerweile mehrere Iterationen hinter sich.

Implementierungen

MPD-RaspberryPi-ESP8266

Auch bekannt als Musiclight2.

Bei dieser Variante spielt ein Music Player Daemon (z.B. auf einem Raspberry Pi) Musik ab. Das Audosignal wird über ein FIFO an das Musiclight-Programm weitergegeben. Dieses berechnet die LED-Farben und sendet diese per UDP an einen Daemon (ws2801d), der die LEDs ansteuert.

Der ws2801d kann entweder auf einem Raspberry Pi laufen und die LEDs über SPI ansteuern oder auf einem ESP8266 implementiert sein (womit die LED-Leiste nicht direkt beim Abspielgerät stehen muss).

STMusiclight

STMusiclight ist eine Implementierung des Musiclights auf einem STM32F4. Das Audiosignal kommt hier analog von einem Mikrofon und wird mit Hilfe des internen ADCs eingetastet. Die WS2801-LED-Leiste wird direkt vom Mikrocontroller über SPI angesteuert.

Musiclight 4

Basierend auf Musiclight 2 soll alles besser werden:

  • RGBW-Strips (RGB + Weiße LED) vom Typ SK6812 werden verwendet
  • Schöner Hardwareaufbau, bei dem man nicht direkt in die LEDs schaut und keine weiße Wand braucht, auf die die LEDs leuchten können
  • mehr Power! (mehrere Strips parallel)

Status:

  • Prototyp läuft mit Ansteuerung über ein Zybo-Board
    • Leider ist das Board zu teuer für „Massenproduktion“
  • Ersatz durch Raspberry Pi + Hat zur Protokollkonvertierung und Pegelwandlung in Arbeit

Funktionsweise

Die Funktionsweise ist in diesem Blogpost beschrieben (schon etwas älter, aber das Grundprinzip ist noch sehr ähnlich). Dort gibt es auch ein Demo-Video.

Ansteuerung der LED-Leiste in Musiclight 4

Die Ansteuerung der LED-Leiste ist zweistufig abstrahiert: einmal auf SPI, um sie effizient über den Raspberry Pi ansteuern zu können und dann auf UDP für die einfache Ansteuerung von mehreren Geräten.

SPI-Protokoll

Unser LEDstrip Raspi-Hat wird per SPI angesteuert.

Verbunden sind die Raspi-Pins 8/9/10/11, somit ist der Hat in einem normalen Raspbian als /dev/spidev0.0 ansprechbar.

Weiterhin verwendet der Hat GPIO 22 als "!BUSY"-Signal. Solange dieser Pin low ist, darf keine SPI-Übertragung initiert werden.

Die maximale SPI-Bitrate ist nicht getestet, 12MHz funktioniert aber anscheinend gut.

Das erste Byte eines SPI-Transfers beschreibt ein Kommando:

CMD Beschreibung
0x01 Config
0x02 SetData
0x80 Flush
0x82 SetData and Flush
SPI-Command Config (0x01)

Konfiguriert das Raspi-Hat. Derzeit lässt sich nur einstellen, wieviele Bytes des internen Buffers beim Flush an die LED-Strips herausgeschrieben werden.

[0] [1] [2]
CMD (0x01) Bytes per Strip (low byte) Bytes per Strip (high byte)
SPI-Command SetData (0x02)

Setzt Daten in einem internen Buffer. Für jeden angesteuerten LED-Strip gibt es einen Buffer.

Der Offset gibt an, an welcher Byte-Position im Buffer Daten gesetzt werden sollen, dieser wird nach jedem übertragenem Datenbyte inkrementiert.

Danach folgen beliebig viele Datenbytes.

[0] [1] [2] [3] [4] [5] ...
CMD (0x02) Buffer (0..3) Buffer-Offset (low byte) Buffer-Offset (high byte) Data[0] Data[1] ...
SPI-Command Flush (0x80)

Sendet den aktuellen Inhalt der Buffer an die LED-Strips

[0]
CMD (0x80)
SPI-Command SetData and Flush (0x82)

Setzt Daten in einem intern Buffer und führt danach ein Flush aus.

[0] [1] [2] [3] [4] [5] ...
CMD (0x82) Buffer (0..3) Buffer-Offset (low byte) Buffer-Offset (high byte) Data[0] Data[1] ...

UDP-Protokoll

Ein UDP-Befehl besteht aus folgenden Feldern, gesendet in Network Byte Order (MSB zuerst). Ein Befehl besteht immer aus 8 Byte. Für mehr Übertragungseffizienz können mehrere Befehle in einem UDP-Paket versendet werden.

  • action (1 Byte): Auszuführender Befehl
    • SET_COLOUR (= 0): Setzt die Farbe direkt beim nächsten Update
    • FADE_COLOUR (= 1): Blendet langsam zur angegebenen Farbe über
    • ADD_COLOUR (= 2): Addiert die angegebene Farbe zur aktuell gesetzten
    • SET_FADESTEP (= 3): Setzt die Überblendgeschwindigkeit (Inkrement pro Frame, 100 FPS)
  • strip (1 Byte): Nummer des Strips
  • module (2 Byte): Nummer der LED
  • red (1 Byte): Wert des roten Kanals bzw. die Überblendgeschwindigkeit, wenn action == SET_FADESTEP
  • green (1 Byte): Wert des grünen Kanals
  • blue (1 Byte): Wert des blauen Kanals
  • white (1 Byte): Wert des weißen Kanals

Quelltext