Inzwischen habe ich nun endlich mal ein kleines Bastelprojekt fertigbekommen, an dem ich schon ne ganze Weile schraube. Es geht um ein Extreme Feedback Device für das Projekt, in dem ich jobmäßig gerade beschäftigt bin. In dem wird nämlich Jenkins als Continuous-Integration-Plattform eingesetzt, d.h. in regelmäßigen Abständen wird ein Software-Build automatisch ausgeführt und das Ergebnis dann getestet, wobei sich ein Status von grün (alles bestens) über gelb (Build ok, aber mindestens ein Test ist fehlgeschlagen) bis rot (Build-Fehler) ergibt. Den kann man dann im Webinterface des Jenkins sehen, was sehr praktisch ist, weil man so mit nur kurzer Verzögerung nach Code-Checkins darüber informiert wird, ob die eigenen Code-Änderungen gut mit denen anderer Entwickler harmonieren oder im Zusammenspiel mit diesen irgendetwas unerwarteterweise kaputt gegangen ist. Aber eigentlich ist das ziemlich langweilig, das immer nachzugucken, und die Mails, die das CI-System automatisch bei Problemen versendet, sind auch irgendwie nett, aber unspektakulär. Deswegen kam vor vielen Jahren mal jemand auf die geniale Idee, irgendwelche realen Gerätschaften so mit einem Rechner zu koppeln, dass sie den aktuellen Build-Zustand quasi "greifbar" in der realen Welt visualisieren - und DAS sind Extreme Feedback Devices, oder kurz XFDs.
Bevor es losgeht mit diesem doch eher länglichen Artikel zeige ich am besten zur "Motivation" mal gleich das Endergebnis :-)
Es ist eine Lava-Lampe! Eine Lava-Lampe mit Netzwerkanschluss!! Eine bunte Lava-Lampe mit Netzwerkanschluss, die ihre Farbe wechseln kann!!! Die Farben korrespondieren wie eben erklärt mit dem Zustand des zu überwachenden Builds - ist die Lampe also grün, ist alles bestens, wird sie gelb ist irgendwo mindestens ein Test fehlgeschlagen und wenn sie rot ist, ist die Kacke gewaltig am Dampfen!
Stellte sich heraus, dass es in der Tat sogar höchst passendes Rohmaterial dafür gibt. Und nicht nur irgendeine Lava-Lampe, nein, sogar ein limitiertes Original von Mathmos, dem Erfinder der Lavalampen! Mehr Style geht nun wirklich nicht mehr :-) also musste so ein Ding her!
Als nächstes war zu klären, wie die Lampe beleuchtet und der Farbwechsel gesteuert werden sollte. Da die Lampe von sich aus schon auf LED-Technologie basiert, war die Leuchtmittelfrage schnell geklärt - LEDs sind simpel zu schalten, billig, brauchen wenig Strom und in jeder Farbe zu bekommen, ich würde also entweder die eingebauten LEDs dafür hernehmen oder eigene stattdessen einbauen, je nachdem was praktikabler ist. Beim ersten Öffnen der Lampe stellte sich dann raus, dass wohl letzteres der Fall ist: es sind zwar nur zwei unterschiedliche LED-Farben verbaut, nämlich blau und rot (blau wird durch die Eigenfarbe der "Lava" optisch zu grünem Licht, und durch Mischung mit Rot kann man ein Gelborange erzeugen), aber die LEDs saßen direkt auf einer kleinen Platine, welche die Heizung für die Lava steuert - da kann ich mich nicht so einfach mit meiner eigenen Steuerung dazwischenklemmen. Es würde also eine eigene "Beleuchtungseinheit" erforderlich werden - und wenn ich das eh schon mache, kann ich auch gleich noch ein paar mehr LEDs für mehr Power verbauen und zudem gelbe LEDs dazunehmen, um die gelbe Farbe intensiver hinzubekommen als nur durch die Mischung. Gelb ist immerhin wichtig, zeigt es doch an, dass die Tests fehlgeschlagen sind, also den Hauptfehlerfall bei einer vorbildlich guten Testabdeckung *räusper* ;-).
Gut, Beleuchtung geklärt, bleibt die Steuerung. Die meisten Selbstbau-XFDs, die man im Web so findet, hängen einfach an irgendeinem alten Rechner, der dann die CI-Webseite pollt, den Status ausliest und dann per USB-Steckerleiste oder ähnlichem Strom ein und aus schaltet. Das hat den Vorteil, dass es simpel zu bauen und zu programmieren ist, aber man hat eben ständig einen Rechner mehr laufen - irgendwie unelegant. Wollte ich so nicht haben - meine Idealvorstellung war mehr sowas wie eine Netzwerkbuchse an der Lampe, die darüber selbsttätig den Status abfragt und das Licht dann sanft zur neuen Farbe überblendet. Ein Mikrocontroller musste also her, und ein Netzwerkinterface dafür! Damit war auch gleich sichergestellt, dass die Lampe nicht nur einen hohen Style-, sondern auch einen ausreichend hohen Nerd-Faktor haben würde :-)
Praktischerweise bietet Pollin da einen schönen Bausatz unter dem Namen AVR NET-IO an, der für günstiges Geld ziemlich genau das enthält, was ich brauchte: einen ausreichend potenten Mikrocontroller, ein Ethernet-Interface (zwar nur 10 MBit, aber die Datenrate bekommt man mit einem 8-Bit-Mikrocontroller eh nicht mal ansatzweise ausgereizt), direkte Kompatibilität mit den 12V Spannung, mit der auch die Lavalampe läuft und mehr als genug steuerbare Ausgänge. Zwar ist die Platine relativ groß, so dass diese definitiv nicht ins Lampengehäuse passen würde, aber immerhin hat sie Europakartenformat, so dass man dafür viele passende Gehäuse findet. Oh, und es gibt im Wiki von mikrocontroller.net eine Menge Infos zu dem recht beliebten Bausatz und auch einiges an Code im Netz, der dafür geschrieben wurde, was immer praktisch ist, weil man dann nicht ganz von Null anfangen muss. Den Bausatz habe ich dann letztlich in ein schlichtes schwarzes Kunststoffgehäuse gesteckt, in dessen Blenden ich Löcher für das Netzwerkkabel, den seriellen Port (nutze ich im Moment gar nicht, aber just in case...) und einen Taster gesägt habe - und natürlich für das fünfadrige Kabel zur LED-Einheit, über welches die Schaltung auch mit Strom aus der Lampe versorgt werden würde. Das Ganze sah dann in verbauter Form wie auf folgendem Bild aus:

Zurück also zur Beleuchtung. Die LEDs sollten auf möglichst einfache Weise angeschlossen werden, also versuchte ich es im ersten Schritt mit einer simplen Reihenschaltung von drei (blau) bzw. 5 (gelb und rot) 3mm-LEDs sowie pro Farbe einem Transistor zum Schalten. Vorwiderstände hatte ich keine eingeplant, und um maximale Helligkeit zu erhalten waren die Reihenschaltungen so ausgelegt, dass die LEDs an ihrer Maximalspannung laufen würden. Das sah erst ganz gut aus: die resultierende Platine hatte gerade mal 3cm im Durchmesser, die LEDs leuchteten kräftig. Aber nach dem Einbau in die Lampe wie auf dem folgenden Bild gezeigt - der Einfachheit halber setzte ich die LED-Platine direkt auf die Originalplatine, die senkrecht in der Lampe steckt - erwies sich die Schaltung als problematisch.

Die LEDs erzeugen durch die hohe Spannung und den daher hohen Strom einiges an Wärme, und zusammen mit der Hitze von der Heizeinheit, die direkt über der Platine montiert war, knockte das die LEDs der Reihe nach aus. Nach einer halben Stunde Testbetrieb flackerte alles nur noch, und als ich die Platine dann anschließend wieder ausbaute waren deutliche Flecken darauf zu erkennen. Das Ding war reif für den Müll.
Beim zweiten Versuch war ich dann vorsichtiger:
Dieser neue Aufbau funktionierte dann problemlos. Im Schaltplan und auf dem Board sieht das folgendermaßen aus...


...und in montierter Form dann so:

Im Betrieb ergibt das ein wunderbares Farbenspiel :-)

Und auch nach Aufsetzen des Lampengehäuses mit der Heizplatte kommt das Licht noch problemlos wie geplant durch das Loch in der Mitte:

Also nichts wie ins Büro damit! Der erste Praxistest war dann aber leider sehr ernüchternd :( es stellte sich raus, dass die ambiente Helligkeit da doch ein klein wenig höher ist wie in meiner dunklen Bude, mit dem Effekt, dass man die Farbe der Lampe selbst ohne direkte Sonneneinstrahlung kaum erkennen konnte. Daraufhin hab ich die Lampe dann erst mal aus akutem Frust ein paar Monate in die Ecke gepfeffert.
Irgendwann wollt ich es dann aber doch nochmal probieren, diesmal mit den richtig dicken Brocken unter den LEDs: 1- bzw. 3-Watt-Brummer sollten die Milliwatt-Funzeln ablösen. Da ich davon max. 3 unter das Loch bekommen würde, und zwei rote in Reihe grad passend an 5V betrieben werden konnten entschied ich mich dafür, die gelbe Variante auszulassen und Gelb stattdessen durch gleichzeitiges Aktivieren der einen blauen 3-Watt-LED und der zwei roten 1-Watt-LEDs zu bilden, wie das die Originalschaltung der Lampe auch getan hat.
Zur Stromversorgung kommt ein 7805 (in der Variante 78S05 für größere Stromstärken) zum Einsatz, der die 12V auf 5V runterregelt. Im Foto sieht man vor allem den Aufsteckkühlkörper, der das Ding auf Betriebstemperatur halten soll. Aufgebaut ist alles auf der guten alten Lochrasterplatine :) ja, ich war faul, insbesondere zu faul, mein Platinen-Ätz-Werkzeug rauszukramen.

Aber: es funktioniert! Und die Helligkeit ist "augenlichtraubend"!

Weil die neuen LEDs leider anders wie die kleinen einen sehr breiten Abstrahlwinkel von 120 Grad haben, musste ich mir allerdings noch was einfallen lassen, um möglichst alles Licht nach oben durch das Loch zu kanalisieren. Die Lösung ist pragmatisch simpel: ein Lichttunnel aus Pappe, innen ausgekleidet mit Alufolie. Der hat auch noch den angenehmen Nebeneffekt, dass er einiges an Wärmestrahlung von den LEDs, die ja selber genug Wärme produzieren, fernzuhalten scheint. Da hätte ich mal früher drauf kommen sollen ;-)

In dieser Variante war die Lampe dann auch hell genug für die typische Tageslichtsituation im Büro, wenngleich die kräftigen Farben nach wie vor erst bei Einbrechen der Dämmerung so richtig zur Geltung kommen.
Dass in besagtem Sourcecode nicht nur das nackte TCP/IP-Protokoll, sondern auch gleich noch ein rudimentärer Webserver mit GET- und POST-Request-Verarbeitung implementiert war, machte mir das Erreichen eines der eher ambitionierteren Ziele meines Projekts erheblich einfacher: meine XFD-Lampe sollte ein Webinterface haben, über welches sie konfiguriert und auch direkt gesteuert werden kann. Also bohrte ich den Webserver entsprechend auf, erstellte eine Konfigurationsseite (unnötigen Schnickschnack wie User-Authentifizierung habe ich im Interesse eines kompakten Ergebnisses weggelassen, so dass am Ende wirklich eine Seite für das ganze Interface genügte) und schrieb einen ganzen Batzen Code zur dynamischen Erzeugung dieser Seite bzw. zum Parsen von POST-Antworten, wenn der User über die Seite irgendwas ändern will. Dabei lernt man eine ganz andere Seite der Webentwicklung kennen: so Krempel wie Rails oder Java Servlets oder PHP hat man auf einem Mikrocontroller natürlich nicht zur Verfügung - da muss wirklich jedes Zeichen händisch in C-Code an seine Stelle in der fertigen Seite gesetzt und die Seite dabei parallel schon mal an den Empfänger rausgesendet werden (denn in die verbliebenen paar hundert Byte RAM auf dem Controller passt nicht einmal meine spartanische Konfigurationsseite in ihrer Gänze hinein!) - Antworten vom Webbrowser werden ebenso Zeichen für Zeichen durchgeackert.
Aber die ganze Mühe wurde belohnt: Nicht nur funktioniert das Webinterface einwandfrei mit allen Browsern auf meinem Rechner, nein, sogar mit dem iPhone kann die Lampe gleich out-of-the-box gesteuert werden :-)

Damit die Lampe ihren eigentlichen Zweck erfüllen konnte, brauchte sie jedoch noch eine letzte Komponente: einen HTTP-Client, der den Jenkins-Server nach dem RSS-Feed des gewünschten Projekts fragen und anschließend daraus den Status des letzten Builds extrahieren könnte. Auch für diese Aufgabe fand sich in einem der Beispielprojekte aus der uIP-Original-Release-Version praktischerweise eine Vorlage, die mit einigen Handgriffen für meine Zwecke angepasst werden konnte - na ja gut, ein paar mehr Handgriffe waren nötig, denn speziell das Parsen des RSS-Feeds, das auch wieder komplett Low-Level Zeichen für Zeichen vonstatten gehen muss, war schon eine gewisse Aufgabe. Aber schlussendlich war alles Nötige beisammen und der erste Funktionstest bestanden. Sicher befindet sich noch der ein oder andere Bug in der Software, aber wer Interesse haben sollte und nicht vor meinem hässlichen, irgendwie zusammengestöpselten und großteils mies kommentierten C-Code zurückschreckt kann sich das ganze Paket im Quellcode gern hier herunterladen.
Ich geh jetzt jedenfalls erst mal ein paar Builds schrotten, um die roten LEDs "lastzutesten" ;-)
