Skip to main content
ESPBoards

ESPHome Display Setup - Touchscreen, Brightness Control and More

Learn how to set up a fully functional ESPHome display with touchscreen capabilities, brightness control, and custom images. Perfect for interactive interfaces.


After successfully uploading the ESPHome program to the ESP32 and getting the 7-inch display working seamlessly, we are going to implement another exciting feature: the integrated touch interface!

In this guide, we’ll not only explore the touch capabilities but also implement brightness control to enhance the display’s usability and responsiveness. Also, we are going to explore how to use fonts on the display with ESPHome, the ESPHome font icons and how to show images on the display with ESPHome.

This post goes through the different step-by-step stages implementing the Touch Screen capabilities, adding fonts for showing text on the screen and using images. If you just want to see the working example, jump straight to Final Example.

Adding Touch Screen Capabilitie to ESPHome #

The GT911 is a capacitive touchscreen controller IC commonly used with TFT LCD displays to enable touchscreen functionality. It supports multitouch and high-precision touch input, making it suitable for modern touch interfaces.

We are using the previously discussed Elecrow 7" Display ES32 Board, which you can get on Aliexpress for around 50$. Which includes the GT911 Touch as well.
The prices are subject to change. Check current price:
Amazon com
Amazon de logo
Aliexpress logo

GT911 Key Features #

  • Touch Type: Capacitive touch, supporting up to 5 touch points.
  • Communication Interface: I²C (Inter-Integrated Circuit) and sometimes SPI.
  • Touch Resolution: High resolution, often up to 4096x4096.
  • Compatibility: Works with many TFT LCD panels.
  • Operating Voltage: Typically 3.3V.
  • Customization: Configurable parameters for touch sensitivity and gestures.

To use the GT911 capacitive Touch Screen with ESPHome, fill in the following configuration:

touchscreen:
platform: gt911
id: my_touchscreen
display: my_display
interrupt_pin: 38

This configuration enables the touchscreen functionality using the GT911 controller. It assigns an identifier using id: my_touchscreen, linking it to the display defined with display: my_display. The interrupt_pin parameter specifies GPIO38 as the pin for detecting touch input, ensuring the screen responds efficiently to interactions.

ESPHome Display Brightness Control with Touch Screen #

To control the display's brightness using the touchscreen, we’ll add an LVGL slider to the interface. This slider will be linked to the display backlight, defined earlier as id: back_light. When the slider value changes, the on_value action will trigger light.turn_on to adjust the brightness dynamically.

The brightness level is set using brightness: !lambda 'return x / 255;', where the slider's value is divided by 255 to provide a range between 0.0 and 1.0, as required by ESPHome. Additionally, we set min_value to 8 to ensure the screen doesn't go completely dark, maintaining some level of visibility even at the lowest brightness.

lvgl:
pages:
- id: room_page
widgets:
- slider:
id: dimmer_slider
x: 20
y: 50
width: 30
height: 220
pad_all: 8
min_value: 8
max_value: 255
value: 128 # Default slider value (50% brightness)
on_value:
- light.turn_on:
id: back_light
brightness: !lambda 'return x / 255;' # Convert 0-255 to 0.0-1.0

If you upload the code now, you will see a Slider. Try moving it with the finger and you should see the screen's brightness change. However, we are not yet uploading the code, as we will add some text to show the brightness value on scree and will see how to use icons and images with ESPHome display first.

Customizing the ESP32 Display: Fonts, Icons, and Images #

Enhancing your ESPHome display involves more than just getting it to work. Customization is key to creating a visually appealing and functional interface. Adding custom fonts, icons, and images will help us build a nice UI.

Adding Fonts #

ESPHome program by default doesn't have any fonts included. If we want to show text, we have to include the fonts manually first. Fonts can be imported by specifying a font file (such as TTF) and defining its properties in the ESPHome configuration.

  1. Download the Font

Download the ttf file of the font of your preference. For this example we will be using the Roboto Condensed.

  1. Add the Font to Config Folder

Go to your project's directory and inside config folder, create a new one called fonts. Put the ttf of the font you have downloaded earlier inside this folder.

  1. Fill in the ESPHome program
font:
- file: "fonts/RobotoCondensed-Regular.ttf"
id: roboto_icons_100
size: 100
bpp: 4

- file: "fonts/RobotoCondensed-Regular.ttf"
id: roboto_icons_36
size: 36
bpp: 4

We are using the same ttf font from config/fonts/ twice here, to define two font sizes - size: 100 and size: 36 and name name as:

  • roboto_icons_100
  • roboto_icons_36

Using Font Icons #

Go to Pictogrammers GitHub repository and download the TrueType font with all the icons in it. From a recent version folder, download the materialdesignicons-webfont.ttf file and place it in your ESPHome config directory under a folder named fonts, same as you did with a previous font.

You can choose the icons in Pictogrammers page.

To the previously defined font roboto_icons_100, we add an extras seection, where we define the icons font file file: "fonts/materialdesignicons-webfont.ttf" and specify the glyphs or icons we want to use:

font:
- file: "fonts/RobotoCondensed-Regular.ttf"
id: roboto_icons_100
size: 100
bpp: 4
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs: [
"\U000F02D1", # mdi-heart
"\U000F05D4", # mdi-airplane-landing
"\U000F035B", # mdi-memory
]

And to see how it looks like, lets add some text with icons to the lvgl section room page:

        - label:
text: "\U000F035B ESPBoards"
align: CENTER
text_align: CENTER
text_font: roboto_icons_100

- label:
id: brightness_label
x: 70
y: 50
text: "Brightness: 50%" # Default text
text_align: LEFT
text_font: roboto_icons_36

You can find more information on how to use the font icons on ESP32 dispaly in ESPHome Cookbook.

Displaying Slider Value on ESPHome Display #

Now that we have the text elements set up, there’s one issue left: the brightness text, which is supposed to display the screen brightness in percentages, doesn’t update dynamically when moving the slider. Let’s fix that.

In the lvgl configuration, under the on_value field where the display brightness is adjusted, we’ll add a new action. This action will update the text element to reflect the slider’s current value as a percentage. Using ESPHome’s lvgl capabilities, you can also customize this further, such as integrating images or icons that dynamically adjust based on the brightness level. For reference, you can explore esphome lvgl show image functionality.

              - lvgl.label.update:
id: brightness_label
text: !lambda |-
char buf[32];
sprintf(buf, "Brightness: %.0f%%", (x / 255) * 100);
return std::string(buf);

This will update the text on the display and show the backlight's brightness in percents.

Showing Images on ESPHome Display #

Adding images to your ESPHome display is a great way to enhance its visual appeal and make your interface more interactive. Whether you want to display logos, icons, or decorative elements.

  1. Create an Image Folder

Open your project’s config folder and create a new folder called img. This will be the dedicated folder for storing your image files.

  1. dd Your Image

Place the desired image file into the newly created img folder. For example, We added an image called logo.png.

  1. Define the Image in ESPHome Configuration

Reference the image file in your ESPHome configuration by defining it with the image component, like following:

image:
- file: img/logo.png
id: logo_image
resize: 100x100
  1. Show the image on display. Note we also added x and y parameters to move the items into position. Add this to the lvgl configuration under the brightness text:
        - label:
text: "ESPBoards \U000F02D1"
align: CENTER
text_align: CENTER
x: 0
y: 0
text_font: roboto_icons_100

- image:
align: CENTER
src: logo_image
id: img_id
x: -50
y: -100
radius: 20
clip_corner: true

By following these steps, you will be able to display custom images on your ESPHome-powered screen.

ESPHome Touchscreen Display Brightness Control Full Code Example #

Below is the complete ESPHome configuration that ties together all the elements we’ve discussed: setting up the display, enabling touch functionality, adding a brightness control slider, and integrating custom images and fonts.

esphome:
name: elecrow
friendly_name: elecrow
platformio_options:
build_flags: "-DBOARD_HAS_PSRAM"
board_build.esp-idf.memory_type: qio_opi
board_build.flash_mode: dio
#board_upload.maximum_ram_size: 524288

esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
platform_version: 6.8.1
version: 5.3.0
# Required to achieve sufficient PSRAM bandwidth
sdkconfig_options:
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: y
CONFIG_ESP32S3_DATA_CACHE_64KB: y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
CONFIG_SPIRAM_RODATA: y

psram:
mode: octal
speed: 80MHz

# Enable logging
logger:

# Enable Home Assistant API
api:
encryption:
key: "z2St0xlmvRBi5ZV//qTxekV0U7z4SkQYWD9eFGr84ms="

wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password

# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "70-Home Fallback Hotspot"
password: "RX8krOujSsOo"

captive_portal:


output:
- platform: ledc
pin: 2
frequency: 1220
id: gpio_backlight_pwm

light:
- platform: monochromatic
output: gpio_backlight_pwm
name: ${devicename} Display Backlight
id: back_light
restore_mode: ALWAYS_ON

touchscreen:
platform: gt911
id: my_touchscreen
display: my_display
interrupt_pin: 38

i2c:
sda: 19
scl: 20

display:
- platform: rpi_dpi_rgb
id: my_display
data_pins:
red:
- 14
- 21
- 47
- 48
- 45
green:
- 9
- 46
- 3
- 8
- 16
- 1
blue:
- 15
- 7
- 6
- 5
- 4
de_pin: 41
hsync_pin: 39
vsync_pin: 40
pclk_pin: 0

hsync_front_porch: 40
hsync_pulse_width: 48
hsync_back_porch: 13

vsync_front_porch: 1
vsync_pulse_width: 31
vsync_back_porch: 13

pclk_inverted: true
# pclk_frequency: 15000000

color_order: RGB

auto_clear_enabled: false
update_interval: 30s
dimensions:
width: 800
height: 480

font:
- file: "fonts/RobotoCondensed-Regular.ttf"
id: roboto_icons_100
size: 100
bpp: 4
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs: [
"\U000F02D1", # mdi-heart
"\U000F05D4", # mdi-airplane-landing
"\U000F035B", # mdi-memory
]

- file: "fonts/RobotoCondensed-Regular.ttf"
id: roboto_icons_36
size: 36
bpp: 4

image:
- file: img/logo.png
id: logo_image
resize: 100x100

lvgl:
pages:
- id: room_page
widgets:
- slider:
id: dimmer_slider
x: 20
y: 50
width: 30
height: 220
pad_all: 8
min_value: 8
max_value: 255
value: 128 # Default slider value (50% brightness)
on_value:
- light.turn_on:
id: back_light
brightness: !lambda 'return x / 255;' # Convert 0-255 to 0.0-1.0 for light dimming
- lvgl.label.update:
id: brightness_label
text: !lambda |-
char buf[32];
sprintf(buf, "Brightness: %.0f%%", (x / 255) * 100);
return std::string(buf);

- label:
id: brightness_label
x: 70
y: 50
text: "Brightness: 50%" # Default text
text_align: LEFT
text_font: roboto_icons_36

- label:
text: "ESPBoards \U000F02D1"
align: CENTER
text_align: CENTER
x: 0
y: 0
text_font: roboto_icons_100

- image:
align: CENTER
src: logo_image
id: img_id
x: -50
y: -100
radius: 20
clip_corner: true

If you're not sure how to upload the ESPHome configuration to ESP32, please check the Guide to Setting Up and Troubleshooting ESPHome

Conclusion #

With this setup, you now have a fully functional display powered by ESPHome, complete with touchscreen capabilities, brightness control, and custom images. The display is now interactive, providing a solid foundation for building sophisticated smart home interfaces.

But this is just the beginning! In the next step, we’ll explore how to fetch data from an API using ESPHome’s HTTP capabilities, opening up exciting possibilities for displaying real-time information like weather, news, or sensor data directly on your screen.