Utilisez le service d'affichage thread-safe pour un écran OLED SSD1306 128 × 64 avec U8G2 afin d'y dessiner
Aperçu
Le service d'affichage est un wrapper global et thread-safe autour du pilote U8G2 pour un OLED SSD1306 128 × 64. Vous l'utilisez pour restituer le texte et les graphiques de n'importe quelle tâche sans scintillement ni déchirure. Un mutex FreeRTOS garantit un accès exclusif pendant que vous dessinez ; les fonctions d'assistance gèrent l'effacement des régions, l'actualisation partielle, le découpage et la mise en cache du texte.
Cette page documente l'API de développement au niveau du micrologiciel utilisée sur nos appareils. Pour connaître le comportement de l'affichage destiné à l'utilisateur (par exemple, masquer les écrans de temps restant ou d'état de l'appareil), consultez les pages associées à la fin.
Conditions préalables
- ESP32 avec interface I2C matérielle disponible
- Bibliothèque U8G2 intégrée à la compilation de votre micrologiciel
- FreeRTOS (pour le mutex d'affichage)
- Broches configurées pour SDA/SCL dans le
Pins.hde votre carte
Configuration matérielle
| Propriété | Valeur |
|---|---|
| Affichage | SSD1306 OLED |
| Résolution | 128×64 pixels |
| Interface | I2C (matériel) |
| Rotation | U8G2_R0 (0°) |
| Adresse I2C | 0x3C |
| Contraste | 255 (maximum) |
Certains constructeurs U8G2 attendent l'adresse I2C 8 bits. Si tel est le cas, transmettez 0x3C << 1. Vérifiez que cela correspond à la signature de votre constructeur.
Modèle de mise en page
L'écran est traité comme une grille de cellules de 8 × 8 pixels :
- Grille : 8 lignes × 16 colonnes
- Origine : (0,0) en haut à gauche
- Taille de cellule : 8 × 8 pixels
Régions
- Cellules 0 à 12 : texte d'en-tête (13 cellules = 104 px)
- Cellules 13 à 15 : icônes d'état (3 cellules = 24 px)
- 6 lignes de hauteur (48 px)
- 16 cellules de large (128 px)
- Tout le contenu principal devrait s'afficher ici
- Cellules 0 à 14 : texte de pied de page (15 cellules = 120 px)
- Cellule 15 : indicateur de délai d'attente (1 cellule = 8 px)
Les API de texte U8G2 utilisent la ligne de base pour y. Pour les polices de 8 pixels de hauteur, commencez la première ligne de texte à y = 8, puis ajoutez la hauteur d’ascendante/hauteur de ligne de la police pour les lignes suivantes.
Sécurité des threads
Le service d'affichage fournit un mutex FreeRTOS. Verrouillez-le toujours avant de dessiner et déverrouillez-le lorsque vous avez terminé.
#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
extern SemaphoreHandle_t displayMutex;Si vous ne parvenez pas à libérer le mutex, toutes les autres tâches nécessitant l'affichage seront bloquées. Associez toujours un xSemaphoreTake réussi avec un xSemaphoreGive dans un chemin de style finally.
Modèle d'utilisation de base
// 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);
}Initialisation
Appelez initDisplay() une fois au démarrage.
#pragma once
void initDisplay();Créer des ressources et configurer le panneau
initDisplay() crée le mutex d'affichage, initialise l'instance d'affichage U8G2, définit l'adressage/rotation/contraste et efface le tampon.
Après l'initialisation, l'écran doit être vide et rétroéclairé, et displayMutex doit être non nul.
Vérifier le dessin
Affichez une seule ligne de texte dans la zone de la page.
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
clearPage();
display.setFont(u8g2_font_spleen5x8_mu);
display.drawStr(0, 16, "SANITY PASS");
refreshPage();
xSemaphoreGive(displayMutex);
}Aides à l'effacement
Effacez efficacement uniquement ce que vous envisagez de redessiner. Toutes les fonctions d'aide utilisent updateDisplayArea() en interne pour effectuer une actualisation partielle de la région affectée.
| Fonction | Description | Région effacée |
|---|---|---|
clearHeader() | Efface uniquement le texte de l'en-tête | Ligne 0, cellules 0 à 12 |
clearIcons() | Efface uniquement la zone d'icône | Ligne 0, cellules 13 à 15 |
clearFooter() | Efface uniquement le texte du pied de page | Ligne 7, cellules 0 à 14 |
clearTimeout() | Efface l'indicateur de délai d'attente | Ligne 7, cellule 15 |
clearPage(includeFooter=false, includeHeader=false) | Efface la zone de la page ; en-tête/pied de page en option | Lignes 1 à 6 (plus en-tête/pied de page sur demande) |
void clearHeader();
void clearIcons();
void clearFooter();
void clearTimeout();
void clearPage(bool includeFooter = false, bool includeHeader = false);clearPage() définit une fenêtre de découpage pour empêcher le contenu de se répandre dans l'en-tête ou le pied de page.
Aides à l'actualisation
Appelez une fonction d’actualisation après avoir modifié une région. Elle effectue une mise à jour minimale de l’affichage.
| Fonction | Description | Région mise à jour |
|---|---|---|
refreshHeader() | Envoie le texte d'en-tête | Ligne 0, cellules 0 à 12 |
refreshIcons() | Envoie la zone d'icônes | Ligne 0, cellules 13 à 15 |
refreshFooter() | Envoie le texte du pied de page | Ligne 7, cellules 0 à 14 |
refreshTimeout() | Met à jour l'indicateur de délai d'attente | Ligne 7, cellule 15 |
refreshPage(includeFooter=false, includeHeader=false) | Envoie le contenu principal ; en-tête/pied de page en option | Lignes 1 à 6 (plus en-tête/pied de page sur demande) |
void refreshHeader();
void refreshIcons();
void refreshFooter();
void refreshTimeout();
void refreshPage(bool includeFooter = false, bool includeHeader = false);Fonctions d'aide au contenu
setHeader()
Définit le texte de l'en-tête. Le service convertit la dernière valeur en majuscules et la met en cache pour éviter les redessins redondants.
void setHeader(String &text);Si vous appelez setHeader() avec la même valeur, le service ignore le dessin et l'actualisation.
setFooter()
Définit le texte du pied de page aligné à gauche et à droite. Les deux sont en majuscules et mis en cache.
void setFooter(String &left, String &right);- La chaîne gauche s'aligne sur le bord gauche de la région du pied de page
- La chaîne droite s'aligne sur le bord droit de la région du pied de page
drawWrappedText()
Dessinez du texte avec retour à la ligne automatique et alignement central en option.
int drawWrappedText(int x, int y, const String &text, bool center = false);intrequired
Coordonnée x de départ en pixels.
intrequired
Coordonnée de départ de la ligne de base y en pixels.
Stringrequired
Texte à restituer. Prend en charge le littéral \n pour les sauts de ligne.
bool
Centrez chaque ligne renvoyée à la ligne dans la zone de page lorsque center vaut true.
returnintrequired
Nombre de lignes dessinées.
Modèles courants
Dessiner un écran complet
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
clearPage();
display.setFont(u8g2_font_spleen5x8_mu);
display.drawStr(0, 16, "MAIN CONTENT");
refreshPage();
xSemaphoreGive(displayMutex);
}Ce modèle efface uniquement la zone de la page, dessine du nouveau contenu et effectue une actualisation partielle pour plus de rapidité.
Mettre à jour l'en-tête uniquement
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);
}Dessiner du texte centré avec retour automatique à la ligne
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);
}Directives de dessin
Verrouillez le mutex pour chaque séquence de dessin
Regroupez les opérations de dessin et d’actualisation dans une section critique protégée par displayMutex.
if (xSemaphoreTake(displayMutex, portMAX_DELAY) == pdTRUE) {
// Drawing
xSemaphoreGive(displayMutex);
}Préférez les aides régionales aux effacements complets
Minimisez le trafic de bus et le scintillement en utilisant les assistants clear*() et refresh*().
clearPage();
display.drawStr(0, 16, "Content");
refreshPage();// Full‑buffer clears cost time and cause visible flicker
// display.clearBuffer();Respectez les limites
Conservez le contenu dans :
- En-tête : ligne 0, cellules 0 à 12
- Icônes : ligne 0, cellules 13 à 15
- Page : lignes 1 à 6
- Pied de page : ligne 7, cellules 0 à 14 ; indicateur de délai d’attente dans la cellule 15
Utilisez clearPage() pour empêcher le contenu de la page d’empiéter sur l’en-tête ou le pied de page.
Choisissez des polices lisibles
| Zone | Police recommandée |
|---|---|
| En-tête/pied de page | u8g2_font_spleen5x8_mu |
| Contenu des pages | Choisissez une police lisible ; ajustez l'espacement des lignes selon les métriques de la police |
Tenez compte de la hauteur d’ascendante de la police et de la hauteur totale des lignes lors du calcul des décalages y entre les lignes.
Considérations sur les performances
- Les mises à jour partielles ne redessinent que les régions que vous avez modifiées
- La mise en cache du texte évite les cycles de dessin/actualisation inutiles
- Le découpage maintient le dessin dans la région prévue et réduit le surdessin
- Les séquences protégées par mutex empêchent le déchirement d'image entre les tâches
Dépannage
- Confirmez que
initDisplay()est appelé une fois - Vérifiez l'adresse I2C (essayez
0x3Cet0x3C << 1selon le constructeur) - Assurez-vous que SDA/SCL correspondent au
Pins.hde votre carte.
- Utilisez les effacements/actualisations de région au lieu des effacements complets du tampon
- Regroupez votre dessin dans un bloc protégé par mutex
- Évitez les changements de police inutiles entre les appels de dessin
- N'oubliez pas que U8G2 utilise une ligne de base pour
y. - Commencez la première ligne de police de 8 px à
y = 8ou calculez à partir de la hauteur d’ascendante de la police.
- Libérez toujours le mutex dans les chemins d'erreur
- Préférez les wrappers de style RAII ou les modèles
goto cleanup
Dépendances
| Dépendance | But |
|---|---|
| U8G2 | Rendu SSD1306 et gestion des polices |
| FreeRTOS | Mutex pour la sécurité des threads |
| ESP32 HAL | Interface matérielle I2C |
Pins.h | Définitions des broches de la carte pour SDA/SCL |
Pages connexes
Masquer le temps restant affiché (fonctionnalité utilisateur)
Comment l'interface utilisateur masque le temps restant sur l'appareil, le tableau de bord et les notifications.
Flux d'affichage du déverrouillage d'urgence
Flux d’écran et conséquences du déclenchement du déverrouillage d’urgence sur l’appareil.
Matrice de prise en charge des appareils
Appareils pris en charge et prévus pour 2025-2026.