Lopaka Basics 03: Farbe

Dieselbe Idee wie in den ersten zwei Episoden, jetzt in Vollfarbe: ein Wohnzimmer-Dashboard auf einem Farbdisplay, in wenigen Minuten gebaut.
In dieser Episode findest du heraus, wie ein Farbscreen seine Farben macht, was RGB565 bedeutet und warum ein einzelnes Fullscreen-Bild nicht auf einen Arduino UNO passt. Dann baust du das Dashboard in Lopaka mit abgerundeten Karten, farbigem Text, getönten Icons und einem kleinen Farbbild und führst es auf einem ESP32 aus.
Was du bauen wirst: ein 320×240-Farb-Dashboard mit einem Titel und der Zeit, drei abgerundeten Karten für Temperatur, Luftfeuchtigkeit und Luftqualität und einer Zeile über das Wetter draußen. Was du brauchst: einen Browser und den Online-Simulator aus Episode 1. Ein echtes Board ist optional.
Wie ein Farbscreen funktioniert
Ein Pixel sind drei winzige Lichter
Auf dem OLED aus den letzten zwei Episoden ist ein Pixel entweder an oder aus. Auf einem Farbdisplay besteht jedes Pixel aus drei winzigen Lichtern: Rot, Grün und Blau. Jedes kann mit beliebiger Helligkeit leuchten, und aus normaler Betrachtungsentfernung mischt dein Auge sie zu einer Farbe.
Mische sie, und du erhältst jede Farbe. Rot und Grün zusammen ergeben Gelb. Alle drei mit voller Leistung ergeben Weiß. Alle drei aus ist Schwarz.
![]()
RGB565: eine Farbe in zwei Bytes
Dein Computer speichert eine Farbe in 24 Bits: 8 für Rot, 8 für Grün und 8 für Blau, etwa 16,7 Millionen Farben. Das ist die Farbe, die du als #FF8200 in eine Webseite oder in Lopaka tippst: zwei Hex-Ziffern pro Licht.
Kleine Chips und ihre Displays nutzen meist 16 Bits, in einem Format namens RGB565:
- 5 Bits für Rot,
- 6 Bits für Grün,
- 5 Bits für Blau.
Grün bekommt das zusätzliche Bit, weil unsere Augen dafür am empfindlichsten sind. Das ergibt 65.536 Farben, und jedes Pixel braucht genau zwei Bytes.

Warum ein Bild nicht auf einen UNO passt
Jetzt die Rechnung. Ein 320×240-Screen hat 320 × 240 = 76.800 Pixel. Mit zwei Bytes pro Pixel braucht ein Fullscreen-Bild 153.600 Bytes, etwa 150 KB.
Ein Arduino UNO hat 32 KB Flash für das ganze Programm. Ein Fullscreen-Bild ist fast das Fünffache davon. Also zeichnest du auf Farbscreens mit Formen und Text und hältst Bilder klein.

Schritt 1: Ein neues Farbprojekt
Klicke auf + Neues Projekt und öffne die Liste Plattform. Wähle für diese Episode AdafruitGFX Color: Adafruit GFX ist eine der beliebtesten Grafikbibliotheken für Farbdisplays. Lopaka beschreibt sie als „die gemeinsame Zeichenschicht unter den meisten Adafruit-Display-Treibern“: Du kombinierst sie mit dem Treiber für dein genaues Panel, etwa Adafruit_ILI9341, Farben sind als RGB565 gepackt, und das Zeichnen geht direkt ans Panel.
Fülle dann den Rest des Dialogs aus:
- Titel: „Color Weather“.
- Screen-Größe: 320×240.
- Hintergrundfarbe:
#0F1B2D, ein dunkles Blau.
Klicke auf Speichern.

Lopaka wandelt jede Farbe in RGB565 um
Das Code-Panel hat bereits eine Zeile:
tft.fillScreen(0x8C5);fillScreen malt das ganze Display in einer Farbe, und 0x8C5 ist das dunkle Blau in RGB565. Lopaka macht die Umwandlung für jede Farbe, die du wählst. Von Hand geht es so: Behalte die oberen 5 Bits von Rot, die oberen 6 Bits von Grün und die oberen 5 Bits von Blau und schreibe sie nacheinander.
| Hex | Obere Bits | |
|---|---|---|
| red | 0x0F | 00001 |
| green | 0x1B | 000110 |
| blue | 0x2D | 00101 |
Zusammen ist das 0000100011000101, oder 0x08C5. Lopaka schreibt es ohne die führende Null.
Schritt 2: Drei abgerundete Karten
Wähle das Rechteck-Werkzeug und ziehe eine Karte auf der Zeichenfläche. Setze im Inspektor R auf 12, um die Ecken zu runden, schalte Gefüllt ein und tippe #FF8200 in Füllfarbe für Orange. Eine Zeile erscheint im Code:
tft.fillRoundRect(10, 56, 96, 140, 12, 0xFC00);Die Zahlen sind x, y, Breite, Höhe, Eckenradius und Farbe. Eine Form ist eine Codezeile, egal wie groß sie ist: Diese Karte spannt 96 × 140 Pixel, und die Zeile, die sie zeichnet, braucht wenige Bytes Flash.
Wiederhole es für die anderen zwei Karten: Blau #2D7FF9 und Grün #22B573. Alle drei sind 96 Pixel breit und 140 hoch, bei y 56, und sie beginnen bei x 10, 112 und 214. Das lässt einen 10-Pixel-Rand auf beiden Seiten des Screens und 6 Pixel zwischen den Karten: 10 + 3 × 96 + 2 × 6 + 10 = 320.

Schritt 3: Text in Farbe
Text funktioniert wie in den ersten zwei Episoden, und jetzt kann er jede Farbe annehmen. Wähle das Text-Werkzeug (Aa): Eine neue Text-Ebene erscheint auf der Zeichenfläche. Tippe den Text in den Inspektor, wähle eine Schriftart und setze Füllfarbe. Ein neuer Text startet in der Farbe, die du zuletzt genutzt hast, also prüfe die Farbe jedes Mal.
Titel und Zeit
Living roomin FreeSansBold12pt7b, Weiß#FFFFFF, in der oberen linken Ecke.07:45in FreeSans12pt7b, helles Graublau#9FB3C8, in der oberen rechten Ecke.
tft.setTextColor(0xFFFF);
tft.setTextWrap(false);
tft.setFont(&FreeSansBold12pt7b);
tft.setCursor(12, 35);
tft.print("Living room");setTextColor setzt die Farbe für jeden Text danach, also schreibt Lopaka sie nur erneut, wenn die Farbe wechselt. setTextWrap(false) hält einen langen Text auf einer Zeile, statt ihn am Rand des Screens umzubrechen.
Bei FreeSans-Schriftarten ist das y von setCursor die Grundlinie: die letzte Pixelzeile der Buchstaben. Im Inspektor hat der Titel Y 36, die Linie unter dieser Zeile (die Lineale zählen die Linien zwischen Pixeln, wie in Episode 1), also sagt der Code 35.
Eine kleine Beschriftung und eine große Zahl auf jeder Karte
Jede Karte bekommt eine kleine Beschriftung in der klassischen Schriftart und eine große Zahl in einer fetten FreeSans:
- Die Beschriftungen
TEMP,HUMIDundAIRnutzen Adafruit 5x7, die in die Bibliothek eingebaute klassische Schriftart, mit Größe auf2gesetzt. - Die Zahlen
23C,48%undOKnutzen FreeSansBold18pt7b.
Alle sechs Texte sind weiß. Platziere jede Beschriftung nahe am oberen Rand ihrer Karte und jede Zahl nahe am unteren Rand.

Die klassische Schriftart lässt sich zwei- oder dreimal hochskalieren: Größe 2 verwandelt jedes Pixel eines Buchstabens in einen 2×2-Block. Der Code für Beschriftung und Zahl:
tft.setTextSize(2);
tft.setFont();
tft.setCursor(20, 72);
tft.print("TEMP");
tft.setTextSize(1);
tft.setFont(&FreeSansBold18pt7b);
tft.setCursor(20, 179);
tft.print("23C");setFont() mit nichts in den Klammern wechselt zurück zur klassischen Schriftart. Die klassische Schriftart zählt y anders: setCursor nimmt die obere linke Ecke des Textes, nicht die Grundlinie. Die Buchstaben der Beschriftung sind 7 Pixel hoch, 14 bei Größe 2, also wird aus den 86 des Inspektors 86 − 14 = 72 im Code. Lopaka macht diese Umwandlung für dich. Vor der FreeSans-Zahl setzt es die Größe auf 1 zurück, damit die große Schriftart nicht verdoppelt wird.
Der Text sagt 23C, nicht 23°C: FreeSans-Schriftarten enthalten nur die grundlegenden ASCII-Zeichen, und das Gradzeichen ist keines davon.
Schriftarten kosten nur Flash, wenn du sie nutzt
FreeSans und die anderen Schriftarten in der Liste werden mit der Adafruit-GFX-Bibliothek ausgeliefert. Jede Schriftart ist eine separate Datei und braucht nur Flash, wenn dein Screen sie nutzt. Lopaka fügt ein #include für jede Schriftart hinzu, die das Design nutzt, hier drei:
#include "FreeSans12pt7b.h"
#include "FreeSansBold12pt7b.h"
#include "FreeSansBold18pt7b.h"Schritt 4: Getönte Icons
Öffne den Tab Bilder, suche ein Icon und klicke es, um es zum Screen hinzuzufügen. Füge drei hinzu:
- ein Thermometer (suche „thermo“),
- einen Tropfen (suche „drop“),
- ein Blatt (suche „leaf“).
Gehe zurück zu Ebenen und lege jedes Icon unter die Beschriftung seiner Karte.
Icons aus der Bibliothek sind einfarbig, also kannst du sie tönen, damit sie zu deinem Design passen. Wähle jedes Icon aus und setze seine Füllfarbe auf das dunkle Blau des Hintergrunds, #0F1B2D. Auf den hellen Karten sehen die Icons jetzt wie ausgeschnitten aus.
![]()
Im Code wird ein einfarbiges Icon zu drawBitmap:
tft.drawBitmap(20, 104, image_streamline_weather_temperature_thermometer__weather_png_bits, 21, 21, 0x8C5);Die Argumente sind die Position, das Bit-Array, die Breite und Höhe und die Farbe. Das Array speichert ein Bit pro Pixel, wie auf dem OLED in Episode 2: Das Thermometer ist 21×21 Pixel, 3 Bytes pro Zeile, 63 Bytes insgesamt. Die Farbe ist eine separate Zahl im Code, also lässt sich dasselbe Icon in jeder Farbe zeichnen, ohne eine zweite Kopie.
Schritt 5: Ein Farbbild
Lade es als RGB hoch
Bilder können auch Vollfarbe sein. Klicke im Tab Bilder auf Hochladen und wähle ein Bild, auf dieselbe Weise wie in Episode 2. Diesmal wechsle den Konverter von Monochrom zu RGB.

Der Zähler oben zeigt die Kosten. In seiner vollen Größe von 240×240 Pixeln würde dieses Bild 240 × 240 × 2 = 115.200 Bytes brauchen, mehr als das Dreifache des ganzen Flash eines UNO.
Verkleinere es auf 40×40
Setze Maße auf W 40 und H 40. Jetzt braucht das Bild 40 × 40 × 2 = 3.200 Bytes, etwa drei Kilobyte. Das ist der Sweet Spot für Farbbilder: kleine, farbenfrohe Details. Klicke auf Importieren.
Im Code wird das Bild zu einem Array von 1.600 RGB565-Zahlen, eine pro Pixel, und einer Zeile, die es zeichnet:
tft.drawRGBBitmap(12, 197, image_sun_cloud_pixels, 40, 40);Anders als drawBitmap nimmt dieser Aufruf keine Farbe: Jedes Pixel bringt seine eigene mit.
Die untere Zeile
Lege das Bild in die untere linke Ecke und füge daneben eine weitere Textzeile hinzu: Outside: 18C, sunny in Adafruit 5x7, Größe 2, in demselben Graublau #9FB3C8 wie die Zeit.
Schritt 6: Hole den Code
Eine Karte, drei Dialekte
Jede Bibliothek spricht ihren eigenen Dialekt. Dieselbe abgerundete Karte ist drawRBox in U8g2, fillRoundRect in Adafruit GFX und ein gestyltes Objekt in LVGL. Lopaka schreibt den für die Plattform, die du gewählt hast.

Kopiere und lade die Schriftartdateien herunter
Klicke über dem Code auf Kopieren. Unter den Schaltern neben dem Code listet Lopaka die Schriftarten und Bilder, die das Design nutzt. Klicke jede der drei Schriftartdateien, um sie herunterzuladen, und lege die Dateien neben deinen Sketch. Das Bild und die Icons sind bereits als Arrays im kopierten Code, also brauchst du die Bilddateien nicht.

Wenn du die Schriftartdateien vergisst, stoppt der Compiler mit fatal error: FreeSans12pt7b.h: No such file or directory.
Lopaka generiert diesen Code für das Dashboard. Das Bild-Array ist 1.600 Zahlen lang, also ist es hier gekürzt; Kopieren gibt dir alles.
// [BEGIN lopaka generated]
#include "FreeSans12pt7b.h"
#include "FreeSansBold12pt7b.h"
#include "FreeSansBold18pt7b.h"
static const unsigned char PROGMEM image_drop_bits[] = {0x10,0x38,0x7c,0x7c,0xfe,0xde,0xde,0xde,0x7c,0x38};
static const unsigned char PROGMEM image_streamline_ecology_leaf_bug__ecology_png_bits[] = {0x00,0x00,0x30,0x00,0x00,0x48,0x00,0x00,0x88,0x00,0x3f,0x08,0x03,0xe0,0x08,0x0c,0x00,0x08,0x10,0xe0,0x08,0x21,0x70,0x88,0x41,0xd1,0x08,0x40,0xe2,0x08,0x80,0x0c,0x08,0x80,0x30,0x10,0x80,0xc0,0x10,0x83,0x00,0x20,0x84,0x00,0x20,0x88,0x00,0x40,0x50,0x00,0x80,0x20,0x03,0x00,0x50,0x0c,0x00,0x8f,0xf0,0x00,0x80,0x00,0x00};
static const unsigned char PROGMEM image_streamline_weather_temperature_thermometer__weather_png_bits[] = {0x03,0x00,0x00,0x04,0x80,0x00,0x04,0x80,0x00,0x04,0x87,0x80,0x04,0x80,0x00,0x04,0x80,0x00,0x04,0x80,0x00,0x04,0x87,0x80,0x04,0x80,0x00,0x04,0x80,0x00,0x07,0x80,0x00,0x07,0x87,0x80,0x07,0x80,0x00,0x07,0x80,0x00,0x0f,0xc0,0x00,0x1f,0x60,0x00,0x1f,0xa0,0x00,0x1f,0xa0,0x00,0x1f,0xe0,0x00,0x0f,0xc0,0x00,0x07,0x80,0x00};
static const uint16_t PROGMEM image_sun_cloud_pixels[] = {/* 1,600 RGB565 values, shortened here */};
void drawScreen_1(void) {
tft.fillScreen(0x8C5);
// rect 1
tft.fillRoundRect(10, 56, 96, 140, 12, 0xFC00);
// rect 2
tft.fillRoundRect(112, 56, 96, 140, 12, 0x2BFF);
// rect 3
tft.fillRoundRect(214, 56, 96, 140, 12, 0x25AE);
// string 4
tft.setTextColor(0xFFFF);
tft.setTextWrap(false);
tft.setFont(&FreeSansBold12pt7b);
tft.setCursor(12, 35);
tft.print("Living room");
// string 5
tft.setTextColor(0x9D99);
tft.setFont(&FreeSans12pt7b);
tft.setCursor(246, 35);
tft.print("07:45");
// string 6
tft.setTextColor(0xFFFF);
tft.setTextSize(2);
tft.setFont();
tft.setCursor(20, 72);
tft.print("TEMP");
// string 7
tft.setTextSize(1);
tft.setFont(&FreeSansBold18pt7b);
tft.setCursor(20, 179);
tft.print("23C");
// string 8
tft.setTextSize(2);
tft.setFont();
tft.setCursor(122, 72);
tft.print("HUMID");
// string 9
tft.setTextSize(1);
tft.setFont(&FreeSansBold18pt7b);
tft.setCursor(122, 179);
tft.print("48%");
// string 10
tft.setTextSize(2);
tft.setFont();
tft.setCursor(224, 72);
tft.print("AIR");
// string 11
tft.setTextSize(1);
tft.setFont(&FreeSansBold18pt7b);
tft.setCursor(224, 179);
tft.print("OK");
// streamline-weather-temperature-thermometer--weather.png
tft.drawBitmap(20, 104, image_streamline_weather_temperature_thermometer__weather_png_bits, 21, 21, 0x8C5);
// drop
tft.drawBitmap(122, 104, image_drop_bits, 7, 10, 0x8C5);
// streamline-ecology-leaf-bug--ecology.png
tft.drawBitmap(224, 104, image_streamline_ecology_leaf_bug__ecology_png_bits, 21, 21, 0x8C5);
// sun_cloud
tft.drawRGBBitmap(12, 197, image_sun_cloud_pixels, 40, 40);
// string 16
tft.setTextColor(0x9D99);
tft.setTextSize(2);
tft.setFont();
tft.setCursor(62, 211);
tft.print("Outside: 18C, sunny");
}
// [END lopaka generated]Schritt 7: Führe ihn auf einem ESP32 aus
Der Sketch
Diesmal führen wir den Screen auf einem ESP32 aus, einem schnelleren Board, beliebt für Farbscreens; ein typisches ESP32-Board hat 4 MB Flash. Das Display ist ein 320×240-ILI9341-Modul über SPI.
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// ILI9341 320x240 color display on SPI
#define TFT_CS 15
#define TFT_DC 2
#define TFT_RST 4
Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
// Paste the Lopaka code here
void setup() {
tft.begin();
tft.setRotation(1); // landscape, 320x240
drawScreen_1();
}
void loop() {
}Adafruit_ILI9341 tft(...)erstellt das Display-Objekt und sagt ihm, welche Pins es für Chip Select, Data/Command und Reset nutzt. Der Code von Lopaka nennt estft, also behalte diesen Namen.- Der ILI9341 ist ein Hochformat-Panel, 240 breit und 320 hoch.
setRotation(1)dreht ihn ins Querformat, 320×240, die Größe, die wir entworfen haben. drawScreen_1()läuft einmal, insetup(). Der Screen behält sein Bild, bis etwas darüber zeichnet, also bleibtloop()vorerst leer.
Verdrahte ihn im Simulator
Starte im Simulator aus Episode 1 ein neues ESP32-Projekt und füge ein ILI9341-Display hinzu. Verbinde es:
- VCC und LED (die Hintergrundbeleuchtung) mit 3V3, GND mit GND,
- CS mit 15, D/C mit 2, RST mit 4,
- MOSI mit 23, SCK mit 18, MISO mit 19.
Füge die Bibliotheken Adafruit ILI9341 und Adafruit GFX Library hinzu, füge den Sketch mit dem Lopaka-Code an seiner Stelle ein, füge die drei Schriftartdateien zum Projekt hinzu und drücke Play. Das Dashboard erscheint auf dem simulierten Display.

Kein Frame-Puffer
Erinnerst du dich an den Frame-Puffer aus Episode 1, das ganze Bild, das im RAM gehalten wird, bevor es ans Display geht? Bei 320×240 in Farbe bräuchte er dieselben 150 KB wie ein Fullscreen-Bild. Farbbibliotheken wie Adafruit GFX überspringen ihn und zeichnen direkt aufs Display: Jedes fillRoundRect und print sendet seine Pixel sofort über SPI.
Das hält den RAM-Verbrauch winzig. Für den ESP32 kompiliert, nutzt der Sketch 23 % des Programmplatzes und 7 % des RAM. Derselbe Sketch, für einen Arduino UNO kompiliert:
Sketch uses 25946 bytes (80%) of program storage space. Maximum is 32256 bytes.
Global variables use 317 bytes (15%) of dynamic memory, leaving 1731 bytes for local variables. Maximum is 2048 bytes.Nur 15 % des RAM des UNO. Der Flash ist der enge Teil: 80 %, und die drei Schriftarten und das 3.200-Byte-Bild sind ein großer Anteil davon.
Auf einem echten Board
- Signalspannung. Der ESP32 arbeitet mit 3,3 V, wie der ILI9341. Viele günstige ILI9341-Module haben keinen Pegelwandler, also prüfe auf einem 5-V-Board wie dem UNO die Artikelbeschreibung deines Moduls, bevor du es verdrahtest.
- Der Controller. Manche 320×240-Module nutzen stattdessen den ST7789-Controller. Binde bei diesen
Adafruit_ST7789.hein, erstelle das Display alsAdafruit_ST7789 tft(TFT_CS, TFT_DC, TFT_RST);und starte es mittft.init(240, 320);statttft.begin();. Der Lopaka-Code bleibt derselbe.
Schritt 8: Ideen aus der Galerie
Brauchst du Ideen? Die Projektgalerie hat Tausende öffentlicher Projekte. Öffne eines, drücke Fork, und Lopaka kopiert es in deine Projekte, bereit zum Ändern.
Zusammenfassung
- Drei Lichter ergeben jede Farbe: Jedes Pixel mischt Rot, Grün und Blau.
- RGB565 packt sie in zwei Bytes: 5 Bits Rot, 6 Grün, 5 Blau, und Lopaka wandelt jede Farbe für dich um.
- Formen schlagen große Bilder: Eine Karte ist eine Codezeile, ein Fullscreen-Bild sind 150 KB, also halte Bilder klein.
Nächste Episode: Live-Daten. Wir lassen diese Zahlen sich von selbst ändern. Lies Episode 4 oder schaue sie auf YouTube.
Bereit, es zu versuchen? Öffne Lopaka und baue dein eigenes Farb-Dashboard.