esp32 tft display library manufacturer
TFT_display_init() Perform display initialization sequence. Sets orientation to landscape; clears the screen. SPI interface must already be setup, tft_disp_type, _width, _height variables must be set.
compile_font_file Function which compiles font c source file to binary font file which can be used in TFT_setFont() function to select external font. Created file has the same name as source file and extension .fnt
This module is the 3.2” version of the ESP32 touchscreen display, based on ESP32-WROVER, with a built-in 2M pixel OV2640 camera. The LCD is 320x240 TFT, with driver is ILI9341, it uses SPI for communication with ESP32, the SPI main clock could be up to 60M~80M, make the display smooth enough for videos; and the camera OV2640 with pixel 2M, with this camera, you can make applications such as remote photography, face recognition…
While the camera not used, you can freely use all these pins with the breakout connectors, to connect the ESP32 display with sensors/ actuators, suitable for IoT applications.
The TFT display is a kind of LCD that is connected to each pixel using a transistor and it features low current consumption, high-quality, high-resolution and backlight. This 2.8-inch full color LCD has a narrow PCB display. The resolution is 320×280 pixels and it has a four-wire SPI interface and white backlight.
Makerfabs has launched a 3.5-inch TFT touchscreen display with built-in WiFi and Bluetooth connectivity through an ESP32-S3 dual-core Tensilica LX7 microcontroller clocked at 240 MHz with vector instructions for AI acceleration.
This display offers a 320×480 resolution through the ILI9488 LCD driver, uses a 16-bit parallel interface for communication with ESP32-S3 clocked at up to 20 Mhz making it suitable for smooth graphics user interface, and the company also claims it is smooth enough for video displays, but more on that later.
Espressif Systems ESP32-S3 dual-core Tensilica LX7 @ up to 240 MHz with vector instructions for AI acceleration, 512KB RAM, 2.4 GHz WiFi 4 and Bluetooth 5.0 LE with support for long-range, up to 2Mbps data rate, mesh networking
Display – 3.5-inch color TFT LCD with 480×320 resolution, 16-bit parallel interface (ILI94988 driver), and capacitive touch panel (FT6263); backlight controller
The display can be programmed with the Arduino IDE. Sample code using the LovyanGFX library and EAGLE schematics and PCB layout can be found on Github. Makerfabs also designed an ESP32-S2 model that lacks Bluetooth connectivity, and the ESP32-S3 touchscreen display comes with more RAM and eMMC flash.
I was tipped about this display by Jon, a regular reader and commenter on CNX Software, who bought it, and said it works as advertised. The ESP32-S3 can really drive a high-speed display with a parallel LCD interface. However, it can’t stream video because there is no H.264 decoder, but it is great if you want a responsive GUI.
Makerfabs ESP32-S3 16-bit parallel capacitive touchscreen display is sold for $39.80 plus shipping, and the ESP32-S2 model is the same price with a resistive display, and there’s a capacitive display option for $4 more. As a side note, we previously wrote about another, smaller ESP32-S3 display, namely the LilyGO T-Display-S3, with a 1.9-inch display connected over a slower 8-bit parallel interface, and no touchscreen function that sells for around $17.
//#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)
In our last article, we’ve focused on the wiring and underlying protocols of our custom ESP32 primary flight display. It’s time to start bringing this contraption to life with the use of code. We will focus on displaying our first graphics, layer shapes, and display game data and position elements relative to each other.
The ESP32, in its core, is vastly different from an Arduino (while similar at the same time). Most of the libraries that we’ve been using in the past will work perfectly fine interchangeably between an ESP32 and an Arduino. There are certain instances where a custom ESP32 library is needed to drive certain components or handle board-specific logic. The TFT screen is one of those components that requires a specific ESP32 oriented library. But why do we use a special library for the encoder then? Even though the default Arduino libraries might sometimes work on an ESP32, there are cases where a board-specific library optimizes and streamlines the process for us.
If we want to draw a black background, we need to set every pixel to black. We can address each pixel individually, so we don’t have to refresh the entire frame to display a new element. To make this process easier, the TFT_eSPI divides our pixels into a grid. An X-axis marks the horizontal axis (the columns), while a Y-axis marks the rows. Because we use the screen in a horizontal position the top left corner has the coordinates X0, Y0. The bottom-right coordinates will then be? You guessed it correctly X480, Y320. This grid system will be the foundation of our graphics. Went to draw something in the middle? Just divide the maximum height and width by 2 and you’ll get the middle coordinates.
Mine clearly states that it uses an ST7796S chip. Other common chips are the ILI9341 or the ILI19488. The wiring doesn’t differentiate between these screens it is just the low-level commands that differ. Luckily these differences get handled by the TFT_eSSPI library. We just need to make sure that we tell the library what type of chip we use.
In the code example below you’ll see that I uncommented the #define ST7796_DRIVER (once again yours might differ). This ensures the library uses the correct commands to match our screen.
//#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)
If we scroll down further we find a block that has specific pins for an ESP8266 (see the code block below). We will be using an ESP32 and not an ESP8266 (the precursor of the ESP32). Therefore we want to comment all these lines out.
The block underneath this header lets us define the pins where we’ve connected our TFT screen to our ESP32. In the previous article, we’ve taken a deep dive into the wiring if you want to read up on the subject. To make things easier I’ve enclosed the wiring diagram in the image below.
Our goal is to match the setup block with the pins that we’ve used on our board. Luckily we’ve already used the pins that either are mandatory (the dedicated SPI pins) or are recommended by the library. All we have to do is comment out the first six #defines.
Our screen makes use of the SPI interface. The SPI interface on our ESP32 needs to be manually enabled by including this header file or else both components can’t communicate.
To enable the screen we need to initialize the display. Because we only want to initialize the screen once we add this code to the setup block. The setup block only gets executed when our board boots (or when it gets reset). The loop block will contain all of our code that gets executed repeatedly.
We could already upload this code but our screen would still be white as snow. Our screen isn’t a high-end product. But in our case, it doesn’t have to be. The downside is that it has a smaller color range. Most non-budget screens can produce a 24-bit color range while ours can only display a 16-bit color range.
The TFT_eSPI library packs several default colors. I’d recommend taking a look at the TFT_eSPI.h file that is located in the TFT_eSPI library folder. Besides the colors, you are also able to find all the available functions that we can utilize. It’s good practice to do this each time you use a new library. Even though you might not understand everything that happens under the hood it gives you a good overview of all the functionalities. Just studying the code of libraries could also learn you a trick or two (it has learned me a ton).
Our screen is still white by default. We want to have a black background on our screen instead of white. We could paint each pixel black one at a time but that would be quite cumbersome. Luckily the library has a .fillScreen(color) function. The text “color” can be found between the (). This tells us that color is a parameter required for the fillScreen function. If we want to paint our screen black we could pass this function the color TFT_BLACK. TFT_BLACK is like an alias the library made for the color black. We could also pass the color hex value directly (0x0000). We might want to change our background color at a later point so it’s wise to create a variable that holds your background value (trust me you’ll thank me later).
To add our silver square to simulate a chrome-like trim around the comm data we’re going to draw a solid filled square. There are two options we can utilize in the TFT_eSPI library. The first is the drawRect function. While this may seem like the logical thing to do but it will only draw a one-pixel wide square. If we want a wider rectangle we could draw multiple rectangles inside of each other for every pixel we want.
To get the screen width from our library we use the getViewportHeight function. This might sound counterintuitive since we want to retrieve the width. The library we’re using has portrait mode as the default mode. Because we flip our screens horizontally the width becomes the height and vice versa.
Once again the library will come to our rescue with the fillTriangle function. To create a triangle we need to coordinate sets (X and Y coordinates). Each point can be moved by changing the coordinates. For this, we could also create a schematic.
When we upload this code to our board nothing will be displayed. The final step we haven’t added yet is calling the initializeRadio function from our setup block. It may seem trivial but after uploading this last adjustment our screen comes to life.
We’ve finally got all the graphical elements in place. Time to display some actual information that we can use. Our first step will be to include the Bits and Droids library and create an object. The data handling function will be the first code we add to our loop function. This function ensures that when we receive data from our connector and we store it in the appropriate place. To display text we need to add the font file as well.
When we display text there are a few things to keep in mind. First of all, how does our screen display text? It prints every letter at the desired location. In an ideal world going from 0 – 2, this would look like this in each frame.
It will just draw the character on top of the previous character resulting in a graphical mess. To avoid this we need to draw the character while we also redraw the space around the character with the same color as the background. The TFT_eSPI library has a function for this called drawString() and drawFloat(). It won’t just display the text it also takes care of the background.
If you want to practice this concept I’d suggest adding a header in the top left corner that displays the current screen. I went with a header that says “COM 1”.
tft.drawString((String)buttonTextArray[i], buttonArray[i].xStart + buttonArray[i].width / 2-6, buttonArray[i].yStart + buttonArray[i].height / 2 - 9);
The initialization of our radio elements is something we want to perform only once. There is no need to draw every element over and over again. To save our ESP32 from a gruesome job we add a function that we’ll call the radio mode. If the radio mode is active we will initialize the radio screen once and display the data if new data came in. This modular approach lets us easily swap screens at a later point. Now we add a radio mode, next time add a fuel gauge mode, and so on. By doing this we only have to implement the logic that swaps modes and we’re set.
tft.drawString((String)buttonTextArray[i], buttonArray[i].xStart + buttonArray[i].width / 2-6, buttonArray[i].yStart + buttonArray[i].height / 2 - 9);
The content is intended to be updated from time to time, I will add more details if I found new display or library update. You can also help me enrich the content by leaving comments below.
You can run various IoT projects prefectly without any display. But not all IoT project only feed data in single direction (IoT to server), some IoT also gather real time information from the server for displaying.
My previous instructables, ESP32 Photo Clock is am example, it download a current minute photo from the Internet, decode the JPEG photo and display it.
Many Arduino projects use monochrome display, one of the reason is the limited resources of a MCU. 320 pixels width, 240 pixels height and 8 bits color for each RGB color channel means 230 KB for each full screen picture. But normal Arduino (ATmega328) only have 32 KB flash and it is time consuming (over a second) to read data from SD card and draw it to the color display.
ESP32 have changed the game! It have much faster processing power (16 MHz vs 240 MHz dual core), much more RAM (2 KB vs over 200 KB) and much more flash (32 KB vs 4 MB), so it is capable to utilize more color and higher resolution image for displaying. At the same time it is capable to do some RAM hungry process such as Animated GIF, JPEG or PNG file decoding, it is a very important feature for displaying information gathered from the internet.
Color display have many type of interfaces: Serial Peripheral Interface (SPI), 6-bit, 8-bit, 16-bit, 18-bit and 24-bit parallel interfaces and also NeoPixel!
SPI dominate the hobby electronics market, most likely because of fewer wire required to connect. Most display in my drawer only have SPI pins breaking out, so this instructables focus on SPI display and a few 8-bit display.
NeoPixel matrix is a very special type of color display. If you are interested in NeoPixel matrix display, here are some of my instructables using it:
There are various color display for hobby electronics: LCD, IPS LCD, OLED with different resolutions and different driver chips. LCD can have higher image density but OLED have better viewable angle, IPS LCD can have both. OLED have more power efficient for each light up pixel but may have burn-in problems. Color OLED operate in 14 V, it means you need a dedicate step-up circuit, but it is not a problem if you simply use with a break-out board. LCD in most case can direct operate in 3.3 V, the same operating voltage as ESP32, so you can consider not use break out board to make a slimmer product.
Software support on the other side also influence your selection. You can develop ESP32 program with Arduino IDE or direct use ESP-IDF. But since ESP-IDF did not have too much display library and not much display hardware supported, so I will concentrate on Arduino display libraries only.
For the beginner, I think buying adafruit, or similar supportive vendor, hardware and using its Arduino library can have good seamless experience (though I have no budget to try it all). TFT_eSPI library have better performance but configuration require make changes in the library folder. Ucglib and UTFT-ESP run a little bit slow but it support many hardware and it is a popular library, you can find many Arduino projects using it. LovyanGFX library start appear at 2019, it support many dev device such as M5Stack, M5StickC, TTGO T-Watch, ODROID-GO, ESP-WROVER-KIT, WioTerminal and more. I am also writing a new library called Arduino_GFX since 2019.
OLED have a big advantage, the pixel only draw power if it lights up. On the other hand, LCD back light always draw full power even you are displaying a black screen. So OLED can help save some power for the project powered by a battery.
The initial code have some variation, the color order can be RGB or BGR and the y coordinate range also have a few pixels variation. Some library differential it by red, green or black tag but the tag color may not always help. The worst case is alter the tag option one by one until you can see a fine result. The above last picture is an example of using wrong tag option, you can find 3 pixels height noise bar on the top.
Thanks for the popularity of wearable gadget, I can find more small size IPS LCD in the market this year(2018). The above picture is an 0.96" 80x160 IPS color LCD using ST7735 driver chip. As you can see in the 3rd picture, you can treat it as a 128x160 color display in code but only the middle part is actually displaying. The 4th picture is the display without breakout board, it is thin, tiny and very fit for a wearable project!
SSD1283A is 1.6" 130x130 display, it claim only consume 0.1 in sleep mode and backlight turned off. In sleep mode the last drawn screen still readable under sufficient lighting.
ST7789 also a common driver chip in ESP32 community. One of the reason is ESP32 official development kit using it. As same as ILI9341, ST7789 also can drive 240x320 resolution.
This also the highest pixel density color display in my drawer. As same as normal LCD, it can direct operate in 3.3 V, so it is very good for making slim wearable device.
There are many display libraries that can support various hardware. I have picked 4 of most popular Arduino library for comparison:Adafruit GFX Family
The display speed is one of the most important thing we consider to select which library. I have chosen TFT_eSPI PDQ test for this comparison. I have made some effort to rewrite the PDQ test that can run in 4 libraries. All test will run with the same 2.8" ILI9341 LCD.
As I found TFT_eSPI is the most potential display library for ESP32 in this instructables, I have paid some effort to add support for all my display in hand. The newly added display support marked letter M in red at the above picture, here is my enhanced version:
Adafruit sell various display module in hobby electronics market and they also have very good support in software level. Their display libraries all built on a parent class called Adafruit_GFX, so I call it Adafruit GFX Family. This library generally support most Arduino hardware (also ESP32).
In Arduino Library Manager simply search "adafruit display", you can see all the family members. If you want to install it, say ILI9341, simply select "Adafruit ILI9341" and then click install. Remember also install its dependent library "Adafruit GFX Library".
This library method signature is very similar to Adafruit GFX, but it is tailor-made for ESP8266 or ESP32. I think the source code is optimised for ESP32, so the PDQ result is much faster than other libraries.
Note: The most difficult part using this library is you are required to configure this library before you can use it. The configuration file is located at the library folder, it should be "Arduino/libraries/TFT_eSPI/User_setup.h" under you own documents folder. It have many comments help you to do that, please follow the comments step by step to finish the configuration. Here is my User_setup.h for ILI9341:
ESP32 + ILI9341 can run at SPI speed 40 MHz, it require some code change at library folder. The above pictures are the fine tuned result. Here are the code change summary:
ST7735 and ILI9341 are the most popular display, this 2 are better option for the beginner. You may notice LCD have a big weakness, the viewable angle, some color lost outside the viewable angle and the screen become unreadable. If you have enough budget, OLED or IPS LCD have much better viewable angle.
In most case, we study how to use a code library by searching sample on the web. I have tried search four libraries keyword in Github, Adafruit is most popular and UTFT the second.
Only Adafruit GFX Family is fully configurable in user code level, other 3 libraries require some configuration in the library folder. And also Adafruit have very good portal, there are many detailed post teach you how to use their products.
ILI9341 should be most valuable display for the beginner. Adafruit GFX Library should be most easy to use for the beginner, and since TFT_eSPI have very similar method signature, it is very easy to switch to a faster library later on.
OLED require 14 V to light up the pixel so it is not easy to decouple the breakout board. On the other hand, LCD (also IPS LCD) usually operate in 3.3 V, as same as the ESP32. In most case, there are only the LED control circuit required between LCD and ESP32, i.e. a transistor and few resistors. So it relatively easy to make it.
If you read through the data sheet of the color display, you may find most of color display can support 18 bit color depth (6 bit for each RGB channel). 18 bit color depth can have a better image quality that 16 bit color depth (5 bit in red and blue channel, 6 bit for green channel). However, only Ucglib actually run at 18 bit color depth (262,144 colors), other 3 libraries all run at 16 bit color depth (65,536 colors). It is because 18 bit color depth actually require transfer 3 bytes (24 bit) of data for each pixel, it means 50% more data require to transfer and store in memory. It is one of the reason why Ucglib run slower, but it can have a better image quality.
Thank you very much for posting this detailed review of the color display option available for "Duino users. You have saved me hours, maybe days of time wandering the web looking for information.0
Great article! Very interested in round displays. There are available round displays based on st7687s (128 * 128) and st7789 (240 * 240), but I have not found any information on practical use.
Hello! Yes, I purchased this display from keyestudio, connected it to esp32 using this library from dfrobot. It is only necessary to consider that the pinout of the display connectors differs from dfrobot and keyestudio.
I"m wanting to connect a VGA camera, the sort you find as a little module on eBay with OVPxxxx chip, to a screen such as ILxxxx family, which appears to have direct VGA input. I think it will work if I connect the camera directly with no MCU, but I"d also like to add a cross-hair to the display (for a drill targetting system). I wonder is it possible to intercept the serial video data and change individual pixels in a streaming fashion, instead of loading a whole screen into memory, changing it and passing it on? I ask because it seems to me it would need a much less powerful MCU.0
Thank you so much for such a great article. I have been trying to choose the best library to use for a project that will use either a SSD1351 or a ST7735 both being 128x128. The key to my project is to be able to dump a frame buffer in to the display and then recalculate the next frame buffer. :)
Those 2 pins must be dedicated to the display, otherwise the display will get confused without the CS pin. One DAT/CLK to LCD and another DAT/CLK to I2C.
Hello! Thank"s for your instruction. I want to use your 8pin ili9486 320x480 spi display with one of your presented libraries and esp32. 1.) Could you please tell me the connections between the display and the esp32 and 2.) which numbers do I have to write into the line utft myglcd (ili9486,?,?,?,?)?
TFT_display_init() Perform display initialization sequence. Sets orientation to landscape; clears the screen. SPI interface must already be setup, tft_disp_type, _width, _height variables must be set.
compile_font_file Function which compiles font c source file to font file which can be used in TFT_setFont() function to select external font. Created file have the same name as source file and extension .fnt
"Upper layer" main development board contains ESP32-PICO-D4 SiP, battery connector & charger circuit with LiPo charge status LEDs, Reset & pull-up IO0 buttons, and a green LED on GPIO4.
Clone of the SparkFun ESP32 Thing board. Compact ESP32 based development board with battery connector, and the typical development board component accoutrements.
The ESP32-LyraTD-MSC Audio-Mic HDK (hardware development kit) combines the ESP32-LyraTD-MSC ("audio-mic development board") with a secondary "top" board.
The ESP32 touch sensor development kit, ESP32-Sense Kit, is used for evaluating and developing ESP32 touch sensor system. ESP32-Sense Kit consists of one motherboard and multiple daughterboards. The motherboard contains a display unit, a main control unit and a debug unit. The daughterboards have touch electrodes in different combinations or shapes, such as linear slider, wheel slider, matrix buttons and spring buttons, depending on the application scenarios. Users can design and add their own daughterboards for special usage cases.
ESP-WROOM-32 based development board with SH1106 OLED display (128×64 pixels), RJ-45 Ethernet connector, CAN-bus connector, Micro USB connector, USB-to-UART bridge, LiPo battery connector and charging circuit.
ESP32 development board with ePaper display, TI PCM5102A DAC, ICS43434 MEMS Microphone, CP2102N USB-to-UART bridge, microSD card slot, and LiPo charger.
My project is to build a data logger. I"m using an ESP32 and a 2,8" SPI TFT-LCD with an ILI9341 controller and integrated SD-card slot along with some other sensors. I us the Arduino IDE because of the libraries and documentation. As seen in the code below, before starting the SD card everything works fine. However, after the SD card gets started (or any other function that originated from an included library gets called) any commands for the TFT simply get ignored. What is the reason for this?