ILI9341 Arduino: TFT-Display anschließen, Touch und Bilder von SD
ILI9341-TFT-Display am Arduino anschließen: 3,3-V-Pegelwandler am Uno, Adafruit GFX, XPT2046-Touch, BMP von SD, ESP32 mit TFT_eSPI, weißer Bildschirm gelöst.
Ein ILI9341 am Arduino ist der günstigste und verbreitetste Weg, deinem Projekt ein Display mit 240×320 Pixeln und 65.000 Farben zu geben. Diese 2,4- und 2,8-Zoll-TFT-Module auf roter Platine werden per SPI mit nur wenigen Kabeln angeschlossen; die Touch-Versionen haben zusätzlich einen XPT2046-Touch-Controller und einen microSD-Kartenslot. Mit einem einzigen Modul zeigst du farbige Grafiken, Touch-Buttons und Bilder von der Karte. Ideal für Menüs, Dashboards, Spiele und Bilderrahmen, bei denen ein OLED oder ein Zeichen-LCD nicht mehr reicht.
In dieser Anleitung lernst du Schritt für Schritt, wie das Modul funktioniert, wie du die 5-V-Ausgänge des Arduino Uno sicher an die 3,3-V-Eingänge des Displays anschließt, wie du mit den Bibliotheken Adafruit_ILI9341 und Adafruit GFX Text, Formen und Farben zeichnest, den Touchscreen ausliest und BMP-Bilder von der SD-Karte anzeigst. Danach geht es um deutlich schnelleres Zeichnen auf dem ESP32 mit TFT_eSPI, MicroPython auf dem Raspberry Pi Pico und alle Ursachen für den "weißen Bildschirm", über den fast jeder einmal stolpert.

Was ist das ILI9341-TFT-Display und wie funktioniert es?
Der ILI9341 ist der Treiberchip hinter dem Glas. Er enthält rund 172 KB Bildspeicher (GRAM), der alle 240×320 Pixel aufnimmt. Der Arduino schickt Befehle und Farbdaten per SPI in diesen Speicher, und der Chip frischt das Bild selbstständig dutzende Male pro Sekunde auf. Deshalb muss das Bild nicht im RAM des Arduino liegen: Selbst ein Uno mit 2 KB RAM kann ein großes Farbdisplay ansteuern. Um etwas zu zeichnen, wählst du zuerst ein Fenster (x, y, Breite, Höhe) und schickst dann die Pixel dieses Fensters nacheinander. Der DC-Pin sagt dem Chip, ob das gesendete Byte ein Befehl (LOW) oder Daten (HIGH) sind. Farben werden meist im RGB565-Format übertragen, also mit 16 Bit pro Pixel: 5 Bit Rot, 6 Bit Grün, 5 Bit Blau. Wie der SPI-Bus funktioniert, erfährst du ausführlich in Was ist SPI.
| Merkmal | Wert |
|---|---|
| Treiberchip | ILI9341 |
| Auflösung | 240×320 Pixel (im Querformat 320×240) |
| Farbe | 65.536 Farben mit RGB565 (der Chip kann 262.000) |
| Displaygrößen | 2,2", 2,4", 2,8" und 3,2" (alle 240×320) |
| Schnittstelle | 4-Draht-SPI: CS, DC, SCK, MOSI (MISO zum Lesen) |
| Versorgung (VCC) | 3,3–5 V (Spannungsregler auf der Platine) |
| Logikpegel | 3,3 V (nicht 5-V-tolerant) |
| Leistungsaufnahme | Etwa 0,3–0,6 W, größtenteils Hintergrundbeleuchtung |
| Touch | Resistiv, XPT2046-Controller (bei Touch-Modellen) |
| Zusatzhardware | microSD-Kartenslot (eigene SPI-Pins) |
2,4 Zoll oder 2,8 Zoll? SPI-Modul oder Uno-Shield
| Merkmal | 2,4"-SPI-Modul | 2,8"-SPI-Modul | 2,4"-Uno-Shield |
|---|---|---|---|
| Auflösung | 240×320 | 240×320 | 240×320 |
| Anschluss | SPI, mit Kabeln | SPI, mit Kabeln | 8 Bit parallel, wird auf den Uno gesteckt |
| Belegte Pins | 5 für das Display, 8–9 mit Touch und SD | 5 für das Display, 8–9 mit Touch und SD | Fast alle (D2–D9, A0–A4, D10–D13 für SD) |
| Treiber | ILI9341 | ILI9341 | Unterschiedlich: ILI9341, ILI9325, ST7789 und andere |
| Bibliothek | Adafruit_ILI9341, TFT_eSPI | Adafruit_ILI9341, TFT_eSPI | MCUFRIEND_kbv |
| Touch | XPT2046 (SPI) | XPT2046 (SPI) | 4-Draht analog (TouchScreen-Bibliothek) |
| ESP32 und Pico | Geeignet | Geeignet | Für Uno und Mega gebaut |
Dieser Artikel behandelt das SPI-Modul, weil es auch mit ESP32 und Pico funktioniert und am Uno die meisten Pins frei lässt. Die beiden SPI-Module haben exakt dieselben Pins und denselben Code; das 2,8-Zoll-Display hat etwas größere Pixel, deshalb triffst du Touch-Buttons leichter. Wird dein Display als Shield direkt auf den Uno gesteckt, können die SPI-Bibliotheken es nicht ansteuern, und das Ergebnis ist meist ein weißer Bildschirm. Für so ein Shield installierst du die Bibliothek MCUFRIEND_kbv, liest mit tft.readID() die Treiber-ID aus (0x9341 beim ILI9341) und startest es mit tft.begin(ID). Eine kleinere, aber schärfere Alternative ist das ST7789-TFT-Display; alle Optionen im Vergleich findest du unter Arduino-Display-Arten.
ILI9341-Pinbelegung und Anschlusstabelle
An einer Kante des Moduls sitzt die 14-polige Hauptleiste: Die ersten 9 Pins sind für das Display, die letzten 5, die mit T_ beginnen, für den Touch. Die 4 Pins an der gegenüberliegenden Kante (SD_CS, SD_MOSI, SD_MISO, SD_SCK) führen zum Kartenslot. Alle drei Bausteine können sich denselben SPI-Bus (SCK, MOSI, MISO) teilen; nur ihre CS-Pins müssen getrennt sein. Die Tabelle passt zu allen Sketches in diesem Artikel; am Pico hängt der Touch wegen des Geschwindigkeitsunterschieds an einem eigenen SPI-Bus.
| Modul-Pin | Arduino Uno (über Pegelwandler) | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 | 3V3(OUT) |
| GND | GND | GND | GND |
| CS | D10 | GPIO 15 | GP17 |
| RESET | D8 | GPIO 4 | GP21 |
| DC | D9 | GPIO 2 | GP20 |
| SDI (MOSI) | D11 | GPIO 23 | GP19 |
| SCK | D13 | GPIO 18 | GP18 |
| LED | 3.3V | 3V3 | 3V3(OUT) |
| SDO (MISO) | D12 (direkt) | GPIO 19 | GP16 |
| T_CLK | D13 | GPIO 18 | GP10 |
| T_CS | D7 | GPIO 21 | GP13 |
| T_DIN | D11 | GPIO 23 | GP11 |
| T_DO | D12 (direkt) | GPIO 19 | GP12 |
| T_IRQ | D2 (direkt) | Frei | Frei |
| SD_CS | D4 | GPIO 5 | Frei |
| SD_MOSI / SD_MISO / SD_SCK | D11 / D12 / D13 | GPIO 23 / 19 / 18 | Frei |
3,3-V-Pegelwandlung am Arduino Uno
ESP32 und Raspberry Pi Pico arbeiten ohnehin mit 3,3 V, deshalb kannst du das Display direkt anschließen. Bei 5-V-Boards wie Uno, Nano und Mega muss dagegen jede Leitung vom Arduino zum Display auf 3,3 V gebracht werden: CS, DC, RESET, SCK, MOSI und, wenn du Touch und SD nutzt, T_CLK, T_DIN, T_CS, SD_CS, SD_MOSI und SD_SCK. Die Leitungen SDO, T_DO, SD_MISO und T_IRQ, die vom Display zum Arduino laufen, brauchen keinen Wandler: Der Uno erkennt alles über 3 V als HIGH, und ein 3,3-V-Ausgang erfüllt das. In der Praxis gibt es vier Wege:
- Puffer-IC 74HC4050 (die sauberste Lösung): Er läuft mit 3,3 V, verträgt 5 V an den Eingängen und wandelt 6 Leitungen in einem Chip. Er ist schnell und arbeitet bei 8 MHz SPI problemlos. Der ältere CD4050 funktioniert auch, ist aber langsam; wird das Bild fehlerhaft, musst du die SPI-Geschwindigkeit senken. Für das Display allein reichen 5 Leitungen; mit Touch und SD kommen T_CS und SD_CS dazu, also 7 Leitungen. Für die siebte nimmst du einen zweiten Chip oder einen Spannungsteiler.
- Spannungsteiler aus Widerständen: Setze für jede Leitung 1 kΩ zwischen Arduino-Pin und Display-Pin und 2 kΩ zwischen Display-Pin und GND; so erhältst du 5 V × 2 / 3 ≈ 3,3 V. Andere Widerstandspaare berechnest du mit dem Spannungsteiler-Rechner. Das ist billig, aber 10 Widerstände für 5 Leitungen machen das Steckbrett voll.
- Fertiges Pegelwandler-Modul: 4- oder 8-Kanal-Module mit BSS138-MOSFETs sind leicht zu verdrahten, aber ihre Pull-up-Widerstände verschleifen die Signalflanken bei hohen Geschwindigkeiten. Wird das Bild fehlerhaft, senke SPI mit tft.begin(4000000) auf 4 MHz. Die Methoden im Vergleich findest du unter Logik-Pegelwandler.
- Die Methode, die du meiden solltest: Der beliebte Trick "10 kΩ in Reihe auf jeder Leitung" leitet die überschüssige Spannung in die internen Schutzdioden des Chips. Das kann eine Weile funktionieren, ist aber unzuverlässig und kann das Display auf Dauer beschädigen.
Schritt für Schritt: erster Test mit Adafruit_ILI9341
- Öffne in der Arduino IDE den Bibliotheksverwalter, suche nach Adafruit ILI9341 und installiere sie. Wenn nach Abhängigkeiten gefragt wird, wähle Install all, damit auch Adafruit GFX und Adafruit BusIO installiert werden. Ist es deine erste Bibliothek, hilft dir Arduino-Bibliothek hinzufügen.
- Installiere für den Touch zusätzlich die Bibliothek XPT2046_Touchscreen von Paul Stoffregen. Die SD-Bibliothek ist in der Arduino IDE bereits enthalten.
- Schließe das Display nach der Tabelle oben an, am Uno über einen Pegelwandler. Für den ersten Test kannst du die Touch- und SD-Pins frei lassen.
- Lade den folgenden Sketch hoch und öffne den seriellen Monitor mit 9600 Baud. Auf dem Display sollten Text und Formen erscheinen, im seriellen Monitor die Diagnosewerte des Displays.
- Probiere auch die mitgelieferten Beispiele: Datei > Beispiele > Adafruit ILI9341 > graphicstest misst, wie viele Mikrosekunden jede Zeichenoperation dauert.
1#include <SPI.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_ILI9341.h>
4
5#define TFT_CS 10 // ekran seçme / chip select
6#define TFT_DC 9 // komut/veri seçimi / command/data select
7#define TFT_RST 8 // donanım reset / hardware reset
8
9Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST); // donanım SPI: D11 MOSI, D13 SCK / hardware SPI
10uint16_t orange; // kendi rengimiz / our own colour
11
12void setup() {
13 Serial.begin(9600);
14 tft.begin(); // Uno'da 8 MHz SPI / 8 MHz SPI on Uno
15
16 // Teşhis: çalışan ekranda 0x94 ve 0xC0 beklenir / Diagnostics: a working display reports 0x94 and 0xC0
17 Serial.print(F("Power Mode: 0x"));
18 Serial.println(tft.readcommand8(ILI9341_RDMODE), HEX);
19 Serial.print(F("Self Diagnostic: 0x"));
20 Serial.println(tft.readcommand8(ILI9341_RDSELFDIAG), HEX);
21
22 tft.setRotation(1); // yatay, 320x240 / landscape, 320x240
23 tft.fillScreen(ILI9341_BLACK);
24 orange = tft.color565(255, 128, 0); // RGB'den RGB565'e / RGB to RGB565
25
26 tft.setTextColor(ILI9341_WHITE);
27 tft.setTextSize(3); // 18x24 piksel karakter / 18x24 px characters
28 tft.setCursor(10, 10);
29 tft.print(F("BlueGrays"));
30 tft.setTextColor(ILI9341_CYAN);
31 tft.setTextSize(2);
32 tft.setCursor(10, 45);
33 tft.print(F("ILI9341 320x240"));
34
35 tft.fillRect(10, 75, 90, 60, ILI9341_RED); // dolu dikdörtgen / filled rectangle
36 tft.drawRect(115, 75, 90, 60, ILI9341_GREEN); // çerçeve / outline
37 tft.fillCircle(265, 105, 30, ILI9341_BLUE); // dolu daire / filled circle
38 tft.fillRoundRect(10, 150, 140, 50, 10, orange); // yuvarlak köşeli düğme / rounded button
39 tft.drawTriangle(180, 200, 240, 150, 300, 200, ILI9341_YELLOW);
40 tft.drawFastHLine(0, 220, 320, ILI9341_MAGENTA); // yatay çizgi / horizontal line
41}
42
43void loop() {
44 // Arka plan rengiyle yazınca eski rakam silinir, ekran titremez / writing with a background colour erases the old digits, no flicker
45 tft.setTextColor(ILI9341_WHITE, orange);
46 tft.setTextSize(2);
47 tft.setCursor(22, 167);
48 tft.print(millis() / 1000);
49 tft.print(F(" s"));
50 delay(200);
51}| Funktion | Was sie macht |
|---|---|
| tft.begin(frequenz) | Startet das Display; ohne Frequenz nutzt es 8 MHz SPI am Uno und 40 MHz am ESP32 |
| tft.setRotation(0–3) | Wählt die Ausrichtung: 0 und 2 Hochformat (240×320), 1 und 3 Querformat (320×240) |
| tft.fillScreen(farbe) | Füllt den ganzen Bildschirm mit einer Farbe |
| tft.setTextColor(text, hintergrund) | Setzt die Textfarbe; mit Hintergrundfarbe wird alter Text sauber überschrieben |
| tft.setTextSize(n) | Vergrößert den Text n-fach; Größe 1 = Zeichen mit 6×8 Pixeln |
| tft.drawRect / fillRect(x, y, breite, hoehe, farbe) | Rechteckrahmen oder gefülltes Rechteck |
| tft.fillRoundRect(x, y, breite, hoehe, r, farbe) | Gefülltes Rechteck mit runden Ecken; ideal für Buttons |
| tft.drawCircle / fillCircle(x, y, r, farbe) | Kreis oder gefüllter Kreis |
| tft.color565(r, g, b) | Wandelt RGB-Werte von 0–255 in eine 16-Bit-Farbe um |
| tft.readcommand8(befehl) | Liest ein Register des Displays (MISO muss angeschlossen sein); zur Fehlersuche |
Fertige Farbkonstanten (19 Stück, etwa ILI9341_RED, ILI9341_NAVY und ILI9341_ORANGE) bringt die Bibliothek mit; für eigene Farben nutzt du color565(). Die Funktion setzt die oberen 5 Bit von Rot, die oberen 6 Bit von Grün und die oberen 5 Bit von Blau nebeneinander: Farbe = (R >> 3) << 11 | (G >> 2) << 5 | (B >> 3). Für Orange (255, 165, 0) ergeben zum Beispiel 31 << 11 = 0xF800 und 41 << 5 = 0x0520 zusammen 0xFD20, also genau den Wert von ILI9341_ORANGE in der Bibliothek. Grün bekommt ein Bit mehr, weil das menschliche Auge für Grün empfindlicher ist.
Den XPT2046-Touchscreen auslesen
Bei Touch-Modulen liegt eine dünne resistive Schicht über dem Glas. Wo dein Finger oder ein Stift drückt, berühren sich zwei leitende Schichten; der XPT2046 misst die X- und Y-Position dieses Punktes mit einem 12-Bit-ADC als Rohwerte von 0 bis 4095 und liefert zusätzlich einen Druckwert (Z). Die Bibliothek wertet einen Z-Wert unter 400 als keine Berührung. Der Chip hängt am selben SPI-Bus wie das Display, spricht aber langsamer, mit etwa 2 MHz; die Bibliothek stellt die Geschwindigkeit bei jedem Lesen selbst ein. Der T_IRQ-Pin geht bei Berührung auf LOW und erspart dem Prozessor unnötige Abfragen. Der folgende Sketch macht aus dem Display ein kleines Zeichenbrett: Oben wählst du eine Farbe aus den Kästchen, und mit dem Button "SIL" (Löschen) leerst du den Bildschirm.
1#include <SPI.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_ILI9341.h>
4#include <XPT2046_Touchscreen.h>
5
6#define TFT_CS 10
7#define TFT_DC 9
8#define TFT_RST 8
9#define T_CS 7 // dokunmatik seçme / touch chip select
10#define T_IRQ 2 // dokununca LOW olur / goes LOW on touch
11#define SD_CS 4 // SD kullanılmıyor, HIGH tutulur / SD unused, kept HIGH
12
13// Kalibrasyon: Seri Monitör'deki ham değerlerle değiştir / Calibration: replace with the raw values from Serial Monitor
14#define TS_MINX 300
15#define TS_MAXX 3800
16#define TS_MINY 300
17#define TS_MAXY 3800
18
19Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
20XPT2046_Touchscreen ts(T_CS, T_IRQ);
21
22uint16_t brush = ILI9341_YELLOW; // fırça rengi / brush colour
23
24void drawPalette() {
25 tft.fillRect(0, 0, 40, 40, ILI9341_RED);
26 tft.fillRect(40, 0, 40, 40, ILI9341_GREEN);
27 tft.fillRect(80, 0, 40, 40, ILI9341_BLUE);
28 tft.fillRect(120, 0, 40, 40, ILI9341_YELLOW);
29 tft.drawRect(260, 0, 60, 40, ILI9341_WHITE); // silme düğmesi / clear button
30 tft.setTextColor(ILI9341_WHITE);
31 tft.setTextSize(2);
32 tft.setCursor(273, 13);
33 tft.print(F("SIL"));
34}
35
36void setup() {
37 Serial.begin(9600);
38 pinMode(SD_CS, OUTPUT);
39 digitalWrite(SD_CS, HIGH); // SD kart hattı meşgul etmesin / keep the SD card off the bus
40 tft.begin();
41 tft.setRotation(1); // ekran yatay / display landscape
42 ts.begin();
43 ts.setRotation(1); // dokunmatik de aynı yönde / touch in the same orientation
44 tft.fillScreen(ILI9341_BLACK);
45 drawPalette();
46}
47
48void loop() {
49 if (!ts.touched()) return; // dokunma yok / no touch
50 TS_Point p = ts.getPoint(); // ham x, y (0-4095) ve basınç z / raw x, y and pressure z
51 Serial.print(p.x); Serial.print(',');
52 Serial.print(p.y); Serial.print(',');
53 Serial.println(p.z);
54
55 int16_t x = constrain(map(p.x, TS_MINX, TS_MAXX, 0, 319), 0, 319); // ekran koordinatı / screen coordinate
56 int16_t y = constrain(map(p.y, TS_MINY, TS_MAXY, 0, 239), 0, 239);
57
58 if (y < 40) { // üst şerit: palet ve düğme / top strip: palette and button
59 if (x < 40) brush = ILI9341_RED;
60 else if (x < 80) brush = ILI9341_GREEN;
61 else if (x < 120) brush = ILI9341_BLUE;
62 else if (x < 160) brush = ILI9341_YELLOW;
63 else if (x >= 260) { tft.fillScreen(ILI9341_BLACK); drawPalette(); }
64 } else {
65 tft.fillCircle(x, y, 3, brush); // parmağın altına nokta / dot under the finger
66 }
67}Die Rohwerte sind in den Ecken nicht genau 0 und 4095; bei den meisten Modulen liegen die Ränder etwa zwischen 200–400 und 3700–3900. Zum Kalibrieren öffnest du den seriellen Monitor, tippst mit einem Stift in die linke obere und die rechte untere Ecke und trägst die angezeigten x- und y-Werte in TS_MINX, TS_MAXX, TS_MINY und TS_MAXY ein. Erscheint der Punkt gespiegelt zu deinem Finger, tausche Min- und Max-Wert dieser Achse in map(); sind X und Y komplett vertauscht, probiere für ts.setRotation() die Werte 0 bis 3. Ein echtes Menü funktioniert genauso: Du zeichnest Buttons und prüfst, in welchem Rechteck der berührte Punkt liegt. Die resistive Schicht reagiert auch auf den Finger, für kleine Buttons ist eine stiftartige Spitze aber genauer.
BMP-Bilder von der SD-Karte anzeigen
Mit dem microSD-Slot auf der Rückseite des Moduls kannst du Logos, Hintergründe und Fotos auf einer Karte speichern und auf dem Display zeigen. Um ein Bild vorzubereiten, verkleinerst du ein Foto auf 320×240 Pixel und speicherst es in Paint als 24-Bit-Bitmap (.bmp). Weil die SD-Bibliothek des Arduino mit kurzen Dateinamen arbeitet, nimm einen Namen mit höchstens 8 Zeichen wie RESIM.BMP und formatiere die Karte mit FAT32. Details zur Karte selbst und die Lösung für den Fehler initialization failed findest du unter Arduino-SD-Kartenmodul. Denk daran: Auch dieser Slot arbeitet mit 3,3 V, am Uno müssen also auch SD_CS, SD_MOSI und SD_SCK über den Pegelwandler laufen.
1#include <SPI.h>
2#include <SD.h>
3#include <Adafruit_GFX.h>
4#include <Adafruit_ILI9341.h>
5
6#define TFT_CS 10
7#define TFT_DC 9
8#define TFT_RST 8
9#define SD_CS 4
10#define T_CS 7
11#define CHUNK 20 // tek okumada 20 piksel (60 bayt) / 20 pixels (60 bytes) per read
12
13Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
14
15uint16_t read16(File &f) { // BMP sayıları küçük uçlu / BMP numbers are little-endian
16 uint16_t lo = f.read();
17 uint16_t hi = f.read();
18 return lo | (hi << 8);
19}
20
21uint32_t read32(File &f) {
22 uint32_t lo = read16(f);
23 uint32_t hi = read16(f);
24 return lo | (hi << 16);
25}
26
27bool drawBmp(const char *name, int16_t x, int16_t y) {
28 File f = SD.open(name);
29 if (!f) return false; // dosya yok / file not found
30 if (read16(f) != 0x4D42) { f.close(); return false; } // "BM" imzası / "BM" signature
31 read32(f); // dosya boyutu / file size
32 read32(f); // ayrılmış alan / reserved
33 uint32_t offset = read32(f); // piksel verisinin başı / start of pixel data
34 read32(f); // başlık boyutu / header size
35 int32_t w = (int32_t)read32(f);
36 int32_t h = (int32_t)read32(f);
37 read16(f); // düzlem sayısı / colour planes
38 uint16_t depth = read16(f);
39 uint32_t comp = read32(f);
40 if (depth != 24 || comp != 0) { f.close(); return false; } // yalnız 24 bit, sıkıştırmasız / 24-bit uncompressed only
41
42 bool bottomUp = true; // BMP satırları alttan üste / rows are stored bottom-up
43 if (h < 0) { h = -h; bottomUp = false; }
44 uint32_t rowSize = (w * 3 + 3) & ~3UL; // satırlar 4 baytın katı / rows padded to 4 bytes
45 int32_t drawW = w, drawH = h;
46 if (x + drawW > tft.width()) drawW = tft.width() - x; // ekrana sığmayanı kırp / clip to the screen
47 if (y + drawH > tft.height()) drawH = tft.height() - y;
48
49 uint8_t sdBuf[CHUNK * 3];
50 uint16_t line[CHUNK];
51 for (int32_t row = 0; row < drawH; row++) {
52 uint32_t pos = offset + (bottomUp ? (h - 1 - row) : row) * rowSize;
53 f.seek(pos); // satırın başına git / jump to the start of the row
54 for (int32_t col = 0; col < drawW; col += CHUNK) {
55 int16_t n = drawW - col;
56 if (n > CHUNK) n = CHUNK;
57 f.read(sdBuf, n * 3);
58 for (int16_t i = 0; i < n; i++) { // BGR'den RGB565'e / BGR to RGB565
59 line[i] = tft.color565(sdBuf[i * 3 + 2], sdBuf[i * 3 + 1], sdBuf[i * 3]);
60 }
61 tft.drawRGBBitmap(x + col, y + row, line, n, 1); // parçayı ekrana bas / push the chunk to the screen
62 }
63 }
64 f.close();
65 return true;
66}
67
68void setup() {
69 Serial.begin(9600);
70 pinMode(T_CS, OUTPUT);
71 digitalWrite(T_CS, HIGH); // dokunmatik hattı meşgul etmesin / keep touch off the bus
72 tft.begin();
73 tft.setRotation(1); // 320x240 yatay / landscape
74 tft.fillScreen(ILI9341_BLACK);
75 tft.setTextSize(2);
76
77 if (!SD.begin(SD_CS)) { // kart başlatılamadı / card init failed
78 tft.setTextColor(ILI9341_RED);
79 tft.setCursor(10, 10);
80 tft.print(F("SD kart bulunamadi"));
81 return;
82 }
83 uint32_t t = millis();
84 if (!drawBmp("RESIM.BMP", 0, 0)) {
85 tft.setTextColor(ILI9341_YELLOW);
86 tft.setCursor(10, 10);
87 tft.print(F("RESIM.BMP okunamadi"));
88 }
89 Serial.print(F("Cizim suresi / Draw time (ms): "));
90 Serial.println(millis() - t);
91}
92
93void loop() {
94}Die ersten 54 Bytes einer BMP-Datei sind der Header: Dort stehen die Signatur "BM", der Beginn der Pixeldaten, Breite, Höhe und Farbtiefe. Die Pixel liegen in der Reihenfolge Blau, Grün, Rot (BGR) und normalerweise von unten nach oben in der Datei, und jede Zeile wird auf ein Vielfaches von 4 Bytes aufgefüllt. Deshalb springt der Sketch für jede Bildschirmzeile an die richtige Stelle der Datei, liest jeweils 20 Pixel (60 Bytes), wandelt sie in RGB565 um und zeichnet sie mit drawRGBBitmap(). In kleinen Stücken zu arbeiten, hält alles im RAM des Uno und lässt SD-Karte und Display abwechselnd denselben SPI-Bus nutzen. Die Zeichenzeit wird im seriellen Monitor ausgegeben; am Uno baut sich ein Vollbild Zeile für Zeile innerhalb weniger Sekunden auf. Willst du PNG oder JPEG anzeigen und viel schneller zeichnen, wechsle zum ESP32 mit den Bibliotheken TFT_eSPI und TJpg_Decoder.
Schnelles Zeichnen auf dem ESP32 mit TFT_eSPI

Der ESP32 arbeitet mit 3,3 V und kann SPI mit bis zu 40 MHz betreiben; du brauchst also keinen Pegelwandler, und das Füllen des ganzen Bildschirms sinkt theoretisch auf etwa 31 Millisekunden. Um dieses Tempo wirklich zu nutzen, ist Bodmers Bibliothek TFT_eSPI die übliche Wahl. Sie greift direkt auf die SPI-Hardware des ESP32 zu, unterstützt kantengeglättete Schriften und vor allem Off-Screen-Puffer, die Sprites heißen. Du zeichnest im RAM so viel du willst in ein Sprite und schickst das Ergebnis in einem Rutsch an das Display; so flackern selbst schnell wechselnde Grafiken nicht. Der Unterschied bei TFT_eSPI: Die Pins stehen nicht im Sketch, sondern in der Datei User_Setup.h im Bibliotheksordner. Öffne sie, kommentiere die standardmäßig aktiven ESP8266-Pinzeilen (NodeMCU) aus und aktiviere diese:
1// TFT_eSPI/User_Setup.h içinde yalnız bu satırlar açık kalsın / keep only these lines active in TFT_eSPI/User_Setup.h
2#define ILI9341_DRIVER
3
4#define TFT_MISO 19
5#define TFT_MOSI 23
6#define TFT_SCLK 18
7#define TFT_CS 15 // ekran seçme / chip select
8#define TFT_DC 2 // komut/veri / data/command
9#define TFT_RST 4 // sıfırlama / reset
10#define TOUCH_CS 21 // dokunmatik seçme (T_CS) / touch chip select (T_CS)
11
12#define LOAD_GLCD // 1: 8 piksel yazı tipi / 8 px font
13#define LOAD_FONT2 // 2: 16 piksel / 16 px
14#define LOAD_FONT4 // 4: 26 piksel / 26 px
15#define LOAD_FONT7 // 7: 7 segment rakamlar / 7-segment digits
16#define LOAD_GFXFF // Adafruit FreeFont'lar / Adafruit FreeFonts
17#define SMOOTH_FONT
18
19#define SPI_FREQUENCY 40000000 // kablolar uzunsa 27000000 / 27 MHz with long wires
20#define SPI_READ_FREQUENCY 20000000
21#define SPI_TOUCH_FREQUENCY 25000001#include <SPI.h>
2#include <TFT_eSPI.h> // pinler User_Setup.h içinde / pins are set in User_Setup.h
3
4TFT_eSPI tft = TFT_eSPI();
5TFT_eSprite graph = TFT_eSprite(&tft); // ekran dışı çizim alanı / off-screen canvas
6
7// Touch_calibrate örneğinin verdiği 5 sayıyla değiştir / replace with the 5 numbers from the Touch_calibrate example
8uint16_t calData[5] = {286, 3534, 283, 3600, 6};
9
10const int GW = 300, GH = 100; // grafik boyutu / graph size
11uint8_t samples[GW]; // son 300 ölçüm / last 300 readings
12uint32_t frames = 0, fps = 0, lastFps = 0;
13
14void setup() {
15 tft.init();
16 tft.setRotation(1); // yatay, 320x240 / landscape, 320x240
17 tft.setTouch(calData);
18 tft.fillScreen(TFT_BLACK);
19 tft.setTextColor(TFT_WHITE, TFT_BLACK);
20 tft.drawString("ESP32 + TFT_eSPI", 10, 8, 4); // 4 numaralı yazı tipi, 26 px / font 4, 26 px
21 graph.createSprite(GW, GH); // 300x100x2 bayt = 60 KB RAM / 60 KB of RAM
22}
23
24void loop() {
25 memmove(samples, samples + 1, GW - 1); // grafiği sola kaydır / scroll the graph left
26 samples[GW - 1] = map(analogRead(34), 0, 4095, 0, GH - 1); // GPIO 34'teki potansiyometre / pot on GPIO 34
27
28 graph.fillSprite(TFT_BLACK);
29 for (int y = 0; y < GH; y += 25) graph.drawFastHLine(0, y, GW, TFT_DARKGREY); // ızgara / grid
30 for (int x = 1; x < GW; x++) {
31 graph.drawLine(x - 1, GH - 1 - samples[x - 1], x, GH - 1 - samples[x], TFT_GREEN);
32 }
33 graph.setTextColor(TFT_YELLOW);
34 graph.drawString(String(fps) + " FPS", 4, 4, 2);
35 graph.pushSprite(10, 50); // tek seferde ekrana gönder, titreme yok / push in one go, no flicker
36
37 uint16_t tx, ty;
38 if (tft.getTouch(&tx, &ty)) { // dokunulduysa / if touched
39 tft.fillRect(10, 170, 300, 30, TFT_BLACK);
40 tft.setTextColor(TFT_CYAN, TFT_BLACK);
41 tft.drawString("Dokunma / Touch: " + String(tx) + ", " + String(ty), 10, 175, 2);
42 }
43
44 frames++;
45 if (millis() - lastFps >= 1000) { // saniyede bir FPS hesapla / compute FPS once per second
46 fps = frames;
47 frames = 0;
48 lastFps = millis();
49 }
50}Der Sketch zeichnet den Wert eines Potentiometers an GPIO 34 als laufendes Diagramm und zeigt die Bilder pro Sekunde (FPS) in der Ecke des Sprites. Ein Sprite mit 300×100 Pixeln in 16-Bit-Farbe belegt 60 KB RAM; das ist etwa das 30-Fache des gesamten Uno-Speichers, für den ESP32 aber kein Problem. Beim Touch werden T_CLK, T_DIN und T_DO mit SCK, MOSI und MISO des Displays verbunden, nur T_CS (GPIO 21) bleibt getrennt. Für deine eigenen Kalibrierwerte startest du einmal das TFT_eSPI-Beispiel Generic > Touch_calibrate, tippst auf die Eckpfeile und kopierst die 5 Zahlen aus dem seriellen Monitor in das Array calData. Die fertige Zeile Setup42_ILI9341_ESP32.h in User_Setup_Select.h wählt dieselben Display-Pins, die Zeile TOUCH_CS musst du dort aber selbst ergänzen. Bist du neu beim ESP32, lies zuerst Was ist der ESP32.
ILI9341 mit Raspberry Pi Pico und MicroPython
Auch der Pico ist ein 3,3-V-Board, deshalb wird das Display direkt angeschlossen. Der meistgenutzte MicroPython-Treiber sind die Dateien ili9341.py und xpt2046.py aus rdaggers Repository micropython-ili9341; kopiere einfach beide mit Thonny auf den Pico. Im folgenden Code hängt das Display an SPI0 mit 40 MHz und der Touch an einem eigenen SPI1-Bus mit 1 MHz, sodass der Geschwindigkeitsunterschied der beiden Chips kein Problem ist. Der Code zeichnet Text und Formen und setzt dann gelbe Punkte dorthin, wo du tippst, also ein einfaches Zeichenbrett. Nutzt du Pico und Thonny zum ersten Mal, beginne mit Was ist der Raspberry Pi Pico.
1from machine import Pin, SPI
2from time import sleep_ms
3from ili9341 import Display, color565 # ili9341.py Pico'da olmalı / must be on the Pico
4from xpt2046 import Touch # xpt2046.py Pico'da olmalı / must be on the Pico
5
6# Ekran: SPI0, 40 MHz / Display: SPI0, 40 MHz
7spi_tft = SPI(0, baudrate=40000000, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
8tft = Display(spi_tft, cs=Pin(17), dc=Pin(20), rst=Pin(21), width=240, height=320, rotation=0)
9
10# Dokunmatik: ayrı SPI1, 1 MHz / Touch: separate SPI1, 1 MHz
11spi_touch = SPI(1, baudrate=1000000, sck=Pin(10), mosi=Pin(11), miso=Pin(12))
12touch = Touch(spi_touch, cs=Pin(13), width=240, height=320)
13
14WHITE = color565(255, 255, 255)
15YELLOW = color565(255, 255, 0)
16
17tft.clear(color565(0, 0, 0)) # ekranı temizle / clear the screen
18tft.draw_text8x8(10, 10, "BlueGrays + Pico", WHITE)
19tft.fill_rectangle(10, 30, 100, 50, color565(255, 0, 0)) # dolu dikdörtgen / filled rectangle
20tft.draw_rectangle(130, 30, 100, 50, color565(0, 255, 0)) # çerçeve / outline
21tft.fill_circle(60, 130, 30, color565(0, 128, 255)) # dolu daire / filled circle
22tft.draw_line(0, 175, 239, 175, color565(255, 0, 255)) # çizgi / line
23tft.draw_text8x8(10, 185, "Ekrana dokun / Touch me", YELLOW)
24
25while True:
26 raw = touch.raw_touch() # dokunma yoksa None / None when not touched
27 if raw is not None:
28 x, y = touch.normalize(*raw) # ham değeri piksele çevir / raw value to pixels
29 y = 319 - y # eksen ters ise / if the axis is inverted
30 x = min(max(x, 3), 236) # ekran dışına taşma / keep inside the screen
31 y = min(max(y, 3), 316)
32 tft.fill_circle(x, y, 3, YELLOW)
33 sleep_ms(20)Im Hochformat (rotation=0) ist die Breite 240 und die Höhe 320; für das Querformat gibst du zusammen mit rotation=90 auch width=320 und height=240 an. Die Standardkalibrierung des Touch-Treibers (x_min=100, x_max=1962) passt nicht zu jedem Modul; liegt der Punkt daneben, gib die raw_touch()-Werte aus und übergib Touch() deine eigenen Werte für x_min, x_max, y_min und y_max. Für Bilder liest die Funktion draw_image() des Treibers .raw-Dateien, die in RGB565 umgewandelt sind; das Skript utils/img2rgb565.py aus dem Repository erledigt die Umwandlung auf deinem Computer.
Weißer Bildschirm: Ursachen und Lösung
Das bekannteste ILI9341-Problem ist ein komplett weißer Bildschirm bei eingeschalteter Hintergrundbeleuchtung. Ein weißer Bildschirm ist eigentlich ein Hinweis: Versorgung und Hintergrundbeleuchtung funktionieren, aber der Treiberchip wurde nie initialisiert. Bekommt das Panel keine Befehle, lassen die Pixel das Licht durch und der Bildschirm wirkt weiß. Das Problem liegt also fast immer in der Kommunikation. Geh die Tabelle von oben nach unten durch:
| Symptom | Mögliche Ursache | Lösung |
|---|---|---|
| Weißer Bildschirm, direkt am Uno angeschlossen | 5-V-Signale, kein Pegelwandler | 74HC4050 oder Spannungsteiler verwenden; bei beschädigtem Chip das Modul tauschen |
| Weißer Bildschirm, Kabel stecken | CS und DC vertauscht oder die Pinnummern im Code passen nicht zur Verdrahtung | TFT_CS, TFT_DC und TFT_RST einzeln mit der Tabelle vergleichen |
| Weißer Bildschirm, RESET offen | RESET nicht angeschlossen oder am falschen Pin | RESET an den Pin aus dem Code oder an 3,3 V legen; nie offen lassen |
| Weißer Bildschirm am ESP32 (TFT_eSPI) | User_Setup.h nicht angepasst oder durch ein Update gelöscht | ESP8266-Zeilen deaktivieren und ESP32-Pins sowie ILI9341_DRIVER neu eintragen |
| Gelegentlich weiß, verschobenes oder gestörtes Bild | Lange Jumperkabel, zu hohe SPI-Frequenz, wackelige Steckbrett-Kontakte | Kabel unter 10–15 cm halten; SPI auf 20–27 MHz senken, am Uno auf 4 MHz |
| Nur mit Touch oder SD weiß | Der CS-Pin des anderen Bausteins ist offen und blockiert den Bus | Jeden ungenutzten CS-Pin im Code als OUTPUT setzen und auf HIGH schalten |
| Läuft mit keinem Code | Das Display ist kein ILI9341 (ST7789, ILI9488) oder ein paralleles Shield | Aufdruck auf der Rückseite lesen; 3,5 Zoll mit 320×480 ist ein ILI9488, ein Shield braucht MCUFRIEND_kbv |
| Weißer Bildschirm, Hintergrundlicht flackert | Zu schwache Versorgung | VCC aus 5 V versorgen, anderes USB-Kabel und Netzteil probieren |
Weitere häufige Fehler
- Falsche Farben: Erscheint Rot als Blau, arbeitet das Panel in BGR-Reihenfolge; ändere in TFT_eSPI die Einstellung TFT_RGB_ORDER. Sehen die Farben wie ein Negativ aus, probiere tft.invertDisplay(true).
- Bild steht kopf oder ist gespiegelt: Ändere den Wert von setRotation() zwischen 0 und 3 und passe die Touch-Achsen entsprechend an.
- Display läuft, aber Touch oder SD nicht: Prüfe, ob T_CS und SD_CS mit den Pins im Code übereinstimmen. Bei manchen Modulen gibt der SDO-Ausgang des Displays den Bus nicht frei; trenne dann den SDO-Pin des Displays, nur das Diagnose-Auslesen funktioniert danach nicht mehr.
- Das BMP erscheint nicht: Die Karte ist nicht FAT32, der Dateiname hat mehr als 8 Zeichen oder das Bild ist kein 24-Bit-Bild. Wähle in Paint unbedingt 24 Bit; 16- und 32-Bit-BMPs zeichnet dieser Sketch nicht.
- Umlaute fehlen: Die Standardschrift von GFX enthält keine Zeichen wie ä, ö, ü oder ß. In TFT_eSPI kannst du eine eigene Smooth-Font erzeugen oder eine GFX-Schrift verwenden, die diese Zeichen enthält.
- Das Display ist langsam: Ein Vollbild-Refresh dauert am Uno mindestens 0,15 Sekunden. Für Animationen und Spiele wechsle zu ESP32 oder Pico und zeichne nur den Bereich neu, der sich ändert.
- Das Modul wird heiß: Vielleicht liegen 5 V an VCC bei geschlossener J1, oder VCC und GND sind vertauscht; trenne sofort die Versorgung.
Projektideen mit dem ILI9341
- Touch-Smart-Home-Panel: Steuere Licht und Relais über große Buttons auf dem Display; Ideen findest du unter Arduino-Smart-Home-Projekt.
- Farbige Wetteranzeige: Zeige das Wetter, das der ESP32 aus dem Internet holt, mit Symbolen und großen Ziffern (ESP32-Wetterstation).
- Sensor-Dashboard: Stelle Temperatur, Feuchte und Luftdruck eines BME280 als Zeigerinstrumente mit einem Verlauf der letzten 24 Stunden dar.
- Retro-Spielkonsole: Spiele Snake, Pong oder Tetris in Farbe; nimm zur Steuerung ein Joystick-Modul und hol dir Ideen bei Arduino-Spieleprojekte.
- Digitaler Bilderrahmen: Wechsle die BMP-Bilder auf der SD-Karte alle paar Sekunden.
- Mini-Oszilloskop: Zeichne analogRead-Werte auf dem ESP32 mit einem Sprite als flüssige Kurve.
- Touch-Codeschloss: Zeichne ein Ziffernfeld auf das Display und öffne bei richtigem Code ein Relais oder einen Servo.
Der ILI9341 ist der günstigste Weg, deinen Projekten eine farbige Touch-Oberfläche zu geben: Lerne die Grundlagen des Zeichnens mit dem Uno und wechsle zum ESP32 mit TFT_eSPI, sobald du Tempo und flüssige Animationen brauchst. Willst du lieber mit einem kleineren Display anfangen, ist OLED-Display (SSD1306) ein guter Einstieg. In der BlueGrays-App findest du die ESP32-Wetteranzeige, den Temperaturlogger, den Parksensor und Spieleprojekte mit Display, jeweils mit Schaltplänen und Code Schritt für Schritt.
Häufige Fragen
Funktioniert das ILI9341-Display mit 5 V?
Der VCC-Pin des Moduls verträgt 3,3–5 V, weil auf der Platine ein 3,3-V-Regler sitzt. Die Signalpins wie CS, DC, SCK und MOSI sind aber nur für 3,3 V ausgelegt. Am Arduino Uno gehört auf diese Leitungen ein Pegelwandler, etwa ein 74HC4050 oder Spannungsteiler.
Warum zeigt mein ILI9341 nur einen weißen Bildschirm?
Ein weißer Bildschirm bedeutet, dass die Hintergrundbeleuchtung leuchtet, der Treiberchip aber nie initialisiert wurde. Die häufigsten Ursachen sind falsch verdrahtete CS-, DC- oder RESET-Pins, ein fehlender Pegelwandler am Uno, eine nicht angepasste User_Setup.h bei TFT_eSPI und ein Display, das gar kein ILI9341 ist.
Welche Bibliothek brauche ich für den ILI9341?
Für Arduino Uno, Nano und Mega ist Adafruit_ILI9341 mit Adafruit GFX am einfachsten. Auf ESP32, ESP8266 und RP2040 nimmt man meist das deutlich schnellere TFT_eSPI. Parallele 2,4-Zoll-Shields zum Aufstecken auf den Uno brauchen dagegen MCUFRIEND_kbv.
Wie kalibriere ich den ILI9341-Touchscreen?
Der Touch-Controller XPT2046 liefert Rohwerte von 0 bis 4095. Notiere die kleinsten und größten Werte, die der serielle Monitor beim Tippen in die Ecken zeigt, und rechne sie mit map() in Bildschirmkoordinaten um. Mit TFT_eSPI erledigt das Beispiel Touch_calibrate diese Arbeit und gibt ein fertiges Kalibrier-Array aus.
Was ist der Unterschied zwischen ILI9341 mit 2,4 und 2,8 Zoll?
Beide haben 240×320 Pixel und nutzen dieselben Pins und denselben Code. Das 2,8-Zoll-Display hat etwas größere Pixel, deshalb ist Text leichter lesbar und Touch-Buttons lassen sich besser treffen. Das 2,4-Zoll-Modul passt in kleinere Gehäuse.
Kann ich den ILI9341 mit einem Arduino Nano verwenden?
Ja. Die SPI-Pins des Nano sind dieselben wie beim Uno: D13 SCK, D11 MOSI und D12 MISO. Auch der Nano arbeitet mit 5-V-Logik, du brauchst also einen Pegelwandler. Die 2 KB RAM reichen, um das Display anzusteuern, aber nicht für große Bilder; die liest du stückweise von der SD-Karte.
Projekte, die du danach bauen kannst
Alle Projekte ansehen
ESP32 HTTPClient + Wetter-API (mit SSD1306-OLED-Display)
In diesem Projekt führen wir mit dem ESP32 über das Internet mithilfe von HTTPClient.h einen REST-API-Aufruf an die Wetter-API (wttr.in) durch. Im Gegensatz zur vorherigen I2C-LCD-Version verwenden wir hier ein SSD1306-OLED-Display (128×64) – dies ermöglicht große Schriftarten, Vektor-Symbole und eine reichhaltige visuelle Darstellung auf einem einzigen Bildschirm. Für die Wetteranzeige werden 7 verschiedene Vektor-Symbole (sonnig, teilweise bewölkt, bewölkt, regnerisch, schneereich, stürmisch

ESP32 Temperatur-Datenlogger (DHT22 + DS1307 RTC + microSD + OLED)
Baue einen zeitgestempelten Temperaturlogger mit ESP32! Lese Temperatur/Feuchtigkeit vom DHT22 jede Minute, hole die aktuelle Zeit vom DS1307 RTC und protokolliere auf microSD-Karte als CSV. Das OLED zeigt live Temperatur (große Schrift), Luftfeuchtigkeit, Zeitstempel und Logzähler. Die /temp_log.csv-Datei auf der SD-Karte öffnet sich in Excel, Google Sheets oder Python pandas zur Analyse — perfekt für Gewächshausüberwachung, Raumtemperaturverfolgung, Laboraufzeichnung, Lebensmittellageru

ESP32-Farbmischerlampe (3 Potentiometer + RGB-LED + OLED)
Eine intelligente Farbmischer-Lampe mit ESP32, die durch Drehen von drei Potentiometern die gewünschte Farbe mischt! Wenn Sie die Potentiometer für Rot, Grün und Blau drehen, ändert die RGB-LED mit gemeinsamer Kathode sofort ihre Farbe. Auf dem SSD1306-OLED-Display werden für jede Farbe Werte im Bereich von 0 bis 255, visuelle Füllbalken und der HEX-Webfarbcode (z. B. #FF8040) in Echtzeit angezeigt. Ein professionelles Mini-Farbstudio – vermittelt in einem einzigen Projekt Kenntnisse über die RG

ESP32-Parksensor (HC-SR04 + 5-LED-Leiste + Summer + OLED)
Die ESP32-Version des Parkhilfesensors für Autos! Mit dem Ultraschallsensor HC-SR04 messen wir den Abstand zum Objekt vor dem Fahrzeug. Je weiter sich das Objekt nähert, desto mehr leuchten die 5 LEDs der Leiste auf (grün → gelb → rot) und die Intervalle der Summer-Signaltöne werden kürzer. Wenn das Objekt sehr nahe kommt (unter 10 cm), ertönt ein Daueralarm und alle LEDs leuchten. Auf dem SSD1306-OLED-Display werden der aktuelle Wert in cm in großer Schrift, ein Statustext (NICHT / VORSICHT / N

Paddle-Ball-Spiel - SSD1306
Ein Ball, zwei Schläger und du: Du spielst Tischtennis, eines der allerersten Videospiele, auf einem kleinen OLED-Display. Mit zwei Knöpfen bewegst du deinen Schläger rechts nach oben und unten, den l

OLED T-Rex Run: Arduino Dinosaurier Spiel
Das Dinosaurierspiel, das erscheint, wenn das Internet weg ist, jetzt auf deinem Schreibtisch: Der Dino rennt über das kleine OLED-Display, Kakteen kommen auf ihn zu, und du springst mit einem einzige

ESP32 I2C-LCD-Display (16×2)
In diesem Projekt zeigen wir Text an, indem wir ein 16x2-Zeichen-LCD-Display über das I2C-Protokoll an den ESP32 anschließen. Dank I2C können wir das Display mit nur zwei Datenpins (SDA und SCL) steuern; die Verschwendung von 6+ Pins bei einer klassischen parallelen Verbindung entfällt. Der Code schreibt in die erste Zeile eine feste Meldung und in die zweite Zeile einen Zähler, der sich jede Sekunde erhöht. Außerdem lassen wir zu Beginn den I2C-Scanner laufen und geben die Adresse des Displays

Arduino LCD-Runner-Spiel
Seitlich scrollendes Endlos-Laufspiel, das auf einem 16x2-Zeichen-LCD-Bildschirm läuft. Der Held läuft automatisch, der Spieler springt über Hindernisse, indem er die Taste drückt. Zufällige Hindernisse erscheinen in der oberen und unteren Reihe. Passiver Buzzer spielt Eröffnungsmelodie, Sprunggeräusch, 50-Punkte-Feierton und Spielende-Melodie. Beim Start wird der Splash-Screen "BlueGrays - Arduino Projects" angezeigt.
Weitere Artikel
BlueGrays-App
Diese Schaltung Schritt für Schritt auf dem Handy nachbauen
Schaltplan, Code und Teileliste auf einem Bildschirm. Über 200 Arduino-, ESP32- und Pico-Projekte zum Nachbauen.
Mit dem Handy scannen
Richte die Kamera auf den Code, dann öffnet sich der App-Store deines Handys.
oder im Store öffnen

