Lounge Beleuchtung
Die Beleuchtung in der Lounge besteht aus ca. 2200 LEDs vom Typ WS2812B. Und werden von einem FPGA-Board bespielt. Wir nutzen Lightsd um die Effekte auf den LEDs zu konfigurieren.
Lightsd
Lightsd ist eine in C++ geschriebene Anwendung welche anhand der in der
config.yml
beschriebenen Effekt erzeugt. Wärend der Ausführung können die
meisten Parameter via MQTT angepassst werden .Das beinhaltet die aktiven
Operationen als auch deren Parameter (bspw. Helligkeit, Farbwerte, …).
Effekte via Netzwerk einspielen
Zum Entwickeln von Effekten ist es durchaus sehr angenehm wenn man diese lokal
ausprobieren kann und nach etwas lokalem Testen auf den LEDs in der W17 testen
kann. Lightsd
unterstützt das Anzeigen von per UDP Empfangenen Frames. Jeder
Frame ist dabei ein (fragmentierte) UDP Paket mit vielen HSV-Werten. Jeder HSV
Wert besteht aus drei float32 Feldern (in der Reihenfolge H, S, V). Es gibt
keinen zusätzlichen Längenindikator.
Der entsprechende Input kann via Homeassistant aktiviert
werden. Derzeit wird er als "Lightsd UDP Input (Port 1337)" geführt. Der Host
an den die Pakete geschickt werden müssen ist lightsd.cccda.de
. (TODO: offline)
Prototyping mit Python
Wer auch immer gerne Python verwendet um Effekte zu basteln findet ein paar hilfreiche Python Skripte im GitLab. Ein gutes Beispiel ist Raindrop.
Prototyping mit Lua über MQTT
Unter der MQTT-Adresse w17/lounge/light/mqtt-lua/code/set
kann man ein Lua-Skript als Wert hinterlegen, welches von Lightsd dann ausgeführt wird:
mosquitto_pub -h mqtt.cccda.de -t w17/lounge/light/mqtt-lua/code/set -m 'function render(pBuffer)
local buffer = HSVBuffer(pBuffer)
local size = buffer:size()
for i = 0, size -1 do
buffer:set(i, i * (360.0/size), 0.8, 0.8)
end
end
'
Soundvis
Seit dem Umzug in die W17 funktioniert unser altes Soundvis script leider nicht mehr ausreichend gut. Mit dem Wechsel von ~24 LEDs auf über 2000 LEDs haben wir das Limit erreicht. Nach einigen Abenden gibt es mittlerweile einen neuen Ansatz das Problem zu lösen: Wir haben einen Daemon entwicklet welcher (remote) auf whisky den Sound via Pulseaudio abgreift. Der Sound wird dann analysiert und die Erbenisse (nach FFT) per TCP auf port 1338 (auf whisky) bereitgestellt.
Jedes Datenpaket hat das folgende Format (alle Werte in Little Endian):
Name | Type | Beschreibung |
---|---|---|
Length | uint32_t | Anzahl der Bins |
samples | float32[Length] | Array der Bins |
Die Frequenz steigt mit dem Index. Das erste Bin hat die niedrigste Frequenz. Die Frequenzauflösung ist zur Zeit 12 Bins pro Oktave (also 1 pro Halbton) bei 7 Oktaven. Die Oktaven werden um den Ton 440Hz angeordnet, 4 darüber, 3 darunter. Das ergibt ein Frequenzspektrum von 55Hz-7040Hz. Es wird alle 16ms ein Paket gesandt, auch wenn die tieferen Frequenzen seltener gesampled werden.
Pynq
Das Pynq (derzeit auf dem hängenden Rack in der Lounge) bespielt die zwei LED stripes in der Lounge. Das Board enthält auch zwei ARM cores auf denen Linux läuft.
Der source code für die in Bluespec geschriebenen Teil liegt im GitLab.
Zugriff auf die LEDs erhält man durch Speicher der gemappt wurde. Zugriff
erfolgt mittels lightsd
und dem DevMem
output. Die default Konfiguration
passt auf unser Setup. Lediglich die Anzahl der stripes und der jeweiligen
Anzahl an LEDs muss konfiguriert werden.
Das Memory Layout ist folgendes:
Offset | |
---|---|
Data Offset | 0x1ff00000 |
Configuration Offset | 0x40000000 |
Ab der Stelle von Confiugration Offset
sind folgende Felder verfügbar:
Name | Type | Beschreibung |
---|---|---|
t0l | uint32_t | T0L Zeit in us |
t0h | uint32_t | T0H Zeit in us |
t1l | uint32_t | T1L Zeit in us |
t1h | uint32_t | T1H Zeit in us |
res | uint32_t | ?????????????? |
read_addr | uint32_t | Adresse der Daten |
led_count | uint32_t[50] | Liste der LED counts, je element ein stripe |
Ab der angegebenen read_add
bzw. Data Offset
findet man folgende Daten:
Name | Type | Beschreibung |
---|---|---|
LEDs | LargeRGB[N] | Array aller LEDs (0->N) |
LargeRGB hat das Format:
Name | Type | Beschreibung |
---|---|---|
b | uint8_t | blue in RGB |
g | uint8_t | green in RGB |
r | uint8_t | red in RGB |
empty | uint8_t | empty, for future use |