Zum Inhalt springen

Lopaka Basics 02: Text, Schriftarten & Icons ​

Ein SSD1306-OLED-Modul, das ein Morgen-Dashboard mit WLAN- und Akku-Icons, dem Datum FRI 24 OCT, der Zeit 07:45 und einer weißen Statusleiste mit Sonnen-Icon und Sunny 23C zeigt

Eine Uhr, das Wetter und ein Bild vom Mond, alles auf einem Screen von der Größe einer Briefmarke. Text, Schriftarten, Icons und Bilder machen einen kleinen Screen nützlich, und auf einem Mikrocontroller kostet jedes davon Speicher.

In dieser Episode findest du heraus, was eine Schriftart auf einem Mikrocontroller ist, wo sie gespeichert wird und wie viel Platz sie braucht. Dann baust du ein kleines Morgen-Dashboard in Lopaka mit zwei Screens, einer Statusleiste mit invertiertem Text und deinem eigenen Bild, in Punkte verwandelt, und führst es auf einem simulierten Arduino UNO aus.

Was du bauen wirst: ein 128×64-OLED-Dashboard mit zwei Screens. Morning zeigt die Zeit, das Datum, WLAN- und Akku-Icons und eine Wetterleiste. Night zeigt ein Bild vom Mond und die Zeit. Was du brauchst: einen Browser und das Simulatorprojekt aus Episode 1. Ein echtes Board ist optional.

Eine Schriftart ist ein Satz von Bildern ​

Ein Bild pro Zeichen ​

Ein Mikrocontroller weiß nicht, was Buchstaben sind. Um „07:45“ zu zeigen, braucht die Grafikbibliothek ein kleines Bild für jedes Zeichen: eines für 0, eines für 7, eines für : und so weiter. Eine Schriftart auf einem Mikrocontroller ist ein Satz winziger Bilder, eines für jedes Zeichen, das sie zeichnen kann.

Größerer Text, größere Bilder ​

Jedes Bild ist ein Raster aus Pixeln. Eine größere Schriftart bedeutet größere Raster: Dieselbe Ziffer 2 ist in einer kleinen Schriftart 5×9 Pixel groß und in einer großen 12×18. Jedes dieser Bilder muss auf dem Chip gespeichert werden, also braucht eine größere Schriftart mehr Speicher.

Ein Buchstabe ist ein winziges Bild: die Ziffer 7 auf einem Pixelraster, die fünf Bilder, die 07:45 ausmachen, und die Ziffer 2 in drei Größen, 5×9, 6×11 und 12×18

Zwei Arten von Speicher ​

Flash ist das Bücherregal, RAM ist der Schreibtisch ​

Ein Mikrocontroller hat zwei Arten von Speicher:

  • Flash hält dein Programm, Schriftarten und Bilder. Er funktioniert wie ein Bücherregal: Alles, was das Programm brauchen könnte, wird dort gespeichert, und es bleibt dort, wenn der Strom aus ist.
  • RAM ist der kleine Schreibtisch, an dem die Arbeit passiert: die Werte, an denen das Programm gerade arbeitet.

Auf einem Arduino UNO hält das Bücherregal 32 KB und der Schreibtisch nur 2 KB.

Wie viel eine Schriftart kostet ​

Eine kleine Schriftart braucht etwa ein Kilobyte Flash, eine große zwei bis vier. Wir maßen es, indem wir einen Sketch für einen UNO mit einem Text in einer einzigen Schriftart kompilierten und ihn mit einem Sketch ohne Text verglichen: 4x6 fügte 1,1 KB hinzu, profont22 2,1 KB, profont29 2,5 KB und timR24 3,7 KB.

Zwei Arten von Speicher auf einem Arduino UNO: 32 KB Flash, das Bücherregal für Programm, Schriftarten und Bilder, mit Schriftarten von 1,1, 2,1, 2,5 und 3,7 KB neben dem Programm, und 2 KB RAM, der Schreibtisch

Jede Schriftart wird einmal gespeichert, egal wie viele Texte sie nutzen. Die praktische Regel: zwei oder drei Schriftarten pro Screen. Um zu sehen, welche Schriftarten dein Design nutzt, schau dir die setFont-Zeilen im Code-Panel von Lopaka an: Jeder unterschiedliche Schriftartname dort ist eine weitere Schriftart auf dem Bücherregal.

Schritt 1: Ein neues Projekt ​

Gleicher Start wie in Episode 1: Klicke auf + Neues Projekt, wähle die Plattform U8g2, behalte die Screen-Größe bei 128×64 und gib dem Projekt einen Titel, „Morning Dashboard“. Klicke auf Speichern.

Schritt 2: Text ​

Die Zeit in einer großen Schriftart ​

Wähle das Text-Werkzeug (Aa), klicke auf die Zeichenfläche und wähle die neue Ebene string 1 aus. Ersetze im Inspektor den Text durch 07:45, öffne die Liste Schriftart und wähle profont29, eine Schriftart, die sich leicht aus der anderen Ecke des Raumes lesen lässt.

Klicke oben im Inspektor auf den Button Horizontal zentrieren und setze Y auf 40. Der Code liest jetzt:

cpp
u8g2.setFont(u8g2_font_profont29_tr);
u8g2.drawStr(24, 40, "07:45");

Die Schriftartliste im Inspektor geöffnet mit profont29, ausgewählt für den Text 07:45, der bei X 24 und Y 40 zentriert auf der Zeichenfläche sitzt

Beide Zahlen lassen sich von Hand prüfen. Jedes Zeichen von profont29 ist 16 Pixel breit, also ist „07:45“ 5 × 16 = 80 Pixel breit, und (128 − 80) / 2 = 24 legt es in die Mitte. Die 40 ist die Grundlinie, die Linie, auf der die Ziffern stehen, wie in Episode 1: Die Ziffern füllen die Zeilen darüber.

Das Datum in einer kleinen Schriftart ​

Füge einen weiteren Text hinzu, FRI 24 OCT. Ein neuer Text startet in der letzten Schriftart, die du genutzt hast, also wechsle ihn zur kleinen 5x8. Zentriere ihn horizontal und setze Y auf 11. Zehn Zeichen mit 5 Pixeln machen 50 Pixel, was drawStr(39, 11, "FRI 24 OCT") ergibt.

Deine eigene Schriftart ​

Willst du einen anderen Look? Der erste Eintrag der Liste Schriftart, Schriftart importieren..., nimmt eine TrueType-Datei (.ttf; .otf, .woff und .bdf gehen auch), und Lopaka verwandelt sie in Pixel mit der Höhe, die du wählst. Im Video importierten wir Press Start 2P, eine kostenlose Pixel-Schriftart, und setzten Schrifthöhe auf 8. Die Vorschau zeigt die ganze Schriftart: 95 winzige Bilder, jedes druckbare Zeichen vom Leerzeichen bis ~.

Der Dialog Schriftartvorschau für Press Start 2P mit Schrifthöhe 8 und allen 95 Zeichen in drei Zeilen

Klicke auf Importieren, und die Schriftart ist einsatzbereit. Der ausgewählte Text wechselt zu ihr, und der Code erhält eine zusätzliche Zeile, #include "Press_Start_2P_8.h". Dieser Header hält die Schriftartdaten. Ein Button mit demselben Namen erscheint unter dem Code: Lade die Datei herunter und lege sie neben deinen Sketch, sonst kompiliert der Sketch nicht.

Das Dashboard behält die eingebauten Schriftarten. Wenn du den Import an der Zeit ausprobiert hast, wechsle sie zurück zu profont29.

Schritt 3: Icons ​

Suchen und hinzufügen ​

Lopaka hat mehr als zweitausend Icons eingebaut. Öffne links den Tab Bilder, tippe in das Suchfeld und klicke auf ein Icon, um es zum Screen hinzuzufügen. Füge drei hinzu:

  • wifi_25 (suche „wifi“),
  • battery_30 (suche „battery“),
  • weather_sun (suche „sun“).

Alle drei sind im Gaai-Set.

Bringe jedes Icon an seinen Platz ​

Ziehe die Icons auf der Zeichenfläche an ihren Platz: WLAN in die obere linke Ecke, den Akku in die obere rechte Ecke, die Sonne in die untere linke Ecke.

Ein Icon sind 32 Bytes ​

Ein Icon ist auch ein winziges Bild. Die Sonne ist 15 Pixel breit und 16 hoch, und auf einem einfarbigen Screen ist jedes Pixel ein Bit: an oder aus. Acht Pixel passen in ein Byte. Eine Zeile mit 15 Pixeln braucht zwei Bytes, und das letzte Bit bleibt ungenutzt, also ist das ganze Icon 2 Bytes × 16 Zeilen = 32 Bytes.

Das 15 × 16 Pixel große Sonnen-Icon mit einer hervorgehobenen Zeile: seine Pixel als die Bits 00010000 00010000, die Bytes 0x08 0x08, 8 Pixel pro Byte, 2 Bytes pro Zeile mal 16 Zeilen sind 32 Bytes, und das Array image_weather_sun_bits

Im Code wird das Icon zu dieser Liste von Zahlen. Die Bibliothek liest sie und zeichnet die Pixel:

cpp
static const unsigned char image_weather_sun_bits[] U8X8_PROGMEM = {0x80,0x00,0x84,0x10,0x08,0x08,0xc0,0x01,0x31,0x46,0x12,0x24,0x08,0x08,0x08,0x08,0x08,0x08,0x12,0x24,0x31,0x46,0xc0,0x01,0x08,0x08,0x84,0x10,0x80,0x00,0x00,0x00};
cpp
u8g2.drawXBMP(5, 47, 15, 16, image_weather_sun_bits);

drawXBMP nimmt die Position, die Breite und Höhe des Bildes und das Array. In diesem Format, XBM genannt, ist das erste Pixel einer Zeile das niedrigste Bit des Bytes. Deshalb liest sich die hervorgehobene Zeile von links nach rechts 00010000, wird aber als 0x08 gespeichert.

Die anderen beiden Icons sind 19×16 und 24×16 Pixel. Beide brauchen drei Bytes pro Zeile, je 48 Bytes.

Schritt 4: Invertierter Text ​

Eine weiße Leiste mit dunklem Text ​

Zeichne für eine Statusleiste ein gefülltes Rechteck und lege Text darüber:

  1. Wähle das Rechteck-Werkzeug, ziehe ein Rechteck auf der Zeichenfläche und setze X 0, Y 46, W 128, H 18. Schalte Gefüllt ein. Die Leiste deckt jetzt die unteren 18 Zeilen des Screens ab, Zeilen 46 bis 63.
  2. Das neue Rechteck ist die oberste Ebene und versteckt die Sonne. Drücke Strg + ↓ (Cmd + ↓ auf einem Mac), um es eine Ebene nach unten zu schieben, unter weather_sun.
  3. Wähle weather_sun aus und schalte Invertiert (XOR) ein.
  4. Füge einen Text Sunny 23C (mit zwei Leerzeichen) hinzu, wähle die Schriftart 6x10, setze X 28 und Y 59 und schalte Invertiert (XOR) ein.

Sonne und Text schneiden in Schwarz durch die weiße Leiste.

Der Morning-Screen mit einer weißen Leiste am unteren Rand; Sonne und Text Sunny 23C sind in Schwarz darauf gezeichnet, und der Inspektor zeigt string 7 mit der Schriftart 6x10, X 28, Y 59 und Invertiert (XOR) an

XOR: Wo Formen überlappen, kippen die Pixel ​

Invertiert nutzt einen Trick namens XOR. Wo immer eine neue Form etwas bereits Gezeichnetes überlappt, kippen die Pixel: Ein leuchtendes Pixel unter der Form wird dunkel, ein dunkles leuchtet auf. Auf einem einfarbigen Screen bekommst du so dunklen Text auf einer hellen Leiste.

XOR, Überlappung kippt: dunkles 07:45 auf einer weißen Leiste; an plus aus ergibt an, an plus an ergibt aus

Im Code ist das eine Zeile vor der Sonne:

cpp
// rect 6
u8g2.drawBox(0, 46, 128, 18);
// weather_sun
u8g2.setDrawColor(2);
u8g2.drawXBMP(5, 47, 15, 16, image_weather_sun_bits);
// string 7
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(28, 59, "Sunny  23C");

setDrawColor(2) schaltet U8g2 in den XOR-Modus, und der Modus bleibt an, bis der Code ihn wieder ändert. Deshalb braucht der Text nach der Sonne keinen zweiten Aufruf. Die Reihenfolge der Ebenen zählt hier: Die Leiste muss zuerst gezeichnet werden, damit Sonne und Text etwas zum Kippen haben.

Schritt 5: Dein eigenes Bild ​

Lade ein Bild hoch ​

Du kannst auch deine eigenen Bilder mitbringen. Klicke im Tab Bilder auf Hochladen und wähle eine Bilddatei. Lopaka öffnet einen Importdialog, der es für das Display umwandelt. Wir nutzten ein fotoähnliches Bild vom Mond.

Setze Maße auf W 48 und H 48 und schalte Palette invertieren ein: Der Mond ist hell auf dunklem Hintergrund, und das macht den Mond zu den leuchtenden Pixeln auf dem OLED.

Dithering verwandelt Grau in Punkte ​

Dieser Screen hat kein Grau. Jedes Pixel ist schwarz oder weiß. Die einfachste Umwandlung schneidet bei halber Helligkeit: Hellere Pixel gehen an, dunklere aus. Auf dem Mond bleibt davon nur ein weißer Fleck, und die ganze Schattierung ist verloren.

Dithering behebt das. Es mischt schwarze und weiße Punkte, dichter, wo das Bild heller ist, sodass dein Auge aus der Entfernung Graustufen sieht.

Derselbe Mond auf drei Arten: das Original in Graustufen, bei 50 % zu einem flachen weißen Fleck geschnitten und in Punkte gedithert, die das Grau vortäuschen, mit einer Nahaufnahme des Punktmusters

Wähle einen Stil in der Liste Dithering: Floyd-Steinberg, Atkinson, Bayer 8x8 oder Kein Dithering. Wir behielten Floyd-Steinberg. Klicke auf Importieren.

Der Bildimportdialog mit dem Mond bei 48 × 48 Pixeln, Floyd-Steinberg-Dithering und eingeschalteter Palette invertieren; die Vorschau zeigt den Mond als Muster aus Punkten

Bei 48 × 48 Pixeln braucht das Bild 48 / 8 × 48 = 288 Bytes.

Ein zweiter Screen für die Nacht ​

Geben wir dem Mond einen eigenen Screen. Ein Projekt kann so viele Screens halten, wie du brauchst.

  1. Doppelklicke auf den Namen des Screens über der Zeichenfläche und benenne Screen 1 in Morning um.
  2. Klicke im Ebenen-Panel auf Screen hinzufügen und benenne den neuen Screen in Night um.

Lege den Mond auf den Night-Screen bei X 6, Y 8 und füge zwei Texte hinzu:

  • Good night in 6x10 bei X 62, Y 26,
  • 22:30 in profont22 bei X 62, Y 50.

Beide Screens Seite an Seite auf der Lopaka-Zeichenfläche: Morning mit der Zeit 07:45 und der Wetterleiste, Night mit dem geditherten Mond, Good night und 22:30; das Code-Panel hat einen Tab für jeden Screen

Jeder Screen wird im Code zu seiner eigenen Funktion: drawMorning() und drawNight(), benannt nach den Screens. Das Code-Panel hat einen Tab für jeden Screen. Dein Sketch entscheidet, welchen er zeigt, und wann.

Schritt 6: PROGMEM ​

Eine Einstellung, die es wert ist, sie zu kennen: Als PROGMEM deklarieren, in der Liste der Schalter neben dem Code. Sie ist standardmäßig an.

Der Night-Code-Tab: image_moon_bits ist mit U8X8_PROGMEM deklariert und wird mit drawXBMP gezeichnet; die Schalter neben dem Code beginnen mit Als PROGMEM deklarieren, eingeschaltet

Auf einem AVR-Board wie dem UNO wird ein konstantes Array beim Programmstart ins RAM kopiert, wenn es nicht für Flash markiert ist. U8X8_PROGMEM hält die Bilddaten im Flash, auf dem Bücherregal, sodass sie den kleinen RAM-Schreibtisch nicht überfüllen, und drawXBMP (mit dem P) liest sie von dort. Mit ausgeschaltetem Schalter schreibt Lopaka drawXBM und die Arrays ohne U8X8_PROGMEM.

Der Unterschied für dieses Dashboard: Die vier Bilder brauchen 416 Bytes. Für einen UNO kompiliert, nutzt der Sketch 78 % des RAM mit PROGMEM und 98 % ohne. Ohne bleiben nur 32 Bytes für alles übrig, was das Programm während des Laufens tut, und der Sketch kann abstürzen oder sich seltsam verhalten.

Genutztes RAM auf einem Arduino UNO: 78 % mit PROGMEM, 98 % ohne PROGMEM, nur 32 Bytes übrig

Schritt 7: Führe ihn aus ​

Der Code ​

Klicke im Tab Morning auf Kopieren, füge ihn in deinen Sketch ein und mache dann dasselbe im Tab Night. Kopieren nimmt den Code des offenen Tabs. Das ist der Code, den Lopaka für die zwei Screens generiert:

cpp
// [BEGIN lopaka generated]
static const unsigned char image_battery_30_bits[] U8X8_PROGMEM = {0x00,0x00,0x00,0xf0,0xff,0x7f,0x08,0x00,0x80,0x08,0x00,0xaa,0x0e,0x00,0xaa,0x01,0x00,0xaa,0x01,0x00,0xaa,0x01,0x00,0xaa,0x01,0x00,0xaa,0x01,0x00,0xaa,0x0e,0x00,0xaa,0x08,0x00,0xaa,0x08,0x00,0x80,0xf0,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00};
static const unsigned char image_weather_sun_bits[] U8X8_PROGMEM = {0x80,0x00,0x84,0x10,0x08,0x08,0xc0,0x01,0x31,0x46,0x12,0x24,0x08,0x08,0x08,0x08,0x08,0x08,0x12,0x24,0x31,0x46,0xc0,0x01,0x08,0x08,0x84,0x10,0x80,0x00,0x00,0x00};
static const unsigned char image_wifi_25_bits[] U8X8_PROGMEM = {0x80,0x0f,0x00,0x60,0x30,0x00,0x18,0xc0,0x00,0x84,0x0f,0x01,0x62,0x30,0x02,0x11,0x40,0x04,0x0a,0x87,0x02,0xc4,0x18,0x01,0x28,0xa0,0x00,0x10,0x47,0x00,0xa0,0x2f,0x00,0xc0,0x1d,0x00,0x80,0x0a,0x00,0x00,0x07,0x00,0x00,0x02,0x00,0x00,0x00,0x00};
void drawMorning(void) {
    u8g2.setFontMode(1);
    u8g2.setBitmapMode(1);
    // string 1
    u8g2.setFont(u8g2_font_profont29_tr);
    u8g2.drawStr(24, 40, "07:45");
    // string 2
    u8g2.setFont(u8g2_font_5x8_tr);
    u8g2.drawStr(39, 11, "FRI 24 OCT");
    // wifi_25
    u8g2.drawXBMP(2, 0, 19, 16, image_wifi_25_bits);
    // battery_30
    u8g2.drawXBMP(102, 0, 24, 16, image_battery_30_bits);
    // rect 6
    u8g2.drawBox(0, 46, 128, 18);
    // weather_sun
    u8g2.setDrawColor(2);
    u8g2.drawXBMP(5, 47, 15, 16, image_weather_sun_bits);
    // string 7
    u8g2.setFont(u8g2_font_6x10_tr);
    u8g2.drawStr(28, 59, "Sunny  23C");
}
// [END lopaka generated]

// [BEGIN lopaka generated]
static const unsigned char image_moon_bits[] U8X8_PROGMEM = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x0a,0x00,0x00,0x00,0x00,0x7f,0x57,0x00,0x00,0x00,0xc0,0xee,0xad,0x00,0x00,0x00,0xf0,0xbf,0xbb,0x05,0x00,0x00,0xd8,0xfb,0x56,0x09,0x00,0x00,0xfc,0xbf,0xbf,0x12,0x00,0x00,0xfe,0xff,0xd5,0x06,0x00,0x00,0xdf,0x6f,0xbf,0x2a,0x00,0x80,0x7f,0xbb,0xd5,0x42,0x00,0xc0,0xdf,0x7f,0xbf,0x2a,0x00,0xc0,0xff,0xfe,0xd6,0x8a,0x00,0xe0,0xff,0xdf,0xbb,0x2a,0x00,0x60,0xff,0xff,0x6e,0x95,0x00,0xf0,0xff,0xbf,0xb7,0x4a,0x00,0xd0,0xff,0xef,0xdd,0x12,0x02,0xf0,0xff,0xff,0xb7,0x56,0x00,0xf0,0xff,0xbd,0x6e,0x09,0x01,0xf8,0xbf,0xef,0x5b,0x53,0x00,0xe8,0xfd,0xff,0xd6,0x14,0x10,0x78,0xff,0xdd,0xad,0x8a,0x00,0xe8,0x6f,0x77,0x5b,0x11,0x00,0xf8,0xff,0xdf,0x56,0x45,0x04,0xd0,0x5e,0x7d,0xab,0x10,0x00,0xf8,0xfb,0xd7,0x56,0x05,0x00,0x50,0xef,0xbe,0x55,0x41,0x00,0xf0,0xbd,0x6b,0x55,0x0a,0x04,0x50,0xf7,0xd6,0xaa,0x00,0x00,0xd0,0xad,0xbd,0x0a,0x25,0x00,0xa0,0x76,0xab,0x52,0x00,0x02,0x60,0xdb,0x56,0x25,0x01,0x00,0x40,0xad,0x55,0x49,0x08,0x00,0x80,0x6a,0x55,0x15,0x82,0x00,0x80,0x5a,0x55,0x82,0x00,0x00,0x00,0xa5,0x4a,0x29,0x00,0x00,0x00,0x2a,0x29,0x00,0x00,0x00,0x00,0x48,0x92,0x02,0x20,0x00,0x00,0xa4,0x04,0x08,0x04,0x00,0x00,0x00,0x51,0x80,0x00,0x00,0x00,0x20,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
void drawNight(void) {
    u8g2.setFontMode(1);
    u8g2.setBitmapMode(1);
    // moon
    u8g2.drawXBMP(6, 8, 48, 48, image_moon_bits);
    // string 9
    u8g2.setFont(u8g2_font_6x10_tr);
    u8g2.drawStr(62, 26, "Good night");
    // string 10
    u8g2.setFont(u8g2_font_profont22_tr);
    u8g2.drawStr(62, 50, "22:30");
}
// [END lopaka generated]

6x10 erscheint in beiden Funktionen, aber es ist dieselbe Schriftart und wird einmal im Flash gespeichert. Das ganze Design nutzt vier Schriftarten: profont29, 5x8, 6x10 und profont22.

Der Sketch ​

Beginne mit dem Sketch der letzten Episode und ändere loop() so, dass er jeden Screen drei Sekunden lang zeigt:

cpp
#include <U8g2lib.h>
#include <Wire.h>

// 128x64 OLED display on I2C
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

// Paste the Lopaka code here

void setup() {
  u8g2.begin();
}

void loop() {
  u8g2.clearBuffer();
  // show each screen for 3 seconds
  if ((millis() / 3000) % 2 == 0) drawMorning();
  else drawNight();
  u8g2.sendBuffer();
}

millis() zählt die Millisekunden seit dem Start des Boards. Geteilt durch 3000 wächst es jede drei Sekunden um eins, und % 2 verwandelt das in 0, 1, 0, 1. Bei 0 zeichnet der Sketch Morning, bei 1 Night. Wie in Episode 1 zeichnen beide Funktionen zwischen clearBuffer() und sendBuffer().

Führe ihn im Simulator aus ​

Öffne das Simulatorprojekt aus Episode 1: ein Arduino UNO, ein SSD1306-OLED, verdrahtet mit GND, 5V, A5 (SCL) und A4 (SDA), und die U8g2-Bibliothek. Ersetze den Sketch durch den obigen, füge den Lopaka-Code an seiner Stelle ein und drücke Play. Das Display wechselt jede drei Sekunden zwischen den zwei Screens.

Der Simulator, der den Sketch ausführt: Das simulierte OLED, verbunden mit einem Arduino UNO, zeigt den Morning-Screen mit 07:45 und Sunny 23C

Wir prüften beide Screens Pixel für Pixel: Die Lopaka-Zeichenfläche, der von der U8g2-Bibliothek gezeichnete Screen und das simulierte Display sind identisch.

Wie viel Speicher das alles braucht ​

Das Ganze, mit vier Schriftarten, drei Icons und einem Bild, passt in weniger als die Hälfte des Flash des UNO. Der Compiler meldet:

Sketch uses 15394 bytes (47%) of program storage space. Maximum is 32256 bytes.
Global variables use 1600 bytes (78%) of dynamic memory, leaving 448 bytes for local variables. Maximum is 2048 bytes.

Der größte Teil der 1.600 Bytes RAM ist der 1.024-Byte-Frame-Puffer aus Episode 1. Für diesen Sketch ist das in Ordnung.

Zusammenfassung ​

  1. Schriftarten und Icons sind Bilder: Jedes Zeichen einer Schriftart und jedes Icon ist ein kleines Raster aus Pixeln, ein Bit pro Pixel.
  2. Bilder kosten Speicher: Eine Schriftart braucht ein bis vier Kilobyte Flash, also nutze zwei oder drei pro Screen und halte Bilder mit PROGMEM im Flash.
  3. Dithering verwandelt Grau in Punkte: Wähle einen Dithering-Stil, wenn du ein Foto importierst, und der einfarbige Screen zeigt Schattierungen.

Nächste Episode: Farbe. Dieselbe Art von Oberfläche auf einem Farb-TFT-Display, und was RGB565 bedeutet. Lies Episode 3 oder schaue sie auf YouTube.

Bereit, es zu versuchen? Öffne Lopaka und baue dein eigenes Dashboard.