Gebruik de threadveilige weergaveservice om op het 128×64 SSD1306 OLED-scherm met U8G2 te tekenen
Overzicht
De weergaveservice is een globale, threadveilige wrapper rond de U8G2-driver voor een 128×64 SSD1306 OLED. U gebruikt deze om tekst en grafische elementen vanuit elke taak weer te geven zonder flikkering of beeldscheuren. Een FreeRTOS-mutex garandeert exclusieve toegang terwijl u tekent; helperfuncties zorgen voor het wissen van regio's, gedeeltelijk vernieuwen, knippen en tekstcaching.
Deze pagina documenteert de ontwikkelaars-API op firmwareniveau die op onze apparaten wordt gebruikt. Voor gebruikersgericht weergavegedrag (bijvoorbeeld het verbergen van de schermen voor de resterende tijd of de apparaatstatus), zie de gerelateerde pagina's aan het einde.
Vereisten
- ESP32 met hardware I2C beschikbaar
- U8G2-bibliotheek geïntegreerd in uw firmware-build
- FreeRTOS (voor de displaymutex)
- Pinnen geconfigureerd voor SDA/SCL in de
Pins.hvan uw bord
Hardwareconfiguratie
| Eigenschap | Waarde |
|---|---|
| Display | SSD1306 OLED |
| Resolutie | 128×64 pixels |
| Interface | I2C (hardware) |
| Rotatie | U8G2_R0 (0°) |
| I2C-adres | 0x3C |
| Contrast | 255 (max.) |
Sommige U8G2-constructeurs verwachten het 8-bits I2C-adres. Als dat zo is, geef dan 0x3C << 1 door. Controleer of dit overeenkomt met uw constructorhandtekening.
Indelingsmodel
Het scherm wordt behandeld als een raster van cellen van 8×8 pixels:
- Raster: 8 rijen × 16 kolommen
- Oorsprong: (0,0) linksboven
- Celgrootte: 8×8 pixels
Regio's
- Cellen 0–12: koptekst (13 cellen = 104 px)
- Cellen 13–15: statuspictogrammen (3 cellen = 24 px)
- 6 rijen hoog (48 px)
- 16 cellen breed (128 px)
- Alle hoofdinhoud moet hier worden weergegeven
- Cellen 0–14: voettekst (15 cellen = 120 px)
- Cel 15: Time-outindicator (1 cel = 8 px)
U8G2-tekst-API's gebruiken de basislijn voor y. Voor lettertypen van 8 pixels hoog begint u de eerste tekstregel bij y = 8 en voegt u vervolgens de stamhoogte/lijnhoogte van het lettertype toe voor de daaropvolgende regels.
Threadveiligheid
De weergaveservice biedt een FreeRTOS-mutex. Vergrendel deze altijd voordat u tekent en ontgrendel de mutex wanneer u klaar bent.
#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
extern SemaphoreHandle_t displayMutex;Als u de mutex niet vrijgeeft, worden alle andere taken die het display nodig hebben geblokkeerd. Koppel een geslaagde xSemaphoreTake altijd aan xSemaphoreGive in een pad in finally-stijl.
Basisgebruikspatroon
// 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);
}Initialisatie
Roep één keer initDisplay() op bij het opstarten.
#pragma once
void initDisplay();Maak bronnen aan en configureer het paneel
initDisplay() creëert de weergave-mutex, initialiseert de U8G2-weergave-instantie, stelt adressering/rotatie/contrast in en wist de buffer.
Na initialisatie moet het scherm leeg zijn en van achteren verlicht zijn, en displayMutex mag niet nul zijn.
Tekenen controleren
Teken één regel tekst in het paginagebied.
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
clearPage();
display.setFont(u8g2_font_spleen5x8_mu);
display.drawStr(0, 16, "SANITY PASS");
refreshPage();
xSemaphoreGive(displayMutex);
}Wishelpers
Wis efficiënt alleen wat u opnieuw wilt tekenen. Alle helpers gebruiken intern updateDisplayArea() om de getroffen regio gedeeltelijk te vernieuwen.
| Functie | Beschrijving | Regio gewist |
|---|---|---|
clearHeader() | Wist alleen koptekst | Rij 0, cellen 0–12 |
clearIcons() | Wist alleen het pictogramgebied | Rij 0, cellen 13–15 |
clearFooter() | Wist alleen de voettekst | Rij 7, cellen 0–14 |
clearTimeout() | Wist de time-outindicator | Rij 7, cel 15 |
clearPage(includeFooter=false, includeHeader=false) | Wist het paginagebied; optionele kop-/voettekst | Rijen 1–6 (plus kop-/voettekst indien gevraagd) |
void clearHeader();
void clearIcons();
void clearFooter();
void clearTimeout();
void clearPage(bool includeFooter = false, bool includeHeader = false);clearPage() stelt een uitknipvenster in om te voorkomen dat inhoud in de kop- of voettekst terechtkomt.
Vernieuwingshelpers
Roep een vernieuwingshelper op nadat u een regio hebt gewijzigd. Deze voeren minimale updates uit op het display.
| Functie | Beschrijving | Regio bijgewerkt |
|---|---|---|
refreshHeader() | Werkt de koptekst bij | Rij 0, cellen 0–12 |
refreshIcons() | Werkt het pictogramgebied bij | Rij 0, cellen 13–15 |
refreshFooter() | Werkt de voettekst bij | Rij 7, cellen 0–14 |
refreshTimeout() | Werkt de time-outindicator bij | Rij 7, cel 15 |
refreshPage(includeFooter=false, includeHeader=false) | Werkt de hoofdinhoud bij; optionele kop-/voettekst | Rijen 1–6 (plus kop-/voettekst indien gevraagd) |
void refreshHeader();
void refreshIcons();
void refreshFooter();
void refreshTimeout();
void refreshPage(bool includeFooter = false, bool includeHeader = false);Inhoudhelpers
setHeader()
Stelt de koptekst in. De service zet de laatste waarde om in hoofdletters en slaat deze op in de cache om onnodig opnieuw tekenen te voorkomen.
void setHeader(String &text);Als u setHeader() met dezelfde waarde aanroept, slaat de service zowel het tekenen als het vernieuwen over.
setFooter()
Stelt de links- en rechts uitgelijnde voettekst in. Beide zijn in hoofdletters en in de cache opgeslagen.
void setFooter(String &left, String &right);- De linkertekenreeks wordt uitgelijnd met de linkerrand van het voettekstgebied
- De rechtertekenreeks wordt uitgelijnd met de rechterrand van het voettekstgebied
drawWrappedText()
Teken tekst met automatische tekstterugloop en optionele middenuitlijning.
int drawWrappedText(int x, int y, const String &text, bool center = false);intrequired
Begincoördinaat x in pixels.
intrequired
Begin-y-coördinaat van de basislijn in pixels.
Stringrequired
Tekst om weer te geven. Ondersteunt letterlijke \n voor regeleinden.
bool
Centreer elke omgebroken regel binnen het paginagebied wanneer true is.
returnintrequired
Aantal getekende regels.
Algemene patronen
Teken een volledig scherm
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
clearPage();
display.setFont(u8g2_font_spleen5x8_mu);
display.drawStr(0, 16, "MAIN CONTENT");
refreshPage();
xSemaphoreGive(displayMutex);
}Dit patroon maakt alleen het paginagebied leeg, tekent nieuwe inhoud en voert een gedeeltelijke vernieuwing uit voor snelheid.
Werk alleen de koptekst bij
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);
}Teken gecentreerde tekst met automatische regelafbreking
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);
}Richtlijnen tekenen
Vergrendel de mutex voor elke tekenbewerking
Plaats teken- en vernieuwingsbewerkingen in een door displayMutex bewaakte kritieke sectie.
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
// Drawing
xSemaphoreGive(displayMutex);
}Geef de voorkeur aan regiohelpers boven volledig wissen
Minimaliseer busverkeer en flikkering met behulp van clear*()- en refresh*()-helpers.
clearPage();
display.drawStr(0, 16, "Content");
refreshPage();// Full‑buffer clears cost time and cause visible flicker
// display.clearBuffer();Respecteer grenzen
Houd de inhoud binnen:
- Kop: rij 0, cellen 0–12
- Pictogrammen: rij 0, cellen 13–15
- Pagina: rijen 1–6
- Voettekst: rij 7, cellen 0–14; time-outindicator in cel 15
Gebruik clearPage() om pagina-inhoud weg te knippen van de kop-/voettekst.
Kies leesbare lettertypen
| Gebied | Aanbevolen lettertype |
|---|---|
| Koptekst/voettekst | u8g2_font_spleen5x8_mu |
| Pagina-inhoud | Kies voor leesbaarheid; pas de regelafstand aan op basis van lettertypemetriek |
Houd rekening met de stamhoogte van het lettertype en de totale lijnhoogte bij het berekenen van de y-verschuivingen tussen regels.
Prestatieoverwegingen
- Bij gedeeltelijke updates worden alleen de regio's opnieuw getekend die u hebt gewijzigd
- Tekstcaching vermijdt onnodige teken-/vernieuwingscycli
- Door te knippen blijft het tekenen binnen het beoogde gebied en wordt overtekenen beperkt
- Door mutex beveiligde reeksen voorkomen beeldscheuren midden in een frame tussen taken
Problemen oplossen
- Bevestig dat
initDisplay()één keer wordt aangeroepen - Controleer het I2C-adres (probeer
0x3Cen0x3C << 1, afhankelijk van de constructor) - Zorg ervoor dat SDA/SCL overeenkomen met de
Pins.hvan uw bord
- Wis en vernieuw regio's in plaats van volledige buffers te wissen
- Bundel uw tekenbewerkingen in één door de mutex beschermd blok
- Vermijd onnodige lettertypewijzigingen tussen tekenaanroepen
- Onthoud dat U8G2 een basislijn gebruikt voor
y - Begin de eerste lettertyperegel van 8 px op
y = 8of bereken vanaf de stamhoogte van het lettertype
- Laat de mutex altijd los in foutpaden
- Geef de voorkeur aan wrappers in RAII-stijl of
goto cleanup-patronen
Afhankelijkheden
| Afhankelijkheid | Doel |
|---|---|
| U8G2 | SSD1306-rendering en lettertypeverwerking |
| FreeRTOS | Mutex voor threadveiligheid |
| ESP32 HAL | Hardware-I2C-interface |
Pins.h | Definities van bordpins voor SDA/SCL |
Gerelateerde pagina's
Weergavetijd verbergen (gebruikersfunctie)
Hoe de gebruikersinterface de resterende tijd verbergt op apparaten, dashboards en meldingen.
Weergaveverloop voor noodontgrendeling
Schermverloop en gevolgen van het activeren van Noodontgrendeling op het apparaat.
Ondersteuningsmatrix voor apparaten
Ondersteunde en geplande apparaten voor de periode 2025-2026.