Zum Inhalt springen

WS2812 Pixeldisplay

Inhaltsverzeichnis

Update 8. Juni 2018: Das Git Repository zum Projekt ist online!

LED-Leisten sind in den letzten Jahren immer beliebter geworden - super einfach kann man sich zu Hause eine professionell aussehende Beleuchtung einrichten und diese auch noch steuern: Farbe, Helligkeit, Animationen - alles ist einstellbar!

Aber diese Leisten haben den Nachteil, dass man keine einzelne LED steuern kann - nur immer die gesamte Leiste. Mit dem WS2812 Controller in LEDs ist aber genau das möglich: man kann einzelne LEDs auf dem Streifen ansteuern und so viel komplexere Animationen (z.B. einen Farbregenbogen) abspielen.

Das Protokoll ist sogar dafür geeignet, ganze Displays zu basteln. Und genau das haben wir getan.

Das Protokoll des WS2812B

Das WS2812B-Protokoll basiert komplett auf Timings. Je nach dem, wie lange der Wechsel zwischen High- und Low-Level auf der Datenleitung dauert, wird entweder “0”, “1” oder “Return/Reset” interpretiert.

So lange nur “0” oder “1” erkannt wird, reichen die einzelnen LEDs die Daten einfach durch - immer in 24-Bit langen Gruppen (jeweils 8 Bit für Rot, Grün und Blau-Werte). Sobald ein “Return/Reset” erkannt wird, werden die empfangenen Daten auf den Ausgang geschaltet und die LED leuchtet in der konfigurierten Farbe.

Das exakte Protokoll beschreibt WorldSemi in ihrem Datenblatt zur WS2812B-LED.

Die Timing-Angaben dort sind jedoch etwas streng formuliert - Josh von josh.com hat sich die Tabelle aus dem Datenblatt mal genauer angeschaut und dabei herausgefunden, dass die Timings gar nicht so unerreichbar streng sind, wie im Datenblatt angegeben.

Folgende Zeiten hat er identifiziert:

Symbol Parameter Min Typisch Max Einheit
T0H 0 code ,high voltage time 200 350 500 ns
T1H 1 code ,high voltage time 550 700 ns
TLD data, low voltage time 450 600 5.000 ns
TLL latch, low voltage time 6.000 ns

Daraus kann man ablesen, dass es eigentlich nur zwei Limits gibt, die man einhalten muss:

  • die Dauer von T0H (< 500 ns)
  • die Dauer von TLD (< 5.000 ns)

Mit dem TLD-Puls unter 5.000 ns zu bleiben ist nicht schwer und auch die Dauer des T0H ist noch ohne Extravaganzen einhaltbar.

Damit der LED-Streifen aber beliebig lang werden kann, sollte man dennoch versuchen, möglichst nah an die typischen Werte heran zu kommen. Etwaige Abweichungen davon pflanzen sich nämlich durch alle LEDs fort und werden durch fehlerhafte Lötstellen o.ä. irgendwann so verzerrt (“Stille Post”, anyone?), dass sie nicht mehr stimmen. Die Folge ist plötzliches und helles Aufblitzen einzelner LEDs oder LED-Abschnitte.

Steuerung

Theoretisch sind die WS2812B-LEDs zwar mit einem Arduino steuerbar, um aber etwas agiler entwickeln zu können, haben wir uns zunächst für einen RaspberryPi entschieden. Durch die hohe Taktfrequenz mussten wir uns bei den ersten Gehversuchen mit den WS2812 weniger Gedanken um das Timing machen.

Außerdem können wir auch dem RPi ganz bequem Teile der NeoPixel Bibliothek von Adafruit nutzen, für die es praktischerweise einen Python Wrapper für den Raspberry Pi gibt.

Mit diesem kann man kinderleicht (siehe python/examples/strandtest.py) die WS2812 zum Leuchten bringen.

Ansteuerung als Display

Eigentlich handelt es sich bei unserem Display nur um einen 7,5 Meter langen Streifen mit LEDs. Damit daraus ein Display wird, mussten wir den Streifen in den 50cm lange Stücke schneiden und diese in Displayform aufkleben und wieder verlöten.

In der Software wird z.B. für die Anzeige von Bildern dann noch folgender Codeschnipsel verwendet, um Bilder und Animationen korrekt auf unsere Displayform von 30x30 LEDs umzurechnen:

// im buffer befindet sich das anzuzeigende Bild
i = 0
for y in range(0, displayHeight):
    for x in range(0, displayWidth):
        if y%2 != 0:
            r,g,b = buffer.getpixel((29-x,y))
        else:
            r,g,b = buffer.getpixel((x,y))

        strip.setPixelColor(i, Color(r, g, b))
        i += 1

Hier kann man erkennen, dass wir jede zweite (bzw. ungerade) Zeile von hinten nach vorne auslesen müssen - denn mit jeder Zeile ändert sich die Richtung in die unsere LED-Streifen “zeigen”. Das kann man z.B. hier anhand der Pfeile für Data In (DI) und Data Out (DO) gut sehen:

WS2812B Streifen geloetet

Git Repository

Alle Demos von der Maker Faire sowie unsere Ansteuerung des Displays findet ihr in dem dazugehörigen Git Repository unter https://gitea.breadboarder.de/members/ws2812-display

Stromversorgung

Während die Verdrahtung der LED-Streifen recht intuitiv funktioniert (+5V, Data, GND jeweils miteinander verbinden), sollte man bei der Stromversorgung einen guten Puffer einplanen. Manche Streifen schalten direkt nach dem Anlegen von Spannung auf maximale Helligkeit und fordern damit eine Menge Strom: pro WS2812B-LED muss man mit dem Strom von drei einzelnen LEDs rechnen, also drei mal 20 mA. Bei 5V ergibt das schon eine nötige Leistung von 30 Watt! Zusätzlich haben LED-Streifen meist relativ dünne Kupferstreifen für die Stromleitung, sodass auf einen halben Meter LED-Streifen ein Spannungsabfall von 0,5V einzurechnen ist - eine sternförmige/parallele Stromversorgung aller Streifen ist daher Pflicht.

Außerdem empfiehlt es sich, den steuernden Controller/RaspberryPi vor einschalten der LEDs hochzufahren. So kann der Controller damit beginnen, daas “LED aus”-Signal zu senden, bevor die LEDs voll leuchten. So muss man dann auch kein “9000” Watt-Netzteil verwenden, sondern es reicht eines mit robuter Strombegrenzung und Peakstromverträglichkeit für ein kurzes Aufblitzen aller LEDs.

Ein 100 Ohm Widerstand in der Datenleitung verhindert zusätzlich den Ausfall eines GPIO-Pins am RPi (da die LEDs sonst versuchen, ihren Versorgungsstrom aus der Datenleitung zu ziehen).

Dieses Projekt wurde auf der MakerFaire 2018 in Berlin ausgestellt

Quellen

  1. NeoPixels Revealed: How to (not need to) generate precisely timed signals
  2. github.com/cpldcpu/light_ws2812
  3. pigpio
  4. pinout.xyz
  5. github.com/jgarff/rpi_ws281x