Raspberry Pi und grafische Displays (OLED, TFT)

In einem vorangegangenen Blog-Beitrag hatten wir zunächst LCDs am Raspberry Pi sowohl über GPIO-Pins als auch über I2C angeschlossen. Diese robusten Displays mit je 16 Zeichen in zwei Zeilen bzw. je 20 Zeichen in vier Zeilen sind allerdings zeichenorientiert. Damit können wir weder eine analoge Uhr, oder ein Zeigerinstrument für Messwerte, noch Bilder darstellen. Dafür benötigen wir im mobilen Einsatz entweder ein OLED- oder ein TFT-Display. Hier eine kleine Übersicht:

Bezeichnung

Techn.

Bus

Diag.

Pix. x

Pix. y

Controller

0,91 Zoll I2C OLED Display

OLED

I2C

0,91

128

32

SSD1306

0,96 Zoll I2C OLED Display

OLED

I2C

0,96

128

64

SSD1306

1,3 Zoll I2C OLED Display

OLED

I2C

1,3

128

64

SH1106

0,66 Oled Display Shield

OLED

I2C

0,66

64

48

SSD1306

1,77 Zoll SPI TFT-Display

TFT

SPI

1,77

128

160

ST7735

1,8 Zoll SPI TFT-Display

TFT

SPI

1,8

128

160

ST7735


Beginnen wir mit dem leichter zu handhabenden Bussystem I2C und damit den OLED-Displays. Die Abkürzung OLED steht für organische Leuchtdiode (organic light emitting diode). Es handelt sich um ein leuchtendes Dünnschichtbauelement aus organischen halbleitenden Materialien. Die elektrische Stromdichte und Leuchtdichte sind geringer als bei herkömmlichen LEDs.

Die Schaltung von I2C-Bauteilen am Raspberry Pi ist sehr einfach. Man verbindet die physischen Pins

  • 1 = 3,3V
  • 3 = I2C-SDA
  • 5 = I2C-SCL
  • 6 oder 9 = Ground

mit Jumper-Kabeln. Die Displays sind beschriftet. Da kann eigentlich nichts schief gehen.

In der Raspberry Pi-Konfiguration wird die I2C-Schnittstelle aktiviert und dann prüfen wir als erstes die I2C-Adressen der angeschlossenen Geräte. Dafür wird das Tool i2cdetect mit den Parametern -y 1 im Terminal aufgerufen.

Alle OLED-Displays haben die I2C-Adresse 0x3C. Die hier angezeigte zweite Adresse 0x76 gehört zum Sensor BME-280, der von den letzten Versuchen noch angeschlossen ist.

Programm-Bibliothek:

Für die Programmierung des Displays ist man gut beraten, eine Programm-Bibliothek für Python zu installieren. Die Empfehlung lautet luma.oled von Richard Hull und vielen anderen. Diese stetig weiterentwickelte, sehr umfangreiche Sammlung von Python-Modulen eignet sich für eine Vielzahl von Displays, die sich bei der Auflösung und beim Bild-Controller unterscheiden können. Wer ein aktuelles Raspberry Pi OS besitzt, kann die Python-Module und eine Sammlung von Beispielprogrammen direkt auf dem Raspberry Pi installieren (Beschreibung folgt). Wer tiefer einsteigen möchte, oder andere Hardware-Konfigurationen benutzt, dem seien folgende Links empfohlen:

https://github.com/rm-hull/luma.oled    # Python-Module (Bibliothek)

https://github.com/rm-hull/luma.examples    # Beispiel-Programme

https://luma-oled.readthedocs.io/en/latest/    # Dokumentation

Auch diese Bibliothek hat Eingang gefunden bei PyPi (The Python Package Index (PyPI) is a repository of software for the Python programming language.) und man kann es deshalb direkt auf dem Raspi mit dem Tool pip installieren.

Das erste Modul heißt luma.oled, der Terminal-Befehl lautet also:

 $ sudo pip install luma.oled                        # siehe auch Anmerkung zu SPI / ST7735

Ohne dass ich es explizit gelesen habe, scheint Python 2.7 nicht mehr verwendet zu werden, so dass pip statt pip3 und python statt python3 genauso gut verwendet werden können. 

In der Dokumentation steht, dass man erstens weitere Bibliotheken (Dependencies) installieren muss und zweitens für den user (bisher pi, heute selbstgewählter user-Name) mit
sudo usermod -a -G spi,gpio,i2c user   dem user Zugriffsrechte für die Schnittstellen gewähren muss. Beides ist bei einem aktuellen Raspberry Pi OS nicht mehr nötig.

Die Beispielprogramme sind heute nicht mehr Teil der Bibliothek, sondern in einem eigenen Github-Repository verfügbar. Zum Herunterladen wird der Befehl git clone mit dem Link verwendet.

 $ git clone https://github.com/rm-hull/luma.examples.git
 $ cd luma.examples

Hier befindet sich ein weiteres Unterverzeichnis examples, in das man wechseln kann. Mit ls werden die Programme angezeigt, siehe Bild.

Die Bibliothek arbeitet mit Voreinstellungen, und zwar I2C-Interface, Adresse 0x3C, dem Bild-Controller SSD1306 und der Auflösung 128x64. Alle diese Vorgaben treffen für das 0,96“-OLED-Display zu, das mit dem Demoprogramm demo.py auf Anhieb funktioniert. Einfach im Terminal

 $ python demo.py

eingeben und es erscheinen grafische Elemente und „Hello World“ im Display.

Das gleiche gilt, wenn man das Python-Programm z.B. mit Thonny startet. Aber eben nur dann, wenn die Voreinstellungen zutreffen. Ansonsten muss man das Programm im Terminal mit weiteren Parametern starten, die in der Funktion def main() mit get_device() übernommen werden.

Demo-Programme im Terminal:

Das trifft z.B. auf das 1,3“ OLED-Display zu, das als Bild-Controller den SH1106 verwendet. Wie man welche Parameter übergibt, kann man über die Hilfefunktion erfahren. Also zunächst den Parameter --help oder -h eingeben. Der Programm-Aufruf für das 1,3“ OLED-Display lautet demnach:

 $ python demo.py -d sh1106

Das 0,91“OLED-Display verwendet zwar auch den SSD1306, hat aber nur eine Auflösung von 128x32 Pixeln. Bevor Sie dieses schmale Display anschließen eine kurze Warnung: meist liegt die Reihenfolge der Pins an I2C-Geräten bei VCC-GND-SCL-SDA, nicht beim 0,91“ OLED! Die Reihenfolge lautet hier GND-VCC-SCL-SDA. Der Programm-Aufruf erfolgt mit dem Parameter --height 32

 $ python demo.py --height 32

Wenn man dauerhaft mehrere Parameter übergeben muss, kann man diese auch in einer Konfigurationsdatei (Dateiendung .conf) abspeichern. Es gibt sogar ein Unterverzeichnis conf unter luma.examples, in dem für eine Reihe von Displays bereits diese Dateien vorhanden sind. Ich entdecke die Datei st7735.conf, also für den Bild-Controller ST7735, der bei dem 1,8“TFT-Display mit SPI-Schnittstelle verbaut ist.

In dieser Textdatei entdecke ich sogar die Pinbelegung der Pins, die beim Raspberry Pi nicht zwingend vergeben sind.

  • RESET geht an GPIO24 = phys. Pin 18
  • data-command (am Display A0) an GPIO23 = phys. Pin 16
  • backlight LED an GPIO18 = phys. Pin 12 (das ist besser als an 3,3V!)
  • VCC = 5V, also phys. Pin 2 oder 4
  • GND an irgendeinen Ground pin
  • SCK an phys. Pin 23
  • SDA (besser bekannt als MOSI bzw. COPI) an phys. Pin 19
  • CS an CE0 = phys. Pin 24

Achtung: Rückseitenansicht! Der VCC-Anschluss hat eine quadratische Umrandung; im folgenden Schaltbild ganz oben.

Den Programmaufruf starte ich aus dem übergeordneten Verzeichnis luma.examples, damit ich leicht auf die Unterverzeichnisse conf und examples zugreifen kann.

 $ python examples/demo.py  --config  conf/st7735.conf

Nachdem bislang alles auf Anhieb geklappt hatte, bekomme ich nun die Fehlermeldung, dass st7735 nicht zu den bekannten Displays zählt, eben den verschiedenen OLED Bild-Controllern.

Nach längerer Recherche - die Dokumentation ist leider weder aktuell noch vollständig - finde ich in einem Forum den Hinweis, dass die Beispiele zwar für fast alle Displays funktionieren, jedoch die Bibliothek luma.oled eben nur für die aufgezählten OLED-Displays. Also mit pip eine weitere Bibliothek installieren:

 $ sudo pip install luma.lcd

https://luma-lcd.readthedocs.io/en/latest/              # Dokumentation

Man hätte auch gleich beide Bibliotheken installieren können (siehe Hinweis oben), aber das steht nirgendwo.

 $ sudo pip install luma oled luma.lcd            # Installation beider Bibliotheken für OLED und LCD/TFT

Nun funktioniert auch das TFT-Display mit dem obigen Programm-Aufruf.

Nachdem ich auch das Beispielprogramm clock.py mit allen Displays im Terminal gestartet und erfolgreich getestet habe, möchte ich ausprobieren, wie diese Programme in der Python-Umgebung, z.B. Thonny oder IDLE, funktionieren.

OLED-Displays in der Python-Umgebung:

Wie oben beschrieben gab es für das 0,96“-OLED-Display keine Schwierigkeiten, denn hier sind ja keine Parameter zu übergeben. Die Beispielprogramme demo.py und clock.py funktionieren wie gewünscht. 

Für das 1,3“-OLED-Display mit dem Bild-Controller SH1106 wird das Objekt device wie folgt instanziiert:

 from luma.core.interface.serial import i2c
 from luma.core.render import canvas
 from luma.oled.device import ssd1306, ssd1309, ssd1325, ssd1331, sh1106, ws0010
 
 serial = i2c(port=1, address=0x3C)
 device = sh11066(serial)

Im Gegenzug entfallen die Zeilen:

 from demo_opts import get_device
 device = get_device()

Die Funktion get_device() aus dem Modul demo_opts braucht nicht importiert werden.

TFT-Displays in der Python-Umgebung:

Für das 1,8“-TFT-Display müssen erwartungsgemäß mehr Angaben eingefügt werden:

 from luma.core.interface.serial import spi
 from luma.core.render import canvas
 from luma.lcd.device import st7735
 
 serial = spi(port=0, device=0, gpio_DC=23, gpio_RST=24)
 device = st7735(serial)

Trotz intensiven Studiums der Module habe ich nicht herausgefunden, wie die GPIO-Steuerung der Hintergrundbeleuchtung aktiviert wird. Dauerhaft an 3,3V anschließen führt zwar zu einem Bild, aber bei Inaktivität leuchtet die Hintergrundbeleuchtung sehr hell.

Deshalb habe ich den LED-Pin an GPIO18 belassen und die entsprechenden Befehle für das Umschalten zwischen LOW und HIGH ergänzt.

 import RPi.GPIO as GPIO
 gpio_LED=18
 GPIO.setmode(GPIO.BCM)
 GPIO.setup(gpio_LED, GPIO.OUT, initial=0)

und dann

 GPIO.output(gpio_LED, 1)     

bzw. hinter dem device.cleanup()

 GPIO.output(gpio_LED, 0)     

Download der beiden angepassten Beispielprogramme clock_sh1106_I2C.py und clock_st7735_SPI.py

Viel Spaß beim Einbinden der kleinen Grafik-Displays in Ihre Projekte.

DisplaysProjekte für anfängerRaspberry pi

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert