U8g2 drawXBMP: SSD1306-Bitmap-Probleme beheben

Eine umgewandelte Bitmap kann sauber kompilieren und trotzdem falsch auf einem SSD1306 erscheinen: leer, innerhalb jeder Achtergruppe von Pixeln gespiegelt, mit jeder Zeile ein bisschen weiter verschoben oder über den Screen wiederholt. Die übliche Reaktion ist, das Bild erneut mit anderen Einstellungen durch den Konverter zu jagen. Das hilft selten, denn die Bytes sind selten das einzige Problem.
Ein Byte-Array allein sagt nicht, wie breit das Bild ist, welches Bit das linkste Pixel ist, wie jede Zeile aufgefüllt wird oder wie dein Display-Konstruktor erwartet, dass das Bild gezeichnet wird. Machst du eines davon falsch, wird aus denselben korrekt aussehenden Daten ein schiefes oder durcheinandergewürfeltes Bild. Die Prüfungen unten trennen diese Ursachen der Reihe nach: Beweise zuerst den Firmware-Zeichenpfad mit einer Bitmap, deren korrekte Ausgabe du auswendig kennst, und vergleiche dann dein eigenes Bild damit.
Für eine XBM-Bitmap im Programmspeicher nutze u8g2.drawXBMP(x, y, width, height, bits). Breite und Höhe sind Pixelmaße. Wenn ein umgewandeltes SSD1306-Bild leer, gespiegelt oder verschoben ist, prüfe sein Format und seine Zeichenschleife, bevor du es erneut umwandelst.
Eine von U8g2 akzeptierte Bitmap ist nicht unbedingt das native Pufferlayout des SSD1306-Controllers. Bytes ohne Umwandlung zwischen diesen Darstellungen zu kopieren, kann ein Muster erzeugen, das fast richtig aussieht.
Teste mit einer kleinen asymmetrischen Bitmap
Dieses 8 × 8-Beispiel ist absichtlich ungleichmäßig. Es hilft, ein korrekt ausgerichtetes Bild von einem gespiegelten zu unterscheiden:
static const unsigned char corner_bits[] U8X8_PROGMEM = {
0x01, 0x03, 0x07, 0x0F,
0x01, 0x01, 0x01, 0x00
};
void drawBitmapTest() {
u8g2.setDrawColor(1);
u8g2.drawXBMP(0, 0, 8, 8, corner_bits);
}Füge es zu einem Sketch mit einem funktionierenden u8g2-Display-Objekt hinzu. In XBM-Zeilendaten steht das niedrige Bit für das linkste Pixel in jedem Byte. Die erste Zeile oben leuchtet ihr linkstes Pixel; die vierte leuchtet vier Pixel von links. Die Bitmap-Implementierung von U8g2 zeigt, wie diese Bits gelesen werden.

Testmuster, 8 × 8: eine Treppe, die von der oberen linken Ecke wächst, dann eine einzelne Spalte. Wenn deine von rechts wächst, passt die Bit-Reihenfolge nicht. Lade die passende XBM-Datei herunter.
Wenn dieser Test funktioniert, dein Logo aber nicht, behalte die Display-Einrichtung und prüfe die Daten des Logos.
Nutze die Zeichenschleife, die zu deinem Konstruktor passt
Ein Full-Buffer-Konstruktor enthält _F_. Zeichne in diesen Puffer und sende ihn dann:
u8g2.clearBuffer();
drawBitmapTest();
u8g2.sendBuffer();Für einen Page-Buffer-Konstruktor, etwa einen mit _1_, wiederhole die Zeichenfunktion in der Bildschleife:
u8g2.firstPage();
do {
drawBitmapTest();
} while (u8g2.nextPage());Nutze den Modus, den dein vorhandener Konstruktor auswählt. Die U8g2-Einrichtungsreferenz erklärt die Namensgebung und Pufferwahl. Wenn du das Display zum ersten Mal einrichtest, folge der U8g2-Integrationsanleitung von Lopaka und behalte den controllerspezifischen Konstruktor aus dem funktionierenden Beispiel.
Passe Breite, Höhe und Zeilenauffüllung an
Eine XBM-Zeile belegt eine ganze Anzahl von Bytes. Bei einer Breite von 13 Pixeln nutzt jede Zeile zwei Bytes, mit drei ungenutzten Bits an ihrem Ende. Ein Bild mit acht Zeilen braucht daher 16 Bytes.
bytes per row = (width + 7) / 8, using integer division
total bytes = bytes per row * heightWenn du 16 als Breite übergibst, weil die Zeile zwei Bytes hat, zeichnet die API 16 Pixel. Übergib stattdessen die ursprüngliche Pixelbreite. Wenn du die Breite änderst, ohne die Daten neu zu packen, können Zeilen an falschen Stellen beginnen.
Die ältere drawBitmap()-Schnittstelle nutzt eine Byte-Anzahl für die horizontale Größe, während drawXBM() und drawXBMP() Pixel nutzen. Die U8g2-Zeichenreferenz dokumentiert den Unterschied und empfiehlt die XBM-Funktionen.
Lies das Symptom, bevor du Einstellungen änderst
| Symptom | Prüfung |
|---|---|
| Text und Testbild sind beide leer | Konstruktor, Initialisierung, Verkabelung und Display-Adresse |
| Testbild funktioniert; eigenes Bild ist leer | Array-Inhalt, Maße, Zeichenfarbe und Koordinaten |
| Pixel kehren sich in jeder Achtergruppe um | Quell-Bit-Reihenfolge versus XBM-Bit-Reihenfolge |
| Zeilen verschieben sich oder wiederholen sich | Zeilenauffüllung und die der Funktion übergebene Breite |
| Richtiges Bild, falsches Vordergrund-/Hintergrundverhalten | Bitmap-Modus, Zeichenfarbe und wie der Hintergrund gelöscht wird |
Wenn du ein Icon verschiebst, zeichne auch den betroffenen Hintergrund neu. Sonst können leuchtende Pixel von der vorherigen Position übrig bleiben. Entscheide, ob die Anwendung den vollen Puffer löscht oder nur den geänderten Bereich neu malt.
Exportiere die Bitmap mit ihrem Zeichenaufruf
Für ein neues Logo behandelt die Anleitung zum U8g2-Bildkonverter die Vorbereitung in Lopaka. Behalte generierte Breite, Höhe, Array und Zeichenaufruf zusammen, wenn du das Ergebnis in die Firmware überträgst.
Das Screen-Design überlässt Display-Konstruktor und Bus-Einrichtung weiterhin deinem Projekt. SSD1306- und SH1106-Module können eine Auflösung teilen und trotzdem eine unterschiedliche Controller-Einrichtung brauchen. Eine visuelle Vorschau kann Verkabelung oder eine I2C-Adresse nicht validieren.
Häufige Fragen
Zeichnet drawXBMP den ganzen Screen automatisch?
Es zeichnet die Maße, die ihm übergeben werden, an den gewählten Koordinaten. Ein kleines Logo bleibt ein kleines Logo; positioniere es explizit oder bereite eine Fullscreen-Bitmap vor.
Kann ich die Bytes einer PNG-Datei in das Array einfügen?
Nein. Die Funktion erwartet gepackte monochrome Pixel, keine komprimierte PNG-Datei. Wandle das Bild zuerst um.
Wie prüfe ich das Layout, bevor ich erneut flashe?
Nutze die kleine asymmetrische Bitmap, um den Firmware-Pfad zu verifizieren, und prüfe dann das echte Asset in Lopaka. Das gibt dir eine bekannte funktionierende Referenz, während du das Logo anpasst.