ESP32-2432S028 mit 2.8" Touchscreen (Cheap Yellow Display)
Utilities Test Display und Touch

Bevor ihr mit diesem Artikel startet, solltet ihr euch zum Einstieg in die Materie zuerst ein wenig einlesen und die Hardware und das Pinout des TouchScreen-ESP32 ESP32-2432S028R-kennenlernen.

Außerdem solltet ihr euch eine Entwicklungsumgebung mit PlatformIO einrichten, wie in diesem Artikel besprochen. Danach solltet ihr noch den Artikel Programmierung des Displays mit der TFT_eSPI-Library lesen, in dem ihr lernt, wie wir etwas auf dem Display ausgeben.

Sowie den Artikel über die Programmierung des Touchscreen Digitizer XPT2046, der im Cheap Yellow Display steckt.

Damit wäre dann die Hardware-Ansteuerung von Display und Touchscreen bewerkstelligt. Nun kommt als Dialogsystem die LGVL Library obendrauf. In diesem Artikel erfahrt ihr, wie man diese für die weitere Verwendung einbindet und mit der Standard-LVGL-Demo (die, mit dem das Gerät ausgeliefert wurde) testet.

Im darauffolgenden Artikel haben wir dann gelernt, wie man LVGL-Dialoge entwirft und mittels Events steuert. Damit haben wir genügend gelernt, um unsere eigenen Anwendungen mit LVGL-Dialogen zu programmieren.

Doc Cool's Utilities V2


Im letzten Artikel habe ich die erste Version von Doc Cool's Utilities vorgestellt. Dies soll eine Sammlung von nützlichen Programmen sein, die über ein Menü aufgerufen werden sollen.

Da ich bemerkt habe, das es auch einige englischsprachige Leser gibt, versuche ich, die Dialog im Programm in (einfachem) Englisch zu halten, damit mehr Leute etwas davon haben, denn die fertige Firmware wird es wieder zum Download geben.

Außerdem spare ich mir, den kompletten Source-Code immer wieder zu wiederholen. Der steht ja schon in den vorhergehenden Artikeln. Ich werde also nur noch auf die neu hinzugekommenen Sachen eingehen. Das macht die ganzen Erklärungen kürzer und übersichtlicher.

Aus technischen Gründen, nämlich damit die WLAN-Antenne und evtl. weitere Antenne nicht von der Hand verdeckt werden und weil es der natürlicher Handhaltung am meisten entspricht, habe ich mich für ein Design der Dialoge im Portrait-Modus, also hochkant, entschieden.

Nochmal kurz zur ersten Version


In der ersten Version habe ich das Utility "RGB-LED-Changer" vorgestellt. Wie genau der funktioniert und programmiert wird, das könnt ihr im entsprechenden Artikel nachlesen.

Trotzdem zeige ich euch den Dialog noch einmal rechts. Fällt euch etwas auf?

Ja genau, es ist kein Foto vom CYD-Bildschirm mehr, sondern ein Screenshot. Die TFT_eSPI-Library bietet nämlich die äußerst praktische Funktion, die Farben der Pixel auf dem Bildschirm, genauso wie er in diesem Moment dargestellt wird, auszulesen. Das geht entweder für jeden Pixel einzeln mit tft.readPixel(x,y); wobei man da einen 16-Bit-Wert (einen uint16_t) zurückbekommt mit der RGB565-Farbe.

Nur ganz kurz dazu, was eine RGB565-Farbe ist: hier werden in den linken 5 Bit der Rotwert, in den nächsten 6 Bit der Grün-Wert und in den rechten 5 Bit der Blauwert gespeichert. Die Bittiefe ist also nicht jeweils 8 Bit, sondern 5, 6 und 5 Bit, daher auch der Name. Diesen 2-Byte-RGB565-Wert (mit 16 bit) kann man aber leicht in einem 3-Byte-RGB888-Wert (mit 24 Bit) umrechnen: statt der 256 (2 8) Abstufungen für RGB888 hat man dann halt nur 32 (2 5) bzw. 64 (2 6). Ein RGB5 Wert mit 31 (bzw. ein RGB6-Wert mit 63) entspricht also einem RGB8-Wert mit 255. Entsprechend hat ein RGB5 Wert mit 15 (bzw. ein RGB6-Wert mit 31) nur die halben Intensitivität und entspricht einem RGB8-Wert von 127.

Aber diese Umrechnerei mache ich gar nicht auf dem ESP32, sondern mit einem kleinen, selbstgeschriebenen Windows-Programm auf dem PC, der mir das umgerechnete Bild auch gleich als verlustfreies .bmp-Bild speichert. Von da aus kann ich es dann zu einem .png oder .jpg oder .webp-Bild machen.

Und außerdem benutze ich tft.readRect(0, y, tft.width(), 1, (uint16_t *) buf); aus der TFT_eSPI-Library, der mir immer gleich einen Zeile von 240 Pixeln, also 480 Bytes liefert. Das ist mein Kompromiss in Sachen Speichernutzung und Abspeicher-Geschwindigkeit. Jedes Byte einzeln auf die SD zu schreiben dauert entschieden länger als gleich 480 Bytes.

Das ESP32 SPI-Dilemma

Der espressiv ESP32 hat genau zwei nutzbare Hardware-SPI-Busse: HSPI und VSPI. Und einen dritten, der aber zur Anbindung des internen Flash vergeben ist:

MOSIMISOCLKCS
VSPIGPIO 23GPIO 19GPIO 18GPIO 5
HSPIGPIO 13GPIO 12GPIO 14GPIO 15

Aus der Pinout-Dokumentation wissen wir: Bisher hatte ich an HSPI den TFT und über VSPI den XPT2046. Einen weiteren Hardware-SPI-Bus, auf dem ich die SD-Karte (eigentlich ja VSPI) benutzen könnte, gibt es nicht.

Das Schreiben auf SD bereiteteenorme Probleme, wenn VSPI und HSPI schon durch die TFT_eSPI und die XPT2046_Touchscreen (von PaulStoffregen) belegt sind. Das äußert sich durch Fehlermeldungen wie
sdCommand(): Card Failed! cmd: 0x0d ff_sd_status(): Check status failed
die auftreten jedesmal, wenn TFT und SD gleichzeitig etwas schreiben wollen, was bei mir so ca. alle 63 Byte der Fall war. An in flüssiges, fehlerfreies Schreiben auf SD KArte war nicht zu denken.

Es gibt zwar eine Client-Select (CS) Leitung, mit der beide Libs anzeigen, wenn sie den Bus benutzen, aber das in allen 3 SPI-Bus-Nutzer-Routinen ständig abzufragen wäre eine sehr komplizierte Angelegenheit.

Als Lösung sah ich nur, denjenige Hardware-Teil, der am wenigsten auf Performance angewiesen ist, per Software-SPI statt Hardware-SPI anzusprechen. Soft SPI ist natürlich langsamer, aber für den Touch-Controller sollte es ausreichen. SD und TFT brauchen die Hardware-Performance. Außerdem passen die Pins auch zu HSPI und VSPI (auch wenn man die Pinbelegung umbiegen kann).

Ich war schon fast drauf und dran, die Soft SPI-Library red-scorp/SoftSPIB zu benutzen, um selbst etwas für die XPT2046-Abfrage zu schreiben, aber dann stieß ich auf die XPT2046_Bitbang_Slim Library on Nitek, die genau das wohl schon erledigt.

Die funktioniert soweit auch ganz gut, auch wenn ich damit hin und wieder mal, eher selten, eine Warnung von LVGL bekam, die XPT2046-Koordinaten lägen außerdem des gültigen Bereichs. Eine zusätzliche Sicherheitsabfrage hat das Problem dann aber beseitigt und das XPT2046 läuft jetzt gut auf Software SPI.

Unsere platformio.ini musste natürlich entsprechend angepasst werden:
lib_deps = bodmer/TFT_eSPI@2.5.43 ;red-scorp/SoftSPIB @ 1.1.2 ;https://github.com/PaulStoffregen/XPT2046_Touchscreen nitek/XPT2046_Bitbang_Slim@2.0.0 ; https://github.com/TheNitek/XPT2046_Bitbang_Arduino_Library lvgl/lvgl@9.1.0 ;https://github.com/Bodmer/TJpg_Decoder
Die neue XPT2046-Lib liefert auch die Raw-Werte zwischen 0 und 4095, die ich benutze und so können die Einträge bei
build_flags = ... -D XPT2046_XMIN=290 -D XPT2046_XMAX=3670 -D XPT2046_YMIN=230 -D XPT2046_YMAX=3860
so bleiben, wie sie sind.

Und jetzt, wo die SD-Karte ihr eigenes Hardware-VSPI für sich allein hat, funktioniert das Screenshot-Schreiben auch fehlerfrei und performant.

Neues Utility: Display-Screen


Nachdem die Basis nochmals verbessert wurde, kann es jetzt an das Schreiben von neuen Utilities gehen.

Ich habe mir gedacht, dass ein Screen-Test ganz nützlich sein könnte, um tote oder immer leuchtende Pixel schnell ausfindig zu machen.

Dazu geht man alle Grundfarben durch, was rot, grün und blau wären. Würde man das TFT unter einem Mikroskop betrachten, würde man erkennen, dass jeder Bildschirmpixel aus drei Subpixeln besteht, die jeweils rot, grün oder blau leuchten und aus denen die Anzeigefarbe gemischt wird.

Schaltet man jetzt zum Beispiel alles auf reines rot, dann sollten nur die roten Subpixel leuchten. Tut es ein einzelner roter Sub-Pixel nicht, leuchtet also nicht mehr, fällt das schnell auf.

Und um zu erkennen, ob etwa ein roter Sub-Pixel immer leuchtet - auch das gibt es häufig - gibt es am Schluss den schwarzen Screen. Der reinweiße Screen entlarvt Sub-Pixel die nicht mehr leuchten: an dieser Stelle leuchtet dann ein Pixel mit der Restfarbe der noch funktionierenden Pixel.

Der Pixel-Test wird einfach per Knopfdruck gestartet und danach schaut man sich jeweils den Screen an und sucht nach defekten Pixeln. Per Tippen auf das Display geht es zur nächsten Farben, bis man wieder im Hauptscreen landet.

Hier gibt es auch einen Slider, um die Helligkeit der Hintergrundbeleuchtung einzustellen. Mit dem Zurück-Button unten rechts geht es dann zurück. Die Helligkeit bleibt dabei erhalten. Man kann dies also auch dazu benutzen, diese einzustellen und dann damit woanders weiterzumachen, wenn einem 100% zu hell sind.

Angesteuert wird die Helligkeits-LED über PWM über Pin GPIO 21, den wir über "-D TFT_BL=21" ja schon in der platformio.ini definiert haben. Das PWM wird wie bei den RGB-LEDs bewerkstelligt:
void tftBrightness_init() { ledcSetup(ledChnH, ledFrq, ledRes); ledcAttachPin(TFT_BL, ledChnH); setTftBrightness(255); }

Neues Utility: Touchscreen-Test und Kalibrierung


Das Funktionsprinzip kennen wir ja schon aus dem Artikel Programmierung des Touchscreen Digitizer XPT2046, wobei wir dort noch die XPT2046-Library von Stoffregen und zur Anzeige die TFT_eSPI-Library selbst benutzt haben.

Die Werte werden jetzt allerdings als LVGL-Label angezeigt. Sonst ändert sich nicht viel, außer das statt eines einzelnen Pixels jetzt auch ein kleiner Kreis darum gezeichnet wird, um die Klick-Position besser erkennnen zu können.

Wie gehabt fährt man mit dem Stift die Maximalpositionen an, das heißt die Ränder und Ecken und das Tool findet so die Minimal- und Maximalwerte heraus. Klickt man dann auf Save, werden die Werte auf SD-Karte gespeichert und ab sofort zur Berechnung der richtigen Position herangezogen. Besser noch: sie werden beim nächsten Einschalten automatisch geladen und wiederverwendet.

Jedes CYD sollte über ihre eigene SD-Karte verfügen und so seine eigenen Einstellungen haben. So passt die Position nach dem Kalibrieren immer, auch wenn die Touch-Folie bei einem CYD ein wenig versetzt aufgeklebt sein sollte.

Auf einen Zurück-Button habe ich hier verzichtet, damit mehr Platz zum Ausprobieren der Touch-Position übrig bleibt. Also einfach die Reset-Taste drücke. Dann kann man auch gleich das Laden der Einstellungen überprüfen. Sollte man etwas total schief gegangen sein, hilft a) ohne SD starten, dann einstecken und Kalibrierung neu speichern oder b) die Einstellungsdatei /settings/xpt2046.ini auf der SD löschen.

Firmware Download via ESP Web Tools


Du möchtest die Firmware schon einmal ausprobieren, ohne die Entwicklungsumgebung zu installieren oder zu programmieren?

Kein Problem. Schließe einfach dein ESP32 an einen USB-Port deines PC an und klicke auf den deinem Gerät entsprechenden Button:

Die Firmware-Installation funktioniert leider nur mit Google Chrome und Chromium-basierten Browsern wie Microsoft Edge, Opera, Vivaldi oder Brave; jedoch nicht mit Firefox. Bitte benutze eine HTTPS-Verbindung, HTTP funktioniert nicht.

Die Firmware-Installation funktioniert leider nur mit Google Chrome und Chromium-basierten Browsern wie Microsoft Edge, Opera, Vivaldi oder Brave; jedoch nicht mit Firefox. Bitte benutze eine HTTPS-Verbindung, HTTP funktioniert nicht.

Demo und Video

Ich habe wieder ein kleine Demonstrations-Video gemacht, dass die neuen Dialoge in Aktion zeigt:


Mein Fazit zu dieser Programmier-Episode

Viel Zeit habe ich damit verbracht, herauszufinden, woran der Fehler lag, warum die SD-Karte beim Schreiben immer mit Fehler abbrach, genauer auf die SPI-Architektur des ESP32 zu schauen und den Hardware-SPI durch einen Software-SPI für das XPT2046-Interface auszutauschen. Aber ich habe auch wieder viel dazu gelernt, was mein Verständnis von ESP32 vertieft hat. Das Wissen wird mir sicher noch einmal nützlich sein.

Und ehrlich gesagt, habe ich mehr Zeit als gewollt damit verbracht, abzuschätzen, an welche Position ein Dialogelement muss, um nach dem Hochladen zu merken, dass mir das nicht gut genug aussieht und ich es verschoben habe. Wenn das neu kompilieren und hochladen nicht immer so lange dauern würde... Aber ich werde besser in der Abschätzung der Bilschirmkoordinaten und evtl. erstelle ich mir noch ein Template mit Koordinatenlinien, dass ich ausdrucken und in das ich Dialoge zeichnen kann. Aber ob das den Aufwand lohnt?

Das jetzt TFT, Touch und SD gut nebeneinander funktionieren, ist viel wert für die Tools, die da noch kommen werden.

Weitere Aussichten

Im nächsten Teil unserer ESP32-2432S028R-Artikelserien geht es dann um einen WLAN-Scanner, einen Settings-Dialog und eine Rastereinblendung, die das Dialogdesign einfacher macht. Wer noch nicht genug hat, kann da gleich weiter lesen und lernen.

Quellen, Literaturverweise und weiterführende Links