AdaFruit NeoPixel am Raspberry

Für mein StompBox Projekt möchte ich eine coole Visualisierung mit LED haben; ich hab mich für die NeoPixel von AdaFruit entschieden.

Was sind NeoPixel?

NeoPixel sind eine Technolgie des in New York ansässigen Elektronik-Herstellers AdaFruit. NeoPixel sind LEDs, die sich koppeln lassen, aber nur über ein einziges Datenkabel angebunden werden. Wenn man LEDs manuell verschaltet, braucht man pro LED ein eigenes Datenkabel, welches wiederum einen GPIO Pin beansprucht. Ein NeoPixel besteht aus 3 Einzel-LEDS für die Grundfarben, sowie einen Mini Chip (WS2811), welcher die Ansteuerung der Einzel-LEDs übernimmt. Egal wieviele LEDs hintereinandergeschaltet werden - es genügt ein einziges Datenkabel; der Datenstrom wird einfach weitergereicht. Jeder Chip entnimmt die jeweils ersten Daten und schneidet sie aus dem Datenpaket (shift), bevor sie an den nächsten Pixel weitergereicht werden.

Die Verkabelung der Pixel ist dann relativ einfach - man muss nur die Stromversorgung der NeoPixel und die Datenleitung anschließen. AdaFruit stellt die NeoPixel in bereits gekoppelten Modulen zur Verfükgung: als Kreise, Kreisgsegmente oder Kabel.

Arduino vs Raspberry

Ein Raspberry mit Raspbian Betriebssystem ist kein Echtzeit System - der Kernel entscheidet, wann welcher Prozess laufen darf. Das ist ein ziemliches Problem für die Ansteuerung der NeoPixel, die ein exaktes Timing der Signale erwarten. So hat dann auch Adafruit die NeoPixel für den Arduino und nicht den Raspberry entwickelt.

Dank der Bibliothek https://github.com/jgarff/rpi_ws281x von Jeremy Garff funktionieren die NeoPixel nun auch am Raspberry. Der Trick besteht darin, die NeoPixel Daten per Direct Memory Access - ohne CPU - zum PWM Controller zu schieben, der diese dann auf die Leitung gibt.

12 NeoPixel im Ring

Ich hab mir bei AdaFruit einen Ring aus 12 NeoPixeln bestellt. 12 LEDs im Kreis - damit kann man prima eine Uhr bauen. Ich möchte die über die Stompbox aufgezeichneten Rythmus Patterns als im Kreis laufende Lichtsignale visualisieren. Ein Kreis ist nunmal eine ideale Visualisierungsmöglichkeit für sich wiederholende Ereignisse.

Stromversorgung

AdaFruit empfiehlt eine separate 5 Volt Stromversorgung für die NeoPixel; eine Versorgung über den Raspberry kann diesen beschädigen. Jeder einzelne Pixel kann bis 60 mA Strom ziehen - abhängig von der (per Software einstellbaren) Helligkeit. Das Netzteil muss ausreichend groß dimensioniert werden.

Man sollte auf jeden Fall vermeiden, die NeoPixel über die 3 Volt Leitung anzuschließen. Diese darf maximal 50 mA Leistung abliefern. Meiner Meinung nach ist der 5 Volt Pin vom Raspberry direkt mit dem USB Power Anschluss verbunden, läuft also nicht über die Bauteile der Platine. Mit einem 2 Ampere USB Netzteil müsste das eigentlich klappen - auch wenn die Anleitungen bei AdaFruit davon abraten.

Software Installation

Der Beschreibung https://learn.adafruit.com/neopixels-on-raspberry-pi/software folgend:

Schaltung

Die Schaltung ist simpel. Man speist die NeoPixel mit 5 Volt, der “IN” Port der Pixel wird mit einem GPIO Pin verbunden, der PWM unterstützt. Der OUT Port wird mit dem nächsten NeoPixelsegment verbunden (und dort am IN angeschlossen). Ich hab nur ein NeoPixel - der OUT bleit einfach frei. Es gibt zwei PWM channels; die rpi_ws281x Library ermöglicht es beide zu nutzen. Erlaubt sind:

  • Channel 0:
    • Pin 12 (BCM 18)
    • Pin 32 (BCM 12)
  • Channel 1:
    • Pin 33 (BCM 13)
    • Pin 35 (BCM 19)

** Wichtig: wenn man den Kanal 1 nutzen will, muss man den Channel bei der Initialisierung mit angeben. ** In den den von ADaFruit beigelegten Beispielen wird die Verwendung des Channels nicht deutlich; die Python Library ist aber dafür vorbereitet:

# LED strip configuration:
LED_COUNT      = 12      # Number of LED pixels.
LED_PIN        = 13      # GPIO pin connected to the pixels (must support PWM!).
LED_CHANNEL    = 1       # PWM Channel must correspond to chosen LED_PIN PWM!
LED_FREQ_HZ    = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA        = 5       # DMA channel to use for generating signal (try 5)
LED_BRIGHTNESS = 50     # Set to 0 for darkest and 255 for brightest
LED_INVERT     = False   # True to invert the signal (when using NPN transistor level shift)

...

# Main program logic follows:
if __name__ == '__main__':
        # Create NeoPixel object with appropriate configuration.
        strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)
        # Intialize the library (must be called once before other functions).
        strip.begin()

NeoPixel und HifiBerry Audio

Leider hab ich es nicht hinbekommen, die NeoPixel parallel zu dem DAC PHAT Audio Hat zu benutzen. Sobald ich eine Audioausgabe starte, blockiert die LED Animation und umgekehrt. Das ist ärgerlich, laut HifiBerry Dokumentation werden nur die GPIOs 18-21 (PINs 12, 35, 38 and 40) belegt.

Am DAC PHAT scheint es nicht zu liegen - auch wenn ich diesen gar nicht anschliesse, treten die Störungen auf.

Falsches Image

Ich hab mich ein paar Stunden abgemüht, die Demos zum Laufen zu bringen. Die LEDs zeigten immer nur ein chaotisches Flackern. Um zu verifizieren, dass die NeoPixels nicht kaputt sind, hab ich sie an einen Arduino Uno angeschlossen - hier liefen sie ohne Probleme.

Letztendlich lag es an einem modifizierten Image, das ich verwende hatte (2016-10-18-pitft-28r.img, ein Spezialimage zur Verwendung eines Touch TFT Displays). Mit dem Standard Image 2016-11-25-raspbian-jessie.img wie auch dem jessie-lite dagegen hatte ich keine Probleme.

Lichtschutzfaktor

Die NeoPixel sind wirklich sehr hell - man muss auf seine Augen aufpassen. Ich habe die brightness auf 50 (255 ist Maximum) gesetzt - auch das sind sie noch hell. Am besten ist es, wenn man sie hinter ein brechendes Material (Milchglasscheibe, Papier) legt.

Beispielanwendung: Uhr

12 LEDs im Kreis - das schreit nach einer Uhr. Allerdings ist es gar nicht so einfach, auf nur einem Kreis Stunden, Minuten und Sekunden so unterzubringen, dass man auch die Uhrzeit ablesen kann:

  • Einzig die Stundenanzeige ist bei 12 LEDs exakt platzierbar
  • Minuten und Stunden müssen von 60 Einheiten auf 12 Elemente abgebildet werden; also im 5er Raster
  • Für die Minutenanzeige ist das nicht dramatisch, man rundet diese ohnehin häufig im Kopf (“20 nach 12” anstelle von exakten 12:22)
  • Für die Sekundenanzeige ist das wirklich blöd, da man den Sekundentakt auch sehen will. Im 5er Raster springt die Sekundenanzige nur alle 5 Sekunden - das entspricht nicht der Erwartung
  • Wenn Minute und Stunde das gleiche LED beanspruchen, lassen sich diese schwer unterscheiden.

Meine Lösungen:

  • Minuten werden nicht nur durch eine LED, sondern durch alle LEDs von 1 an dargestellt. 20 Minuten lassen also die LEDs 1,2 3,4 leuchten.
  • Stunden und Minuten mischen ihre Farben zusammen, wenn sie die selbe LED beanspruchen.
  • Die Sekunden leuchten jede Sekunde auf und “verglühen” dann wieder. Außerdem läuft eine rote LED pro Sekunde im Kreis.

Richtig zufrieden bin ich damit noch nicht, aber für die erste Evaluierung der NeoPixel reicht es.

Mein Beispielscript auf github: simple-neopixel-clock