Raspberry Pi: OLED-Display 128×64 mit Python ansteuern (I2C)

Im Prinzip kommt ein Raspberry Pi ja ganz ohne Ein-/Ausgabe-Geräte aus – je nachdem, was man damit macht. Manchmal ist es aber schon recht praktisch, sich ein paar Informationen auf einem Display ausgeben lassen. In diesem Beitrag wollen wir ein kleines 0,96'' OLED-Display mit 128x64 Pixeln über die I2C-Schnittstelle ansteuern.

Raspberry Pi mit angeschlossenem 0,96″-OLED-Display

Raspberry Pi vorbereiten

Voraussetzung für alles folgende ist, dass Euer Raspberry Pi betriebsbereit ist. Wie man das Image auf eine SD-Karte bekommt und den RPi einrichtet, hatte ich hier schonmal beschrieben.

Von Haus aus ist die I2C-Schnittstelle am Raspberry Pi deaktiviert. Um diese nun einzuschalten verbinden wir uns per SSH und starten die Konfigurationsoberfläche vom Raspberry Pi:

$ sudo raspi-config

Dort gehen wir zum Punkt 5 (Interfacing Options) -> P5 (I2C) -> ENTER und bestätigen die Abfrage, ob wir I2C aktivieren wollen, mit <Ja>. Anschließend verlassen wir raspi-config.

Jetzt installieren wir noch ein paar Pakete, die wir für unser Script brauchen und starten den RPi neu:

$ sudo apt-get install python-smbus i2c-tools git python-pil
$ sudo reboot

OLED-Display anschließen

Mit ein paar Steckbrücken verbinden wir den Raspberry Pi mit dem OLED-Display. Bei meinem Display ist es egal, ob man 5V oder 3,3V nutzt. Prüft das besser bei Eurem nochmal.

Raspberry Pi: OLED-Display über I2C anschließen

Raspberry Pi: OLED-Display über I2C anschließen

Adresse ermitteln

Da I2C ein Bus-System für mehrere Teilnehme ist, haben alle auch eine Busadresse. Bei diesen kleinen Displays hat sich so etwas wie ein Standard durchgesetzt. Bei fast allen lautet die Adresse 0x3C. Das lässt sich einfach überprüfen, indem wir folgenden Befehl absetzen:

$ i2cdetect -y 1

Als Ausgabe erhalten wir dann so eine Tabelle, der wir als Adresse des einzigen Busteilnehmers 3c entnehmen können:

pi@raspberrypi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

Die Adresse 0x3c ist in der von uns verwendeten Python-Bibliothek schon vorausgewählt, sodass wir der Adresse keine weitere Beachtung schenken müssen.

Python-Code

Bibliothek einbinden

Für die Ansteuerung des Displays machen wir uns eine kleine Python-Bibliothek auf Github zu Nutze. Die klonen wir und haben damit alles, was wir benötigen:

$ git clone https://github.com/BLavery/lib_oled96

Wir wechseln in das Verzeichnis lib_oled96 und legen uns dort eine neue Script-Datei an:

$ cd lib_oled96
$ touch display.py
$ chmod 777 display.py

Anschließend öffnen wir die soeben erstellte Datei in einem beliebigen Editor und fangen mit der Programmierung an:

$ nano display.py

Beispiel 1: Hallo Welt

Raspberry Pi: OLED-Display-Beispiel "Hallo Welt"

Raspberry Pi: OLED-Display-Beispiel „Hallo Welt“

#!/usr/bin/env python
# coding=utf-8

# Bibliotheken importieren
from lib_oled96 import ssd1306
from smbus import SMBus

# Display einrichten
i2cbus = SMBus(1)			# 0 = Raspberry Pi 1, 1 = Raspberry Pi > 1
oled = ssd1306(i2cbus)

# Ein paar Abkürzungen, um den Code zu entschlacken
draw = oled.canvas

# Display zum Start löschen
oled.cls()
oled.display()

# Hallo Welt
draw.text((20, 16), "Hallo", fill=1)
draw.text((60, 40), "Welt!", fill=1)

# Ausgaben auf Display schreiben
oled.display()

Der Klassiker in der Programmierung schreibt einfach ein paar Worte aufs Display. Die Zeilen 1-10 im Script liefern dabei die Grundfunktionalitäten und Zeile 13 dient lediglich dazu, den Code etwas zu verschlanken. Interessant wird es ab Zeile 16, denn hier beginnt die echte Ausgabe aufs Display. Der hier verwendete Befehl oled.cls() löscht den kompletten Inhalt und oled.display() schreibt die bisherigen Ausgaben auf das OLED-Display.

Alle Display-Informationen werden solange gesammelt, bis sie mit dem Befehl oled.display() auf das Display übertragen werden.

Auf den Zeilen 20 und 21 wird dann die eigentliche Textausgabe erzeugt. Die Syntax lautet draw.text((<x>, <y>), <Inhalt>, [<Schriftart>], [<Formatierung>]). Die Angaben <x>, <y> stehen hier für die Koordinaten auf dem Display, bezogen auf die obere linke Ecke. Das Wort „Hallo“ wird also 20 Pixel nach rechts und 16 Pixel nach unten verschoben. Das Wort „Welt“ dann demzufolge um 60 Pixel nach rechts und 40 Pixel nach unten. Zeile 24 erzeugt wieder die Anzeige auf dem Display.

Den Code kopieren wir einfach in den Editor, speichern und schließen diesen (Strg+X) und führen das Script aus:

$ ./display.py

Beispiel 2: Schriften formatieren

Raspberry Pi: OLED-Display-Beispiel "Hallo Welt" mit formatierter Schrift

Raspberry Pi: OLED-Display-Beispiel „Hallo Welt“ mit formatierter Schrift

#!/usr/bin/env python
# coding=utf-8

# Bibliotheken importieren
from lib_oled96 import ssd1306
from smbus import SMBus
from PIL import ImageFont

# Display einrichten
i2cbus = SMBus(1)			# 0 = Raspberry Pi 1, 1 = Raspberry Pi > 1
oled = ssd1306(i2cbus)

# Ein paar Abkürzungen, um den Code zu entschlacken
draw = oled.canvas

# Schriftarten festlegen
FreeSans12 = ImageFont.truetype('FreeSans.ttf', 12)
FreeSans20 = ImageFont.truetype('FreeSans.ttf', 20)

# Display zum Start löschen
oled.cls()
oled.display()

# Hallo Welt
draw.text((20, 16), "Hallo", font=FreeSans12, fill=1)
draw.text((60, 40), "Welt!", font=FreeSans20, fill=1)

# Ausgaben auf Display schreiben
oled.display()

Wir gehen einen Schritt weiter und formatieren die ausgegebene Schrift. Dazu erweitern wir unser Script um Elemente der Bibliothek PIL (Zeile 7), legen die Schriftarten fest (Zeilen 17 und 18) und wenden sie als Formatierung auf den Text an (Zeilen 25 und 26).

Beispiel 3: Formen zeichnen

Raspberry Pi: OLED-Display-Beispiel mit Formen

Raspberry Pi: OLED-Display-Beispiel mit Formen

#!/usr/bin/env python
# coding=utf-8

# Bibliotheken importieren
from lib_oled96 import ssd1306
from smbus import SMBus

# Display einrichten
i2cbus = SMBus(1)			# 0 = Raspberry Pi 1, 1 = Raspberry Pi > 1
oled = ssd1306(i2cbus)

# Ein paar Abkürzungen, um den Code zu entschlacken
draw = oled.canvas

# Display zum Start löschen
oled.cls()
oled.display()

# Formen zeichnen
draw.line((4, 2, 20, oled.height-1), fill=1)					# diagonale Linie
draw.rectangle((22, 2, 30, oled.height-1), outline=1, fill=0)	# Rechteck
draw.rectangle((32, 2, 40, oled.height-1), outline=0, fill=1)	# Rechteck, ausgefüllt
draw.ellipse((42, 2, 60, oled.height-1), outline=1, fill=0)		# Ellipse
draw.line((76, 2, 76, 63), fill=1)								# vertikale Linie
draw.arc((62, 2, 90, 63), -90, 90, fill=1)						# Bogen
draw.polygon([(92, 63), (110, 63), (101, 2)], outline=1, fill=0) # Polygon (Dreieck)

# Ausgaben auf Display schreiben
oled.display()

Für das Zeichnen von Formen haben wir bereits alles an Bord, was benötigt wird. Zur Verfügung stehen verschiedene Grundformen. In nachfolgender Auflistung stehen x1 , y1 für die Startkoordinaten und x2, y2 für die Endkoordinaten:

  • Linien: draw.line((x1, y1, x2, y2), fill=1)
  • Rechteck (nur Rahmen): draw.rectangle((x1, y1, x2, y2), outline=1, fill=0)
  • Rechteck (ausgefüllt): draw.rectangle((x1, y1, x2, y2), outline=1, fill=1)
  • Ellipse: draw.ellipse((x1, y1, x2, y2), outline=1, fill=0)
  • Polygon: draw.polygon([(x1, y1), (x2, y2), (x3, y3)], outline=1, fill=0)
    Die Eckpunkte werden als Array angegeben. (x1, y1) erste Ecke, (x2, y2) zweite Ecke, (x3, y3) dritte Ecke, …
  • Bogen: draw.arc((x1, y1, x2, y2), α1, α2, fill=1)
    α1, α2 stehen für den Startwinkel und den Endwinkel, gerechnet im Uhrzeigersinn, begonnen bei 3:00 Uhr. Der Platzbedarf eines Bogens ist der selbe, wie der einer Ellipse, jedoch wird nur der angegebene Winkel gezeichnet.

Ürbrigens: mit oled.height und oled.width kann man über die gesamte Bildschirmbreite zeichnen.

Beispiel 4: Bilddateien

Raspberry Pi: OLED-Display-Beispiel Bilddatei anzeigen

Raspberry Pi: OLED-Display-Beispiel Bilddatei anzeigen

#!/usr/bin/env python
# coding=utf-8
 
# Bibliotheken importieren
from lib_oled96 import ssd1306
from smbus import SMBus
from PIL import Image
 
# Display einrichten
i2cbus = SMBus(1)            # 0 = Raspberry Pi 1, 1 = Raspberry Pi > 1
oled = ssd1306(i2cbus)
 
# Ein paar Abkürzungen, um den Code zu entschlacken
draw = oled.canvas
 
# Display zum Start löschen
oled.cls()
oled.display()
 
# Bilddatei ausgeben
draw.bitmap((32, 0), Image.open('pi_logo.png'), fill=1)
 
# Ausgaben auf Display schreiben
oled.display()

Um ein Bild anzeigen zu können, wird wieder die PIL-Bibliothek benötigt. Die Funktionsweise ist sonst wieder die vorher. Angegeben werden müssen die Koordinaten, Pfad zur Bilddatei und Formatierung.

Beispiel 5: Bild invertieren

Raspberry Pi: OLED-Display-Beispiel Bild invertieren

Raspberry Pi: OLED-Display-Beispiel Bild invertieren

#!/usr/bin/env python
# coding=utf-8
 
# Bibliotheken importieren
from lib_oled96 import ssd1306
from smbus import SMBus
from PIL import Image
 
# Display einrichten
i2cbus = SMBus(1)            # 0 = Raspberry Pi 1, 1 = Raspberry Pi > 1
oled = ssd1306(i2cbus)
 
# Ein paar Abkürzungen, um den Code zu entschlacken
draw = oled.canvas
 
# Display zum Start löschen
oled.cls()
oled.display()
 
# Bilddatei ausgeben
draw.rectangle((32, 0, 95, 63), outline=1, fill=1)
draw.bitmap((32, 0), Image.open('pi_logo.png'), fill=0)
 
# Ausgaben auf Display schreiben
oled.display()

Um ein Bild zu invertieren zeichnen wir im Hintergrund ein gefülltes Rechteck und stellen fill beim Bild auf 0.

Sonstiges

Im Prinzip haben wir nun alles, was wir benötigen, um unser Display mit Leben zu befüllen. Wer weitere Inspiration benötigt schaut sich einfach mal die Beispiele an, die mit dem Git-Repository kamen.

Ein Hinweis zu den Bildern: Mein Display ist nicht defekt und meine Kamera auch nicht. In Wirklichkeit macht das Display eine wundervolle Farbe, die durch die Bildwiederholungen einfach schwer flimmerfrei einzufangen ist.

Sebastian

Sebastian

...ist staatlich geprüfter Techniker für Elektrotechnik, Schwerpunkt Prozessautomatisierung und Energietechnik. Die Themen Automatisierung und Programmierung haben es ihm besonders angetan.
Außerdem ist er für jede technische Spielerei zu haben 😉
Sebastian

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Translate »