Ein Touch-Panel an der Wand, das Licht schaltet, die Temperatur zeigt und dein Home Assistant steuert – für 15–22 €. Klingt nach Bastel-Wochenende? Ist es nicht: Das Cheap Yellow Display (CYD) ist ein fertiges Board mit ESP32, 2,8-Zoll-Touchscreen und USB-Anschluss. Kein Löten, kein Verkabeln. Du flashst einmal ESPHome drauf, kopierst meine Konfiguration, trägst deine Entitäten ein – fertig.
In diesem Guide bauen wir Schritt für Schritt ein Wand-Dashboard mit Uhr, Temperatur, zwei Lichtschaltern und „Alles aus“, das sich nachts automatisch dimmt. Die Konfiguration ist auf dem aktuellen ESPHome getestet (2026.6) – inklusive der Stolperfallen, die seit ESPHome 2026.4 viele Anleitungen im Netz kaputt gemacht haben.
Was du brauchst
- ESP32-2432S028R „Cheap Yellow Display“ – 2,8″, 320×240, resistiver Touch. Bei Amazon ca. 20–22 € (schnell da), bei AliExpress ab ca. 12 € (2–3 Wochen). Achte beim Kauf auf genau diese Bezeichnung.
- USB-Netzteil 5 V / 1 A + Micro-USB-Kabel (bei der neuen Revision auch USB-C). Ein altes Handy-Netzteil reicht.
- Home Assistant mit dem ESPHome Device Builder (Add-on) – oder ESPHome auf einem anderen Rechner.
- Einen Rechner mit Chrome oder Edge zum ersten Flashen per USB.
- Optional: ein 3D-gedrucktes Gehäuse (Tisch, Wand oder Unterputz – dazu unten mehr).
Das ESP32-2432S028R – ESP32, 2,8″-Touchscreen, Lichtsensor, RGB-LED und microSD auf einer Platine. Genau das Board, für das die Konfiguration unten geschrieben ist. Achte auf die Modellnummer; die 3,5″-Variante hat andere Pins.
Dasselbe Board direkt aus China – meist deutlich günstiger, dafür 2–3 Wochen Lieferzeit. Achte darauf, die Variante mit Touch („Touch“/„Resistive“) und die 2,8″-Größe zu wählen; Netzteil und Kabel sind meist nicht dabei.
Schritt 1: ESPHome vorbereiten
- In Home Assistant: Einstellungen → Add-ons → Add-on Store → „ESPHome Device Builder“ installieren und starten (Haken bei „In der Seitenleiste anzeigen“).
- ESPHome öffnen → „+ New Device“ → Name
wanddisplay→ Gerätetyp ESP32 → Anlegen. Ein Basisgerät wird erstellt. - Falls noch nicht vorhanden: In ESPHome oben rechts über das Menü „Secrets“ öffnen und deine WLAN-Daten eintragen:
wifi_ssid: "DeinWLAN"
wifi_password: "DeinPasswort"Schritt 2: Die Konfiguration
Öffne das neue Gerät in ESPHome mit „Edit“, lösche den gesamten Inhalt und füge diese Konfiguration ein. Anpassen musst du nur den Block substitutions ganz oben – deine Entitäten und Beschriftungen. Alles andere kann bleiben.
substitutions:
name: wanddisplay
friendly_name: Wand-Dashboard
# ---- Hier deine Entitäten eintragen ----
licht_1: light.wohnzimmer
licht_1_name: "Wohnzimmer"
licht_2: light.kueche
licht_2_name: "Küche"
temp_sensor: sensor.wohnzimmer_temperatur
alles_aus: script.alles_aus
esphome:
name: ${name}
friendly_name: ${friendly_name}
esp32:
board: esp32dev
framework:
type: arduino
logger:
api:
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "${friendly_name} Setup"
captive_portal:
time:
- platform: homeassistant
id: ha_time
on_time_sync:
- script.execute: update_time
# ---- Zwei SPI-Busse: Display und Touch ----
spi:
- id: lcd
clk_pin: GPIO14
mosi_pin: GPIO13
- id: touch_bus
clk_pin: GPIO25
mosi_pin: GPIO32
miso_pin: GPIO39
# ---- Hintergrundbeleuchtung + RGB-LED ----
output:
- platform: ledc
pin: GPIO21
id: backlight_pwm
- platform: ledc
pin: GPIO4
id: led_red
inverted: true
- platform: ledc
pin: GPIO16
id: led_green
inverted: true
- platform: ledc
pin: GPIO17
id: led_blue
inverted: true
light:
- platform: monochromatic
output: backlight_pwm
id: backlight
name: "Display-Helligkeit"
restore_mode: ALWAYS_ON
- platform: rgb
name: "Status-LED"
id: status_led
red: led_red
green: led_green
blue: led_blue
restore_mode: ALWAYS_OFF
# ---- Sensoren ----
sensor:
# Lichtsensor auf der Platine: dimmt das Display nachts
- platform: adc
pin: GPIO34
id: ldr
name: "Umgebungslicht"
attenuation: 12db
update_interval: 10s
filters:
- sliding_window_moving_average:
window_size: 3
send_every: 1
on_value:
then:
- light.turn_on:
id: backlight
brightness: !lambda |-
// Schwelle an dein Board anpassen: Im Log (Sensor "Umgebungslicht")
// den Wert bei Dunkelheit und bei Licht notieren. Je nach Revision
// steigt ODER faellt die Spannung bei Dunkelheit - dann "<" statt ">".
return x > 2.6 ? 0.25 : 1.0;
# Temperatur aus Home Assistant
- platform: homeassistant
id: temp
entity_id: ${temp_sensor}
on_value:
then:
- lvgl.label.update:
id: lbl_temp
text: !lambda 'return str_sprintf("%.1f °C", x);'
# ---- Lichtzustand aus Home Assistant spiegeln ----
binary_sensor:
- platform: homeassistant
id: licht_1_state
entity_id: ${licht_1}
on_state:
then:
- lvgl.widget.update:
id: btn_licht_1
state:
checked: !lambda 'return x;'
- platform: homeassistant
id: licht_2_state
entity_id: ${licht_2}
on_state:
then:
- lvgl.widget.update:
id: btn_licht_2
state:
checked: !lambda 'return x;'
script:
- id: update_time
then:
- lvgl.label.update:
id: lbl_time
text: !lambda |-
auto t = id(ha_time).now();
if (!t.is_valid()) return std::string("--:--");
return t.strftime("%H:%M");
interval:
- interval: 30s
then:
- script.execute: update_time
# ---- Touch ----
touchscreen:
platform: xpt2046
id: ts_touch
spi_id: touch_bus
cs_pin: 33
interrupt_pin: 36
update_interval: 50ms
threshold: 400
calibration:
x_min: 280
x_max: 3860
y_min: 340
y_max: 3860
transform:
swap_xy: false
mirror_x: true
mirror_y: false
# ---- Display (ESPHome 2026.4+: mipi_spi, Drehung macht LVGL) ----
display:
- platform: mipi_spi
id: my_display
spi_id: lcd
model: ILI9341
cs_pin: 15
dc_pin: 2
invert_colors: false
update_interval: never
auto_clear_enabled: false
dimensions:
width: 240
height: 320
# ---- Oberfläche ----
lvgl:
displays:
- my_display
touchscreens:
- touchscreen_id: ts_touch
rotation: 90
theme:
label:
text_color: 0xE6EDF3
button:
bg_color: 0x12171F
border_color: 0x242E3A
border_width: 1
radius: 14
text_color: 0xE6EDF3
checked:
bg_color: 0x22D3EE
text_color: 0x05141A
pages:
- id: main
bg_color: 0x0A0E14
widgets:
- label:
id: lbl_time
align: TOP_LEFT
x: 14
y: 12
text_font: montserrat_28
text: "--:--"
- label:
id: lbl_temp
align: TOP_RIGHT
x: -14
y: 16
text_font: montserrat_20
text_color: 0x22D3EE
text: "-- °C"
- button:
id: btn_licht_1
align: BOTTOM_LEFT
x: 14
y: -64
width: 140
height: 64
checkable: true
widgets:
- label:
align: CENTER
text: "${licht_1_name}"
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: ${licht_1}
- button:
id: btn_licht_2
align: BOTTOM_RIGHT
x: -14
y: -64
width: 140
height: 64
checkable: true
widgets:
- label:
align: CENTER
text: "${licht_2_name}"
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: ${licht_2}
- button:
align: BOTTOM_MID
y: -8
width: 292
height: 44
widgets:
- label:
align: CENTER
text: "Alles aus"
on_click:
- homeassistant.action:
action: script.turn_on
data:
entity_id: ${alles_aus}Was passiert hier? Zwei SPI-Busse (Display und Touch sind getrennt verdrahtet), die Hintergrundbeleuchtung hängt an GPIO21 und wird über den Lichtsensor (GPIO34) automatisch gedimmt (Schwelle einmal ans eigene Board anpassen, siehe Fehlerbehebung), die RGB-LED ist als Licht in Home Assistant verfügbar (für Statusanzeigen). Die Oberfläche macht LVGL: Uhr oben links, Temperatur oben rechts, zwei Lichtbuttons, die ihren Zustand live aus Home Assistant spiegeln, und ein Sammelbutton. Alle Tastendrücke rufen direkt Home-Assistant-Aktionen auf – ohne eine einzige Automation.
Schritt 3: Flashen
- CYD per USB an den Rechner anschließen, an dem du ESPHome im Browser (Chrome/Edge) geöffnet hast. Windows-Nutzer: Falls kein COM-Port auftaucht, den CH340-Treiber installieren.
- In ESPHome beim Gerät auf „Install“ → „Plug into this computer“ → den seriellen Port auswählen. ESPHome kompiliert (beim ersten Mal 3–8 Minuten) und flasht.
- Danach startet das Board neu, verbindet sich mit deinem WLAN und Home Assistant meldet unter Einstellungen → Geräte & Dienste ein neues ESPHome-Gerät zum Hinzufügen. Alle weiteren Updates laufen ab jetzt drahtlos (OTA).
Schritt 4: Aktionen erlauben (wichtig!)
Standardmäßig darf ein ESPHome-Gerät in Home Assistant nichts schalten. Ohne diesen Haken reagieren die Buttons nicht:
- Einstellungen → Geräte & Dienste → ESPHome
- Bei „Wand-Dashboard“ auf „Konfigurieren“
- Haken bei „Dem Gerät erlauben, Home-Assistant-Aktionen auszuführen“ setzen
Schritt 5: Anpassen
Alles Wichtige steht im substitutions-Block. Willst du mehr, sind das die typischen Erweiterungen:
- Andere Gerätetypen: Statt
light.togglegeht jede Aktion –switch.togglefür Steckdosen,cover.togglefür Rollläden,scene.turn_onfür Szenen. Beim Zustand-Spiegeln dann den passendenbinary_sensorbzw. die Entität anpassen. - Mehr Buttons: Einen
button-Block kopieren,id, Position (align/x/y) und Entität ändern. Bei mehr als vier Buttons lohnt eine zweite Seite (pages) mit Wischgeste – das zeige ich in einem Folge-Guide. - Icons statt Text: LVGL kann Material-Design-Icons als Schrift einbinden (
materialdesignicons-webfont.ttfin den ESPHome-Ordner legen und alsfontmit den gewünschten Glyphen laden). Für den Start reicht Text. - Display nachts ganz aus: Im
on_valuedes Lichtsensorsbrightness: 0.0statt 0.25 – Touch weckt es dann nicht automatisch; dafür einenon_touchimtouchscreen-Block mitlight.turn_onergänzen.
Gehäuse & Montage
Nackt sieht das Board nach Bastelkeller aus. Auf MakerWorld gibt es ein hervorragendes CC0-Gehäuse (also frei nutzbar) genau für dieses Board – mit Tischständer, Wandhalter, Unter-Tisch-Halter und Unterputz-Rahmen für die 68er-Dose, jeweils mit Schwenkgelenk und versteckter Kabelführung: Home Assistant Desk Mount CYD (akuehlewind). Druckzeit ca. 3,5 h mit dem „Optimized“-Profil.
Für die Wandmontage neben einem Lichtschalter ist der Unterputz-Rahmen die eleganteste Lösung; das USB-Netzteil verschwindet dann in einer tiefen Dose (Elektronikdose, ≥ 40 mm). 230 V bleibt Sache des Elektrikers.
Ein einfaches 5-V-USB-Netzteil reicht – das Display zieht unter 1 W. Für den Unterputz-Einbau nimmst du ein möglichst flaches Netzteil, das in die tiefe Dose passt, oder ein 5-V-Hutschienen-/Einbau-Netzteil vom Elektriker.
Fehlerbehebung
- Weißer Bildschirm, aber Gerät ist online: Du nutzt eine alte Anleitung mit
platform: ili9xxxauf ESPHome 2026.4 oder neuer – dieser Treiber wurde durchmipi_spiersetzt. Meine Konfiguration oben ist bereits richtig. Umgekehrt: Auf ESPHome vor 2026.4 gibt esmipi_spinoch nicht – dannplatform: ili9xxx,color_palette: 8BITund beimlcd-SPI zusätzlichmiso_pin: GPIO12, sowierotation: 90aus demlvgl-Block entfernen und stattdessen imdisplayeintransform: swap_xy: truemitdimensions: 320×240setzen. Oder einfach ESPHome aktualisieren. - Verzerrte Farben, Streifen, Pixelsalat: Anderer Display-Controller. Im
display-Blockmodel: ST7789V(oderILI9342) probieren – mehr als das eine Wort ändert sich nicht. - Touch trifft daneben oder ist gespiegelt: Im
touchscreen-Blockmirror_x/mirror_y/swap_xyvariieren. Wenn es nur um wenige Millimeter geht, diecalibration-Werte anpassen: Die Rohwerte siehst du im ESPHome-Log, wenn du die Ecken antippst. - Bild steht auf dem Kopf:
rotation: 90imlvgl-Block auf270ändern (USB-Buchse dann auf der anderen Seite). - Buttons tun nichts: Schritt 4 vergessen – „Home-Assistant-Aktionen erlauben“.
- Uhr zeigt „–:–„: Zeit kommt aus Home Assistant; kurz nach dem Start dauert der Abgleich ein paar Sekunden. Bleibt es leer, ist die API-Verbindung nicht da (Gerät in HA hinzugefügt?).
- Kein COM-Port beim Flashen: CH340-Treiber (Windows) oder ein anderes USB-Kabel – viele Ladekabel haben keine Datenleitungen.
- Display dimmt am Tag oder bleibt nachts hell: Der Lichtsensor ist je nach Board-Revision unterschiedlich beschaltet. Hand über den Sensor (kleines Bauteil neben dem Display) und im ESPHome-Log den Wert von
Umgebungslichtvergleichen: Liegt der Wert bei Dunkelheit höher, passtx > 2.6– liegt er niedriger, drehe den Vergleich aufx < 0.8(Zahl aus dem Log). Die Schwelle in die Mitte zwischen beide Messwerte legen.
Häufige Fragen
Geht das auch mit dem 3,5″-Modell (ESP32-3248S035)? Ja, aber mit anderen Pins und anderem Controller (ST7796). Die Struktur bleibt gleich, die Werte nicht – das wird ein eigener Guide.
Kapazitiver Touch? Das Standard-CYD hat resistiven Touch (drücken statt streicheln). Die „C“-Varianten mit kapazitivem Touch brauchen einen anderen Touch-Block (gt911 über I²C).
Kann das Display Kameras oder Grafiken zeigen? Bilder und Icons ja (LVGL image-Widget), Video-Streams nein – dafür ist der ESP32 zu schwach.
Wie viel Strom zieht das? Etwa 0,6 W bei voller Helligkeit, gedimmt unter 0,4 W – rund 1,50 € im Jahr.
Fazit
Für rund 20 € und eine halbe Stunde bekommst du ein Touch-Panel, das genau das tut, was du brauchst – ohne App, ohne Cloud, ohne Abo. Die Konfiguration oben ist die Basis; von hier aus wächst das Ding mit dir: mehr Buttons, Icons, zweite Seite, Rollläden, Szenen. Und mit dem Unterputz-Rahmen sieht es aus, als hätte es der Elektriker eingebaut.
Wer noch ganz am Anfang steht: Mein Home-Assistant-Starter-Guide bringt dich bis zur ersten Automation. Und wenn du dein ganzes Haus planen willst, hilft der neue Smart-Home-Planer – Raum für Raum mit Geräteliste und Preisen.
A touch panel on the wall that switches your lights, shows the temperature and controls your Home Assistant – for €15–22. Sounds like a weekend of tinkering? It isn’t: the Cheap Yellow Display (CYD) is a ready-made board with an ESP32, a 2.8-inch touchscreen and a USB port. No soldering, no wiring. You flash ESPHome onto it once, copy my config, fill in your entities – done.
In this guide we’ll build, step by step, a wall dashboard with a clock, temperature, two light switches and an „All off“ button that dims itself automatically at night. The config is tested on the current ESPHome (2026.6) – including the pitfalls that have broken a lot of the guides out there since ESPHome 2026.4.
What you need
- ESP32-2432S028R „Cheap Yellow Display“ – 2.8″, 320×240, resistive touch. Around €20–22 on Amazon (arrives fast), from about €12 on AliExpress (2–3 weeks). Make sure you buy exactly this model.
- 5 V / 1 A USB power supply + micro-USB cable (USB-C on the newer revision). An old phone charger will do.
- Home Assistant with the ESPHome Device Builder (add-on) – or ESPHome on another computer.
- A computer with Chrome or Edge for the first flash over USB.
- Optional: a 3D-printed case (desk, wall or flush-mount – more on that below).
The ESP32-2432S028R – ESP32, 2.8″ touchscreen, light sensor, RGB LED and microSD on one board. Exactly the board the configuration below is written for. Check the model number; the 3.5″ version has different pins.
The same board straight from China – usually much cheaper, but with 2–3 weeks delivery. Make sure to pick the version with touch („Touch“/“Resistive“) and the 2.8″ size; power supply and cable are usually not included.
Step 1: Prepare ESPHome
- In Home Assistant: Settings → Add-ons → Add-on Store → install and start „ESPHome Device Builder“ (tick „Show in sidebar“).
- Open ESPHome → „+ New Device“ → name it
wanddisplay→ device type ESP32 → create. A basic device is set up. - If you haven’t already: open „Secrets“ from the menu at the top right in ESPHome and enter your Wi-Fi credentials:
wifi_ssid: "DeinWLAN"
wifi_password: "DeinPasswort"Step 2: The configuration
Open the new device in ESPHome with „Edit“, delete everything in it and paste in this config. The only thing you need to change is the substitutions block at the very top – your entities and labels. Everything else can stay as it is.
substitutions:
name: wanddisplay
friendly_name: Wand-Dashboard
# ---- Hier deine Entitäten eintragen ----
licht_1: light.wohnzimmer
licht_1_name: "Wohnzimmer"
licht_2: light.kueche
licht_2_name: "Küche"
temp_sensor: sensor.wohnzimmer_temperatur
alles_aus: script.alles_aus
esphome:
name: ${name}
friendly_name: ${friendly_name}
esp32:
board: esp32dev
framework:
type: arduino
logger:
api:
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "${friendly_name} Setup"
captive_portal:
time:
- platform: homeassistant
id: ha_time
on_time_sync:
- script.execute: update_time
# ---- Zwei SPI-Busse: Display und Touch ----
spi:
- id: lcd
clk_pin: GPIO14
mosi_pin: GPIO13
- id: touch_bus
clk_pin: GPIO25
mosi_pin: GPIO32
miso_pin: GPIO39
# ---- Hintergrundbeleuchtung + RGB-LED ----
output:
- platform: ledc
pin: GPIO21
id: backlight_pwm
- platform: ledc
pin: GPIO4
id: led_red
inverted: true
- platform: ledc
pin: GPIO16
id: led_green
inverted: true
- platform: ledc
pin: GPIO17
id: led_blue
inverted: true
light:
- platform: monochromatic
output: backlight_pwm
id: backlight
name: "Display-Helligkeit"
restore_mode: ALWAYS_ON
- platform: rgb
name: "Status-LED"
id: status_led
red: led_red
green: led_green
blue: led_blue
restore_mode: ALWAYS_OFF
# ---- Sensoren ----
sensor:
# Lichtsensor auf der Platine: dimmt das Display nachts
- platform: adc
pin: GPIO34
id: ldr
name: "Umgebungslicht"
attenuation: 12db
update_interval: 10s
filters:
- sliding_window_moving_average:
window_size: 3
send_every: 1
on_value:
then:
- light.turn_on:
id: backlight
brightness: !lambda |-
// Schwelle an dein Board anpassen: Im Log (Sensor "Umgebungslicht")
// den Wert bei Dunkelheit und bei Licht notieren. Je nach Revision
// steigt ODER faellt die Spannung bei Dunkelheit - dann "<" statt ">".
return x > 2.6 ? 0.25 : 1.0;
# Temperatur aus Home Assistant
- platform: homeassistant
id: temp
entity_id: ${temp_sensor}
on_value:
then:
- lvgl.label.update:
id: lbl_temp
text: !lambda 'return str_sprintf("%.1f °C", x);'
# ---- Lichtzustand aus Home Assistant spiegeln ----
binary_sensor:
- platform: homeassistant
id: licht_1_state
entity_id: ${licht_1}
on_state:
then:
- lvgl.widget.update:
id: btn_licht_1
state:
checked: !lambda 'return x;'
- platform: homeassistant
id: licht_2_state
entity_id: ${licht_2}
on_state:
then:
- lvgl.widget.update:
id: btn_licht_2
state:
checked: !lambda 'return x;'
script:
- id: update_time
then:
- lvgl.label.update:
id: lbl_time
text: !lambda |-
auto t = id(ha_time).now();
if (!t.is_valid()) return std::string("--:--");
return t.strftime("%H:%M");
interval:
- interval: 30s
then:
- script.execute: update_time
# ---- Touch ----
touchscreen:
platform: xpt2046
id: ts_touch
spi_id: touch_bus
cs_pin: 33
interrupt_pin: 36
update_interval: 50ms
threshold: 400
calibration:
x_min: 280
x_max: 3860
y_min: 340
y_max: 3860
transform:
swap_xy: false
mirror_x: true
mirror_y: false
# ---- Display (ESPHome 2026.4+: mipi_spi, Drehung macht LVGL) ----
display:
- platform: mipi_spi
id: my_display
spi_id: lcd
model: ILI9341
cs_pin: 15
dc_pin: 2
invert_colors: false
update_interval: never
auto_clear_enabled: false
dimensions:
width: 240
height: 320
# ---- Oberfläche ----
lvgl:
displays:
- my_display
touchscreens:
- touchscreen_id: ts_touch
rotation: 90
theme:
label:
text_color: 0xE6EDF3
button:
bg_color: 0x12171F
border_color: 0x242E3A
border_width: 1
radius: 14
text_color: 0xE6EDF3
checked:
bg_color: 0x22D3EE
text_color: 0x05141A
pages:
- id: main
bg_color: 0x0A0E14
widgets:
- label:
id: lbl_time
align: TOP_LEFT
x: 14
y: 12
text_font: montserrat_28
text: "--:--"
- label:
id: lbl_temp
align: TOP_RIGHT
x: -14
y: 16
text_font: montserrat_20
text_color: 0x22D3EE
text: "-- °C"
- button:
id: btn_licht_1
align: BOTTOM_LEFT
x: 14
y: -64
width: 140
height: 64
checkable: true
widgets:
- label:
align: CENTER
text: "${licht_1_name}"
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: ${licht_1}
- button:
id: btn_licht_2
align: BOTTOM_RIGHT
x: -14
y: -64
width: 140
height: 64
checkable: true
widgets:
- label:
align: CENTER
text: "${licht_2_name}"
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: ${licht_2}
- button:
align: BOTTOM_MID
y: -8
width: 292
height: 44
widgets:
- label:
align: CENTER
text: "Alles aus"
on_click:
- homeassistant.action:
action: script.turn_on
data:
entity_id: ${alles_aus}What’s going on here? Two SPI buses (display and touch are wired separately), the backlight sits on GPIO21 and is dimmed automatically by the light sensor (GPIO34) (adjust the threshold to your own board once, see Troubleshooting), and the RGB LED shows up as a light in Home Assistant (handy for status indicators). LVGL handles the UI: clock top left, temperature top right, two light buttons that mirror their state live from Home Assistant, and an all-in-one button. Every button press calls Home Assistant actions directly – without a single automation.
Step 3: Flashing
- Connect the CYD via USB to the computer where you have ESPHome open in the browser (Chrome/Edge). Windows users: if no COM port shows up, install the CH340 driver.
- In ESPHome, click „Install“ on the device → „Plug into this computer“ → select the serial port. ESPHome compiles (3–8 minutes the first time) and flashes.
- The board then reboots, connects to your Wi-Fi, and Home Assistant shows a new ESPHome device ready to add under Settings → Devices & services. From now on, all further updates happen wirelessly (OTA).
Step 4: Allow actions (important!)
By default, an ESPHome device isn’t allowed to switch anything in Home Assistant. Without this checkbox, the buttons won’t do anything:
- Settings → Devices & services → ESPHome
- Click „Configure“ on „Wand-Dashboard“
- Tick „Allow the device to perform Home Assistant actions“
Step 5: Customize
Everything important lives in the substitutions block. If you want more, these are the typical extensions:
- Other device types: Instead of
light.toggleyou can use any action –switch.togglefor smart plugs,cover.togglefor blinds,scene.turn_onfor scenes. For state mirroring, adjust the matchingbinary_sensoror entity accordingly. - More buttons: Copy a
buttonblock and change theid, position (align/x/y) and entity. With more than four buttons, a second page (pages) with a swipe gesture makes sense – I’ll show that in a follow-up guide. - Icons instead of text: LVGL can embed Material Design Icons as a font (put
materialdesignicons-webfont.ttfin the ESPHome folder and load it as afontwith the glyphs you want). Text is fine to start with. - Display completely off at night: In the light sensor’s
on_value, usebrightness: 0.0instead of 0.25 – touch won’t wake it automatically then; add anon_touchwithlight.turn_onto thetouchscreenblock for that.
Case & mounting
Bare, the board looks like something out of a hobby basement. On MakerWorld there’s an excellent CC0 case (so free to use) made for exactly this board – with a desk stand, wall mount, under-desk mount and a flush-mount frame for a standard 68 mm wall box, each with a swivel joint and hidden cable routing: Home Assistant Desk Mount CYD (akuehlewind). Print time is about 3.5 h with the „Optimized“ profile.
For wall mounting next to a light switch, the flush-mount frame is the most elegant solution; the USB power supply then disappears into a deep wall box (electronics box, ≥ 40 mm). Anything involving 230 V is a job for an electrician.
A simple 5 V USB power supply is enough – the display draws less than 1 W. For flush mounting, use the flattest power supply you can find that fits a deep wall box, or a 5 V DIN-rail/built-in power supply from an electrician.
Troubleshooting
- White screen, but the device is online: You’re using an old guide with
platform: ili9xxxon ESPHome 2026.4 or newer – that driver has been replaced bymipi_spi. My config above is already correct. The other way round: ESPHome before 2026.4 doesn’t havemipi_spiyet – in that case useplatform: ili9xxx,color_palette: 8BITand additionallymiso_pin: GPIO12on thelcdSPI, removerotation: 90from thelvglblock and instead settransform: swap_xy: truewithdimensions: 320×240in thedisplay. Or just update ESPHome. - Distorted colors, stripes, pixel garbage: Different display controller. Try
model: ST7789V(orILI9342) in thedisplayblock – nothing changes except that one word. - Touch is off target or mirrored: Play with
mirror_x/mirror_y/swap_xyin thetouchscreenblock. If it’s only off by a few millimeters, adjust thecalibrationvalues: you’ll see the raw values in the ESPHome log when you tap the corners. - Image is upside down: Change
rotation: 90in thelvglblock to270(the USB port will then be on the other side). - Buttons do nothing: You skipped step 4 – „Allow Home Assistant actions“.
- Clock shows „–:–„: The time comes from Home Assistant; right after startup, syncing takes a few seconds. If it stays empty, the API connection isn’t there (did you add the device in HA?).
- No COM port when flashing: CH340 driver (Windows) or a different USB cable – a lot of charging cables don’t have data lines.
- Display dims during the day or stays bright at night: The light sensor is wired differently depending on the board revision. Put your hand over the sensor (small component next to the display) and compare the value of
Umgebungslichtin the ESPHome log: if the value is higher in the dark,x > 2.6is right – if it’s lower, flip the comparison tox < 0.8(number from the log). Put the threshold halfway between the two readings.
FAQ
Does this work with the 3.5″ model (ESP32-3248S035) too? Yes, but with different pins and a different controller (ST7796). The structure stays the same, the values don’t – that’ll get its own guide.
Capacitive touch? The standard CYD has resistive touch (press rather than swipe). The „C“ variants with capacitive touch need a different touch block (gt911 via I²C).
Can the display show cameras or graphics? Images and icons yes (LVGL image widget), video streams no – the ESP32 is too weak for that.
How much power does it draw? About 0.6 W at full brightness, under 0.4 W dimmed – roughly €1.50 a year.
Conclusion
For around €20 and half an hour, you get a touch panel that does exactly what you need – no app, no cloud, no subscription. The config above is the foundation; from here the thing grows with you: more buttons, icons, a second page, blinds, scenes. And with the flush-mount frame, it looks like the electrician put it in.
Just getting started? My Home Assistant starter guide takes you all the way to your first automation. And if you want to plan your whole house, the new Smart Home Planner helps – room by room, with a device list and prices.


