There are no significant new features in the initial move to 9.4 to simplify the switchover. Things like other colour depths will be added after that.
Thank you!
Thanks for the work - and confirming - I really was barking up the wrong tree on this one.
I think I am done with the final iteration of my library. You can now truly build a button on an ESP32 screen that controls a light in Home Assistant with one line of code.
This is what it looks like
packages:
button_1: !include
file: esphome-modular-lvgl-buttons/buttons/switch_button.yaml
vars:
uid: button_1
row: 0
column: 0
text: Light
icon: $mdi_lightbulb
entity_id: "switch.athom_smart_plug_v3_50ebc0_switch"
All you need after that is a simple LVGL grid to put the button on that looks like this.
lvgl:
pages:
- id: main_page
layout: 4x4
styles: page_style
<<: !include esphome-modular-lvgl-buttons/widgets/swipe_navigation.yaml
widgets:
The beauty of all this is the simplicity and flexibility. A novice can create their first screen and control a light in 20 seconds and an advanced programmer can mix a few simple prebuilt buttons on a screen with complicated ones that they design from scratch.
I guess i have to update my configuration
![]()
This code doesnāt work - looks like the code was double pasted.
I couldnāt get the screen to display basic text even after fixing the typos, after several hours of debugging, I have a working version in ESPHome 2026.1.5. The key was adding reset_pin 33 to the display block.
I was able to get the Modular buttons Git repository working with some effort.
esphome:
name: waveshare-esp32-p4-touch-lcd-7b
friendly_name: "Waveshare P4 7B"
esp32:
variant: esp32p4
flash_size: 32MB
cpu_frequency: 360MHz
framework:
type: esp-idf
advanced:
enable_idf_experimental_features: true
sdkconfig_options:
CONFIG_SPIRAM_SPEED_200M: y
CONFIG_ESP_TASK_WDT_TIMEOUT_S: "60"
external_components:
- source: github://pr#11886
components: [mipi_dsi]
refresh: 1h
esp32_hosted:
variant: ESP32C6
reset_pin: GPIO54
cmd_pin: GPIO19
clk_pin: GPIO18
d0_pin: GPIO14
d1_pin: GPIO15
d2_pin: GPIO16
d3_pin: GPIO17
active_high: true
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
ota:
- platform: esphome
logger:
hardware_uart: USB_SERIAL_JTAG
web_server:
port: 80
version: 3
psram:
mode: hex
speed: 200MHz
preferences:
flash_write_interval: 5min
esp_ldo:
- voltage: 2.5V
channel: 3
i2c:
- id: bus_a
sda: GPIO07
scl: GPIO08
frequency: 400kHz
touchscreen:
- platform: gt911
id: my_touchscreen
i2c_id: bus_a
reset_pin: GPIO23
update_interval: 50ms
transform:
swap_xy: false
mirror_x: false
mirror_y: false
# Enabled Touch Logger here
on_touch:
- logger.log:
format: "Touch at (%d, %d)"
args: [touch.x, touch.y]
- lambda: |-
ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%d",
touch.x,
touch.y,
touch.x_raw,
touch.y_raw
);
output:
- platform: ledc
id: gpio_backlight_pwm
pin: GPIO32
inverted: true
frequency: 1000Hz
light:
- platform: monochromatic
output: gpio_backlight_pwm
name: "Display Backlight"
id: display_backlight
restore_mode: ALWAYS_ON
default_transition_length: 250ms
display:
- platform: mipi_dsi
id: my_display
model: WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-7B
reset_pin:
number: 33
rotation: 180
update_interval: never
auto_clear_enabled: false
dimensions:
width: 1024
height: 600
lvgl:
buffer_size: 100%
byte_order: little_endian
pages:
- id: main_page
bg_color: 0x000000
widgets:
- label:
text: "Hello World!"
text_color: 0xFFFFFF
align: CENTER
text_font: montserrat_40
Are you using this test code here?
It works and give you a few test buttons. I tested this code recently with 2026.1.5 and it works well.
That demo file also has the Home Assistant Voice Assistant enabled and working.
The code in post #4 in this thread doesnāt work:
The modular buttons code works ok; my Git pull missed a couple of files for some reason - took a while to troubleshoot.
I want to make some improvements to the modular buttons package - Iāll post on Git; number one is modular cover control for the blinds in my house.
I just updated esphome-modular-lvgl-buttons recently. So refresh you git pull to get the latest.
I am making Voice Assistant modular as well so you can include it or not with one line of code.
That would be amazing! Send me a pull request and Iāll add it to esphome-modular-lvgl-buttons
Will do!
Messing around with the voice assistant now. The file fails to validate when including the voice assistant - āmy_microphone not definedā. esp32_microphone is defined in the hardware file, but I canāt find my_microphone defined anywhere.
It validates fine with this, but not far along enough to determine if it works:
Thanks, I just updated that. I fixed it for all six esp32-p4 screens that I supportā¦
guition-esp32-p4-jc1060p470.yaml
guition-esp32-p4-jc4880p443.yaml
guition-esp32-p4-jc8012p4a1.yaml
waveshare-esp32-p4-86-panel.yaml
waveshare-esp32-p4-wifi6-touch-lcd-10.1.yaml
waveshare-esp32-p4-wifi6-touch-lcd-7b.yaml
2026.2.0 adds full support for this screen. I just updates my demo code for it to use the released driver for the screen.
Has anyone had success configuring portrait mode for this device? In portrait mode, it fits perfectly inside the cut-out for the Nutone intercom system Iām removing; but has to be raised above the wall in landscape mode.
After rotating the config 90 degrees, it still thinks the x is 1024 and the y is 600. The touch is stretched / displaced, and the screen display is also stretched / displaced.
hardware file:
---
substitutions:
# --- Defaults ---
orientation: landscape
flipped: "false"
# --- Dimension Logic ---
width_landscape: "1024"
height_landscape: "600"
width_portrait: "600"
height_portrait: "1024"
screen_width: "${width_${orientation}}"
screen_height: "${height_${orientation}}"
# --- Rotation & Touch Logic ---
rotation_landscape_false: "180"
rotation_landscape_true: "0"
rotation_portrait_false: "270"
rotation_portrait_true: "90"
# Touch Swap: Only true for portrait modes
s_landscape_false: "false" #ok
s_landscape_true: "false" #ok
s_portrait_false: "true"
s_portrait_true: "true"
# --- TOUCH MAPPING OVERRIDES ---
# Change if touch is "backwards" or "inverted"
# Landscape TUNING:
mx_landscape_false: "false"
my_landscape_false: "false"
mx_landscape_true: "true"
my_landscape_true: "true"
# PORTRAIT TUNING:
mx_portrait_false: "false"
my_portrait_false: "true"
mx_portrait_true: "true"
my_portrait_true: "false"
# Apply the keys
screen_rotation: "${rotation_${orientation}_${flipped}}"
touch_swap: "${s_${orientation}_${flipped}}"
touch_mirror_x: "${mx_${orientation}_${flipped}}"
touch_mirror_y: "${my_${orientation}_${flipped}}"
esphome:
min_version: 2026.2.0
project:
name: "Waveshare.ESP32-P4-WIFI6-Touch-LCD-7B"
version: "1.0"
esp32:
variant: esp32p4
flash_size: 32MB
cpu_frequency: 360MHz
framework:
type: esp-idf
advanced:
enable_idf_experimental_features: true
esp32_hosted:
variant: ESP32C6
reset_pin: GPIO54
cmd_pin: GPIO19
clk_pin: GPIO18
d0_pin: GPIO14
d1_pin: GPIO15
d2_pin: GPIO16
d3_pin: GPIO17
active_high: true
psram:
mode: hex
speed: 200MHz
preferences:
flash_write_interval: 5min
esp_ldo:
- voltage: 2.5V
channel: 3
# -------------------------------------------
# Touchscreen gt911 i2c
# -------------------------------------------
i2c:
- id: bus_a
sda: GPIO07
scl: GPIO08
frequency: 400kHz
scan: true
touchscreen:
- platform: gt911
id: my_touchscreen
i2c_id: bus_a
reset_pin: GPIO23
update_interval: 32ms
display: main_display
transform:
swap_xy: ${touch_swap}
mirror_x: ${touch_mirror_x}
mirror_y: ${touch_mirror_y}
on_touch:
- logger.log:
format: "Touch at (%d, %d)"
args: [touch.x, touch.y]
- lambda: |-
ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%d",
touch.x,
touch.y,
touch.x_raw,
touch.y_raw
);
# -------------------------------------------
# Backlight
# -------------------------------------------
output:
- platform: ledc
id: gpio_backlight_pwm
pin: GPIO32
inverted: true
frequency: 1000Hz
light:
- platform: monochromatic
output: gpio_backlight_pwm
name: Display Backlight
icon: mdi:lightbulb-on
id: display_backlight
restore_mode: ALWAYS_ON
default_transition_length: 250ms
# -------------------------------------------
# Display
# -------------------------------------------
display:
- platform: mipi_dsi
id: main_display
model: WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-7B
reset_pin:
number: 33
rotation: ${screen_rotation}
update_interval: never
auto_clear_enabled: false
dimensions:
width: ${screen_width}
height: ${screen_height}
# Special LVGL settings required for this display
lvgl:
byte_order: little_endian
# -------------------------------------------
# Audio devices
# -------------------------------------------
# ===== Amplifier Control =====
switch:
- platform: gpio
pin: GPIO53 # BSP_POWER_AMP_IO
name: "Audio Amplifier"
id: audio_amplifier
restore_mode: ALWAYS_OFF
# ===== ES8311 Audio Codec Configuration =====
i2s_audio:
- id: audio_bus
i2s_mclk_pin: GPIO13
i2s_lrclk_pin: GPIO10
i2s_bclk_pin: GPIO12
audio_dac:
- platform: es8311
id: es8311_dac
i2c_id: bus_a
address: 0x18
audio_adc:
- platform: es7210
id: es7210_adc
i2c_id: bus_a
address: 0x40
# ===== Microphone =====
microphone:
- platform: i2s_audio
id: esp32_microphone
i2s_audio_id: audio_bus
i2s_din_pin: GPIO11
sample_rate: 16000
bits_per_sample: 16bit
adc_type: external
# on_data:
# - logger.log:
# format: "Microphone data received: %d bytes"
# args: [x.size()]
# ===== Speaker & Audio Pipeline =====
speaker:
- platform: i2s_audio
id: esp32_speaker
i2s_audio_id: audio_bus
i2s_dout_pin: GPIO9
audio_dac: es8311_dac
dac_type: external
channel: mono
buffer_duration: 100ms
bits_per_sample: 16bit
sample_rate: 48000
- platform: mixer
id: mixing_speaker
output_speaker: esp32_speaker
source_speakers:
- id: announcement_mixing_input
timeout: never
- id: media_mixing_input
timeout: never
- platform: resampler
id: announcement_resampling_speaker
output_speaker: announcement_mixing_input
sample_rate: 48000
bits_per_sample: 16
- platform: resampler
id: media_resampling_speaker
output_speaker: media_mixing_input
sample_rate: 48000
bits_per_sample: 16
Test code:
# Substitution variables used through the codebase
substitutions:
orientation: portrait
#flipped: "true"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: yes
min_auth_mode: wpa2
ap:
ssid: chicken-coop
password: !secret wifi_fallback_password
captive_portal:
web_server:
port: 80
version: 3
api:
encryption:
key: !secret api_key_display-den # Get this from the ESPHome dashboard
ota: # Merge with the OTA file. This will cause a validation warning - safe to ignore
- platform: esphome
password: !secret ota_password_display-den
esphome:
name: "display-den"
friendly_name: "Den Display"
comment: "Waveshare ESP32-P4 WiFi6 Touch LCD 7B 1024px X 600px Smart Screen"
logger:
level: debug
logs:
lvgl: info
hardware_uart: UART0
# Some screens need little_endian byte order and some need big_endian
# this sets the byte order for all the images loaded in this file and the packages as well
image:
defaults:
byte_order: little_endian
packages:
# Harware description file
hardware: !include esphome-modular-lvgl-buttons/hardware/waveshare-esp32-p4-wifi6-touch-lcd-7b.yaml
# This is the main LVGL section. We start with a simple grid.
lvgl:
buffer_size: 100%
width: 600
height: 1024
displays:
- main_display
pages:
- id: main_page
widgets:
- button:
id: simple_test_button
width: 200
height: 100
x: 500
y: 300
widgets:
- label:
text: "HELLO"
align: center
The most success after a couple of days trying is this calibration block in the hardware file, it makes the touchscreen x work, but not the y or the display:
touchscreen:
- platform: gt911
id: my_touchscreen
i2c_id: bus_a
reset_pin: GPIO23
update_interval: 32ms
display: main_display
# Fix for stretching bug?
calibration:
x_min: 0
x_max: 1024
y_min: 0
y_max: 600
I have it working this is my code
touchscreen:
- platform: gt911
id: my_touchscreen
i2c_id: bus_a
reset_pin: GPIO23
update_interval: 50ms
transform:
swap_xy: true
mirror_x: true
mirror_y: false
display:
- platform: mipi_dsi
id: main_display
model: WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-7B
rotation: 90
reset_pin:
number: 33
update_interval: never
auto_clear_enabled: false
But the performance is terrible! mipi_sdi displays do not have hardware rotation so this is implemented in software. Screen is very laggy and unresponsive in this mode.
Unfortunately the best way to do screen rotation would be to use the 2D hardware graphics capabilities of the P4 but there is no ESPHome drive for this yet.
Thatās really funny. That is exactly what I am using the screen for as well! Iām going to see if I can power it using the old wires from the intercom. They go to the basement so I can attach 12v to them.
Thatās really funny. That is exactly what I am using the screen for as well! Iām going to see if I can power it using the old wires from the intercom. They go to the basement so I can attach 12v to them.
Itās very simple / easy to do - here are some pics. Happy to share the 3D printed parts.
The main Nutone panel has 120v power and a transformer. I connected a 120v to 12v DC power supply, then 12v to 5v USB at the remote station. Iāll do a standalone post once all running.
Iām planning a 10" display on the main station, and 7" display on the remote stations. Using landscape mode isnāt terrible - gives space to mount a speaker and sensors. Iām planning a mmWave sensor and temperature / humidity sensor to start.
Looks great! If you put the screen the way you have it now you have room for a speaker.
What case is that?
Self designed / printed; still a work in progress. Iām planning to use the standard speaker included in the waveshare box.
Nice, I am working on a lot of projects like this. Check out my button library if you have not already. I have a lot of prebuilt widgets for a screen like this. I will have a media player soon.
That board and other P4 based boards should include all sorts of cool stuff in the future including video playback.
A hardware mod you might consider is a brightness sensor. I have a part of my library that trys to get the screen brightness so itās not annoying but I really need to have it respond to room light level.
lux sensors are cheap. Thanks.
I looked through the button library - really appreciate your work. Iām starting with the mechanicals and basic room controls to start.
I would like to do an audio intercom eventually also. I donāt use cameras inside my house, but audio only would be nice.




