Einbinden eines OLED-Displays auf Basis des SSD1306

https://bildung.social/deck/@oerinformatik/

https://oer-informatik.de/esp_ssd1306

tl/dr; (ca. 3 min Lesezeit): Kleine OLED-Displays eignen sich hervorragend, um bei MCU-Projekten Messwerte und den Systemstatus auszugeben. Einige beliebte Display bauen auf dem Chip SSD1306 auf. In diesem Artikel finden sich Codeausschnitte und Verdrahtungspläne, um ein einfaches “Hello World” auf dem Display auszugeben. (Zuletzt geändert am 11.11.2025)

Ein günstiges und häufig genutztes Display für Microcontrollerprojekte sind Breakout-Boards auf Basis von SSD1306-Displays. Diese können häufig per I2C und (seltener) per SPI angesprochen werden.

Generelle Überlegungen zu Installation und Inbetriebnahme von Devices am Microcontrollerboard

Das Vorgehen ist eigentlich bei allen Geräten im Arduino-Kosmos identisch, unabhängig davon, ob es ein Sensor, ein Aktor, ein Display oder etwas völlig anderes ist:

  1. Typenbezeichnung suchen: Zuerst muss die Art und Typ des neuen Geräts herausgefunden werden. Manchmal steht dies auf der Platine, manchmal muss man im Netz nach Fotos/Pinouts suchen (siehe unten).

  2. Bibliothek wählen und installieren: Wird mit der Arduino-IDE, so muss im Menü Werkzeuge / Bibliotheken verwalten eine passende Bibliothek für das Gerät gesucht werden. Häufig sind die Bibliotheken von Adafruit relativ gut.

  3. Pins des Geräts recherchieren und Logiklevel prüfen: Zum Anschließen des Geräts benötigen wir die Pinbezeichnungen der jeweils genutzten Platine. Nicht immer ist der Aufdruck auf den Platinen komplett, häufig wirkt ein zusätzliches Pinout (Bildersuche nach “Pinout Gerätebezeichnung”) Wunder. Dabei sollte im Datenblatt auch geprüft werden, ob das Logiklevel der Platine mit dem des Microcontrollers kompatibel ist (Arduino Uno: 5V, ESPs, Arduino Mega: 3,3V).

  4. Freie Pins des Microcontrollers wählen: Bevor wir verdrahten können, sollten wir uns noch entscheiden, welche Schnittstelle wir verwenden wollen (wenn das Gerät mehrere anbietet - z.B. SPI oder I2C). Dazu benötigen wir eine Liste der freien Pins unseres Microcontrollers, der für diese Schnittstelle geeignet ist (für einige ESPs beispielsweise in diesem Artikel). Ggf. hilft auch ein Blick in die Beispielquelltexte mit Hinweisen (s.u.).

  5. Verdrahten und mit Beispielcode erkunden: Dann kann das Gerät verdrahtet werden und über Beispiel-Quelltexte (Datei/ Beispiele häufig ganz unten: “Beispiele angepasster Bibliotheken”) erkundet werden.

Zu (1) Typenbezeichnung suchen: SSD1306 - siehe oben

Zu (2) Bibliothek wählen und installieren: Werkzeuge / Bibliotheken verwalten

Die Suche nach “SSD1306” liefert u.a. die Bibliothek “Adafruit SSD1306”, die ich in dem Beispiel nutze - andere Bibliotheken können aber ebenso eingesetzt werden.

Installieren der Bibliothek “Adafruit SSD1306”
Installieren der Bibliothek “Adafruit SSD1306”

Die Bibliothek benötigt eine Reihe von weiteren Abhängigkeiten, die direkt mit installiert werden können:

Adafruit SSD1306 ist abhängig von BusIO und GFX Library
Adafruit SSD1306 ist abhängig von BusIO und GFX Library

Aufbau und Beispielcode mit der I2C-Schnittstelle

Zu (3) Pins des Geräts recherchieren

Ich schließe das Display per I2C-Schnittstelle an - hierfür sind neben der Spannungsversorgung (3V3, GND) noch die Signale Clock (SCL oder SCK) und Data (SDA) nötig. Falls weitere Pins existieren (z.B. CSB, SDO) sind diese wahrscheinlich für die Ansteuerung per SPI-Schnittstelle gedacht.

Zu (4) Freie Pins des Microcontrollers wählen

Da wir das Display per I2C-Schnittstelle anschließen wollen, nutzen wir einfach die vorgesehenen Pins:

  • bei ESP32 ist dies: GPIO21 für SDA und GPIO22 für SCL.

  • bei ESP8266 ist dies: D2 für SDA und D1 für SCL.

  • bei Arduino Uno ist dies: A4 für SDA und A5 für SCL.

Wenn bereits andere I2C Geräte an diesen Leitungen angeschlossen sind, dann kann das Display zusätzlich parallel angeschlossen werden - schließlich handelt es sich hierbei um ein Bus-System, dass genau für den Anschluss mehrere Geräte gedacht ist.

Es wären auch andere Pins möglich (siehe unten), aber so sparen wir uns etwas Konfigurationsarbeit.

Zu (5) Verdrahten und mit Beispielcode erkunden:

Der Aufbau sieht bei mir mit einem ESP32 Dev V1 so aus (vorsicht: ggf. ist die Pinleiste andersherum aufgelötet und alle Pins gespiegelt):

Beispiel der Verdrahtung des SSD1306 per I2C an einem ESP32 Dev V1 (erstellt mit Fritzing, weitere Quellen hier)
Beispiel der Verdrahtung des SSD1306 per I2C an einem ESP32 Dev V1 (erstellt mit Fritzing, weitere Quellen hier)

Natürlich müssen bei einem anderen Microcontroller auch andere Pins verwendet werden, da die Bibliothek die I2C-Standardpins der jeweiligen Boards verwendet. (Wie man von den Standardports abweichen kann erkläre ich weiter unten).

Die I2C-Schnittstelle identifiziert Geräte am Bus über eine eindeutige Adresse. Jedes Gerät erkennt anhand dieser Adresse, wer Empfänger der Nachrichten am Bus sein soll. Die Adresse umfasst sieben Bit, es gibt also 2^7 = 128 verschiedene Adressen ( also 0 und 127 dezimal, 0x00-0x7F hexadezimal, 0b00000000 - 0b01111111 binär). Damit mehrere Geräte des gleichen Typs angeschlossen werden können, wird häufig nur ein Teil dieser Adresse durch den Hersteller fest vorgegeben, einige Bit können manuell konfiguriert werden.

Das SSD1306-DIsplay wird das letzte Bit angepasst - es können die I2C-Adressen 0x3C (binär: 0b00111100) oder 0x3D (binär: 0b00111101) konfiguriert werden.

Ein minimales Programm, das das Display über die Adafruit-Bibliothek ansteuert, könnte also so aussehen:

Als Beispiel, welche Möglichkeiten das Display bietet, können wir folgenden Code mal genauer inspizieren:

#include <Adafruit_SSD1306.h>

//-------------------------------------------------------------------------------------
// List of Input- and Output-devices and Pins
//-------------------------------------------------------------------------------------
// Datatype | Name of Variable    | Pin No. connected | Name, Behaviour*/
const int     MCU_SDA             = 21;               // GPIO of MCU connected to SDA-Pin of Sensor
const int     MCU_SCL             = 22;               // GPIO of MCU connected to SDCL-Pin of Sensor

//Settings for OLED
const int     I2C_ADDR            = 0x3C;             // I2C-Address of the Display
const int     SCREEN_WIDTH        = 128;              // Anzahl der Pixel - üblich sind 128x32 oder 128x64
const int     SCREEN_HEIGHT       = 64;


Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

unsigned int seitenNr = 0;
unsigned long milliSekundenZeit = 0;

void setup(){
  Serial.begin(115200);
  Wire.begin(MCU_SDA, MCU_SCL); 
  if(!display.begin(-1, I2C_ADDR)) {
      Serial.println(F("SSD1306 allocation failed"));
    }
  milliSekundenZeit = millis();
}

void loop(){
  display.clearDisplay();                  // Lösche alles 
  display.setCursor(0,0);                  // Den Cursor auf Anfang (die obere linke Ecke) setzen
  display.setTextSize(2);                  // Etwas größere, leichter lesbare Schrift (4 Zeilen, 10 Zeichen)
  display.setTextColor(SSD1306_WHITE);     // Helle Schrift (auf dunklem Hintergrund)

  display.setTextSize(2);                  // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);     // Draw white text
  display.setCursor(0, 0);                 // Start at top-left corner
  display.cp437(true);                     //https://de.wikipedia.org/wiki/Codepage_437

  display.setTextSize(2);                  // Textsize 2 => ca. 10 Buchstaben pro Zeile, 4 Zeilen möglich
  display.println("ABCDEFGHIJ");       
  display.setTextSize(1);                  // Textsize 1 => ca. 21 Buchstaben pro Zeile, 8 Zeilen möglich   
  display.println("ABCDEFGHIJKLMNOPQRSTU");  
  display.display();                       // Anzeigen des zusammengestellten Bilds
  delay(1000);

  char textBuffer[21];                     // Formatierte Zahlen lassen sich z.B. über Char-Buffer erzeugen
  sprintf(textBuffer, "Seite    :    %3i ", seitenNr);
  display.println(textBuffer);

  sprintf(textBuffer, "Zeit [s] : %6.1f", (millis()-milliSekundenZeit)/1000.0);
  Serial.println(textBuffer);

  display.println(textBuffer);
  seitenNr++;
  display.display();
  delay(1000);

  display.setTextSize(1);     
  display.println("Zu langen       bricht mitten im Wort um."); // Aufgepasst: zu viel Text fällt hinten rüber...
  int16_t xpos = display.getCursorX();     // Text kann exakt positioniert werden, hier wird aktuelle
  int16_t ypos = display.getCursorY();     // position ausgelesen.
  display.display();
  delay(1000);  

  display.setCursor(xpos+60,ypos-16); //y: Zeile(Size=1)=8, Zeile(Size=2) = 16 / x: Buchstabe(Size=1)=6, Buchstabe(Size=2)=12  
  display.println("Text");
  display.setCursor(xpos,ypos); // Setze Cursor an oben ausgelesen Position am Ende des Texts.
  display.display();
  delay(1000);
  
  display.print("Umlaute: ae=");   // Test wird regulär mit US-Zeichencodierung ausgegeben. Umlaute liegen dort an anderen
  display.print(char(0x84));       // Positionen. Siehe https://de.wikipedia.org/wiki/Codepage_437
  display.print(", ue=");          // Hexadezimalwert entspricht Zeile und Spalte der oben verlinkten Tabelle
  display.print(char(0x81));       // Das ü steht in Zeilenindex 8 / Spaltenindex 1 (Zählung startet bei 0)
  display.display();
  delay(5000);
}

Quellen und weitere Informationen


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: Einbinden eines OLED-Displays auf Basis des SSD1306” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/esp_ssd1306 veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/mcu/arduino-esp. Stand: 11.11.2025.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: