Der lange Weg zur eigenen RGB-LED-Ansteuerung, Teil 4

Wie zu sehen war kann ein Arduino mit etwas Beschaltung schon etwas an LEDs antreiben. Bis zu LED-RGB-Strips mit 500 – 800 mA pro Farbe fehlt zwar noch etwas an Leistung, aber die Richtung ist schon mal korrekt. Also kommt langsam die Frage des Farbmischens und damit des Dimmens auf. Das kann man relativ einfach halt mit Pulsweitenmodulation (bzw. Pulse Width Modulation / PWM) machen, wobei man die LEDs halt nur eine bestimmte Zeit an- und eine andere Zeit ausschaltet. Zum simplen Überprüfen dieser Theorie schaltet der folgende Code das Signal am Pin 13 an und aus:

int pinId = 13;

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(pinId, OUTPUT);

  // initialize serial:
  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {
  for(float i = 1; i < 100; i+=0.1) {
    Serial.println(i);
    digitalWrite(pinId, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay((int)(100/i));         // wait for some time
    digitalWrite(pinId, LOW);    // turn the LED off by making the voltage LOW
    delay((int)(100/(101-i)));   // wait for some time
  }
  for(float i = 100; i > 1; i-=0.1) {
    Serial.println(i);
    digitalWrite(pinId, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay((int)(100/i));         // wait for some time
    digitalWrite(pinId, LOW);    // turn the LED off by making the voltage LOW
    delay((int)(100/(101-i)));   // wait for some time
  }
}

In der setup()-Funktion wird der Pin 13 als Ausgabe geschaltet, dazu noch die serielle Konsole gestartet, damit man auf dem PC mit lesen kann, bei welchem Wert der Arduino gerade ist.
In der Schleife loop() wird dann in sehr simpler Manier das Tastverhältnis gewechselt. Zunächst wird der Pin angeschaltet, und eine relativ lange Zeit (100 Millisekunden) gewartet, bis das Ausschalten kommt, dann wird sehr kurz (1 Millisekunde) gewartet. Da i nur in 0.1er Schritten erhöht wird, wird das Verhältnis von AN nach AUS langsam runter gedreht, bis der Pin schließlich 1 Millisekunde auf AN, und 100 Millisekunden auf AUS steht. Danach wird das dann umgedreht.
Damit werden die angeschlossenen LEDs langsam von fast 100% auf fast 0% und dann wieder auf fast 100% gedimmt.

Das ist schon ganz nett, allerdings ist mir danach aufgefallen, dass der Arduino (bzw. der Atmel-Mikroprozessor) auch Pins hat, die auf dem Board mit „DIGITAL (PWM~)“ markiert sind. Somit sind die Pins 3,5,6,9,10,11 und 13 von Hause aus schon PWM-fähig. Damit kann das Timing des Tastgrads von der Hardware übernommen werden, und ich muss mich damit gar nicht so genau beschäftigen.

Dieser Code dimmt verschiedene Farben von aus nach an und wieder aus. An Pin 9 habe ich da rote, an Pin 10 grüne und an Pin 11 blaue LEDs.

int pinRed = 9;         // Pin 9 is a PWM-'analog'-pin
int pinGreen = 10;      // Pin 10 is a PWM-'analog'-pin
int pinBlue = 11;       // Pin 11 is a PWM-'analog'-pin
int minValue = 0;
int maxValue = 255;
int delayValue = 10;

void setup() {
  // initialize the pins as an output.
  pinMode(pinGreen, OUTPUT);
  pinMode(pinBlue, OUTPUT);
  pinMode(pinRed, OUTPUT);
  analogWrite(pinRed, minValue);
  analogWrite(pinGreen, maxValue);
  analogWrite(pinBlue, minValue);
}

// Fades the PWM output of a pin from the minimum to the maximum
void slowlySwitchOn (int pinId) {
  for(int i = minValue; i <= maxValue; i++) {
    Serial.println(i);
    analogWrite(pinId, i);
    delay(delayValue);
  }  
}

// Fades the PWM output of a pin from the maximum to the minimum
void slowlySwitchOff (int pinId) {
  for(int i = maxValue; i >= minValue; i--) {
    Serial.println(i);
    analogWrite(pinId, i);
    delay(delayValue);
  }
}

// the loop function runs over and over again forever
void loop() {
  // Slowly switch on Green
  slowlySwitchOn(pinGreen);
  
  delay(delayValue * 50);

  // Slowly switch off Green
  slowlySwitchOff(pinGreen);

  delay(delayValue * 50);

  // Slowly switch on Blue  
  slowlySwitchOn(pinBlue);
  
  delay(delayValue * 50);

  // Slowly switch off Blue
  slowlySwitchOff(pinBlue);

  delay(delayValue * 50);

  // Slowly switch on Red  
  slowlySwitchOn(pinRed);
  
  delay(delayValue * 50);
  
  // Slowly switch off Red
  slowlySwitchOff(pinRed);

  delay(delayValue * 50);
}

Ebenso kann man die Farben langsam von einfarbig zu ‚weiß‘ gemischt faden lassen. Der wichtigste Unterschied zum Code davor ist natürlich nicht die Tatsache, dass ich da 3 unterschiedliche Pins und Farben steuer, sondern dass statt digitalWrite(pinId,HIGH|LOW) ein ‚analoger‘ Wert auf die Pins gegeben wird: analogWrite(pinId, value).

Was besonders in diesen beiden Beispielen sichtbar ist, ist der Fakt, dass lineares Dimmen für das menschliche Auge nicht linear ist. Insbesondere wenn es dunkler wird, sieht das Auge zwischen 2 Stufen einen viel größeren Unterschied, als in den helleren Zeiten. Das widerspricht natürlich meinem Wunsch, dass alles langsam und unauffälig passieren soll. Aber dazu dann später. Außerdem müssen die PWM-Signale auch noch an etwas mehr Strom übergeben werden.

Der lange Weg zur eigenen RGB-LED-Ansteuerung, Teil 3

Aufgebaut auf einem Breadboard (bzw. Steckplatine) sieht die Schaltung natürlich ganz anders aus. Für R1 musste ich 2 220 Ω-Widerstände in Reihe schalten (etwa 440 Ω, es sind 5%-Toleranz-Widerstände), ich hatte nichts passenderes, und das ist nah an den berechneten 480 Ω dran (Fehler von 8,3%…). Die LED (D1) ist eine orangene mit 1,8 Volt Vorwärtsspannung, womit dann auch R2 neu berechnet werden muss. Das sind in der Theorie (12 V – 1,8 V) / 0,02 A = 510 Ω. Auch hier wieder war nichts passendes dabei, also passen 220 Ω + 330 Ω = 550 Ω recht gut. Der Transistor ist wie schon erwähnt ein BC547C.

Eine LED ist aber recht lächerlich, insbesondere wo sich dann die Frage stellt, warum ein Transistor notwendig sein sollte. Ich habe hier 5 Module an superhellen (naja) weißen LEDs rum liegen, die nominal mit 12 V und 40 mA betrieben werden. Die Strombegrenzung ist in die Module eingebaut, somit sind dabei die Vorwiderstände nicht notwendig. 5 Stück parallel geschaltet ziehen in meinem Beispiel 154 mA, auch wenn es theoretisch 200 mA sein sollten.

Der lange Weg zur eigenen RGB-LED-Ansteuerung, Teil 2

Da der Arduino nicht allzuviel Last an seinen IO-Ports erlaubt, brauchen wir eine Entkopplung, bzw. Verstärkung. Für niedrige Lasten ist das einfach mit einem Transistor als Schaltstufe zu regeln. Ich habe jetzt gerade nach einfachen Erklärungen für diese Schaltung gesucht, aber das klingt alles zu kompliziert. Um die Schaltungszeichnungen zu verstehen, sollte man die Schaltsymbole kennen. Natürlich sind die international nicht genormt, aber meistens stimmen die schon.

In der ersten Version, wo der Controller (hier ein Arduino, kann aber genauso gut ein Raspberry Pi sein) die LED direkt antreibt, sieht das Schaltbild so aus:

Schaltbild Arduino mit LEDD1 ist hier einfach eine LED. Eine LED ist eine Diode, und eine Diode wiederum lässt Strom nur in eine Richtung durch. An der Seite, wo der Strich ist, oder auch: in der Richtung, in die das Dreieck zeigt, muss der Minuspol (bzw. auch Masse) liegen. Einen Transistor anzutreiben ist genauso einfach, wie eine LED. Sehr vereinfacht ausgedrück besteht ein Transistor aus 2 Dioden. So ersetzen wir die LED mit einem Transistor:

Arduino mit Transistorschalter 1

Betrachten wir dabei nur den fett markierten Bereich (und ignorieren erstmal den Widerstand R1), sieht das sehr ähnlich aus. Auch im Transistor ist ein Dreieck, das Richtung Masse zeigt. Der Arduino ist am Anschluss „B“ (für Basis) mit seinen 0 (aus) oder 3,3 (an) Volt angeschlossen, der Stromkreis wird dann dadurch geschlossen, dass der Emitter (Anschluss „E“) an der Masse angeschlossen ist.

 

Der Widerstand ist zum Schutz des Controllers und des Transistors sinnvoll. Wenn der Controller den Pin anschaltet, läuft (fast) ungehindert Strom zwischen dem Controller-Pin und der Masse. Der Widerstand ist zur Begrenzung dieses Stroms da.

Nach dem Ohmschen Gesetz ist der zu berechnen. In dieser Erklärung geht es um grobe Berechnungen, um es nicht unnötig kompliziert zu machen (für absolute Genauigkeit gibt es hier auch noch keinen Grund), ignoriere ich ein paar unbdeutende Parameter. Demnach ist U / I = R (U = Spannung in Volt, I = Strom in Ampere, R = Widerstand in Ohm). Die Spannung ist bekannt, das sind U=3,3 Volt, der maximal akzeptable Strom für den Arduino kennen wir auch, der ist I = 40 mA = 0,04 A. Danach ist der minimale Widerstand R = 3,3 V / 0,04 A = 82,5 Ohm. Aber, weniger Strom ist immer besser, also sagen wir mal 10 mA wären nett. Also ist der Widerstand R1 = 3,3 V / 0,01 A = 330 Ohm. Ähnliche Werte, wie z.B. 300 sind hier völlig okay. Wir betreiben den Transistor als Schalter, also an oder aus. Je mehr der Controller und der Transistor geschützt werden können, desto besser, aber ein wenig Strom braucht der Transistor doch noch. Sehr simpel zusammen gefasst: ein Widerstand da ist prima, wenn der zu groß wird, schaltet der Transistor nicht, aber je größer, desto besser.

Natürlich sieht man erstmal nichts, wenn wirklich nur der Transistor vom IO-Pin des Arduino angesteuert wird. Dafür aber ist dann der Rest der Schaltung zuständig. Wenn der Transistor vom Arduino Strom kriegt, schaltet er auf „an“. Dann ist (quasi) die LED direkt an die Stromquelle angeschlossen (wieder nur der fett markierte Bereich):

Arduino mit Transistorschalter 2Der Strom fließt dann – gesteuert durch die Basis – von der Stromversorgung über die LED D1 und den Widerstand R2 durch den Transistor über den Anschluss „C“ (Kollektor) aus dem Anschluss „E“ (Emitter) zurück zum Minus-Pol der Stromversorgung. Das bedeutet dann übrigens auch, dass man die Stromversorgung für die LED recht frei wählen kann. Insbesondere können mit den 3,3 V des Arduino LED-Module geschaltet werden, die 12 V benötigen.

Auch hier ist wieder ein Widerstand eingezeichnet. Nehmen wir mal an, die Stromversorgung würde bei 12 Volt arbeiten, und wir würden nur eine LED dran betreiben, dann müsste der Widerstand R2 den Strom über die LED begrenzen. Wieder kommt das Ohmsche Gesetz daher, leicht modifziert allerdings. Die Berechnung des Vorwiderstands einer LED erfolgt folgendermaßen (oder durch dieses verlinkte Script): R2 = (US – ULED) / ILED = (12 V – 4 V) / 0,02 A = 400 Ohm (US = 12 V der Stromversorgung, ULED = 4 Volt für weiße LEDs, ILED = 20mA – ist ein Wert, den eigentlich jede LED aushalten können sollte). Realistisch ist auch das wieder eine konservative Schätzung, da wegen des Transistors nicht wirklich 12 Volt von der Stromversorgung einzurechnen sind.

Damit kommen wir dann zu dem Gesamtschaltbild:

Arduino mit Transistorschalter 3Es bleiben noch ein paar Fragen:

  • sind 0,01 A über die Basis okay?
  • wieviele LEDs, bzw. wieviel Last kann betrieben werden?

Diese Fragen werden durch den Typ des Transistors beantwortet. Grundsätzlich ist die Last erstmal darüber begrenzt, welchen Strom der Transistor schalten kann. Ich habe einen BC547C genommen, weil der hier rum lag. Was die Spannungen angeht, liegen wir hier locker in vernünftigen Bereichen. Zwischen Kollektor und Emitter („C“ und „E“) dürfen bis zu 50 Volt liegen (im Beispiel sind es 12 V), zwischen Emitter und Base („E“ und „B“) dürfen 6 Volt liegen (im Beispiel sind es 3,3 V). IC (Strom über dem Kollektor, oder auch „Collector Current Continuous“) darf dauerhaft nicht höher als 100 mA sein, also 5 LEDs.

Die Verstärkung (DC Current Gain) liegt bei der C-Version bei 400. Das wären bei 0,01 A an der Basis also 4 A. Da der Transistor das aber nicht aushält, ist das offensichtlich zu viel (die 4 Ampere werden natürlich nur erreicht, wenn eine entsprechende Last anliegt…). Um bei einer 400fachen Verstärkung auf nur 100 mA zu kommen, sollte der Basisstrom also theoretisch 0,1 A / 400 = 0,00025 A = 0,25 mA sein. Da wir den Transistor aber zum Schalten gerne in vollem Sättigungsbetrieb haben, wird die Basis eigentlich übersteuert (steht unter „Base Emitter Saturation Voltage“) mit 5 mA. Der Maximalstrom über die Basis liegt weit höher, aber wenn wir den Widerstand vor der Basis mit 5 mA berechnen, sind wir auf einem guten Wert. Um den genau zu berechnen nehmen wir jetzt U = UArduino – VBE (sat) = 3,3 V – 0,9 V = 2,4 V. Also R1 = U / I = 2,4 V / 0,005 A = 480 Ohm. Aber alles zwischen 330 Ohm (wie oben behauptet) und 480 Ohm (und auch jeweils ein wenig drüber hinaus) ist an dieser Stelle absolut okay. Wird der Widerstand zu hoch, kommt nicht die ganze Leistung an den LEDs an, wird er zu niedrig, kann der Transistor durchbrennen. Für Experimente ist da genügend Platz, insbesondere, wo diese Transistoren ein paar Cents kosten.

Der lange Weg zur eigenen RGB-LED-Ansteuerung, Teil 1

Wahrscheinlich ist das meiste, was ich lösen möchte und muss, um meine persönliche Ansteuerung für RGB-LED-Strips zu bekommen, schon kompakt irgendwo zusammen gefasst. Ebenso wahrscheinlich gibt es schon alles fertig zu kaufen, ich vermute aber, dass mir dann der Preis nicht gefallen würde. Außerdem: warum einfach, wenn es auch kompliziert geht.

Ich habe ein wenig Grundahnung von elektronischen Schaltungen, aber das war es auch schon. Im Zuge meiner Beleuchtungswünsche kam und kommt einiges hinzu, und wenn jemand von meinen Erfahrungen profitieren kann, dann würde mich das freuen.

Arduino Leonardo

Netterweise hat mir mein Haus- und Hofelektroniker zu Weihnachten einen Arduino Leonardo geschenkt, der für die ersten Versuche hier gute Dienste leisten kann. Bei der Entwicklungsumgebung ist direkt ein Beispiel, das die LED blinken lässt:

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

Pin 13 wurde deshalb gewählt, weil der nicht nur direkt neben GND (Ground, bzw. Masse) liegt, und die LED einfach in die Buchsen gesteckt werden kann, sondern auch, weil die LED „L“ auf dem Board damit parallel geschaltet ist.

Arduino Leonardo with green LED

Der Arduino kann eine LED direkt antreiben. Die Pins liefern 3,3 Volt und 40 mA. Für erste Versuche sehr nett, aber ein wenig viel für eine LED. Außerdem sollten die Ausgänge natürlich nicht über Gebühr belastet werden.