ESP32-2432S028 mit 2.8" Touchscreen (Cheap Yellow Display)
Programmierung des Displays mit der TFT_eSPI-Library
Bevor ihr mit diesem Artikel startet, solltet ihr euch zuerst ein wenig einlesen und die Hardware und das Pinout des TouchScreen-ESP32 kennenlernen.
Gerade die dort erwähnten verwendeten GPIO-Pins des ESP32-2432S028 werden wir heute brauchen.
Außerdem solltet ihr euch eine Entwicklungsumgebung mit PlatformIO einrichten, wie in diesem Artikel besprochen. Danach könnt ihr hier nahtlos weitermachen.
Das A und O des Cheap Yellow Display ist natürlich der Touchscreen, also dass man (fast) wie auf dem Smartphone Dinge anzeigen und auswählen kann. Die auf den CYDs vorinstallierte Demo-Software zeigt ja schon ein mächtiges Dialogsystem diesbezüglich. Dieses heißt LVGL (Light and Versatile Embedded Graphics Library) und unser großes Ziel ist es, dieses für eigene Dialoge zu benutzen.
Das Dilemma der vorhandenen Libraries und deren Versionen
Ich habe tagelang versucht die "fertigen" Libraries und Beispiele auf GitHub diesbezüglich von hexeguitar und rzeldent zu kompilieren, aber habe nur einen Compiler-Fehler nach dem anderen geerntet. Mal fehlte ein Header-File, mal war eine Funktion unbekannt. Schließlich habe ich aufgegeben.Das ist das Problem bei einem komplexen Projekt mit vielen Abhängigkeiten. Die Libraries anderer, die in diesen Libraries verwendet werden, werden natürlich auch weiterentwickelt und erfahren Veränderungen. Und die neueste Version, die standardmäßig hergenommen wird, ist dann oft nicht mehr zu dem ursprünglichen Code kompatibel. Folge: die Über-Library funktioniert mit den erneuerten Unter-Libraries nicht mehr. Darum ist es extrem wichtig, bei PlatformIO immer die Versionsnummer mit anzugeben, die man einbinden will; ansonsten wird die neueste hergenommen, und die funktioniert vielleicht schon ganz anders.
Der Entwickler der Über-Library hat sich seine Abhängigkeiten (also Unter-Libraries) irgendwann mal in einer bestimmten Version heruntergeladen und lokal auf der Platte installiert. Und arbeitet damit weiter. Und merkt es wahrscheinlich gar nicht, wenn eine Abhängigkeit so aktualisiert wird, dass die neue Library-Version nicht mehr zu seinem Code passt; mit seinem lokalen Code funktioniert ja alles einwandfrei. Dumm dann, wenn er sich nicht einmal notiert hat, welche Versionen der Abhängigkeiten er sich installiert hat und es nicht mehr weiß.
Und eins ist klar: je länger die Kette der Abhängigkeiten, desto anfälliger wird das ganze Kartenhaus, dass es in sich zusammenfällt. Dann kann man, so wie ich, tagelange kompilieren, raten und analysieren und kriegt die Beispiel-Library doch nicht zum Laufen.
Daraus klug geworden, werde ich immer die Version von Libraries notieren, auf die ich aufbaue und auch versuchen, meine Software als fertige Firmware zur Verfügung zu stellen, damit bei euch alles ohne Kompilierungs-Marathon läuft, falls ihr nur erst einmal testen wollt statt selbst eigene Software zu programmieren.
Aufsatz auf der TFT_eSPI-Library von Bodmer
Also werden wir es - wie es auch in der PDF-Datei, die in der Zip-Datei war, die bei mir auf der Verkaufsseite meines ESP32-2432S028 verlinkt war - von Anfang an versuchen und das heißt, wie bauen erst einmal auf die TFT_eSPI-Library von Bodmer auf und bringen die zum Laufen. Das ist fürs erste kompliziert genug. Haben wir die dann zum Laufen gebracht, gehen wir im nächsten Artikel den nächsten Schritt, nämlich die Installation der LVGL-Library von kisvegabor, embeddedt und pete-pjb, die auf TFT_eSPI aufsetzt und das Dialogsystem bereitstellt.Um die Library einzubinden, ist es am einfachsten, ein neues Projekt zu öffnen. Nennen wir es vielleicht "CYD-Displaytest" und wählen wir wie gewohnt das esp32dev-Board aus. Dann editieren wir die platformio.ini zu:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
upload_speed = 460800
upload_port = COM17
monitor_speed = 115200
monitor_port = COM17
lib_deps = bodmer/TFT_eSPI@^2.5.43
Mehr Informationen zu der Library gibt es unter https://registry.platformio.org/libraries/bodmer/TFT_eSPI und https://github.com/Bodmer/TFT_eSPI. Dort finden sich auch die Beispiele, von denen wir nachher ein paar ausprobieren wollen.
Wie wichtig die Angabe der Version ist, zweiter Teil
Und selbst die TFT_eSPI 2.5.43 (3 Monate alt) ist nicht 100% kompatibel zur neuesten ESP32-Platform-Version. Es hat sich schon eine Kleinigkeit geändert und der Compiler gibt folgende Fehlermeldung aus, wenn wir ein Beispielprogramm kompilieren wollen:.pio\libdeps\esp32dev\TFT_eSPI/Processors/TFT_eSPI_ESP32.h:15:25: fatal error: hal/gpio_ll.h: No such file or directory
Also editieren wir die entsprechende Datei, die sich (je nach Benutzername) etwa hier befinden sollte: D:\Users\admin\Documents\PlatformIO\Projects\ESP32-CYD-Display\.pio\libdeps\esp32dev\TFT_eSPI\Processors\TFT_eSPI_ESP32.h. Haben wir sie gefunden, können wir sie einfach in VS Code ziehen und dort editieren. Ab Zeile 11 sollte es dann so aussehen:
// Include processor specific header
#include "soc/spi_reg.h"
#include "driver/spi_master.h"
// wird nicht gefunden! #include "hal/gpio_ll.h"
Alternativ können wir auch auf die alte Version der espressif32-Plattform zurückgehen, indem wir hier Version 6.5.0 angeben, bei der HAL noch vorhanden war.
[env:esp32dev]
platform = espressif32@6.5.0
board = esp32dev
framework = arduino
upload_speed = 460800
upload_port = COM17
monitor_speed = 115200
monitor_port = COM17
lib_deps = bodmer/TFT_eSPI@^2.5.43
Die User_Setup.h
Die TFT_eSPI-Library kann man einer ganzen Reihe von Displays umgehen und darum muss ihr irgendwie mitgeteilt werden, welches Display-Modell wir vorliegen haben und wie die Library es ansprechen soll. Statt jedesmal alles mit #define-Statements an den Anfang der main.cpp zu schreiben, hat Bodmer hier den Weg der User_Setup.h gewählt, in denen alle Einstellungen getroffen werden.Die User_Setup.h ist unterhalb des Projekts in .pio\libdeps\esp32dev\TFT_eSPI\User_Setup.h bzw. im absoluten Pfasd D:\Users\admin\Documents\PlatformIO\Projects\ESP32-CYD-Display\.pio\libdeps\esp32dev\TFT_eSPI\User_Setup.h zu finden und am besten ziehen wir sie in den Editor, um einen Tab "User_Setup.h" oberhalb zu bekommen und komfortabel editieren zu können.
Für unser ESP32-2432S028R brauchen wie folgende Einstellungen:
#define USER_SETUP_INFO "User_Setup"
// Section 1. Call up the right driver file and any options for it
#define ILI9341_2_DRIVER // ESP2432S028R funktioniert mit v1, v2 und v3
//#define ST7789_DRIVER // ESP2432S028R alternativ nur für v3, nicht für v1, sonst bleibt Display weiß
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
#define TFT_HEIGHT 320 // ST7789 240 x 320
#define TFT_INVERSION_ON // nur für ESP2432S028R v3, sonst sind die Farben invers
// Section 2. Define the pins that are used to interface with the display here
// ESP32-2432S028R v1 - v3
#define TFT_MISO 12
#define TFT_MOSI 13
#define TFT_SCLK 14
#define TFT_CS 15
#define TFT_DC 2
#define TFT_RST -1
#define TFT_BL 21
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
// Section 3. Define the fonts that are to be used here
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
#define SMOOTH_FONT
// Section 4. Other options
#define SPI_FREQUENCY 27000000 // evtl. gehen auch 40000000
#define SPI_READ_FREQUENCY 20000000 // Optional reduced SPI frequency for reading TFT
#define SPI_TOUCH_FREQUENCY 2500000 // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here
Das heißt aber auch, dass wir zwei Firmwares für die CYDs haben müssen, eine für V1 und eine für V3, ansonsten stimmen die Farben nicht und sind invers.
Ich habe euch nochmal die komplette User_Setup.h hier hineingestellt und die für uns wichtigen Zeilen gelb markiert. Ansonsten ist es durchaus interessant, sich alle Zeilen und Kommentare einmal durchzulesen, um einen Eindruck der Fähigkeiten der TFT_eSPI-Library zu bekommen:
User_Setup.h (klicken, um diesen Abschnitt auf- und zuzuklappen)
// USER DEFINED SETTINGS
// Set driver type, fonts to be loaded, pins used and SPI control method etc.
//
// See the User_Setup_Select.h file if you wish to be able to define multiple
// setups and then easily select which setup file is used by the compiler.
//
// If this file is edited correctly then all the library example sketches should
// run without the need to make any more changes for a particular hardware setup!
// Note that some sketches are designed for a particular TFT pixel width/height
// User defined information reported by "Read_User_Setup" test & diagnostics example
#define USER_SETUP_INFO "User_Setup"
// Define to disable all #warnings in library (can be put in User_Setup_Select.h)
//#define DISABLE_ALL_LIBRARY_WARNINGS
// ##################################################################################
//
// Section 1. Call up the right driver file and any options for it
//
// ##################################################################################
// Define STM32 to invoke optimised processor support (only for STM32)
//#define STM32
// Defining the STM32 board allows the library to optimise the performance
// for UNO compatible "MCUfriend" style shields
//#define NUCLEO_64_TFT
//#define NUCLEO_144_TFT
// STM32 8-bit parallel only:
// If STN32 Port A or B pins 0-7 are used for 8-bit parallel data bus bits 0-7
// then this will improve rendering performance by a factor of ~8x
//#define STM_PORTA_DATA_BUS
//#define STM_PORTB_DATA_BUS
// Tell the library to use parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT
//#defined TFT_PARALLEL_16_BIT // **** 16-bit parallel ONLY for RP2040 processor ****
// Display type - only define if RPi display
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
// Only define one driver, the other ones must be commented out
//#define ILI9341_DRIVER // Generic driver for common displays
#define ILI9341_2_DRIVER // ESP32-2432S028R v1 - v3, Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
//#define ST7735_DRIVER // Define additional parameters below for this display
//#define ILI9163_DRIVER // Define additional parameters below for this display
//#define S6D02A1_DRIVER
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
//#define HX8357D_DRIVER
//#define ILI9481_DRIVER
//#define ILI9486_DRIVER
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
//#define ST7789_DRIVER // ESP32-2432S028R v3, Full configuration option, define additional parameters below for this display
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
//#define R61581_DRIVER
//#define RM68140_DRIVER
//#define ST7796_DRIVER
//#define SSD1351_DRIVER
//#define SSD1963_480_DRIVER
//#define SSD1963_800_DRIVER
//#define SSD1963_800ALT_DRIVER
//#define ILI9225_DRIVER
//#define GC9A01_DRIVER
// Some displays support SPI reads via the MISO pin, other displays have a single
// bi-directional SDA pin and the library will try to read this via the MOSI line.
// To use the SDA line for reading data from the TFT uncomment the following line:
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
// Try ONE option at a time to find the correct colour order for your display
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
// #define M5STACK
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
// #define TFT_WIDTH 80
// #define TFT_WIDTH 128
// #define TFT_WIDTH 172 // ST7789 172 x 320
// #define TFT_WIDTH 170 // ST7789 170 x 320
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
// #define TFT_HEIGHT 160
// #define TFT_HEIGHT 128
// #define TFT_HEIGHT 240 // ST7789 240 x 240
#define TFT_HEIGHT 320 // ST7789 240 x 320
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
// For ST7735 ONLY, define the type of display, originally this was based on the
// colour of the tab on the screen protector film but this is not always true, so try
// out the different options below if the screen does not display graphics correctly,
// e.g. colours wrong, mirror images, or stray pixels at the edges.
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
// this User_Setup file, then rebuild and upload the sketch to the board again:
// #define ST7735_INITB
// #define ST7735_GREENTAB
// #define ST7735_GREENTAB2
// #define ST7735_GREENTAB3
// #define ST7735_GREENTAB128 // For 128 x 128 display
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
// #define ST7735_ROBOTLCD // For some RobotLCD Arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
// #define ST7735_REDTAB
// #define ST7735_BLACKTAB
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
// If colours are inverted (white shows as black) then uncomment one of the next
// 2 lines try both options, one of the options should correct the inversion.
#define TFT_INVERSION_ON // ESP32-2432S028R v3
// #define TFT_INVERSION_OFF
// ##################################################################################
//
// Section 2. Define the pins that are used to interface with the display here
//
// ##################################################################################
// If a backlight control signal is available then define the TFT_BL pin in Section 2
// below. The backlight will be turned ON when tft.begin() is called, but the library
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
// #define TFT_BL 32 // LED back-light control pin
// #define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
// Typical setup for ESP8266 NodeMCU ESP-12 is :
//
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
// Display LED to NodeMCU pin VIN (or 5V, see below)
// Display SCK to NodeMCU pin D5
// Display SDI/MOSI to NodeMCU pin D7
// Display DC (RS/AO)to NodeMCU pin D3
// Display RESET to NodeMCU pin D4 (or RST, see below)
// Display CS to NodeMCU pin D8 (or GND, see below)
// Display GND to NodeMCU pin GND (0V)
// Display VCC to NodeMCU 5V or 3.3V
//
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
//
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
//
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
//
// The NodeMCU D0 pin can be used for RST
//
//
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
// If 5V is not available at a pin you can use 3.3V but backlight brightness
// will be lower.
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
/*
#define TFT_MISO PIN_D6 // Automatically assigned with ESP8266 if not defined
#define TFT_MOSI PIN_D7 // Automatically assigned with ESP8266 if not defined
#define TFT_SCLK PIN_D5 // Automatically assigned with ESP8266 if not defined
#define TFT_CS PIN_D8 // Chip select control pin D8
#define TFT_DC PIN_D3 // Data Command control pin
#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
*/
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
// ESP32-2432S028R v1 - v3
#define TFT_MISO 12
#define TFT_MOSI 13
#define TFT_SCLK 14
#define TFT_CS 15
#define TFT_DC 2
#define TFT_RST -1
#define TFT_BL 21
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
// but saves pins for other functions. It is best not to connect MISO as some displays
// do not tristate that line when chip select is high!
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
// cannot be connected as well to the same SPI signals.
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
// In ESP8266 overlap mode the following must be defined
//#define TFT_SPI_OVERLAP
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
//#define TFT_CS PIN_D3
//#define TFT_DC PIN_D5 // Data Command control pin
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins
//#define TFT_MISO 19
//#define TFT_MOSI 23
//#define TFT_SCLK 18
//#define TFT_CS 15 // Chip select control pin
//#define TFT_DC 2 // Data Command control pin
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
// For ESP32 Dev board (only tested with GC9A01 display)
// The hardware SPI can be mapped to any pins
//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
//#define TFT_SCLK 14
//#define TFT_CS 5 // Chip select control pin
//#define TFT_DC 27 // Data Command control pin
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
//#define TFT_BL 22 // LED back-light
//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
// For the M5Stack module use these #define lines
//#define TFT_MISO 19
//#define TFT_MOSI 23
//#define TFT_SCLK 18
//#define TFT_CS 14 // Chip select control pin
//#define TFT_DC 27 // Data Command control pin
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
//#define TFT_BL 32 // LED back-light (required for M5Stack)
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
// The library supports 8-bit parallel TFTs with the ESP32, the pin
// selection below is compatible with ESP32 boards in UNO format.
// Wemos D32 boards need to be modified, see diagram in Tools folder.
// Only ILI9481 and ILI9341 based displays have been tested!
// Parallel bus is only supported for the STM32 and ESP32
// Example below is for ESP32 Parallel interface with UNO displays
// Tell the library to use 8-bit parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT
// The ESP32 and TFT the pins used for testing are:
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
//#define TFT_RST 32 // Reset pin, toggles on startup
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
//#define TFT_RD 2 // Read strobe control pin
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
//#define TFT_D1 13 // so a single register write sets/clears all bits.
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
//#define TFT_D3 25 // TFT screen update performance.
//#define TFT_D4 17
//#define TFT_D5 16
//#define TFT_D6 27
//#define TFT_D7 14
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
// The TFT can be connected to SPI port 1 or 2
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
//#define TFT_MOSI PA7
//#define TFT_MISO PA6
//#define TFT_SCLK PA5
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
//#define TFT_MOSI PB15
//#define TFT_MISO PB14
//#define TFT_SCLK PB13
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
//#define TFT_CS D5 // Chip select control pin to TFT CS
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
// OR alternatively, we can use STM32 port reference names PXnn
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
// Use an Arduino pin for initial testing as connecting to processor reset
// may not work (pulse too short at power up?)
// ##################################################################################
//
// Section 3. Define the fonts that are to be used here
//
// ##################################################################################
// Comment out the #defines below with // to stop that font being loaded
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
// normally necessary. If all fonts are loaded the extra FLASH space required is
// about 17Kbytes. To save FLASH space only enable the fonts you need!
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
// this will save ~20kbytes of FLASH
#define SMOOTH_FONT
// ##################################################################################
//
// Section 4. Other options
//
// ##################################################################################
// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
// For RP2040 processor and 8 or 16-bit parallel displays:
// The parallel interface write cycle period is derived from a division of the CPU clock
// speed so scales with the processor clock. This means that the divider ratio may need
// to be increased when overclocking. It may also need to be adjusted dependant on the
// display controller type (ILI94341, HX8357C etc.). If RP2040_PIO_CLK_DIV is not defined
// the library will set default values which may not suit your display.
// The display controller data sheet will specify the minimum write cycle period. The
// controllers often work reliably for shorter periods, however if the period is too short
// the display may not initialise or graphics will become corrupted.
// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
// fast and the TFT driver will not keep up and display corruption appears.
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
// With an ILI9163 display 27 MHz works OK.
// #define SPI_FREQUENCY 1000000
// #define SPI_FREQUENCY 5000000
// #define SPI_FREQUENCY 10000000
// #define SPI_FREQUENCY 20000000
#define SPI_FREQUENCY 27000000
// #define SPI_FREQUENCY 40000000
// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
// #define SPI_FREQUENCY 80000000
// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY 20000000
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY 2500000
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
// then uncomment the following line:
//#define USE_HSPI_PORT
// Comment out the following #define if "SPI Transactions" do not need to be
// supported. When commented out the code size will be smaller and sketches will
// run slightly faster, so leave it commented out unless you need it!
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
// Transaction support is required if other SPI devices are connected.
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
// so changing it here has no effect
// #define SUPPORT_TRANSACTIONS
Beispiel-Programme
Die Beispiel-Programme bei der TFT_eSPI-Library sind für die normale Arduino IDE programmiert, sollten aber größtenteils ohne größere Anpassungen auch unter der Platform IO laufen. Aber bitte nicht vergessen, an den Anfang ein#include <Arduino.h>
zu setzen.Gehen wir ein paar Beispielprogramme durch, die ich kurz vorstellen und beschreiben möchte.
Außerdem biete ich jeweils die Möglichkeit an, die entsprechende Firmware auf das eigenen Cheap Yellow Display via ESP WebTools zu installieren. Damit kann man die Firmware schon einmal ausprobieren, ohne die Entwicklungsumgebung zu installieren oder zu programmieren. Schließe dazu einfach dein ESP32-2432S028 an einen USB-Port deines PC an und klicke auf den zu deinem Cheap Yellow Display passenden Installations-Button. Wählst du das falsche Board, erkennst du es daran, dass die Farben invertiert sind.
Analog Uhr
Die Analog Uhr benutzt Grafikroutinen wie fillCircle(), drawLine() und drawPixel() um eine Uhr zu zeichnen und drawCentreString(), um einen Text mittig zu setzen. Es zeigt auch die Verwendung von Farben auf.
Das Beispiel basiert auf einem Sketch von Gilchrist vom 6/2/2014 (1.0) und ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Clock / TFT_Clock.ino
Analoge Skala
Dies ist ein schönes Beispiel zum Zeichnen einer Skala wie auf einem analogen Messinstrument, samt Anzeigenadel. Das Beispiel benutzt Grafikroutinen wie fillRect(), drawRect(), fillTriangle() und drawLine() um eine Uhr zu zeichnen und setTextColor(), drawString(), drawRightString() und drawCentreString(), um Text zu schreiben. Es zeigt auch die Verwendung von Farben auf.
Das Beispiel basiert auf einem Sketch von Bodmer und ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Meter_linear / TFT_Meter_linear.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//Prototyping
void analogMeter();
void plotNeedle(int value, byte ms_delay);
Analoge Skalen
Dieses Beispiel erweitert das obenstehende um sechs weitere kleine Anzeigen, die einen Wert durch einen kleinen roten Pfeil auf einer vertikalen Skala anzeigen. Es kommen die selben Zeichen- und Textroutinen zum Einsatz und außerdem drawFastHLine().
Das Beispiel basiert auf einem Sketch von Bodmer und ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Meters / TFT_Meters.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//Prototyping
void analogMeter();
void plotNeedle(int value, byte ms_delay);
void plotLinear(char *label, int x, int y);
void plotPointer(void);
Digital Uhr
Die Digital Uhr benutzt Textroutinen wie setTextSize(), setTextColor(), drawChar() und drawNumber() um die Uhrzeit mittig auf den Screen zu schreiben. Es zeigt auch die Verwendung von Farben auf.
Das Beispiel basiert auf einem Sketch von Gilchrist vom 6/2/2014 (1.0) und ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Clock_Digital / TFT_Clock_Digital.ino
Alle Freien Fonts Demo
Die All Free Fonts Demo zeigt, wie man Fonts einbindet und mit ihnen Texte auf das Display schreibt. Die Demo zeigt ein Beispiel jedes Fonts eine kurze Zeit auf dem Bildschirm an.
Das Beispiel basiert auf einem Sketch von Bodmer vom 31/12/16 und ist zu finden unter TFT_eSPI / Examples / 320_x_240 / All_Free_Fonts_Demo / All_Free_Fonts_Demo.ino
Man kann auch die v1 auf einen CYD-V3 brennen bzw. die v3 auf einen CYD-V1, um den Text schwarz auf weiß zu sehen.
Game of Life
Die Simulation Game of Life bzw. Cellular Automata geht auf den Matematiker John Horton Conway zurück. Das Programm von 1970 simuliert eine zufällige Verteilung von Stämmen, die sich vermehren, wenn genügend Platz zum Ausbreiten ist bzw. die aussterben, weil die Bevölkerungsdichte zu hoch ist, um alle zu ernähren. Die Simulation läuft, bis eine gewisse Anzahl Durchläufe (durch NUMGEN definiert) erreicht ist und beginnt dann mit einem neuen Zufallssatz von Neuem.
Das Beispiel basiert auf einem Sketch von RuntimeProjects.com (MIT License 2016) und ist zu finden unter TFT_eSPI / Examples / 320_x_240 / Cellular_Automata / Cellular_Automata.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//prototyping
void drawGrid(void);
void initGrid(void);
void computeCA();
int getNumberOfNeighbors(int x, int y);
Außer fillRect() wird im Beispiel nicht viel von der TFT_eSPI-Library benutzt. Es ist aber einfach nett anzuschauen.Bunter Kreisel
Die Bunter Kreisel Demo ist nett anzusehen und benutzt Grafikroutinen wie setRotation(), fillScreen(), fillArc() und fillTriangle(). Es zeigt auch die Verwendung von Farben auf.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_ArcFill / TFT_ArcFill.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//prototyping
void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour);
unsigned int brightness(unsigned int colour, int brightness);
unsigned int rainbow(byte value);
Bunte Spirale
Die Bunte Spirale Demo ist fast hypnotisch anzusehen und benutzt Grafikroutinen wie setRotation(), fillScreen(), fillArc() und fillTriangle(). Es zeigt auch die Verwendung von Farben auf.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_FillArcSpiral / TFT_FillArcSpiral.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//prototyping
void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour);
unsigned int brightness(unsigned int colour, int brightness);
unsigned int rainbow(byte value);
Mandelbrot / Apfelmännchen
Die Mandelbrot Demo berechnet eine Mandelbrot-Menge (benannt nach Benoît Mandelbrot), auch Apfelmännchen genannt, aus der als Fraktale beeindruckende Grafiken entstehen, in die man immer weiter hineinzoomen kann bzw. die je nach Startwert immer etwas unterschiedlich sind. Zu lernen gibt es zu der Library nicht viel, weil nur drawPixel() in unterschiedlichen Farben benutzt wird. Aber Apfelmännchen sind einfach schön anzuschauen.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Mandlebrot / TFT_Mandlebrot.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//prototyping
unsigned int rainbow(int value);
Ich habe das Beispiel etwas angepasst, damit bei jedem Start, also nach einem Reset, zufällig ein etwas anderer Startvektor benutzt wird, der eine immer andere Grafik erzeugt.Matrix Scrolling
Wer kennt nicht den berühmten Bildschirmschoner aus dem Film Matrix, bei dem grüne Buchstabenreihen von oben nach unten fallen? Diese Demo ahmt diesen Effekt nach. Zu lernen gibt es zu der Library nicht viel, außer den Einsatz von setTextColor() und drawChar() und wie man mittels writecommand() und writedata() den Bildschirm scrollen lässt. Trotzdem: die Demo sieht einfach gut aus.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Matrix / TFT_Matrix.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//Prototyping
void setupScrollArea(uint16_t TFA, uint16_t BFA);
int scroll_slow(int lines, int wait);
void scrollAddress(uint16_t VSP);
Pong Demo
Pong war eines der ersten Videospiele überhaupt. Diese Demo bildet ein Pong-Spiel mit zwei Paddles und einem Ball nach. Bezüglich der Library werden die Funktionen startWrite(), setAddrWindow(), writecommand(), pushColor(), fillRect() und drawRect() eingesetzt. Die Demo ist nicht spielbar.
Das Beispiel basiert auf dem Code von Rparretts PongClock ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Pong / TFT_Pong.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//Prototyping
void initgame();
void midline();
void lpaddle();
void rpaddle();
void calc_target_y();
void ball();
Rainbow One Lib Text Demo
In dieser Demo werden auf einem Hintergrund in allen Regenbogenfarben zahlreiche Textbeispiele angezeigt. Bezüglich der Library werden die Funktionen setTextColor(), setTextSize(), setCursor(), setTextFont(), print(), println(), drawCentreString(), drawString() und drawFastHLine() im Beispiel-Code verwendet.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Rainbow_one_lib / TFT_Rainbow_one_lib.ino
Die Kompilierungsfehler wird man mit folgenden Zeilen am Code-Anfang los:
//Prototyping
void rainbow_fill();
Starfield Simulation
Die klassische Starfield Simulation, bei denen man ein Sternenfeld durchfliegt, mit 1024 Sternen gleichzeitig. In dieser Demo wird eigentlich nur von der Funktion drawPixel() im Beispiel-Code gemacht. Aber es ist immer wieder schön und entspannend, eine solche Demo zu sehen.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Starfield / TFT_Starfield.ino
Serielles Terminalprogramm
Dies ist ein kleines Terminalprogramm, das die auf dem seriellen Port eingehenden Zeichen bei einer Verbinugsgeschwindigkeit von 9600 baud anzeigt. In dieser Demo wird eigentlich nur von der Funktion drawPixel() im Beispiel-Code gemacht. Aber es ist immer wieder schön und entspannend, eine solche Demo zu sehen.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_Terminal / TFT_Terminal.ino
Die Compiler-Fehler bekommt man mit folgenden Zeile am Anfang des Codes weg:
//Prototyping
int scroll_line();
void setupScrollArea(uint16_t tfa, uint16_t bfa);
void scrollAddress(uint16_t vsp);
Grafischer Benchmark
Dies ist ein kleines Benchmarkprogramm, das alle möglichen Grafikroutinen austestet und die Zeit misst, die das System zum Zeichnen braucht. Danach zeigt es die Ergebnisse in einer Tabelle an.
Da es so gut wie jede Grafikroutine einmal anspricht, ist es eine wahre Fundgrube für die Anwendung der Grafikroutinen. Der Code basiert auf Adafruit und Xarks PDQ graphicstest sketch.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / TFT_graphicstest_PDQ / TFT_graphicstest_PDQ.ino
Die Compiler-Fehler bekommt man mit folgenden Zeile am Anfang des Codes weg:
//Prototyping
void printnice(int32_t v);
static inline uint32_t micros_start();
uint32_t testHaD();
uint32_t testFillScreen();
uint32_t testText();
uint32_t testPixels();
uint32_t testLines(uint16_t color);
uint32_t testFastLines(uint16_t color1, uint16_t color2);
uint32_t testRects(uint16_t color);
uint32_t testFilledRects(uint16_t color1, uint16_t color2);
uint32_t testFilledCircles(uint8_t radius, uint16_t color);
uint32_t testCircles(uint8_t radius, uint16_t color);
uint32_t testTriangles();
uint32_t testFilledTriangles();
uint32_t testRoundRects();
uint32_t testFilledRoundRects();
Grafischer Benchmark 2
Dies ist ein kleines Benchmarkprogramm, das alle möglichen Grafikroutinen austestet und die Zeit misst, die das System zum Zeichnen braucht. Danach zeigt es an, wielange es zur Erfüllung der Aufgaben benötigte.
Da es sehr viele Grafikroutinen anspricht, ist es eine wahre Fundgrube für Beispiele der Anwendung der Grafikroutinen. Der Code basiert auf Henning Karlsens Sketch.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / 320_x_240 / UTFT_demo / UTFT_demo.ino
Demo: Im Flash gespeichertes JPEG anzeigen
Dies ist ein kleines Beispielprogramm, das einen als PROGMEM im Flash gespeichertes JPEG eines Pandabären dekodiert und dann anzeigt. Es benutzt zur JPEG-Dekodierung die TJpg_Decoder-Library vom selben Autor, nämlich Bodmer, die folgendermaßen in der platformio.ini eingebunden werden muss:
lib_deps =
bodmer/TFT_eSPI@^2.5.43
https://github.com/Bodmer/TJpg_Decoder
Ich meine, dass die Farben auf dem v3-Display (ST ST7789) wesentlich flauer und mit weniger Kontrast rüberkommen als auf dem v1-Display (ILI9341)
Das Beispiel ist zu finden unter TFT_eSPI / Examples / DMA test / Flash_Jpg_DMA / Flash_Jpg_DMA.inoRotating Cube
In diesem Beispiel wird ein sich drehenden und an den Seiten des Bildschirms abprallender Würfel gezeigt. Dazu werden Sprites und DMA benutzt, um über 100 FPS auf dem CYD zu erreichen.
Das Beispiel basiert auf "RotatingCube" von Daniel Eichhorn und ist zu finden unter TFT_eSPI / Examples / DMA_test SpriteRotatingCube / SpriteRotatingCube.ino
Amiga Bouncing Ball
Welcher ehemalige (oder noch) Commodore-Fan erinnert sich nicht an die legendäre Bouncing-Ball-Demo für den Commodore Amiga, die auf der CES 1984 für Aufsehen gesorgt hat? Heute hat die kleine ESP32-CPU mehr Power als die Motorola 68000 von vor 40 Jahren, und das zu einem tausendstel des Preises. Unser Cheap Yellow Display schafft 85 fps in dieser Demo. Für Leute, die die legendäre Demo nicht kennen: ein gecheckerter Ball hüpft in einer 3D-Welt und prallt am Boden und den Seiten ab.
Das Beispiel ist zu finden unter TFT_eSPI / Examples / DMA_test boing_ball / boing_ball.ino
Der "graphic.h" verpassen wir noch folgende Zeilen am Anfang, damit alles gut kompiliert werden kann:
#include <Arduino.h>
#define SCREENHEIGHT 240
#define SCREENWIDTH 320
Touch-Screen-Funktionen mit TFT_eSPI
In der User_Setup.h kann man für einen Touch-Screen nur den Client-Select (CS) Pin angeben. Es wird fest das SPI-Interface (MISO/MOSI/Clock) benutzt, was auch für den TFT benutzt wird. Es ist im Grunde auch sinnvoll und sparsam, das SPI-Interface für mehrere Dinge zu benutzen und über CS umzuschalten, nur hat das Cheap Yellow Display nunmal zwei unterschiedlich SPI-Interfaces für TFT und Touch-Screen. Und die kann man nirgends in der User_Setup.h angeben und die Möglichkeit ist im Code auch gar nicht vorgesehen.Die TouchScreen-Beispiele funktionieren deshalb leider nicht. Aber wir wollten für dafür ja sowieso die LVGL-Library benutzen.
Weitere Beispiele
Unter https://registry.platformio.org/libraries/bodmer/TFT_eSPI/examples gibt es noch zahlreiche weitere Beispiele, die ich nicht alle durchgetestet habe, die aber sicher einen Blick lohnen, wenn man etwas wie das folgendes tun möchte:- Anzeige von PNG-Grafiken aus dem Flash-Speicher (ähnlich wie für JPG oben)
- Dialogelemente für grafische Benutzeroberflächen (GUI_Widgets)
- eigene und geglättete Schriften
- Sprites
Demo-Video
Ich hoffe, ihr hattet Spaß beim Installieren und Ausprobieren der Beispiele und habt einen Eindruck über die Fähigkeiten der Library bekommen.Vielleicht hilft das folgende Vorführvideo dabei, die Firmwares auszuwählen, die ihr mal testen wollt:
Oder testet sie alle. Mit dem Web-Installer ist das ja schnell erledigt.
Fazit und Aussichten
Es sollte klar geworden sein, was das Display mit der Library alles kann und wie schnell es ist.Im nächsten Teil wollen wir dann versuchen, auch den XPT2046-Digitizer, den Touch-Teil des Displays, zu programmieren.