Verwenden Sie den threadsicheren Anzeigedienst, um mit U8G2 auf das 128×64 SSD1306 OLED zu zeichnen.
Überblick
Der Anzeigedienst ist ein globaler, threadsicherer Wrapper um den U8G2-Treiber für ein 128×64 SSD1306 OLED. Sie verwenden ihn, um Text und Grafiken aus jeder Aufgabe ohne Flimmern oder Tearing zu rendern. Ein FreeRTOS-Mutex garantiert exklusiven Zugriff beim Zeichnen; Hilfsfunktionen kümmern sich um das Löschen von Regionen, die teilweise Aktualisierung, das Ausschneiden und das Zwischenspeichern von Text.
Auf dieser Seite wird die Entwickler-API auf Firmware-Ebene dokumentiert, die auf unseren Geräten verwendet wird. Informationen zum benutzerseitigen Anzeigeverhalten (z. B. Ausblenden der Bildschirme für die verbleibende Zeit oder den Gerätestatus) finden Sie auf den entsprechenden Seiten am Ende.
Voraussetzungen
- ESP32 mit Hardware-I2C verfügbar
- U8G2-Bibliothek in Ihren Firmware-Build integriert
- FreeRTOS (für den Display-Mutex)
- Für SDA/SCL konfigurierte Pins im
Pins.hIhres Boards
Hardwarekonfiguration
| Eigenschaft | Wert |
|---|---|
| Anzeige | SSD1306 OLED |
| Auflösung | 128×64 Pixel |
| Schnittstelle | I2C (Hardware) |
| Drehung | U8G2_R0 (0°) |
| I2C-Adresse | 0x3C |
| Kontrast | 255 (maximal) |
Einige U8G2-Konstruktoren erwarten die 8-Bit-I2C-Adresse. Wenn ja, übergeben Sie 0x3C << 1. Stellen Sie sicher, dass dies mit Ihrer Konstruktorsignatur übereinstimmt.
Layoutmodell
Der Bildschirm wird als Raster aus 8×8-Pixel-Zellen behandelt:
- Raster: 8 Zeilen × 16 Spalten
- Ursprung: (0,0) oben links
- Zellengröße: 8×8 Pixel
Regionen
- Zellen 0–12: Kopftext (13 Zellen = 104 px)
- Zellen 13–15: Statussymbole (3 Zellen = 24 px)
- 6 Zeilen hoch (48 px)
- 16 Zellen breit (128 px)
- Der gesamte Hauptinhalt sollte hier gerendert werden
- Zellen 0–14: Fußzeilentext (15 Zellen = 120 px)
- Zelle 15: Timeout-Anzeige (1 Zelle = 8 px)
U8G2-Text-APIs verwenden die Baseline für y. Beginnen Sie bei Schriftarten mit einer Höhe von 8 Pixeln die erste Textzeile bei y = 8 und fügen Sie dann die Oberlänge/Zeilenhöhe der Schriftart für nachfolgende Zeilen hinzu.
Thread-Sicherheit
Der Anzeigedienst stellt einen FreeRTOS-Mutex bereit. Vor dem Zeichnen immer sperren und wieder entsperren, wenn Sie fertig sind.
#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
extern SemaphoreHandle_t displayMutex;Wenn Sie den Mutex nicht freigeben, werden alle anderen Aufgaben blockiert, die die Anzeige benötigen. Koppeln Sie immer einen erfolgreichen xSemaphoreTake mit xSemaphoreGive in einem Pfad im finally-Stil.
Grundlegendes Nutzungsmuster
// Acquire, draw, refresh affected region(s), release
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
// ... drawing commands, e.g.:
display.drawStr(x, y, "HELLO WORLD");
// Call an appropriate refresh helper (see below)
refreshPage();
xSemaphoreGive(displayMutex);
}Initialisierung
Rufen Sie initDisplay() einmal beim Start auf.
#pragma once
void initDisplay();Erstellen Sie Ressourcen und konfigurieren Sie das Panel
initDisplay() erstellt den Anzeige-Mutex, initialisiert die U8G2-Anzeigeinstanz, legt Adressierung/Rotation/Kontrast fest und löscht den Puffer.
Nach der Initialisierung sollte der Bildschirm leer und von hinten beleuchtet sein und displayMutex darf nicht Null sein.
Zeichnung überprüfen
Rendern Sie eine einzelne Textzeile im Seitenbereich.
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
clearPage();
display.setFont(u8g2_font_spleen5x8_mu);
display.drawStr(0, 16, "SANITY PASS");
refreshPage();
xSemaphoreGive(displayMutex);
}Löschhilfen
Löschen Sie effizient nur das, was Sie neu zeichnen möchten. Alle Hilfsfunktionen verwenden intern updateDisplayArea(), um eine teilweise Aktualisierung der betroffenen Region durchzuführen.
| Funktion | Beschreibung | Region gelöscht |
|---|---|---|
clearHeader() | Löscht nur den Kopfzeilentext | Zeile 0, Zellen 0–12 |
clearIcons() | Löscht nur den Symbolbereich | Zeile 0, Zellen 13–15 |
clearFooter() | Löscht nur Fußzeilentext | Zeile 7, Zellen 0–14 |
clearTimeout() | Löscht die Timeout-Anzeige | Zeile 7, Zelle 15 |
clearPage(includeFooter=false, includeHeader=false) | Löscht den Seitenbereich; optionale Kopf-/Fußzeile | Zeilen 1–6 (plus Kopf-/Fußzeile auf Anfrage) |
void clearHeader();
void clearIcons();
void clearFooter();
void clearTimeout();
void clearPage(bool includeFooter = false, bool includeHeader = false);clearPage() legt ein Clipping-Fenster fest, um zu verhindern, dass Inhalte in die Kopf- oder Fußzeile gelangen.
Aktualisierungs-Hilfsfunktionen
Rufen Sie einen Aktualisierungshelfer auf, nachdem Sie eine Region geändert haben. Diese führen minimale Aktualisierungen der Anzeige durch.
| Funktion | Beschreibung | Region aktualisiert |
|---|---|---|
refreshHeader() | Überträgt den Kopfzeilentext | Zeile 0, Zellen 0–12 |
refreshIcons() | Überträgt den Symbolbereich | Zeile 0, Zellen 13–15 |
refreshFooter() | Überträgt den Fußzeilentext | Zeile 7, Zellen 0–14 |
refreshTimeout() | Aktualisiert die Timeout-Anzeige | Zeile 7, Zelle 15 |
refreshPage(includeFooter=false, includeHeader=false) | Überträgt den Hauptinhalt; optionale Kopf-/Fußzeile | Zeilen 1–6 (plus Kopf-/Fußzeile auf Anfrage) |
void refreshHeader();
void refreshIcons();
void refreshFooter();
void refreshTimeout();
void refreshPage(bool includeFooter = false, bool includeHeader = false);Inhaltshelfer
setHeader()
Legt den Kopfzeilentext fest. Der Dienst wandelt den letzten Wert in Großbuchstaben um und speichert ihn zwischen, um redundante Neuzeichnungen zu vermeiden.
void setHeader(String &text);Wenn Sie setHeader() mit demselben Wert aufrufen, überspringt der Dienst sowohl das Zeichnen als auch die Aktualisierung.
setFooter()
Legt links- und rechtsbündigen Fußzeilentext fest. Beide werden in Großbuchstaben geschrieben und zwischengespeichert.
void setFooter(String &left, String &right);- Die linke Zeichenfolge wird am linken Rand des Fußzeilenbereichs ausgerichtet
- Die rechte Zeichenfolge wird am rechten Rand des Fußzeilenbereichs ausgerichtet
drawWrappedText()
Zeichnen Sie Text mit automatischem Zeilenumbruch und optionaler zentrierter Ausrichtung.
int drawWrappedText(int x, int y, const String &text, bool center = false);intrequired
Start-X-Koordinate in Pixel.
intrequired
Y-Koordinate der Startbasislinie in Pixel.
Stringrequired
Text zum Rendern. Unterstützt das Literal \n für Zeilenumbrüche.
bool
Zentrieren Sie jede umbrochene Zeile innerhalb des Seitenbereichs, wenn true gesetzt ist.
returnintrequired
Anzahl der gezeichneten Zeilen.
Gemeinsame Muster
Zeichnen Sie einen vollständigen Bildschirm
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
clearPage();
display.setFont(u8g2_font_spleen5x8_mu);
display.drawStr(0, 16, "MAIN CONTENT");
refreshPage();
xSemaphoreGive(displayMutex);
}Dieses Muster löscht nur den Seitenbereich, zeichnet neuen Inhalt und führt aus Geschwindigkeitsgründen eine teilweise Aktualisierung durch.
Nur den Header aktualisieren
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
String headerText = "NEW HEADER"; // case‑insensitive; will be uppercased
setHeader(headerText);
// setHeader internally decides whether a refresh is required
xSemaphoreGive(displayMutex);
}Zeichnen Sie umbrochenen, zentrierten Text
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
clearPage();
int lines = drawWrappedText(0, 16, "Long text that will wrap", /*center=*/true);
(void)lines; // optionally use the line count
refreshPage();
xSemaphoreGive(displayMutex);
}Zeichnungsrichtlinien
Sperren Sie den Mutex für jede Zeichensequenz
Fassen Sie Zeichnen und Aktualisieren in einem durch displayMutex geschützten kritischen Abschnitt zusammen.
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
// Drawing
xSemaphoreGive(displayMutex);
}Bevorzugen Sie Regionshelfer gegenüber vollständigen Löschvorgängen
Minimieren Sie Busverkehr und Flimmern, indem Sie die Hilfsprogramme clear*() und refresh*() verwenden.
clearPage();
display.drawStr(0, 16, "Content");
refreshPage();// Full‑buffer clears cost time and cause visible flicker
// display.clearBuffer();Beachten Sie die Grenzen
Halten Sie den Inhalt innerhalb von:
- Kopfzeile: Zeile 0, Zellen 0–12
- Symbole: Zeile 0, Zellen 13–15
- Seite: Zeilen 1–6
- Fußzeile: Zeile 7, Zellen 0–14; Timeout-Anzeige in Zelle 15
Verwenden Sie clearPage(), um den Seiteninhalt von der Kopf-/Fußzeile fernzuhalten.
Wählen Sie lesbare Schriftarten
| Bereich | Empfohlene Schriftart |
|---|---|
| Kopf-/Fußzeile | u8g2_font_spleen5x8_mu |
| Seiteninhalt | Aus Gründen der Lesbarkeit auswählen; passen Sie den Zeilenabstand anhand der Schriftartmetriken an |
Berücksichtigen Sie bei der Berechnung der y-Versätze zwischen Zeilen die Oberlänge der Schriftart und die Gesamtzeilenhöhe.
Leistungsüberlegungen
- Bei Teilaktualisierungen werden nur die von Ihnen geänderten Regionen neu gezeichnet
- Text-Caching vermeidet unnötige Zeichen-/Aktualisierungszyklen
- Durch das Ausschneiden bleibt das Zeichnen innerhalb des vorgesehenen Bereichs und unnötiges Überzeichnen wird reduziert
- Mutex-geschützte Sequenzen verhindern Bildzerreißen mitten im Frame zwischen Aufgaben
Fehlerbehebung
- Bestätigen Sie, dass
initDisplay()einmal aufgerufen wird - Überprüfen Sie die I2C-Adresse (versuchen Sie je nach Konstruktor
0x3Cund0x3C << 1). - Stellen Sie sicher, dass SDA/SCL mit dem
Pins.hIhres Boards übereinstimmen
- Verwenden Sie das Löschen/Aktualisieren von Regionen anstelle des vollständigen Löschens des Puffers
- Bündeln Sie Ihre Zeichenvorgänge in einem durch den Mutex geschützten Block
- Vermeiden Sie unnötige Schriftartänderungen zwischen Zeichenaufrufen
- Denken Sie daran, dass U8G2 eine Baseline für
yverwendet - Beginnen Sie die erste 8-Pixel-Schriftzeile bei
y = 8oder berechnen Sie dies anhand der Oberlänge der Schriftart
- Geben Sie den Mutex immer in Fehlerpfaden frei
- Bevorzugen Sie Wrapper im RAII-Stil oder
goto cleanup-Muster
Abhängigkeiten
| Abhängigkeit | Zweck |
|---|---|
| U8G2 | SSD1306-Rendering und Schriftartenverarbeitung |
| FreeRTOS | Mutex für Thread-Sicherheit |
| ESP32 HAL | Hardware-I2C-Schnittstelle |
Pins.h | Platinen-Pin-Definitionen für SDA/SCL |
Verwandte Seiten
Anzeigezeit ausblenden (Benutzerfunktion)
Wie die Benutzeroberfläche die verbleibende Zeit auf Gerät, Dashboard und Benachrichtigungen verbirgt.
Ablauf der Notentriegelungsanzeige
Bildschirmablauf und Folgen der Auslösung der Notentsperrung auf dem Gerät.
Geräteunterstützungsmatrix
Unterstützte und geplante Geräte im Zeitraum 2025–2026.