U8g2-Anleitung für OLED- und LCD-Displays mit Arduino
Diese Anleitung bringt ein neues U8g2-Projekt von einer leeren Lopaka-Zeichenfläche bis zu einem funktionierenden Arduino-Sketch. Lopaka erzeugt den Zeichencode; du schließt das Display an und initialisierst es, wählst die Pufferung und entscheidest, wann welcher Screen angezeigt wird.
Was ist U8g2?
U8g2 ist eine Grafikbibliothek für monochrome OLED- und LCD-Displays. Sie unterstützt viele Controller, Zeichenprimitive, Bitmaps und eine große Sammlung von Schriftarten. Lopaka erzeugt Code für die grafische U8g2-API, nicht für die reine Text-API U8x8.
Prüfe mit dem offiziellen Setup-Tutorial und der Konstruktorliste, ob U8g2 genau dein Display unterstützt.
Bevor du anfängst
Du brauchst:
- Einen Mikrocontroller und ein monochromes Display, das U8g2 unterstützt.
- Den Namen des Display-Controllers, die Auflösung und die Schnittstelle, zum Beispiel SSD1306, 128×64, Hardware-I2C.
- Das Datenblatt des Displays oder die Verdrahtungsanleitung des Herstellers.
- Ein Arduino-kompatibles Projekt, mit dem du einen einfachen Sketch kompilieren und hochladen kannst.
Achtung
Lopaka erkennt deine Hardware nicht. Zwei Module, die gleich aussehen, können unterschiedliche Controller, Adressen, Pinbelegungen oder Display-Offsets haben.
Schritt 0: U8g2 installieren und testen
Öffne in der Arduino IDE Tools → Manage Libraries, suche nach U8g2 und installiere die Bibliothek von olikraus. So beschreibt es auch das offizielle U8g2-Repository.
Für eine manuelle Installation in Arduino lädst du die offizielle U8g2-Arduino-Distribution herunter und fügst ihr ZIP über Sketch → Include Library → Add .ZIP Library hinzu. Andere Toolchains können dieselbe offizielle Distribution über ihre Verwaltung von Bibliotheksabhängigkeiten nutzen. Nimm bevorzugt eine veröffentlichte Version, außer du brauchst gezielt eine noch unveröffentlichte Änderung.
Bevor du Lopaka-Code hinzufügst, kompiliere eines der U8g2-Beispiele für dein Display und lade es hoch. Läuft das Beispiel, stimmen Konstruktor, Verdrahtung und Installation der Bibliothek.
Schritt 1: Display-Konstruktor wählen
Der Name des Konstruktors legt vier wichtige Dinge fest:
| Teil | Beispiel | Bedeutung |
|---|---|---|
| Controller und Display | SSD1306_128X64_NONAME | Hardwarefamilie und Auflösung |
| Puffer | F, 1 oder 2 | Vollbild- oder Seitenpuffer |
| Schnittstelle | HW_I2C, SW_I2C, 4W_HW_SPI usw. | Bus und Implementierung |
| Argumente | U8G2_R0, Reset- und Bus-Pins | Drehung und Verdrahtung |
Zum Beispiel:
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(
U8G2_R0,
U8X8_PIN_NONE
);Das ist nur ein Beispielkonstruktor für ein 128×64-SSD1306-Display mit Hardware-I2C. Ersetze ihn durch den genauen Konstruktor und die Argumente aus der offiziellen C++-Setup-Liste.
Vollpuffer oder Seitenpuffer?
- Ein Konstruktor mit
_F_hält das ganze Bild im RAM. Zeichne zwischenclearBuffer()undsendBuffer(). - Ein Konstruktor mit
_1_oder_2_nutzt einen kleineren Seitenpuffer. Setze die komplette Zeichenfunktion in die BildschleifefirstPage()/nextPage().
Der Vollpuffermodus ist einfacher und schneller, braucht aber mehr RAM. Bei einem 128×64-Bild mit einem Bit pro Pixel belegt allein der Pixelpuffer 1024 Byte. Der Seitenmodus braucht weniger RAM, zeichnet aber für jede Seite dasselbe Bild neu. Siehe den Leitfaden zu den Puffermodi von U8g2.
Schritt 2: Lopaka-Projekt anlegen
- Öffne lopaka.app und lege ein Projekt an.
- Wähle U8g2 als Plattform.
- Stelle Screen-Größe auf die logische Breite und Höhe des Displays ein. Für ein nicht gedrehtes 128×64-Display nimmst du
128 × 64. - Behalte den schwarzen Standardhintergrund. U8g2 gibt ein Bit pro Pixel aus, Lopaka-Designs unterscheiden also nur zwischen Vordergrund und Hintergrund statt RGB-Farben.
Die Größe der Lopaka-Zeichenfläche legt die Designfläche und das Koordinatensystem fest; sie wählt keinen U8g2-Konstruktor und konfiguriert nicht das physische Display.
Schritt 3: Screen gestalten
Platziere im Editor Text, Bilder und Zeichenprimitive. Die Position (0, 0) ist die linke obere Ecke der Zeichenfläche. Benenne Ebenen vor dem Export um: Aus den Namen werden Kommentare, Bildbezeichner, Animations-Header und optionale Variablennamen.
U8g2-Projekte in Lopaka erzeugen Folgendes:
| Lopaka-Ebene | Arduino-U8g2-Ausgabe |
|---|---|
| Linie | drawLine() |
| Rechteck | drawFrame() / drawBox() |
| Abgerundetes Rechteck | drawRFrame() / drawRBox() |
| Ellipse | drawEllipse() / drawFilledEllipse() |
| Dreieck | drawTriangle(); im U8g2-Inspektor von Lopaka immer gefüllt |
| Polygon | Eine Hilfsfunktion aus geschlossenen drawLine()-Aufrufen; nur Umriss |
| Text | setFont() plus drawStr() oder drawUTF8() |
| Malebene, Icon oder importiertes Bild | Ein monochromes XBM-Array plus drawXBM() oder drawXBMP() |
| Animation | Frame-Daten bzw. Header plus Hilfsfunktionen zur Frame-Auswahl und zum Zeichnen |
Vordergrund, Hintergrund und Invertierung
Das U8g2-Projekt ist monochrom, deshalb zeigt der Inspektor keine RGB-Farbauswahl. Normale Ebenen setzen Pixel; Ebenen mit Invertiert (XOR) nutzen die U8g2-Zeichenfarbe 2 (XOR). Lopaka erzeugt außerdem transparente Schrift- und Bitmap-Modi, damit leere Pixel in Text und Bildern darunterliegende Ebenen nicht löschen.
U8g2 weist darauf hin, dass nicht jede Primitive XOR unterstützt, auch die Ellipsen-Funktionen nicht. Prüfe invertierte Formen auf dem echten Display; siehe setDrawColor.
Position und Text-Grundlinie
Formkoordinaten nutzen die üblichen U8g2-Ursprünge. Text richtet sich nach der Grundlinie der Schriftart, nicht nach der Oberkante der sichtbaren Buchstaben. Ein Schriftartwechsel kann daher die sichtbare vertikale Ausrichtung verändern, auch wenn die Textebene an derselben Position bleibt.
Text lässt sich um 0°, 90°, 180° oder 270° drehen. Lopaka erzeugt bei Bedarf setFontDirection(). Details zu den Koordinaten findest du in der U8g2-API-Referenz.
Schritt 4: Generierten Code konfigurieren
Öffne die Code-Einstellungen und wähle Arduino (Cpp) für einen Arduino-Sketch. U8g2 bietet außerdem die Syntax ESP-IDF (C) für Projekte, die bereits die C-Schnittstelle von U8g2 nutzen; das ist weder eine vollständige ESP-IDF-Anwendung noch eine Hardware-Portierung.
| Einstellung | Was sie bei U8g2 ändert |
|---|---|
| Wrapper-Funktion | Packt den aktiven Screen in void draw{ScreenName}(void) |
| Als PROGMEM deklarieren | Nutzt U8X8_PROGMEM und drawXBMP() für Arduino-Bitmap-Deklarationen |
| Schriftarten einbinden | Bindet heruntergeladene Header eigener Schriftarten ein; integrierte U8g2-Schriftarten brauchen keinen Header |
| Bilder deklarieren | Erzeugt die Bitmap-Arrays für Mal- und Bildebenen |
| Bilddateien einbinden | Erzeugt #include "image_<Name>_bits.h" statt der Inline-Bitmap-Arrays |
| Animations-Hilfsfunktionen | Bindet heruntergeladene Animations-Header ein und erzeugt Hilfsfunktionen für Timing und Zeichnen |
| Variablen deklarieren | Erzeugt Deklarationen für Ebeneneigenschaften, die als Variablen markiert sind |
| Kommentare, Ebenentitel | Fügt der statischen Ausgabe Kommentare mit den Ebenennamen hinzu |
| Display leeren/füllen | Beginnt den Zeichenblock mit u8g2.clearBuffer() (Arduino) oder u8g2_ClearBuffer() (ESP-IDF); siehe Hinweis unten |
Lass unter Arduino alle Optionen außer Display leeren/füllen aktiviert.
Display leeren/füllen unter Arduino
In der Arduino-Vorlage ist Display leeren/füllen standardmäßig aus. Schaltest du es ein, beginnt draw{ScreenName}() mit u8g2.clearBuffer() und löscht damit alles, was dein Sketch vor dem Aufruf in den Puffer gezeichnet hat. Lass es aus, wenn dein loop() den Puffer schon leert oder vorher anderen Inhalt zeichnet. Bei aktivierten Animations-Hilfsfunktionen entfällt der Aufruf, weil die firstPage()/nextPage()-Schleife der Animation jede Seite ohnehin leert. Die ESP-IDF-Vorlage hat die Option standardmäßig eingeschaltet.
Schritt 5: Schriftarten und Bilder exportieren
Integrierte Schriftarten
Lopaka kennt die Liste der in U8g2 integrierten Schriftarten und passt den generierten Code an die gewählte Schriftart an. Ist eine Schriftart in U8g2 integriert, schreibt Lopaka direkt ihr Bibliothekssymbol in den Code und erzeugt keinen separaten Schriftart-Header zum Herunterladen. Zum Beispiel:
u8g2.setFont(u8g2_font_6x10_tr);Steht eine Schriftart nicht auf der Liste der integrierten, behandelt Lopaka sie als eigene Schriftart, erzeugt genau ein passendes Header-Include und listet diesen Header unter Code-Einstellungen → Schriftarten zum Herunterladen auf.
Die Größen integrierter Schriftarten sind fest; wähle eine andere Schriftart, um Text größer oder kleiner zu machen. In der offiziellen U8g2-Schriftartenliste siehst du, welche Zeichen eine Schriftart enthält.
Eigene Schriftarten
U8g2-Projekte akzeptieren BDF-Schriftarten und können TTF, OTF oder WOFF über den Schriftart-Assistenten von Lopaka in fester Größe importieren. In Code-Einstellungen → Schriftarten:
- Lade jede aufgeführte eigene
.h-Datei herunter. - Lege die Header neben deinen Sketch oder den generierten Quellcode.
- Lass Schriftarten einbinden aktiviert, damit die generierten
#include "Font_Name.h"-Zeilen erhalten bleiben.
Nur verwendete Glyphen rendern erzeugt einen kleineren Header, der nur die Zeichen enthält, die passende Textebenen gerade verwenden. Ist ein Textwert eine Laufzeitvariable, exportiert Lopaka die komplette eigene Schriftart, weil es künftige Zeichen nicht vorhersagen kann.
Bilder und Animationen
Statische Bilder werden in 1-Bit-XBM-Daten umgewandelt und können direkt im kopierten Quellcode deklariert werden. Mit aktiviertem Als PROGMEM deklarieren nutzt Lopaka U8X8_PROGMEM und drawXBMP(), passend zu den PROGMEM-Bitmap-Hinweisen von U8g2.
Code-Einstellungen → Bilder listet jedes Bild als image_<Name>_bits.h auf, mit genau den XBM-Bytes, die der Zeichenaufruf erhält. Aktiviere Bilddateien einbinden, um statt des Arrays #include "image_<Name>_bits.h" zu erzeugen und die Pixel im heruntergeladenen Header zu behalten.
Auch Animationen sind monochrom. Lade jede unter Animationen aufgeführte .h-Datei herunter, lege sie zum Sketch und behalte das generierte Include und den Hilfscode. Die Arduino-Hilfsfunktion wählt die Frames mit millis(). Du bist weiterhin dafür verantwortlich, die Update-Hilfsfunktion aufzurufen und den kompletten Screen in der richtigen Pufferschleife neu zu zeichnen.
Achtung
Die Animationsausgabe kann Startcode für setup() und loop() enthalten. Übernimm deren Includes, das Frame-Update und die Zeichen-Hilfsfunktionen in deinen Sketch und nutze dann das Aktualisierungsmuster für Vollpuffer oder Seitenpuffer aus dieser Anleitung. Behalte kein zweites setup() oder loop().
Schritt 6: Code kopieren und einbinden
Lege einen Screen namens Main an, füge eine Textebene und einen Rahmen hinzu und klicke im Code-Bereich von Lopaka auf Kopieren. Eine typische generierte Zeichenfunktion sieht so aus:
void drawMain(void) {
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(8, 18, "Hello!");
u8g2.drawFrame(0, 0, 128, 64);
}Dein Code enthält den Namen deines Screens und deine eigenen Ebenen, Schriftarten und Koordinaten.
Minimaler Sketch mit Vollpuffer
Nutze dieses Muster nur mit einem _F_-Konstruktor:
#include <Arduino.h>
#include <Wire.h>
#include <U8g2lib.h>
// Hardware-specific: replace with the constructor for your display.
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(
U8G2_R0,
U8X8_PIN_NONE
);
// Paste Lopaka asset declarations, custom-font includes, helpers,
// and the generated drawMain() function here.
void drawMain(void) {
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(8, 18, "Hello!");
u8g2.drawFrame(0, 0, 128, 64);
}
void setup(void) {
u8g2.begin();
}
void loop(void) {
u8g2.clearBuffer();
drawMain();
u8g2.sendBuffer();
}Alternative mit Seitenpuffer
Nutze dieses Bildschleifen-Muster mit einem _1_- oder _2_-Konstruktor:
void loop(void) {
u8g2.firstPage();
do {
drawMain();
} while (u8g2.nextPage());
}Ändere im Seitenmodus keinen UI-Zustand innerhalb von drawMain(). U8g2 ruft die Funktion für ein einziges Bild mehrmals auf, und jeder Durchlauf muss dasselbe Bild zeichnen. Aktualisiere Sensorwerte, Navigationszustand und Auswahl des Animations-Frames vor firstPage().
Schritt 7: Laufzeitdaten und weitere Screens hinzufügen
Um einen Wert dynamisch zu machen, wähle seine Eigenschaft im Inspektor aus, aktiviere den Variablenschalter und lass Variablen deklarieren aktiviert. Lopaka ersetzt dann das Literal durch eine benannte Deklaration auf Basis des Ebenennamens. Deine Anwendung kann diesen Wert vor dem nächsten Neuzeichnen aktualisieren.
Jeder Lopaka-Screen wird separat exportiert, und sein Titel wird zum Namen der Zeichenfunktion. Kopiere die Funktion jedes Screens ins Projekt, führe gemeinsame Includes und Assets zusammen, damit sie nur einmal deklariert sind, und entscheide dann, welche Funktion aufgerufen wird:
enum Screen { MAIN, DETAILS };
Screen currentScreen = MAIN;
void drawCurrentScreen(void) {
if (currentScreen == MAIN) {
drawMain();
} else {
drawDetails();
}
}Lopaka erzeugt keine Navigation zwischen Screens, keine Tastenbehandlung, keine Menüs, kein Auslesen von Sensoren und keinen Anwendungszustand.
Was Lopaka übernimmt und was du übernimmst
| Lopaka übernimmt | Du übernimmst |
|---|---|
| Pixel-Layout und Reihenfolge der Ebenen | Verdrahtung, Spannung und Pinbelegung des Displays |
| U8g2-Zeichenaufrufe für unterstützte Ebenen | Den genauen Konstruktor für Controller, Schnittstelle und Puffer |
| Verweise auf integrierte Schriftarten | Installation von U8g2 und der Board-Toolchain |
| Umwandlung eigener Schriftarten und Header zum Download | Die eigenen Header beim Quellcode behalten |
| 1-Bit-Bitmap-Deklarationen | RAM-/Flash-Budget und Wahl des Puffers |
| Optionale Variablen und Animations-Hilfsfunktionen | begin(), Aktualisierungsschleife, Timing und Anwendungszustand |
| Eine benannte Zeichenfunktion pro exportiertem Screen | Eingaben, Navigation, Sensoren und den Zeitpunkt des Neuzeichnens |
Kompilieren, hochladen und iterieren
- Kompiliere vor dem Hochladen. Behebe zuerst jeden fehlenden Header und jedes fehlende Symbol.
- Lade hoch und vergleiche das physische Display mit der Lopaka-Zeichenfläche.
- Passe Konstruktor, Drehung, Größe der Zeichenfläche oder Ebenenpositionen nach Bedarf an.
- Wenn sich das Design ändert, ersetze den kompletten generierten Abschnitt, statt einzelne generierte Aufrufe an mehreren Stellen zu bearbeiten.
Halte Hardware- und Anwendungscode außerhalb des generierten Abschnitts, damit ein neuer Export ihn nicht überschreibt:
// BEGIN LOPAKA GENERATED CODE
// Replace this entire block after exporting again.
// END LOPAKA GENERATED CODEFehlerbehebung
Das Display bleibt leer
- Lade zuerst ein offizielles U8g2-Beispiel mit demselben Konstruktor hoch. Bleibt auch das leer, prüfe Stromversorgung, Masse, Verdrahtung, Controller, Reset-Pin und Schnittstelle.
- Stelle sicher, dass
u8g2.begin()genau einmal ausgeführt wird. - Stelle sicher, dass bei
_F_zwischenclearBuffer()/sendBuffer()gezeichnet wird bzw. bei_1_und_2_innerhalb der komplettenfirstPage()/nextPage()-Schleife. - Scanne bei I2C den Bus und vergleiche das Ergebnis mit der Dokumentation des Moduls. Wenn du
setI2CAddress()aufrufst, erwartet U8g2 die mit zwei multiplizierte Adresse, und der Aufruf muss vorbegin()stehen; siehe die offizielle Referenz.
Das Bild ist verschoben, abgeschnitten, gespiegelt oder gedreht
Prüfe, ob die Lopaka-Zeichenfläche der logischen Displaygröße des Konstruktors entspricht. Wähle die genaue Controller- bzw. Display-Variante: Bei manchen Modulen ist der Controller-RAM breiter als das sichtbare Panel. Nutze U8G2_R0 bis U8G2_R3 im Konstruktor für die Drehung des Displays und halte die Abmessungen in Lopaka passend zu dieser Ausrichtung.
Farben oder überlappende Formen wirken invertiert
U8g2 gibt ein Bit pro Pixel aus, keine Graustufen und kein RGB. Deaktiviere Invertiert (XOR) an der Ebene, wenn XOR nicht beabsichtigt war. Nicht jede U8g2-Primitive unterstützt XOR, prüfe invertierte Ellipsen deshalb auf der Hardware.
Eine Schriftart oder ein Symbol ist nicht definiert
- Namen integrierter Schriftarten müssen in der installierten U8g2-Version existieren und die verwendeten Glyphen enthalten.
- Lade bei einer eigenen Schriftart ihre
.hherunter, lege sie neben den Quellcode und lass Schriftarten einbinden aktiviert. - Wenn Zeichen leer bleiben, deaktiviere Nur verwendete Glyphen rendern und exportiere die eigene Schriftart erneut, besonders wenn sich Text zur Laufzeit ändert.
Dem Sketch geht der Speicher aus
Probiere einen _1_- oder _2_-Konstruktor mit Seitenpuffer, kleinere Bilder, weniger Animations-Frames oder eigene Schriftarten, die nur die benötigten Glyphen enthalten. Integrierte Schriftarten und Assets belegen Flash; der vollständige Display-Puffer belegt RAM.
Bilder wirken grob oder vertauscht
U8g2-Bilder haben ein Bit pro Pixel, deshalb kommt es auf Größe, Zuschnitt, Kontrast, Schwellenwert und Dithering an. Öffne den Bild-Assistenten von Lopaka erneut und prüfe die Vorschau in der endgültigen Pixelgröße. Halte Als PROGMEM deklarieren passend zur generierten Deklaration und zum drawXBMP()-Aufruf.
Der Seitenmodus flackert oder zeigt nur einen Teil des Screens
Rufe die komplette Zeichenfunktion innerhalb der do / while-Bildschleife auf. Zeichne keine Ebenen vor firstPage(), ändere keine Werte zwischen den Seiten und rufe nicht nur firstPage() ohne nextPage() auf.
FAQ
Konfiguriert Lopaka mein SSD1306- oder SH1106-Display?
Nein. Lopaka erzeugt Zeichencode. Den passenden Konstruktor, Bus, die Pins, Adresse, Drehung, den Puffermodus und die Initialisierung wählst du selbst.
Kann ich stattdessen U8x8 verwenden?
Nicht mit der U8g2-Ausgabe von Lopaka. U8x8 ist eine eigene, rein zeichenbasierte API und unterstützt die Grafikprimitive nicht, die Lopaka erzeugt.
Kann Lopaka farbigen U8g2-Code erzeugen?
Nein. Die U8g2-Plattform in Lopaka ist monochrom. Wähle für ein RGB-Display eine Farbplattform wie TFT_eSPI oder ArduinoGFX.
Ist der ESP-IDF-(C)-Export ein vollständiges Firmware-Projekt?
Nein. Er erzeugt Zeichencode für die C-Schnittstelle und Assets. Dein ESP-IDF-Projekt muss die U8g2-Struktur, die GPIO- und Bus-Callbacks, die Task-Schleife, die Initialisierung und die Plattformanbindung selbst konfigurieren.