Wie gut sind COB-LEDs?

Chip on Board-LED-Module – mittlerweile in Flutern sehr weit verbreitet und sehr günstig zu beschaffen.

Da ich bei einer Aufräumaktion eine Schreibtischleuchte (noch mit Leuchtstofflampen und fehlendem Treiber) ergattern konnte war der erste Gedanke: Umrüsten auf LED.

Im Asiamarkt (ok, eBay) gab es 4 Module – 2x warmweiß und 2x kaltweiß – für nicht ganz 6 Euro bei nicht einmal 2 Wochen Versand:

Leider sind Module mit 2700 K Farbtemperatur eher selten, also ca. 3250 K und 6250 K. Aber warum überhaupt verschiedene Werte? Kaltweiß ist besser, um Farben neutral zu sehen, warmweiß ist angenehmer für’s Auge. Allerdings muss man dazu sagen: es ist nur die halbe Wahrheit. Ein wichtiger ist der CRI. Echte weiße LEDs gibt es nicht, es handelt sich in aller Regel um blauen LEDs, die bestimmte Farbstoffe anregen und je nach Material ist das Spektrum und damit die Farbwiedergabe unterschiedlich – aber das nur am Rande.

Um die Spannung und Ströme der Streifen gering zu halten, sind die LEDs in mehrere Stränge, meist mit der Länge 3 angeordnet. Bei einer Flussspannung von 3,2 Volt sind das 9,6 Volt, mit einem Vorwiderstand haben die meisten Streifen eine Betriebsspannung von 12 Volt. Das ist bei den meisten COBs meist nicht der Fall. 4 LEDs in Reihe, mehrere dieser Stränge parallel und fertig. Durch Fertigungstoleranzen schwanken die Vorwärtsspannungen ein bisschen, das kann man im Griff haben aber das kostet natürlich. Bei einigen hundert LEDs für 6 Euro: never ever.

Aber wie schlecht sind sie wirklich? Der Test funktioniert relativ einfach: LED an eine Spannungsquelle anschließen und die Spannung so weit erhöhen, bis sie leicht zu glimmen anfangen – bei den gekauften Exemplaren war das bei 9 Volt:

Montage von 4 Fotos bei gleicher Belichtungszeit

Die Belichtung wurde so eingestellt, dass möglichst keine Übersteuerung der Farbkanäle stattfindet, hat auch fast geklappt.

Man sieht gewisse Ungleichmäßigkeiten, not too bad, not too good either. Richtiges Binning hat auf keinen Fall stattgefunden.

Die Leuchtpunkte der unteren LED wurden ausgeschnitten, ausgerichtet und durch ein kleines Python-Script (mit pillow statt pil) gejagt:

from PIL import Image
im = Image.open('P1120207.png', 'r')
width, height = im.size
pixel_values = list(im.getdata())

y = 8

for x in range(0, width):
px = pixel_values[width*y+x]
print(str(px[0]) + "\t" + str(px[1]) + "\t" + str(px[2]))

Das Script spuckt die RGB-Werte der 8. Zeile aus. Auch wenn der blaue Farbkanal am ehesten heraussticht, ist es besser den grünen zu verwenden – weniger Clipping und durch Chroma-Subsampling (besser kein JPEG verwenden) und des Bayer-Pattern ist grün einfach besser ;).

Aus Excel kam dann folgendes Diagramm:

Mit ein bisschen Phantasie erkennt man die Stranglänge. Die Aussagekraft des Diagramms ist zugegebenermaßen etwas eingeschränkt: Es ist kein kalibriertes System sondern eher ein Schätzeisen aber es reicht für einen groben Vergleich: Es gibt einen ausreißenden Strang (nach oben) und einige LED-Chips in den Stränge, die deutlich darunter liegen. Grundlegend ist die Bewertung mit dem Diagramm aber etwas besser möglich als durch das Ansehen der Bilder, da der Faktor subjektive Wahrnehmung verringert wird und Nuancen in Helligkeitsunterschieden besser erkennbar sind.

Mal sehen, wie sich die Streifen dann im tatsächlichen Einsatz machen…

Was der MCP2221 sonst noch kann

Es gibt Dinge, die Zeit verschwenden, nicht richtig funktionieren und schlussendlich nicht einmal einen Sinn ergeben. Manche nennen das sogar Hobby.

Nachdem mir im Zuge der MCP-USB-Bridges keine Python-Implementierung so richtig gefallen habe, bin ich gerade dabei, selbst eine zu schreiben und mehr oder weniger ausgiebig zu testen.

GPIOs, ADC funktionieren so wie es aussieht genz gut, heute war der DAC dran.
So richtig toll ist er nicht, aber besser als nichts. Um Seine Leidensfähigkeit zu zeigen, musste ein kleines Beispiel her.

Warum nicht einfach so etwas ähnliches wie einen Hellschreiber implementieren? Nur halt extrem ranzig.

In Python geht das ordentlich schnell und einfach:

txt = "Hallo Welt!"

vals = [22,20,18,16,14,12,10,8]

meh = []
for c in txt:
    meh.extend(font[ord(c)-32])
    meh += [0]

for col in meh:
    for reps in range(4):
        curcol = col
        for y in range(8):
            if curcol & 1 == 1:
                dev.dac_setvalue(vals[y])
            else:
                dev.dac_setvalue(0)
            curcol >>= 1
            time.sleep(0.003)

Die Font liegt in als Liste vor, die alle wichtigen Zeichen ab dem Leerzeichen enthält. Vals beinhaltet die Analogwerte der jeweiligen Bits der Zeichen (in der Höhe). Der Text wird sprichwörtlich in eine Bitmap umgewandelt und einfach über den DAC rausgejagt. Damit die Zeichen etwas besser lesbar sind, werden sie 4 mal wiederholt. Die kurze Pause ist nötig, weil sich sonst der MCP verhaspelt.


Ist das nun Kunst oder kann das weg? 😉

Die meisten Daten haben überlebt

Noch ein kleines Update zum letzten Beitrag: Nach vielen On-Off-Zyklen der Festplatte war ddrescue bei 100 % aber doch nicht fertig.

ddrescueview zeigte folgendes:

416,24 GB wiederhergestellt, aber knapp 84 fehlen noch. Hm, das ist ungewöhnlich schlechte Ausbeute, vor allem weil so große Blöcke fehlen. Da muss ich etwas falsch gemacht haben.

Ich höre schon meine alte Ausbildungskollegin schreien „manpage, MANPAGE!!!“

ddrescue läuft mit den Parametern (Reihenfolge zu Dramaturgiezwecken geändert)

-f -r10 -v -n

-f: force overwrite of outfile, braucht man, wenn auf eine Partition geschrieben wird
-r10: Exit after the given number of retry passes
-v: Verbose mode
-n: Skip the scraping phase

Vielleicht sollte ich das letzte weglassen 😉

Gesagt, getan – und ddrescue läuft weiter. Im Schleichmodus werden die restlichen Daten zusammengekratzt. Um diese Schleichfahrt nicht zu blockieren, habe ich den Knockout meines Scripts auf 2 Stunden gesetzt. Nach ein paar weiteren Tagen sieht es wie folgt aus:

Das würde ich als Erfolg bezeichnen. Mit dem Hintergrund, dass die erste Partition der Platte eine versteckte EFI-Partition mit 200 MB ist, sollten die Userdaten vollständig lesbar sein.

Das Volume ließ sich dann auch wieder mounten. Um auf Nummer sicher zu gehen, habe ich aber trotzdem noch ein Image der Partition gezogen.

dd if=/dev/sdxy of=/media/foo/bar/image.bin bs=64K

macht den Job. Wichtig ist, die Blocksize anzugeben, da sonst gefühlt Byteweise kopiert wird und so der Durchsatz unterirdisch ist – ohne Parameter dümpelte der Kopiervorgang von USB 2.0 nach USB 2.0 mit 4 MB/s herum, mit 64K bei 38 MB/s. Mehr geht über die Schnittstelle fast nicht.

ddrescue. aggressiv.

„Nein“ wäre die richtige Antwort gewesen. „Nein“ zur Frage, ob ich eine Festplatte wiederherstellen kann, die vor meinen Augen nochmal fallen gelassen wurde.

„Macht der das was?“

JA, verdammt nochmal – Festplatten (also „klassische“ mit Magnetscheiben) sind mechanisch empfindliche Komponenten.

Naja. Eine zweite Platte für die Wiederherstellung hat er immerhin schon besorgt, also versuche ich mein Glück. Also ein Live-Linux in das olle Thinkpad geworfen und ddrescue gestartet.

Quelle: 500 GB 2,5 Zoll Western Digital Blue, Ziel: 1 TB 2,5 Zoll Seagate.

Zunächst ging es auch ordentlich schnell und ich dachte, der begrenzende Faktor wäre das USB 2.0 am Rechner. Doch auch mit der extra georderten USB 3.0 Expresscard ging es nach ein paar Klimmzügen (zusätzliche Versorgung der Festplatten) nicht wirklich schneller.

Nach den ersten paar Gigabyte sackte die Leserate aber auf mehrere 100 kByte/s ab. Nicht so schlimm, wäre da nicht folgendes Geräusch:

(das nach 10 Sekunden)

Wäre da nur das Geräusch, könnte man vielleicht noch damit leben, aber ddrescue macht nur noch eines: Fehler für Runde zwei melden. Das bringt einen nicht weiter. Also Platte weg und wieder ran. Die ersten paar Stunden mache ich das noch manuell, dementsprechend haben sich knapp 100 GByte Lesefehler und ein wenig Frustration angesammelt. Grmpf. Dabei fiel auf, dass die ersten 30 Sekunden die Übertragungsrate mit 15-30 MByte/s noch relativ hoch war, danach sank sie schlagartig ab und schwankte zwischen 65 und 300 kByte/s.

In einer Woche (Abends, musste in der Nähe sein) kamen so etwa 90 GByte von Platte A auf Platte B. 150 GByte wurden als nicht lesbar markiert.

Um nicht dauernd den USB-Stecker ein- und ausstecken zu müssen, habe kam eines meiner Schubladen-Projekte zum Einsatz, der (verbuggte) USB-Switch. Mit einem Mit einem TS3USB221 (sehr klein und bescheiden zu löten) und einem IRLML2244 lässt sich das angeschlossene Device mit dem PC verbinden und trennen. Die Verbindungsfolgen werden erwartungsgemäß nicht eingehalten und durch einen Denkfehler und zu wenig Koffein schaltete die aktuelle Version entweder die Versorgung oder USB durch. Fädeldraht hat es zumindest vorübergehend gerichtet. Mit einem Schalter ausgestattet bleiben nun die Stecker heile.

Aber zurück zur Datenrettung. Zwei Gedanken: Die Platte alle 30 Sekunden pauschal zu trennen erhöht zwar die Datenrate, aber auch die elektromechanischen Zyklen, was der Lebensdauer nicht wirklich zuträglich ist. Gleichzeitig kommt die Platte nach einem Aussetzer nicht mehr hoch. Sie muss neu gestartet werden. Das kann man überwachen, indem man die Größe der Logfile von ddrescue prüft. Wächst diese stark an, ist etwas im faul. Ferner beendet sich ddrescue automatisch, wenn die Platte sich komplett abwirft.

So viel zum Wissen, aber wie kommt diese Information zum USB-Switch? Am einfachsten wäre es ja, den USB-Port selbst aus- und wieder einzuschalten. Geht in manchen Systemen, aber eine mittelkurze Recherche zeigte: die Erfolgschancen sind eher gering.

Also doch irgendwie anders. Hm. Der Laptop ist zu jung für den Parallelport, einen Microcontroller dafür zu programmieren ist mir ehrlich gesagt auch zu blöd. Hm, DTR und RTS lassen sich doch üblicherweise durch Software schalten und einen USB<>UART-Wandler, bei dem zumindest RTS herausgeführt ist, liegt auch herum.

Unter Linux ist doch alles eine Datei, also sollte es doch ein Leichtes sein, das Flag zu setzen. Leider nicht ganz. ioctl macht zwar genau das, aber es ist nicht persistent. Sobald das Programm sich beendet, wird der Port geschlossen und RTS/DTR ist wieder low. über stty schafft man es zwar auch irgendwie, aber mein Shell-Script begann eh anfangen, ziemlich übel zu stinken.

Nachdem desinfec’t mit Python kommt – warum nicht damit? Mit pyserial kann ich zumindest unter Windows schon einmal alles machen, unter Linux klappt es auch auf Anhieb.

Mittlerweile sieht das Setup so aus:

Die Platte liegt (ich weiß, nicht ganz ideal) auf einer Schütte, der Lüfter hält sie kühl. Am Notebook hängt der USB-Stick mit Scripts und Log (wichtig, da im Notebook kein persistenter Speicher ist), daneben der USB-Switch, der mit dem RTS des USB<>UART-Wandler verbunden ist.

Das Python-Script macht aktuell folgendes:

Verbinden der Platte und warten, bis /dev/sdx (also die Platte) existiert. ddrescue mit den entsprechenden Parametern als subprocess starten. Während es läuft, also .poll() des Prozesses keinen Exitcode ausweist. Weiter wird geprüft ob die Logdatei anschwillt. Dank Caching ist das leider nicht ganz so zielführend, aber immerhin. Das dritte Kriterium ist die Laufzeit. Ist die Datenrettung länger als 10 Minuten aktiv, naja – ich bin nicht stolz drauf. Tritt eine der drei Bedingungen ein, wird die Platte getrennt und gewartet (falls nicht schon passiert), bis ddrescue fertig mit dem Schreiben der Logdatei ist. Nach einer weiteren Wartezeit geht das Spiel von vorne los:

rescue.zip (weil WordPress mir Python-Scripts verbietet)

Für Schäden, die das Script verursachen kann, übernehme ich keine Haftung.

In nicht ganz 24 Stunden sind so nun weitere 130 GByte in Richtung Ersatzplatte gewandert. „Nur“ 35 weitere Gbyte wurden als defekt markiert.

Ob die Aktion erfolgreich gewesen sein wird, kann ich erst in knapp 280 GByte sagen und hoffe, dass auch so viel davon gelesen werden kann.

Abschließend kann ich nur mal wieder sagen: Kein Backup? Kein Mitleid!