Wer so viel auf Elektronikseiten herumhängt wie ich, wird relativ schnell über LED-Strips stolpern, lange flexible Streifen mit einfarbigen oder RGB-LEDs. Neben den billigeren, bei denen alle LEDs gleichzeitig angesteuert werden, gibt es auch RGB-LED-Strips, bei denen jedes LED einzeln angesteuert werden kann (Bezugsquelle). Erfahrungsgemäss sind diese adressierbaren Strips teurer als die erste Variante. Seit ein paar Tagen bin ich im Besitz eines 1-Meter-Streifens und seit kurzem habe ich ihn zum Laufen gebracht. Hauptschwierigkeit bei diesem Projekt war die geeignete Stromversorgung: ein 5V-LED-Strip mit 32 Lämpchen pro Meter à 60 Milliampere zieht fast 2 Ampere Strom pro Meter, wenn alle LEDs gleichzeitig brennen. Das ist wesentlich mehr, als das Arduino-Board oder eine 4.5V-Blockbatterie liefern! Manche Dinge lernt man nur auf die harte Art (davon unten mehr). Eine externe Stromversorgung war also zwingend. Das vorliegende Tutorial ist eine Weiterentwicklung des Tutorials von Adafruit.
Eine generelle Einführung in Arduino-Hardware und Programmierung habe ich in meinem Arduino Cheat Sheet verfasst.
Warnung:
Das vorliegende Projekt verwendet als Stromversorgung für den LED-Strip ein altes ATX-PC-Netzteil. Das unsachgemässe Herumbasteln an PC-Netzteilen kann tödlich sein. Und das im Gegensatz zum Rauchen nicht erst in 30 Jahren, sondern sofort. Ausserdem funktioniert die vorgeschlagene Versorgung, wenn ich das richtig verstanden habe, nur mit 5V-LED-Strips, nicht aber mit der 12Volt-Variante, da in PC-Netzteilen nur der 5V-, nicht aber der 12V-Ausgang stabilisiert ist (Quelle) und somit die 12Volt-Anschlüsse bei der vorgestellten Methode keine stabile Versorgung garantieren (Quelle). Für Unbedarfte empfehle ich unbedingt die Verwendung eines 5V-Netzteils mit mindestens 2000 mA (Bezugsquelle).
Die vorgestellte Schaltung dient zum Experimentieren mit Arduino, sie ist keinesfalls für den Dauerbetrieb gedacht. Ich rate deshalb unbedingt davon ab, den LED-Strip längere Zeit unbeaufsichtigt laufen zu lassen. Bei der Wahl falscher Komponenten (z.B. zu wenig leistungsfähigen Kabeln) droht durch Überlastung Brandgefahr, bei schludriger Verkabelung kann es zu Kurzschlüssen kommen.
Haftungsausschluss
Ich übernehme keinerlei Haftung für Personen- oder Sach-Schäden, die durch den Nachbau des vorgestellten Projektes entstehen könnten. Jeglicher Nachbau erfolgt in eigener Verantwortung!
Projektziel
Einen digital adressierbaren 5V-RGB-Led-Strip mit Arduino steuern, wobei für den LED-Strip eine externe Stromversorgung zum Zuge kommt.
Komponenten
Wichtig ist, dass man den richtigen LED-Strip hat. Es gibt nämlich auf dem Markt eine Unzahl verschiedener LED-Strips. Es muss unbedingt ein RGB-LED-Strip sein, nicht ein einfarbiger. Die LED sind einzeln ansteuerbar (im Englischen nennt man dies „digital“) und der Strip ist im vorliegenden Projekt für 5 Volt ausgelegt (es gibt auch solche für 12V). Gemäss Adafruits gibt es diesen RGB-LED-Strip in einer älteren und einer neueren Variante, die sich v.a. durch die Anzahl Anschlüsse unterscheiden. Ich beziehe mich auf die neuere mit 4 Anschlüssen (die genaue Unterscheidung findet man bei Adafruit). Für dieses Projekt benötigt man die folgenden Komponenten:
- 1 Arduino-Board: im aktuellen Fall ein Arduino mega 2560
- 1 digital adressierbarer RGB-LED-Strip vom Typ LPD8806, Länge 1 Meter (Bezugsquelle Schweiz)
- einige Jumperkabel M/F
- einige Jumperkabel M/M
- 1 USB-Kabel zur Verbindung des Arduino-Boards mit dem PC
- 1 PC mit Arduino-Entwicklungsumgebung
- falls der Strip ohne Stecker kommt, 1 Lötkolben und Lötzinn zum Anlöten der Drähte sowie geeigneter Isolierdraht
Normale Variante der Stromversorgung
- 1 Netzteil AC/DC-Adapter 5V DC, für 1 Meter 2000 mA, für längere Strips proportional mehr (Bezugsquelle Schweiz)
- 1 zum Netzteil passende DC Power Adapter, etwas in dieser Art, darauf achten, dass das Teil bezüglich Male/Female und der Buchsengrösse auch wirklich zum Netzteil passt
Und hier noch die Alternative zum 5V-Netzteil für Kamikaze-Elektrobastler/innen (man beachte den Haftungsausschluss am Artikelanfang!)
- 1 altes ATX-PC-Netzteil
- 1 alte (aber funktionierende!) Festplatte oder Ventilator aus PC als Belastungswiderstand (andere nehmen dazu ein Standlicht aus einem Autoscheinwerfer oder einen richtigen Widerstand, siehe hier)
- 2 Lüsterklemmen (in der Schweiz kennt man dieses Teil unter dem Namen „Zückerli“)
- 10 – 20 cm dicker Isolierdraht
- 1 Abisolierzange oder anderes Werkzeug zum Abisolieren wie Taschenmesser oder Schere
Etwas Kopfzerbrechen bereitete mir das als Belastungswiderstand empfohlene Standlicht: Wo nimmt eine überzeugte NAB (Nichtautobesitzerin) nachts um Elf ein Standlicht her? Draussen auf der Strasse heimlich eines aus einem parkierten Auto ausschrauben? Keine gute Idee! Doch dann schalten sich meine kleinen grauen Zellen ein: Hey, mit Belastungswiderstand meinen die irgendetwas, das Strom zieht. Und was hängt man am besten an diese netten Stecker ohne gemeingefährliches Gebastel? Richtig, das, was früher auch schon daran hing, zum Beispiel eine Festplatte! Und mit alten Festplatten ist unser 2-Computerfreak-Haushalt nun ausserordentlich reichlich bestückt.
Bestückungsplan und Verkabelung
Bei diesem Projekt ist es mit einem Bestückungsplan nicht getan, denn zu der Art, wie das PC-Netzteil verbunden wird, muss ich doch ein paar Worte verlieren. Ich erinnere noch mal an den Haftungsausschluss, das Basteln an PC-Netzteilen ist wirklich gefährlich. Grundregel Nr. 1 ist, dass man die Stromversorgung des Netzteils unterbricht, d.h. das Kabel entfernt, bevor man irgendwelche Manipulationen vornimmt.
Den genauen Aufbau eines ATX-Steckers habe ich hier gefunden. Damit man ein PC-Netzteil überhaupt ausserhalb eines PCs in Betrieb nehmen kann, muss man Power-On überbrücken, indem man den Power-On-Anschluss (Pin 14, meistens grünes Kabel) mit der Masse (Pin 13 oder 15, schwarzes Kabel) verbindet. Ich habe dies mit einem dicken Isolierdraht gemacht, den ich an beiden Enden ca. 0.5 cm abisoliert habe, so dass er gerade bündig in den Steckeranschluss passt. Praktischerweise hatte ich einen Isolierdraht zur Hand, der genau die richtige Dicke für den Stecker hat. Jumperkabel kann man dafür nicht nehmen, sie sind zu dünn und rutschen raus. Und anschliessend hängt man die Festplatte an einen der ungenutzt herumhängenden Stecker. Oder man hängt wie auch immer einen anderen Belastungswiderstand an. Sinnvollerweise testet man nun, ob die Überbrückung geklappt hat, bevor man weiter macht. Also Stromkabel anschliessen und Netzgerät anschalten. Wenn der Ventilator anfängt zu drehen, dann hat man es geschafft.
Danach wieder ausschalten, Kabel abziehen und weiter geht es: Zwei ca. 5 cm lange, auf beiden Seiten ca. 0.5 cm abisolierte Stücke Isolierdraht vorbereiten. Das eine steckt man in einen 5V-Anschluss (einer der Anschlüsse mit rotem Kabel, z.B. Pin Nr 4 vis-a-vis vom grünen Kabel) und das zweite in eine Masse (Pin Nr. 5, schwarzes Kabel). Dies sind unsere Anschlüsse für Arduino und LED-Strip.
Mein LED-Strip kam schon mit einem Stecker mit der pompös nichtssagenden Bezeichnung 4-Pin JST SM, was mir das Verlöten ersparte. Nicht dass ich ein Problem mit Löten hätte, aber das mache ich normalerweise auf dem Balkon im Freien, und bei der aktuellen Wetterlage mit 20 cm Neuschnee ist das nicht wirklich eine Option. Freundlicherweise passen auf die 4 Pins in diesem Stecker genau die Female-Enden meiner Jumperkabel (einfach bei Play-Zone oder einem beliebigen Online-Lieferanten nach „Jumperkabel M/F“ suchen). Nun hatte ich noch die Herausforderung vor mir, einen relativ dicken Isolierdraht mit einem viel dünneren Male-Ende eines Jumperkabels zu verbinden, ohne dass dies in eine lebensgefährliche Bastelei ausartete. Nachdem ich diverse Varianten als fahrlässig oder zu wenig stabil verworfen hatte, brachte wildes Kramen in meiner Komponentensammlung endlich das rettende Teil zum Vorschein: Zückerli beziehungsweise Lüsterklemmen! Damit konnte ich nun einen 5V-Anschluss (rotes Kabel) mit dem 5V-Anschluss des LED-Strips verbinden. Die Masse (GND bzw. schwarzes Kabel) wird dagegen nicht direkt mit dem Strip verkabelt, sondern beide GND-Anschlüsse, jener des ATX-Steckers und jener des LED-Strips kommen in die zwei GND-Anschlüsse des Arduino-Boards. Unbedingt darauf achten, dass 5V- und GND-Anschlüsse nicht verkehrtherum verbunden werden, sonst ist der Streifen hin!
Nun fehlt noch die Verkabelung für die zwei mittleren Pins des Streifens. Sie werden angeschlossen, wie im Adafruit- Tutorial beschrieben, d.h. der mit DI bezeichnete Data-Pin unterhalb GND mit Pin 2 und der mit CI bezeichnete Clock-Pin mit Pin 3 auf dem Arduino-Board. Und das USB-Kabel kommt natürlich wie immer zwischen PC und Arduino-Board.
Code
Für die RGB-LED-Strips gibt es eine pfannenfertige Library namens LPD8806 von Adafruit (hier herunterladen), welche für programmiertechnisch Unbedarfte bereits mit einem ausgefeilten Beispielprogramm aufwartet – das Beispiel namens „strandtest“ – und beachtliche Farbspielereien in allen Regenbogenfarben liefert. Ich zeige deshalb hier nur jenen Code, der meine eigene Kreation ist: Dabei werden die Lämpchen von aussen nach innen eingeschaltet und zwar von kalten Blautönen über Rot, Orange und Gelb bis zum gleissenden Weiss in der Mitte. Der Code ist für einen 1-Meter-Strip mit 32 LED, lässt sich mit etwas herumrechnen aber auch für andere Längen anpassen.
#include "LPD8806.h" #include "SPI.h" /* * digitale RGB LED Strips vom Typ LPD8806 steuern * Weiterentwicklung des Tutorials von Adafruit * Autorin: Silvia Rothen, rothen ecotronics, Bern, Switzerland * http://ecotronics.ch.honorius.sui-inter.net/wordpress/category/physical-computing/ */ /*****************************************************************************/ // Anzahl RGB LEDs int nLEDs = 32; // Die zwei Arduino-Pins, mit denen der LED Strip verbunden ist int dataPin = 2; int clockPin = 3; // Den Strip initialisieren LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin); void setup() { // LED-Strip starten strip.begin(); Serial.begin(9600); // Am Anfang sind alle LEDs aus strip.show(); } void loop() { getHot(200); allOut(); hotline(200, 6); } //Hilfsroutine zum Überprüfen des Codes void printRGB(int i, int j, int r, int g, int b) { Serial.print(i); Serial.print(" "); Serial.print(j); Serial.print(" "); Serial.print(r); Serial.print("/"); Serial.print(g); Serial.print("/"); Serial.print(b); Serial.println(); } //Die LED werden von Links nach Rechts einzeln zugeschaltet, //wobei die Farben von Blau über Rot und Gelb bis zu Weiss laufen //Es brennt nur die im Parameter anzahl übergebene Anzahl LEDs gleichzeitig void hotline(int wait, int anzahl) { int i = 0; int r = 0; int g = 0; int b = 127; int difference = 13; int steps = 11; int j = 0; for (i = 0; i < strip.numPixels() + anzahl; i++) { r = constrain(i * difference, 0, 127); if (i > steps) { g = constrain((i - steps) * difference, 0, 127); } else { g = 0; } if (i < steps) { b = constrain(127 - i * difference, 0, 127); } else { if (i > steps * 2) { b = constrain((i - (steps * 2)) * difference, 0, 127); } else { b = 0; } } strip.setPixelColor(i, strip.Color(r, g, b)); if (i >= anzahl) { strip.setPixelColor((i - anzahl), 0); } printRGB(i, 0, r, g, b); strip.show(); delay(wait); } } //Farblich das gleiche wie oben, //aber jetzt werden die LEDs von aussen nach innen eingeschaltet void getHot(int wait) { int i = 0; int j = 0; int r = 0; int g = 0; int b = 127; int difference = 26; for (i=0; i < 5; i++) { strip.setPixelColor(i, strip.Color(r, g, b)); j = strip.numPixels() - 1 - i; strip.setPixelColor(j, strip.Color(r, g, b)); strip.show(); r = constrain(r + difference, 0, 127); b = constrain(b - difference, 0, 127); printRGB(i, j, r, g, b); delay(wait); } for (i=5; i < 10; i++) { strip.setPixelColor(i, strip.Color(r, g, b)); j = strip.numPixels() - 1 - i; strip.setPixelColor(j, strip.Color(r, g, b)); strip.show(); //r = constrain(r - 32, 0, 127); g = constrain(g + difference, 0, 127); printRGB(i, j, r, g, b); delay(wait); } for (i=10; i < 16; i++) { strip.setPixelColor(i, strip.Color(r, g, b)); j = strip.numPixels() - 1 - i; strip.setPixelColor(j, strip.Color(r, g, b)); strip.show(); b = constrain(b + difference, 0, 127); printRGB(i, j, r, g, b); delay(wait); } strip.show(); } //Hilfsfunktion zum Ausschalten aller LEDs zwischen 2 Mustern void allOut() { int i = 0; for(i=0; i<strip.numPixels(); i++) strip.setPixelColor(i, 0); delay(1000); }
Mit der folgenden kleinen Ergänzung (Paramter backwards und lokale Variable pos) kann man für die Methode im Beispielcode von „strandtest“ die Laufrichtung umdrehen:
//überladene Methode, damit die alte Schnittstelle noch gültig ist void colorWipe(uint32_t c, uint8_t wait) { colorWipe(c, wait, false); } // Fill the dots progressively along the strip. // Der Parameter backwards ermöglicht, // dass die LEDs in beide Richtungen laufen void colorWipe(uint32_t c, uint8_t wait, boolean backwards) { int i; int pos; //pos ersetzt i für beidseitige Lauflichter for (i=0; i < strip.numPixels(); i++) { //in welche Richtung laufen die Lichter if (backwards) { pos = strip.numPixels() - i - 1; } else { pos = i; } strip.setPixelColor(pos, c); strip.show(); delay(wait); } }
Und der Aufruf dazu im Loop:
void loop() { colorWipe(strip.Color(127, 0, 0), 50); // Red //dank überladener Methode benötigt nur jeder 2. Aufruf den 3. Parameter colorWipe(strip.Color( 0, 127, 0), 50, true); // Green colorWipe(strip.Color( 0, 0, 127), 50); // Blue colorWipe(strip.Color( 127, 127, 0), 50, true); // Yellow }
In einem späteren Beitrag habe ich übrigens beschrieben, wie man den Code ergänzen kann, wenn man mit einem Potentiometer zwischen verschiedenen Farbprogrammen wechseln möchte.
Demo
Weiter oben habe ich behauptet, die Stromversorgung sei in diesem Projekt die Herausforderung. Das war allerdings, bevor ich versucht habe, den LED-Strip in voller Aktion aufzunehmen. Mein Samsung Galaxy SII, auf das sonst immer Verlass ist, produzierte völlig überstrahlte Bilder. Und meine digitale Spiegelreflex, die ich nach ein paar unbrauchbaren Handy-Versuchen zu Hilfe nahm, produzierte ein etwas besseres Video, dafür aber in einem unmöglichen Format.