25.09.2018, 14:04
Ich habe ja schon einige Anfragen dazu bekommen, wie man am kleinen Internetradio aus dem Bausatz ein Display betreibt.
Im Prinzip kommt ein 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.
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:
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:
Nun das OLED-Display anschließen.
Mit ein paar Steckbrücken verbinden wir den Pi Zero mit dem OLED-Display. Es gibt SSD1603-OLEDs die können mit 5V und/oder nur mit 3.3V betrieben werden. Die I2C Pins SDA und SCL auf dem Pi Zero sind aber 3.3V (!) Pins. Achtet also darauf. Betreibt Ihr das Display durchweg mit 3.3V ist in der Regel kein Pegelwandler erforderlich.
Nach dem Anschließen kann man das Display schon mal testen, indem man mit einem kleinen Kommandozeilentool die I2C-Adresse des Displays ermittelt.
Da I2C ein Bus-System für mehrere Teilnehmer ist, haben alle Teilnehmer auch eine Busadresse. Bei diesen kleinen OLEDs 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:
Als Ausgabe erhalten wir dann so eine Tabelle, der wir als Adresse des (momentan) 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: -- -- -- -- -- -- -- --
Nun der Python-Code (auf dem Radio läuft ja sowieso vieles in Python, also nutzen wir die Sprache einfach weiter, C wie bei den Arduinos geht natürlich auch).
Für die Ansteuerung des Displays machen wir uns eine kleine fertige Python-Bibliothek auf Github zu Nutze. Die klonen wir und haben damit alles, was wir benötigen:
Wir wechseln in das Verzeichnis lib_oled96 und legen uns dort eine neue Script-Datei an:
Anschließend öffnen wir die soeben erstellte Datei in einem beliebigen Editor und fangen mit der Programmierung an, ich benutze hier den Editor nano:
Die Adresse 0x3c ist in der von uns verwendeten Python-Bibliothek schon vorausgewählt, sodass wir der Adresse keine weitere Beachtung schenken müssen.
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.
ACHTUNG: Alle Display-Manipulationen werden solange gesammelt, bis sie mit dem Befehl oled.display() auf dem Display ausgeführt 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:
Schriften formatieren:
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).
Das Ergebnis sieht dann so aus:
[attachment=54388]
An den entsprechenden Stellen könnte dann der aktuelle Sendername und das gespielte Lied/Programm stehen. Wie man an diese Daten von vlc kommt, habe ich ja im Nachbarthread geschrieben, Otto hatte dazu sogar ein einfaches Script gezeigt.
Mit weiteren Grafikprimitiven ist dann sogar das Zeichnen von Figuren möglich.
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.
Übrigens: mit oled.height und oled.width kann man über die gesamte Bildschirmbreite zeichnen, die Variablen enthalten Angaben zur Höhe und Breite des OLEDs.
Viel Spaß am weiteren Ausbau des Pimoroni-Bausatzes!
Im Prinzip kommt ein 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.
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:
Code:
$ 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:
Code:
$ sudo apt-get install python-smbus i2c-tools git python-pil
Nun das OLED-Display anschließen.
Mit ein paar Steckbrücken verbinden wir den Pi Zero mit dem OLED-Display. Es gibt SSD1603-OLEDs die können mit 5V und/oder nur mit 3.3V betrieben werden. Die I2C Pins SDA und SCL auf dem Pi Zero sind aber 3.3V (!) Pins. Achtet also darauf. Betreibt Ihr das Display durchweg mit 3.3V ist in der Regel kein Pegelwandler erforderlich.
Nach dem Anschließen kann man das Display schon mal testen, indem man mit einem kleinen Kommandozeilentool die I2C-Adresse des Displays ermittelt.
Da I2C ein Bus-System für mehrere Teilnehmer ist, haben alle Teilnehmer auch eine Busadresse. Bei diesen kleinen OLEDs 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:
Code:
$ i2cdetect -y 1
Als Ausgabe erhalten wir dann so eine Tabelle, der wir als Adresse des (momentan) 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: -- -- -- -- -- -- -- --
Nun der Python-Code (auf dem Radio läuft ja sowieso vieles in Python, also nutzen wir die Sprache einfach weiter, C wie bei den Arduinos geht natürlich auch).
Für die Ansteuerung des Displays machen wir uns eine kleine fertige Python-Bibliothek auf Github zu Nutze. Die klonen wir und haben damit alles, was wir benötigen:
Code:
$ git clone https://github.com/BLavery/lib_oled96
Wir wechseln in das Verzeichnis lib_oled96 und legen uns dort eine neue Script-Datei an:
Code:
$ cd lib_oled96
$ touch display.py
$ chmod 755 display.py
Anschließend öffnen wir die soeben erstellte Datei in einem beliebigen Editor und fangen mit der Programmierung an, ich benutze hier den Editor nano:
Code:
$ nano display.py
Die Adresse 0x3c ist in der von uns verwendeten Python-Bibliothek schon vorausgewählt, sodass wir der Adresse keine weitere Beachtung schenken müssen.
Code:
#!/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.
ACHTUNG: Alle Display-Manipulationen werden solange gesammelt, bis sie mit dem Befehl oled.display() auf dem Display ausgeführt 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:
Code:
$ ./display.py
Schriften formatieren:
Code:
#!/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).
Das Ergebnis sieht dann so aus:
[attachment=54388]
An den entsprechenden Stellen könnte dann der aktuelle Sendername und das gespielte Lied/Programm stehen. Wie man an diese Daten von vlc kommt, habe ich ja im Nachbarthread geschrieben, Otto hatte dazu sogar ein einfaches Script gezeigt.
Mit weiteren Grafikprimitiven ist dann sogar das Zeichnen von Figuren möglich.
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.
Übrigens: mit oled.height und oled.width kann man über die gesamte Bildschirmbreite zeichnen, die Variablen enthalten Angaben zur Höhe und Breite des OLEDs.
Viel Spaß am weiteren Ausbau des Pimoroni-Bausatzes!