Auf der Suche nach einem Beispiel für das Serial Periphial Interface fiel mein Blick auf das 4 Zoll e-Paper Display, das ich mir schon vor ein paar Monaten anschauen wollte.

Waveshare 4inch ePaper HAT+
Das HAT besteht in erster Linie aus einem ePaper Display mit 600*400px Auflösung. Wie der Name sagt, unterstützt es den HAT+ Standard und belegt die GPIO Leiste des Raspberry Pi vollständig.
ePaper
elektronisches Papier oder auch elektronische Tinte (eInk) ist eine Displayart, die nicht mit leuchtenden Lichtpunkten wie ein LED-Display oder mit Flüssigkristallen wie LCD arbeitet. Das Display besteht aus vielen kleinen Kugeln, die auf der einen Seite weiß sind und auf der anderen schwarz. Beide Seiten sind unterschiedlich polarisiert. Wenn die Spannung geändert wird, dreht sich dadurch eine Kugel mit der schwarzen Seite nach oben und erzeugt einen Bildpunkt. Mit Farbfiltern vor den Kugeln lassen sich so auch farbige Darstellungen erzeugen.
Dadurch hat ein ePaper Display deutlich höhere Schaltzeiten als das, das du als Monitor benutzt, es benötigt aber durch die Arbeitsweise nur dann Strom, wenn die Anzeige aktualisiert wird und behält auch dann den angezeigten Inhalt bei, wenn der Strom abgeschaltet wird.

Lieferumfang
Neben dem Display auf der Treiberplatine werden ein Adapterkabel zum Anschluss an ESP32 oder Arduino, sowie vier lange und kurze Abstandhalter geliefert. Für das Anschlusskabel steht eine Buchse am Rand der Platine zur Verfügung. Diese stellt die notwendigen Signale zur Verfügung, die über die einzelnen Kabel abgegriffen werden können.Dieses ist beim Raspberry Pi nicht notwendig, da alle benötigten Signale über den GPIO Stecker abgegriffen werden können.
technische Daten
| Displaygröße | 4″ (84.6 * 56.40mm) |
| Gesamtabmessung | 99.00 * 66.00 * 0.85mm |
| Dot Pitch | 0.141 * 0.141mm |
| Auflösung | 600 * 400px |
| Betriebsspannung | 3,3V /5V über GPIO |
| Kommunikation | SPI |
Montage
Zunächst entferne ich die Plastikversiegelung auf den Schraublöchern, bevor ich die vier langen Abstandhalter in die Löcher schraube, die zum Raspberry Pi passen.
Aus einer Fehllieferung habe ich noch einen Raspberry Pi 4B 2GB rumliegen, auf den ich das HAT einfach vorsichtig aufstecke. Die Abstandhalter helfen bei der Ausrichtung. Nach einer Prüfung, ob die GPIO Leiste vollständig auf der Buchse liegt, drücke ich das ePaper fest an. Mit den vier kurzen Abstandhaltern wird das ganze fixiert. Das war schon alles.
SPI aktivieren
In der raspi-config muss jetzt das serial periphial interface aktiviert werden.

Demoprogramme
Die einfachste und schnellste Möglichkeit, das HAT zu testen, ist ein Demoprogramm vom Hersteller. Dazu clone ich mir das Repository mit
git clone https://github.com/waveshare/e-Paper.gitIn diesem Repo liegen scheinbar Demoprogramme für alle ePaper Displays von Waveshare. Nach etwas suchen, habe ich dann das für dieses Modell passende gefunden.
Zunächst müssen wir die lgpio und setuptools Pakete installieren
sudo apt install -y lgpio python3-setuptoolsWaveshare liefert ein Programm zur weiteren Einrichtung mit, daher müssen wir jetzt zunächst mal
python setup.py installlaufen lassen.
Dann wechsle ich ins passende Unterverzeichnis im git Repo. Das Demoprogramm muss mit Root-Rechten über sudo gestartet werden, damit der Zugriff auf SPI gelingt.
cd e-Paper/E-paper_Separate_Program/4inch_e-Paper_E/RaspberryPi_JetsonNano/python/examples
sudo python epd_4in0e_test.pyDas Demoprogramm schreibt einige Zeilen Text auf das Display (einige in japanisch), malt verschiedene geometrische Figuren und zeigt zuletzt ein Bild an.

Programmanalyse
Das Demoprogramm steht unter MIT-Lizenz, so dass wir es uns anschauen können, um zu sehen, wie SPI in der Praxis funktioniert.
Das Pythonprogramm von Waveshare importiert folgende für uns wichtigen Module:
from waveshare_epd import epd4in0e
from PIL import Image,ImageDraw,ImageFont
Ich habe die trivialen imports mal weggelassen. PIL ist die Pillow Library, mit der du in Python grafische Objekte zeichnen kannst. In waveshare_epd liegt die epd4in0e Klasse, mit der unser Display angesteuert werden kann, dieses Modul liegt unter ../lib.
Zunächst wird die Displayklasse instanziiert und das Display initialisiert und gelöscht.
epd = epd4in0e.EPD()
epd.init()
epd.Clear()
Dann benötigen wir eine Art „Leinwand“, auf der wir mit Pillow zeichnen können. Diese hat den RGB Farbraum, die Größe unseres Waveshare 4inch e-Paper HAT+ und einen weißen Hintergrund.
Himage = Image.new('RGB', (epd.width, epd.height), epd.WHITE) # 255: clear the frame
draw = ImageDraw.Draw(Himage)
Das draw Objekt dient zum Zeichnen.
draw.line((5, 170, 80, 245), fill = epd.BLUE)Mit diesem Kommando wird eine blaue Linie vom Punkt (5,17) zum Punkt (80,245) gezeichnet. Die Pillow Dokumentation spricht zwar davon, dass der Ursprung seines Koordinatensystems in der linken oberen Ecke liegt, aber in meinem Testprogramm ist der Punkt (0,0) wie in der Mathematik in der linken unteren Ecke beheimatet. Entweder wird das automatisch umgerechnet oder die Dokumentation ist an dieser Stelle falsch.
Diese Linie ist eine Diagonale in dem unausgefüllten Quadrat

Die zweite Diagonale des unausgefüllten Quadrats wird dann in gelb gezeichnet. Dadurch kommt sie auf dem Foto oben nicht so gut raus.
draw.line((80, 170, 5, 245), fill = epd.YELLOW)Der Rahmen des Quadrats kommt mit
draw.rectangle((5, 170, 80, 245), outline = epd.BLACK)um die beiden Diagonalen herum. Er soll eine schwarze Farbe haben und das Quadrat wird zwischen den Punkten (5,170) und (80,245) aufgespannt. Es fällt dir vielleicht auf, das dies genau Start- und Endpunkte der gelben Diagonalen sind. Mehr braucht es in der Geometrie nicht, um ein Rechteck zu beschreiben.
Bisher haben wir nur auf der Pillow „Leinwand“ gemalt, aber es wird noch nichts auf dem Display angezeigt. Dies geschieht erst mit
epd.display(epd.getbuffer(Himage))Damit werden die Daten an den Displaytreiber übergeben, der sie dann darstellt.
Kommunikation über SPI
Jetzt lass uns mal weiter analysieren, was im Unterbau der EPD Klasse mit der Kommunikation über SPI passiert. Dazu schauen wird uns die display() Methode mal an. Diese bekommt im image Parameter die bemalte Leinwand übergeben.
def display(self, image):
self.send_command(0x10)
self.send_data2(image)
self.TurnOnDisplay()
Zunächst wird das Kommando 0x10 ans Display gesendet, dies teilt ihm vermutlich mit, dass es Daten empfangen soll. Diese sind in image abgelegt und werden mit send_data2() dann übermittelt. Zum Abschluss stellt TurnOnDisplay() sicher, dass das Display eingeschaltet ist und wirklich was anzeigt.
Ich könnte jetzt noch tiefer in den Quellcode gehen und die letzten beiden Methoden vorstellen, aber das führt vermutlich zu weit.
eigenes Demoprogramm
Mit diesem Wissen, habe ein eigenes, kleine Demoprogramm geschrieben. Dazu kopiere ich die beiden Dateien epd4in0e.py und epdconfig.py aus dem lib Verzeichnis in mein eigenes Verzeichnis. Das macht die Arbeit etwas einfacher.
Meine Zeichnung soll die Seitenansicht eines Bretts zeigen, das auf einer roten Kiste aufliegt und ein gelber Ball die Rampe runter rollt. Das Brett wird durch eine blaue, 3 Pixel starke Linie dargestellt. Da sie bei den Koordinaten (0,0) beginnt, beweist das, dass der Ursprung in der linken unteren Ecke liegt.
Die Kiste wird durch ein rot gefülltes Quadrat dargestellt, der Ball ist ein gelb gefüllter Kreis.
#! /usr/bin/python
import os
import time
import logging
from logging import config
import json
import epd4in0e
from PIL import Image,ImageDraw,ImageFont
# Auflösung des ePaper
EPD_WIDTH = 400
EPD_HEIGHT = 600
#Verzeichnis für Grafikdaten
picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic')
# Logging Konfiguration laden.
with open('logging_config.json') as file_config:
config.dictConfig(json.load(file_config))
logger = logging.getLogger(__name__)
def main():
logger.info('initalisiere Display')
epd = epd4in0e.EPD()
epd.init()
epd.Clear()
img = Image.new('RGB', (epd.width, epd.height), epd.WHITE) # 255: clear the frame
draw = ImageDraw.Draw(img)
logger.info('zeichne blaue Linie')
draw.line((0,0, 115, 255), width=3, fill = epd.BLUE)
logger.info('zeichne gefülltes Quadrat')
draw.rectangle((0,170, 75, 245), fill = epd.RED)
logger.info('zeichne gefüllten Kreis')
draw.circle((105,180),20,fill=epd.YELLOW)
# Erst, wenn alles gezeichnet ist, aktualisieren wir das Display.
epd.display(epd.getbuffer(img))
# speichern des Bilds im akzuellen Verzeichnis
img.save('spi_demo.jpg')
time.sleep(5)
logger.info('cleanup')
epd4in0e.epdconfig.module_exit(cleanup=True)
exit()
if __name__ == '__main__':
main()
Nach dem Lauf mit sudo ./spi_demo.py, wird folgendes Bild ins Dateisystem geschrieben. Das Demoprogramm findest du mit der Logging Konfiguration im Git Repo

Auf dem Display selber sieht das ganze dann so aus.

Fazit
Das Waveshare e-Paper HAT+ ist eine gute Möglichkeit, Daten vom Raspberry Pi anzuzeigen, die sich nicht zu häufig ändern. Die Schaltzeiten können natürlich nicht mit denen eines Laptop Bildschirms mithalten. Sollen sie auch gar nicht, den ein ePaper ist nicht dafür gedacht, möglichst schnell wechselnde Informationen anzuzeigen. Dafür benötigt dieses Display nur wenig Strom und der Inhalt bleibt auch dann noch erhalten, wenn der Raspberry Pi keinen Strom mehr liefert.