Da es in unserem Esszimmer immer so zeitlos war (kann natürlich manchmal auch von Vorteil sein), war ich kurz davor, irgend eine günstige Uhr zu kaufen.

Dann kam mir die Idee:
Wieso nicht selbst basteln und mit etwas Mehrwert aufpeppen?

Da ich sowohl im Haus in allen Räumen wie auch draußen die Temperaturen erfasse, samt Regensensor und Barometer, wäre ja ein kleines Display, das alle Werte anzeigt, ganz praktisch ohne dass man dauernd zum Handy oder Laptop greifen muss.
Damit bin ich der aktuellen Entwicklung ausnahmsweise mal hinterher. Kann man sich ja schon kaufen – einfach für nen 4stelligen Betrag für jeden Raum "smarte" Temperatursensoren und noch irgend nen "smartes" dauerleuchtendes Display in den virtuellen Einkaufswagen legen, wäre ja auch eine Möglichkeit gewesen.

Ich habe mich da eher für die günstigere Variante entschieden, die nicht auf die Internetverbindung zu irgend einem "Cloud"-Server angewiesen ist.
Mit einem eInk/ePaper-Display ist die ganze Sache noch dazu einigermaßen stromsparsam. Etwas dauerleuchtendes hätte mich nur genervt.

Erst wollte ich das Projekt mit einem Arduino, bzw einem speziellen ePaper-ESP8266 umsetzen. Allerdings scheiterte ich daran, dass ich keine hilfreichen Infos/Demos finden konnte, wie ich damit ein Bild auf das eInk-Display bekomme.

Letztendlich treibt nun ein Raspberry Pi Zero W das Display an.

Einkaufsliste

  • Raspberry Pi Zero W.
    Zum Beispiel für 14,45 € bei Pimoroni.
    Wenn ich meiner Google-Recherche trauen darf, dann nur 1W Stromverbrauch und von der kleinen Bauform her lässt er sich auch prima hinter der kleinen Uhr verstecken.
  • eInk-Display.
    z.B. 4.2" für 18€ von Waveshare.
    Für die Waveshare-Displays finden sich Installationsanleitung und Beispiele, so dass die Verwendung am Raspberry Pi kein Problem ist. Leider musste ich später feststellen, dass dieses Display nur einen 4-sekündigen vollen Bildschirmrefresh unterstützt und keinen partiellen. Aber für eines mit Partial Refresh hätte ich auf 2.9" Größe zurückrudern müssen (was mir zu klein ist) oder eines mit knapp 10" nehmen, welches gleich mal 100€ mehr kostet. Also dann halt dieses hier.
  • Ein ePaper-HAT für den Pi, um das Display anzuschließen.
    Kostet bei Waveshare dann nochmals 8,65€ extra

Mit 2x Versandkosten und noch einem kleinen Bilderrahmen, um das Display etwas schöner einzurahmen, kommen wir für dieses Projekt auf so etwa 60 € (Netzteil und SD-Karte für den Raspberry Pi nicht mitgerechnet; hat man ja meist rumliegen).
Achtung, ihr Ungeduldigen: Die Waveshare-Komponenten kommen aus dem lieben China und waren bei mir einen Monat lang unterwegs. Es gibt aber immerhin ein gutes Tracking für die Bestellung (wo man zuschauen kann, wie die Ware tagelang am Flughafen rumliegt).

Raspberry Pi einrichten

Aktuelles Raspbian in der Lite-Version herunterladen und auf die SD-Karte flashen. SSH und WLAN zu aktivieren nicht vergessen!
Ein paar Hinweise hierzu in diesem Artikel.

Weiterhin habe ich dann noch folgende Dinge installiert/konfiguriert:

# Erstmal updaten...
sudo apt-get update

# SPI in den "Interface options" (oder "Advanced Options") aktivieren
sudo raspi-config

# Ein paar notwendige Python-Tools installieren
sudo apt-get install python-dev python-smbus python-serial python-imaging -y

# Zwei Zeilen in /etc/modules hinzufügen, so dass die beiden
# Module beim Booten geladen werden
sudo nano /etc/modules

  > am Ende der Datei hinzufügen:
    i2c-dev
    i2c-bcm2708

# Hier habe ich mir einen Schriften-Ordner erstellt und
# ein paar TTF-Schriften reinkopiert, die ich zur späteren
# Darstellung auf dem Display benötige
sudo mkdir -p /usr/share/fonts/truetype/

# Ein Ordner für die Skripte, die ich am liebsten
# von meinem Computer aus bearbeite
# Also muss Samba noch installiert werden...
mkdir ~/scripts
chmod 777 ~/scripts/
sudo apt-get install samba -y
sudo pico /etc/samba/smb.conf

   > am Ende der Datei hinzufügen:
     [scripts]
       comment = Pi Skripte
       path = /home/pi/scripts/
       public = no
       guest ok = no
       browsable = yes
       writeable = yes
       read only = no
       available = yes
       force user = pi
       create mode = 0666
       force create mode = 0666
       directory mask = 2777
       force directory mode = 2777
       inherit permissions = yes
       veto files = /.DS_Store/._.DS_Store/.AppleDouble/.bin/.AppleDesktop/Network Trash Folder/._*/
       delete veto files = yes

# Passwort für die Anmeldung des pi-Users per Samba vergeben
# (hier wird nicht automatisch das Account-Passwort erwartet!)
# und Samba-Dienst neu starten
sudo smbpasswd -a pi
sudo service smbd restart

# Ich habe für meine Skripte Python 3 verwendet.
# Hierfür benötigen wir noch "Pillow", um Bilder zu zeichnen
# Und dies installieren wir am besten über den Python-Modul-Manager "pip",
# welcher auch erst installiert werden muss
# Wer eher an Python 2 hängt, lässt einfach die beiden 3er im Folgenden weg
sudo apt-get install python3-pip -y
pip3 install Pillow

# Ich will noch Icons einbinden, die als PNG vorliegen
# Dafür benötigen wir noch eine Bibliothek
sudo apt-get install libopenjp2-7 -y

# Wird zur Kommunikation zwischen Python und dem Display benötigt
pip3 install spidev
pip3 install RPi.GPIO

Dann benötigt man noch den Demo Code von Waveshare, in dem die zwei Bibliotheken bcm2835 und wiringpi enthalten sind. Zum Entpacken des 7z-Archives empfehle ich The Unarchiver.
Die beiden Bibliotheken kann man ansonsten auch direkt von hier (bcm2835) und hier (wiringPi) herunterladen, wenn man Lust auf ein paar Klicks mehr hat ;-)

utar WiringPi.tar.gz
cd wiringPi/
chmod 777 build
./build
gpio -v


utar Bcm2835-1.39.tar.gz
cd bcm2835-1.39/
./configure
make
sudo make check
sudo make install

Hardware

Beim Verbinden des eInk-Displays mit dem Raspberry Pi kann man eigentlich nicht viel falsch machen: ePaper-HAT auf den Raspberry Pi aufstecken und Display mit oder ohne mitgeliefertem Verlängerungskabel einstecken.
In meinem Versuchsaufbau im Bild rechts hatte ich mal auf die Verlängerung verzichtet.

Oben im Bild das eInk-Display, darunter der vom ePaper-HAT verdeckte Raspberry Pi.

 

Skripte

Die Skripte sind, wie oben bei der Einrichtung bereits angedeutet, in Python 3 geschrieben. Eigentlich finde ich Python (zurückhaltend formuliert) sehr unschön. Aber leider fand' ich nur Beispiele für Python. Die benötigte "Bibliotheks"-Datei epdconfig.py in Perl umzuschreiben überforderte mich dann doch irgendwie...

Drei Versionen meiner eInk/Raspberry-Uhr sind bereits vorhanden.
Zu allen dreien sollten sich noch die beiden Dateien epd4in2.py und epdconfig.py gesellen (direkt ins selbe Verzeichnis legen), die mit beim Demo-Code von Waveshare dabei waren.
Gegebenenfalls muss in der epdconfig.py noch die Display-Auflösung angepasst werden:

# Display resolution
EPD_WIDTH       = 400
EPD_HEIGHT      = 300

Und vielleicht auch die PIN-Definition in epd4in2.py

# Pin definition
RST_PIN         = 17
DC_PIN          = 25
CS_PIN          = 8
BUSY_PIN        = 24

So die Vorgaben für das von mir verwendete Display.

Download und Changelog meiner Skripte

Verwendete Schriften DejaVuSans, LCDAT, Technology und Wettericons (durchwachsen.gif, frost.gif, leicht_regen.gif, regen.gif, sonne.gif, wolke.gif) sind nicht mit enthalten.
Schriften müssen in den in config.ini definierten fontpath abgelegt werden, die Wettericons (um für die Vorsage kleine Bildchen für Sonne oder Wolken anzuzeigen) im definierten wettericonpath
Noch dazu müssen die beiden Dateien epd4in2.py und epdconfig.py aus dem Waveshare-Democode mit in das Verzeichnis zu den Skripten gelegt werden.

Das Skript erwartet von der in der config.ini hinterlegten wetterurl eine JSON-Antwort in einem bestimmten Format:

# Verschiedene Temperaturen mit Sensor-ID, Name, Kurzbezeichnung, Temperatur, Luftfeuchte, Ist aktuell?
{"temp": [{"id" : "9", "name" : "Außentemperatur", "kurz" : "Außen", "temp": "6.7", "feucht": "79", "aktuell": "1"}, {...}],
# Vorhersage heute und morgen, jeweils mit min/max-Temperatur, Sonnenstunden, Regenmengen in 6-Stunden-Zeitrahmen und insgesamt und name des Wettericons
 "vorhersage": { "heute": {"min": "0.2", "max": "7.0", "sonnenstunden": "0.0", "regen_6h": [2.7, 11.4, 5.6, 5.0], "regen_sum": "24.7", "bild": "regen"},
                 "morgen": {... } },
# Aktuell Regen heute
 "regen": "29.7950",
# Luftdruck
 "luftdruck": {"aktuell": "966.660000" }
 }

uhr-v1.2.3.tbz

v1.2.3
  - Wurde nicht aktualisiert, wenn die Vorhersage keine Werte lieferte

uhr-v1.2.2.tbz

v1.2.2
  - Zu Debug-Zwecken kann statt der URL zur Wetterabfrage auch eine Textdatei angegeben werden
  - Neues Widget: Luftdrucktendenz
  - Bugfix: Wohl bedingt durch irgendeine neue Bibliothek gab es beim Regen ein Typen-Problem
  - Nochmals neu zusammenkopiert, weil ich Depp kein Backup von meinem Projekt gemacht habe

uhr-v1.2.tar.gz

v1.2
  - Socket hinzugefügt, um Uhr von extern zu konfigurieren
  - Wetter-Info nun Widget-basierend, um etwas flexibler zu sein
  - Display lässt sich nun um 90° drehen (eigentlich um jedes x-beliebige Grad)
  - Bugfix: Balken der Regenvorhersage sprengten den Rahmen und landeten unter Umständen in der Uhrzeit

uhr-v1.1.tar.gz

v1.1
  - Minütliche Aktualisierung durch neue Klasse RepeatedTimer statt durch sched-Modul gelöst (genauer)
  - Höflicheres Beenden des Programmes durch control-c
  - Höflicheres Beenden des Programmes durch kill
  - Prozess-ID wird bei Programmstart in Datei running.pid geschrieben

uhr-v1.0.tar.gz

v1.0
  - Version 1 halt ;-)
  Aber hier sieht man dank schlankerem Code eher, was vor sich geht

Automatisch beim Systemstart ausführen:

Einfach einen weiteren Job in die crontab einfügen:

crontab -e

Folgende Zeile hinzufügen:

@reboot /pfad/zu/uhr/uhr.py

Funktion:

All 10 Minuten werden von einem vorgegebenen Server die aktuellen Wetterdaten abgerufen und daraus ein PNG-Bild generiert (alles unterhalb der Datumsangabe). Der Pfad dieses Bildes ist in der config.ini als wetterinfofile definiert und kann beliebig sein.
Ich hatte dies ausgekoppelt, da die Wetterdaten sicherlich nicht minütlich abgerufen und umgesetzt werden müssen.

Minütlich wird ein weiteres Bild mit Uhrzeit und Datum generiert und das Wetterinfo-Bild darübergelegt – diese Kombination wird dann auf das Display gesendet.

Das Skript bedarf natürlich einiger Anpassung, sollte sich jemand dafür interessieren, da wohl nicht jedem Interessenten alle Daten zur Verfügung stehen, die ich selbst verwende (aktueller Luftdruck oder Vorhersage-Daten im 6-Stunden-Raster zum Beispiel).

Was ich noch vor habe...

Ab Version 1.2 kann man die Uhr von außen via Socket-Befehle steuern.
Hierzu möchte ich noch auf dem Raspberry selbst eine Website laufen lassen, über die man einige Aspekte der Uhr anpassen/steuern kann und auch im Browser ein Bild der Display-Anzeige zu sehen bekommt.