Smart Mirror

Dieser smarte Spiegel zeigt dir das Wetter, individuelle Nachrichten oder Hochwasserwarnungen an.

Schicke mir eine Nachricht an meinen Smart-Spiegel:

Du kannst mir hier eine persönliche Nachricht schicken. Diese wird mir automatisch angezeigt, wenn ich das nächste Mal ins Badezimmer gehe.

Zum Absenden den Slider nach rechts ziehen

Wie funktioniert das Ganze?

Kennt ihr venezianische Spiegel? Diese besitzen eine sehr dünne reflektierende Schicht, welche einen kleinen Teil des Lichtes durchlassen. Man kann den Spiegel ganz normal als solchen benutzen aber zum Beispiel hinter dem Spiegel ein Display installieren und sieht diese dann durch den Spiegel hindurch leuchten.
Als ich einen solchen Spiegel relativ günstig auf Amazon sah, hab ich beschlossen, daraus einen intelligenten Spiegel für das Badezimmer zu basteln.

Links umd rechts am Spiegel habe ich mit Glaskleber Wandhalterungen und Abstandshalter angeklebt. Seitlich vom Spiegel habe ich zwei weiße LED-Streifen als Beleuchtung installiert.
Mittig habe ich mit Klebeband zwei 64x64 RGB LED Matritzen befestigt. Um Platz zu sparen, habe ich die Stecker abgelötet und direkt mit je einem Arduino Mega2560 als Displaycontroller verbunden. Ein Node-MCU in der Mitte dient als Master.

Die Stromversorgung habe ich über 5V Netzteile sichergestellt. Der Node-MCU ist kontinuierlich an. Er verbindet sich via WLAN mit dem Internet und fragt über TCP/IP meinen Webserver nach Grafiken oder Texten an. Zur Authentifizierung wird ein Key mitgeschickt. Ein PHP-Script verarbeitet die Anfrage und stellt eine der folgenden Informationen bereit:

Je nach Dringlichkeit, Uhrzeit oder per Zufall wird eine der genannten Optionen via PHP verarbeitet und an den Node-MCU geschickt.
In regelmäßigen Abständen frägt der Node-MCU eine neue Nachricht an.

Der Node-MCU speichert die Nachricht und wechselt in den Sleepmode. Wird das Licht eingeschaltet, so bekommen die beiden Atmega-2560 und die LED-Matritzen Strom und ein Interrupt wird an den Node-MCU geschickt. Dieser broadcastet die gespeicherte Nachricht via Serielle Verbindung an die beiden Atmegas, welche wiederum jeweils eine LED-Matrix ansteuern und so zusammen die Nachricht anzeigen.
Anfangs hatte ich etwas Probleme mit Umlauten, aber ich musste lediglich eine andere Codierung und Schriftart verwenden.
Ich finde es schön, wenn man früh aufsteht, und gleich nach dem Duschen über das heutige Wetter informiert wird, oder wenn einem der Badezimmerspiegel eine gute Nacht wünscht oder nachts auf Toilette vor dem Hochwasser warnt, welches sich gerade zusammen braut.

Technische Details

Herausfordernd waren für mich die Hardwarebeschränkungen. Jede LED kann mit 12 Bit (4Bit pro Farbe) in RGB angesteuert werden. Bei 64x64 LEDs macht das bereits 6KB an Daten aus, wobei ein Atmega2560 nur 8KB RAM besitzt. Gleichzeitig kann ich über die Serielle Schnittstelle keine 6KB an Daten schnell genug fehlerfrei übertragen.
Die effizienteste Lösung ist, die Daten serverseitig zu rendern und auf zwei Datenpakete für die linke und rechte Displayhälfte aufzuteilen. Die Datenpakete werden zusätzlich mittels Shannon-Fano-Algorithmus komprimiert und mittels Chunked-Codierung an den Node-MCU übertragen. Je nach Informationsgehalt ist ein Datenpaket zwischen 300 Byte und 1,4KB groß.
Für die serielle Übertragung werden die Datenpakete noch mit einer Prüfsumme versehen und mittels Byte-Stuffing (Ähnlich wie beim CAN-Bus Protokoll) übertragen.
Das tolle an Lempel-Ziv-Markov komprimierten Daten ist, dass diese im Stream verarbeitet werden können, das heißt, die Dekomprimierung kann starten, während die Übertragung noch läuft. Die dekomprimierten Daten werden direkt in den Displaybuffer geschrieben, um RAM zu sparen. Ich habe den Dekomprimierungsalgorithmus aus der LZIP-Bibliothek optimiert, dass er mit nur 350 Bytes an RAM auf einem Arduino auskommt. Somit verbleiben noch 1,5KB für den Seriellen Empfangsbuffer und 150 Bytes für den Stack.
Die ganzen Hardwarebeschränkungen führten dazu, dass ich alles Serverseitig rendern muss, hierfür habe ich die Grafik-Bibliothek für die 64x64 LED Matritzen teilweise von C in PHP umgeschrieben. Moderne TTF-Schriftarten basieren auf Vektorgrafiken, was jedoch bei 8px Schriftgröße zu unschönen Artefakten führt. Ich habe daher eine Erweiterung für die GD-Text Library geschrieben, um BDF-Schriftarten in PHP rendern zu können. BDF Schriftarten basieren auf Bitmaps und es gibt einige, welche auf die Anzeige von LED-Anzeigetafeln optimiert sind.
Auf dem Server läuft eine SQL-Datenbank, in welcher Nachrichten gespeichert werden. Nachrichten können via API-Schnittstelle hinzugefügt werden (z. B. als Push-Benachrichtigung von meinem Hochwassersensor oder als Persönliche Nachrichten von dieser Webseite). Eine Nachricht kann Texte und Grafiken enthalten. Wenn der Node-MCU eine Nachricht anfordert, wird diejenige mit der höchsten Priorität zurückgegeben. Sobald sie auf dem Spiegel angezeigt wird, sendet der Spiegel ein ACK mit der Nachrichten-ID und sie wird aus der Datenbank gelöscht. Sind keine statischen Nachrichten mehr vorhanden, werden dynamisch neue generiert z. B. aus den aktuellen Wetterinformationen oder anhand des Feiertagkalenders oder meinen E-Mails.
Das gesamte System ist abgesichert gegen Cross-Site-Scripting (XSS), SQL-Injections, Remote-Code-Executions, File-Inclusion, DoS, Insecure Deserialization und Command Injection. Alle Übertragungen laufen über eine SSL-Verbindung.


Weitere Artikel

© Veit Götz 2012 - 2024
Impressum
Datenschutz
Statistiken
Spenden