Opps… Sorry finger trouble! Title corrected. Anyway…
With your advice, I was brave enough to roll-back to version 2025.8.x. And after a bit of chopping 'n changing, my problem seems to be related to framework AND Device Builder version.
- framework: arduino / Builder: 2025.10 = Won’t compile (USBserial)
- framework: esp-ide / Builder: 2025.10 = Compiles but display blank ([E][component:154]: display is marked FAILED)
- framework: arduino / Builder: 2025.8 = Compiles & Displays

- framework: esp-ide / Builder: 2025.8 = Compiles but display blank
This is a (possibly relevent) section of the startup log:
[07:50:20][C][spi:075]: Using HW SPI: SPI2_HOST
[07:50:20][C][ili9xxx:089]: ili9xxx
[07:50:20][C][ili9xxx:089]: Rotations: 0 °
[07:50:20][C][ili9xxx:089]: Dimensions: 240px x 320px
[07:50:20][C][ili9xxx:090]: Width Offset: 0
[07:50:20][C][ili9xxx:090]: Height Offset: 0
[07:50:20][C][ili9xxx:099]: Color mode: 16bit
[07:50:20][C][ili9xxx:108]: Data rate: 40MHz
[07:50:20][C][ili9xxx:110]: Reset Pin: GPIO35
[07:50:20][C][ili9xxx:111]: CS Pin: GPIO12
[07:50:20][C][ili9xxx:112]: DC Pin: GPIO37
[07:50:20][C][ili9xxx:114]: Color order: BGR
[07:50:20][C][ili9xxx:114]: Swap_xy: NO
[07:50:20][C][ili9xxx:114]: Mirror_x: YES
[07:50:20][C][ili9xxx:114]: Mirror_y: NO
[07:50:20][C][ili9xxx:114]: Invert colors: NO
[07:50:20][C][ili9xxx:124]: => Failed to init Memory: YES!
[07:50:20][C][ili9xxx:126]: Update Interval: 1.0s
[07:50:20][E][component:145]: display is marked FAILED: unspecified
And this is the complete yaml:
esphome:
name: "esp32s2-msp2807-display"
friendly_name: "esp32s2 msp2807 Display"
esp32:
board: lolin_s2_mini
framework:
#type: arduino
type: esp-idf
# Enable logging
logger:
level: DEBUG
logs:
component: ERROR # Suppress the "component took a long time" message!
xpt2046: ERROR
touchscreen: ERROR
# Enable Home Assistant API
api:
ota:
- platform: esphome
id: my_ota_pw
password: !secret ota_password
wifi:
networks:
#- ssid: !secret wifi_wa60hce
# password: !secret wifi_password
- ssid: !secret wifi_ssid
password: !secret wifi_password
web_server:
port: 80
captive_portal:
font:
- file: "fonts/DejaVuSans.ttf"
id: my_font
size: 20
- file: "fonts/DejaVuSans.ttf"
id: small_font
size: 14
#For MSP2807 pinout/nomenclature see: ~/tft-msp2807/Docs/2.8inch_SPI_Module_MSP2807_User_Manual_EN.pdf
spi: #VSPI
clk_pin: GPIO7 #TFT_SCK (Pin 7) & T_CLK (Pin 10)
miso_pin: GPIO9 #T_DOut (Pin 13)
mosi_pin: GPIO11 #TFT_MOSI (Pin 6) & T_DIN (Pin 12)
display:
- platform: ili9xxx
model: ili9341
id: tft_display
invert_colors: false
cs_pin: GPIO12 #TFT_CS (Pin 3)
reset_pin: GPIO35 #TFT_RST (Pin 4)
dc_pin: GPIO37 #TFT_D/C (Pin 5)
rotation: 0
lambda: |-
//Background Colour
it.fill(Color::BLACK);
it.printf(id(line1x), id(line1y), id(my_font), TextAlign::TOP_LEFT, "Temperature");
it.printf(it.get_width(), id(line1y), id(my_font), TextAlign::TOP_RIGHT, " %.1f°C", id(outside_temp).state);
//Seperator & waste colours
auto red = Color(255, 0, 0);
auto green = Color(0, 255, 0);
it.filled_rectangle(20, 40, 200, 5, red);
it.printf(id(line2x), id(line2y), id(my_font), "Veh.Volts");
it.printf(it.get_width(), id(line2y), id(my_font), TextAlign::TOP_RIGHT, " %.1fV", id(veh_volts).state);
it.printf(id(line3x), id(line3y), id(my_font), "Veh.Amps");
it.printf(it.get_width(), id(line3y), id(my_font), TextAlign::TOP_RIGHT, " %.1fA", id(veh_amps).state);
it.printf(id(line4x), id(line4y), id(my_font), "Lei.Volts");
it.printf(it.get_width(), id(line4y), id(my_font), TextAlign::TOP_RIGHT, " %.1fV", id(lei_volts).state);
it.printf(id(line5x), id(line5y), id(my_font), "Lei.Amps");
it.printf(it.get_width(), id(line5y), id(my_font), TextAlign::TOP_RIGHT, " %.1fA", id(lei_amps).state);
it.filled_rectangle(20, 180, 200, 5, red);
it.printf(id(line6x), id(line6y), id(my_font), "Mobo Bal.");
it.printf(it.get_width(), id(line6y), id(my_font), TextAlign::TOP_RIGHT, " %.1fGB", id(mobo_balance).state);
it.filled_rectangle(20, 220, 200, 5, red);
it.printf(id(line7x), id(line7y), id(my_font), "LPG Level");
it.printf(it.get_width(), id(line7y), id(my_font), TextAlign::TOP_RIGHT, " %.0f%%", id(lpg_level).state);
it.filled_rectangle(20, 270, 200, 5, red);
//it.printf(id(line8x), id(line8y), id(small_font), Color(0xFFFF00), "IP Address:");
//it.printf(it.get_width(), id(line8y), id(small_font), Color(0xFFFF00), TextAlign::TOP_RIGHT, "%s", id(my_ip_addrs).state.c_str() );
it.printf(id(line8x), id(line8y), id(my_font), id(waste_valve).state ? Color(red) : Color(green), "Waste Valve");
it.printf(it.get_width(), id(line8y), id(my_font), id(waste_valve).state ? Color(red) : Color(green), TextAlign::TOP_RIGHT, "%s", id(waste_valve).state ? "OPEN" : "CLOSED" );
#text_sensor:
# - platform: wifi_info
# ip_address:
# id: my_ip_addrs
binary_sensor:
- platform: homeassistant
#entity_id: binary_sensor.esp32_s3_zero_waste
entity_id: binary_sensor.motorhome_ds18b20_waste_temp_waste
id: waste_valve
#on_state:
# then:
# - logger.log: "mpr says: waste value has changed"
sensor:
- platform: homeassistant
entity_id: sensor.motorhome_ds18b20_waste_temp_temperature
id: outside_temp
- platform: homeassistant
entity_id: sensor.motorhome_hlsr10_bat_lei_voltage
id: lei_volts
- platform: homeassistant
entity_id: sensor.motorhome_hlsr10_bat_lei_current
id: lei_amps
- platform: homeassistant
entity_id: sensor.motorhome_hlsr10_bat_veh_voltage
id: veh_volts
#on_value:
# then:
# - logger.log: "mpr says: veh volts has changed"
- platform: homeassistant
entity_id: sensor.motorhome_hlsr10_bat_veh_current
id: veh_amps
- platform: homeassistant
entity_id: sensor.mobo_balance
id: mobo_balance
- platform: homeassistant
#entity_id: sensor.esp32s2_as5600_position
entity_id: sensor.motorhome_as5600_lpg_custom_raw_position
id: lpg_level
output:
- platform: ledc
id: backlight
pin: GPIO16 # TFT_BLIGHT (Pin8)
light:
- platform: monochromatic
id: backlightctl
name: "Backight On/Off"
output: backlight
restore_mode: ALWAYS_ON
switch:
- platform: restart
name: "Display Restart"
touchscreen:
platform: xpt2046
id: my_touchscreen
cs_pin: GPIO39 #T_CS (Pin11)
update_interval: 50ms
threshold: 400
calibration:
x_min: 280
x_max: 3860
y_min: 340
y_max: 3860
on_touch:
- if:
condition:
- lambda: 'return id(backlightctl).current_values.get_brightness() == 0.5;'
then:
- light.dim_relative:
id: backlightctl
relative_brightness: +50%
else:
- light.dim_relative:
id: backlightctl
relative_brightness: -50%
globals:
- id: line1x
type: int
initial_value: '0'
- id: line1y
type: int
initial_value: '0'
- id: line2x
type: int
initial_value: '0'
- id: line2y
type: int
initial_value: '50'
- id: line3x
type: int
initial_value: '0'
- id: line3y
type: int
#initial_value: '100'
initial_value: id(line2y)+30
- id: line4x
type: int
initial_value: '0'
- id: line4y
type: int
#initial_value: '160'
initial_value: id(line3y)+30
- id: line5x
type: int
initial_value: '0'
- id: line5y
type: int
#initial_value: '200'
initial_value: id(line4y)+30
- id: line6x
type: int
initial_value: '0'
- id: line6y
type: int
#initial_value: '200'
initial_value: id(line5y)+50
- id: line7x
type: int
initial_value: '0'
- id: line7y
type: int
initial_value: id(line6y)+50
- id: line8x
type: int
initial_value: '0'
- id: line8y
type: int
initial_value: id(line7y)+50