Anzeigedienst

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.h Ihres Boards

Hardwarekonfiguration

EigenschaftWert
AnzeigeSSD1306 OLED
Auflösung128×64 Pixel
SchnittstelleI2C (Hardware)
DrehungU8G2_R0 (0°)
I2C-Adresse0x3C
Kontrast255 (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

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.

FunktionBeschreibungRegion gelöscht
clearHeader()Löscht nur den KopfzeilentextZeile 0, Zellen 0–12
clearIcons()Löscht nur den SymbolbereichZeile 0, Zellen 13–15
clearFooter()Löscht nur FußzeilentextZeile 7, Zellen 0–14
clearTimeout()Löscht die Timeout-AnzeigeZeile 7, Zelle 15
clearPage(includeFooter=false, includeHeader=false)Löscht den Seitenbereich; optionale Kopf-/FußzeileZeilen 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.

FunktionBeschreibungRegion aktualisiert
refreshHeader()Überträgt den KopfzeilentextZeile 0, Zellen 0–12
refreshIcons()Überträgt den SymbolbereichZeile 0, Zellen 13–15
refreshFooter()Überträgt den FußzeilentextZeile 7, Zellen 0–14
refreshTimeout()Aktualisiert die Timeout-AnzeigeZeile 7, Zelle 15
refreshPage(includeFooter=false, includeHeader=false)Überträgt den Hauptinhalt; optionale Kopf-/FußzeileZeilen 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

BereichEmpfohlene Schriftart
Kopf-/Fußzeileu8g2_font_spleen5x8_mu
SeiteninhaltAus 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

Abhängigkeiten

AbhängigkeitZweck
U8G2SSD1306-Rendering und Schriftartenverarbeitung
FreeRTOSMutex für Thread-Sicherheit
ESP32 HALHardware-I2C-Schnittstelle
Pins.hPlatinen-Pin-Definitionen für SDA/SCL

Verwandte Seiten

Auf dieser Seite