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.

CnMemory – USB 3.0 – SATA – Gehäuse: Spaceloop

Bei Pollin gibt es von CnMemory ein Metallgehäuse mit USB 3.0 <-> SATA Interface für 7.95 €. Ich hatte ein paar bestellt, in der Hoffnung, damit aus meinem Raspberry Pi ein NAS zu machen. Bei einer 100MBit-Anbindung des Pis ist natürlich nicht viel Geschwindigkeit zu wollen, das war daher auch nicht der Grund für diesen Kauf. Wie immer möchte ich eigentlich keinen Strom verbauchen, wenn Geräte nicht gebraucht werden, daher sollte die externe Platte auch möglichst immer im Schlafmodus sein. Mein bisheriges USB-Festplatten-Gehäuse verstand den Schlafparameter von hdparm nicht, „hdparm -S 60“ wurde nur mit einer Fehlermeldung quittiert.

Deshalb habe ich es mit diesem Interface probiert, einzige Erwartung war, dass die Schlafeinstellung durchgeleitet wird. Und: ich bin mehr als zufrieden. Ja, Schlafen bei Nicht-benutzung funktioniert. Aber mehr noch: das alte Gehäuse machte an der USB-Schnittstelle maximal 21 MByte/s, das von CnMemory immerhin 27 MByte/s (direkt vom Raspberry Pi). Die Netzwerkübertragung stieg von max. 5,5 MBytes/s auf 7.8 MByte/s (mittels Samba).

An meinem Desktop, mit USB-3.0-Schnittstellen, ist quasi kein Unterschied zwischen dem On-Board-SATA-Controller und der externen Festplatte zu sehen. Rohe Geschwindigkeitstests zeigen bis zu 180 MByte/s, Kopieren über Windows liegt bei recht konstanten 130 MByte/s.

Einziger Nachteil ist die Wärmeableitung. Auch wenn das Gehäuse aus Metall besteht, existiert keine direkte Wärmekopplung zwischen Festplatte und Gehäuse. Abstandshalter sind alle aus Plastik. Das ist zwar besser als ein reines Plastikghäuse – so kann wenigstens die Luft über das Metallgehäuse besser gekühlt werden – aber eine direkte metallische Verbindung zwischen Platte und Gehäuse wäre schon besser.

Wie dem auch sei, ich bin sehr zufrieden, insbesondere auch mit dem Preis, alleine das 12 Volt Netzteil kostet einzeln fast soviel.

 

Update 2015-06-08: Neue Revision 1.1 reagiert etwas seltsam.

Brother HL-1110 Treiber unter Linux/CUPS/Raspian

Da einer meiner Raspberry-Pis anderer Aufgaben wegen im Dauerbetrieb arbeitet, wollte ich ihn auch als Drucker-Spooler nutzen. Einer meiner Drucker ist ein Brother HL-1110, und wie alles, was ich betreibe, soll der nur dann angeschaltet sein, wenn er wirklich benötigt wird, außerdem soll er im gesamten Netzwerk verfügbar sein.

Um den Drucker per CUPS anzusprechen, muss natürlich erstmal CUPS installiert werden. Ich gehe mal davon aus, dass das schon geschehen ist. Um den Brother-Drcker darüberzu nutzen, muss aber auch ein entsprechender Treiber vorhanden sein. Von der Brother-Support-Seite sind DEB- und RPM-Pakete vorhanden, aber keins, dass direkt auf Raspian funktioniert. Aber es gibt die gute Nachricht, dass der Quell-Code verfügbar ist. Und letztlich braucht es für CUPS nur einen kleinen Teil davon.

Ausgepackt gibt es PPD/brother-HL1110-cups-en.ppd, was man CUPS beim Einrichten eines neuen Druckers direkt als File-Upload geben kann. Zusätzlich braucht es noch filter/brother_lpdwrapper_HL1110, das kopiert man auf dem Ziel-System nach /usr/lib/cups/filter kopiert.

Danach ist der HL-1110 über CUPS für jeden Rechner im Netzwerk verfügbar (je nach Sicherheitseinstellungen, natürlich). Vor allem aber kann ich erst den Druckbefehl abschicken, un später den Drucker anmachen.

 

Update 2017-06-25

Da fehlen wohl ein paar Informationen.

Meine Prämisse: ich drucke von Windows aus auf einen Netzwerkdrucker; die Treiber für den Drucker sind unter Windows installiert.

Wird auf den Drucker etwas ausgegeben, hängt offensichtlich die Verarbeitung davon ab, welcher Datentyp geliefert wird. Wird von Linux aus – z.B. die Testseite von der CUPS-Administration – gedruckt, ist der Datentyp „application/vnd.cups-postscript“. Für den wird brother_lpdwrapper_HL1110 als Treiber genommen (definiert in der PPD). CUPS testet, ob diese Datei vorhanden ist, meldet sonst aber einen Fehler.

Wird hingegen von Windows mit den GDI-Treibern gedruckt, ist der Datentyp „application/vnd.cups-raw“, für den kein Filter definiert ist, da er auch nicht benötigt wird. Der Drucker versteht die erzeugte Datei direkt.

Somit ist CUPS hier nur mit der Verwaltung beschäftigt.

Um den Drucker unter Windows zu installieren, kann man den Druckertreiber von Brother runterladen, tatsächlich den Drucker über USB anschließen (das dämliche Installationsprogramm geht davon aus, dass nur lokaler Druck möglich ist…), den Drucker wieder abziehen und an den Raspberry Pi anschließen.
Oder man entpackt das Paket (z.B. Download für Windows 10 64bit) mit 7zip, dann erhält man unter install\driver\gdi\32_64 die Treiber, die man beim Einrichten des Netzwerkdruckers braucht. Dann entfällt das physische Anschließen.

Mit dem „Source“-Paket, das Brother da anbietet kann kein voll funktionierender Druckertreiber gebaut werden. Da fehlen sehr viele Dateien, insbesonder der Source für rawtobr3, ansonsten könnte man sich alles noch aus den verschiedenen RPM- und DEB-Paketen zusammen suchen.

Raspberry Pi Verkauf über Farnell und RS

… leider liefern beide zumindest in Deutschland nur an Firmenkunden. Da ist wohl etwas nicht ganz so gelaufen, wie sich auch die Raspberry Pi Foundation das gedacht hat.
Mal ganz davon abgesehen, dass heute morgen ab 7:00h die Server dieser beiden Firmen hoffnungslos überlastet waren.

Den Tweets nach zu urteilen waren die Bestände bei Farnell schon gegen halb acht ausverkauft, den Status von RS kann keiner wirklich beurteilen, weil bei denen nur eine Registrierung für Interessensbekundungen zu finden ist, wenn man nach Raspberry Pi sucht.

Aber zumindest für deutsche Privatinteressenten scheint es ja eh uninteressant, ohne Umsatzsteuer-ID-Nummer keine Verkäufe.

Raspberry Pi und die Mirrors

Ich habe meine Resourcen für Raspberry Pi zur Verfügung gestellt, auch hier ist ein Mirror der Files verfügbar. Eigentlich sogar 2, ein weiterer liegt noch auf meiner JiffyBox. Jetzt am Donnerstag sollen ja die Tests der ersten Charge über die Bühne sein.

Leider steht vor dem Erfolg der Schweiß, oder so ähnlich. Aus diesem Grund konnte das mit dem Mirror auch nicht ‚einfach so‘ klappen. Zum einen wollte ich auf meinem virtuellen Server keinen FTP-Zugang einrichten und zum andern lässt der Tarif, den ich hier für meine Webseiten gebucht habe, Directory listing nicht zu. Ich wollte auch nicht unnötig viel Arbeit für die R-Pi-Leute machen, also musste mal eben eine eigene Lösung her. Bestimmt gibt’s dafür eine Lösung auch fertig irgendwo her, aber wo ist dann der Spaß?

Also die Aufgabenstellung: synchronisiere 2 Server mit einem 3. Server und erzeuge ein Directory Listing ohne das Apache-Modul. Meine Lösung sieht vor:

  1. rsync vom raspberry-pi Server auf meinen virtuellen Server
  2. index.html erstellen für jedes Verzeichnis, mit Auflistung aller Unterverzeichnisse und Dateien
  3. Alle Dateien (inklusive der erstellten index.html) vom virtuellen Server auf den Webhosting-Server synchronisieren.

Ist alles ja gar nicht so schwer. Zu 1. wird auf dem virtuellen Server rsync ausgeführt:

rsync -azPv rsync://rsync-source/ /var/www/mirror/

Ich weiß jetzt nicht so wirklich, ob die Leute von Raspberry Pi es so gut fänden, wenn ich die Serveradresse verrate, deshalb lasse ich die hier mal weg.

Zu 2. habe ich dann ein PHP-Skript geschrieben, dass rekursiv durch die Verzeichnisse geht und entsprechende Dateien schreibt. Ja, es ist Quick & Dirty…:

<?php
function createIndex($folderName,$displayRoot) {
    $output = "<html><head><title>$folderName</title></head><body><h1>Index of $displayRoot</h1><table>";
    $i=0;
    $allEntries = null;
    $currHandle = opendir($folderName);
    if ($currHandle !== FALSE) {
        $currEntry = readdir($currHandle);
        while ($currEntry !== FALSE) {
            $allEntries[$i++] = $currEntry;
            $currEntry = readdir($currHandle);
        }
        sort($allEntries);
        foreach ($allEntries as $currEntry) {
            $procThis = $folderName . '/' . $currEntry;
            if (is_dir($procThis)) {
                if ($currEntry != '.' && $currEntry != '..') {
                    createIndex($procThis, $displayRoot . '/' . $currEntry);
                }
                $fsize = 0;
            }
            else {
                $fsize = filesize ($procThis);
            }
            if ($currEntry != '.' && $currEntry != 'index.html') {
                $output .= "\n<tr><td><a href=\"$currEntry\">$currEntry</a></td>";
                if ($fsize > 0) {
                    $output .= '<td>' . $fsize . ' bytes</td><td>' . date ("Y-m-d H:i:s.", filemtime($procThis)) . '</td>';
                }
                else {
                    $output .= '<td></td><td></td>';
                }
            }
            $output .= '</tr>';
        }
    }
    $output .="</table></body></html>";
    $handle = fopen($folderName . '/index.html','w');
    fwrite($handle,$output);
    fflush($handle);
    fclose($handle);
}
createIndex("/var/www/mirror", "/mirror");
?>

Das ganze Verzeichnis wird dann zu 3. per lftp mit dem Webhosting-Server synchronisiert:

open ftp://user:password@ftp.loco-toys.de
mirror -R -v --only-newer /var/www/mirror/ /

Diese 2 Zeilen in eine Datei geschrieben (z.B. synch.lftp) und der Aufruf erfolgt dann mit

lftp -f synch.lftp

Diese 3 Schritte werden dann noch sinnvoll in der crontab eingetragen, und schon haben wir 2 weitere Mirrors für Raspberry Pi.

Bleibt nur noch zu hoffen, dass ich überhaupt einen der Dinger aus der ersten Charge bekomme, und dass meine Mirrors nicht so beliebt sind, dass mir die Domains geperrt werden.

Immer noch keine Raspberry-Pis

Wie im Forum von Raspberry-Pi zu lesen ist, ist der Verkaufstermin auf Ende Januar verschoben worden. Damit verpasse ich die 2. Gelegenheit, zu einem Geburtstag die Dinger in der Hand zu haben. Die ersten 10 Beta-Boards werden zwar bei ebay versteigert, aber so sehr ich den Laden auch unterstützen möchte, die limitierten Versionen mit Echtheitszertifikat kann ich mir nicht leisten.