In my experience when the screen seems to be functioning but is blank, it’s normally the backlight, just make sure there’s no pin or config missing to turn on the backlight
I believe it’s labelled as TFT_RS on that board. You’ll also want to specify CS and RESET. You’ll need a schematic or sample code to figure out which pins they are. And you’ll need to turn on the backlight with the TFT_BL pin - a monochromatic light component will allow you to adjust the brightness.
Thanks for the tips.
Based on this wiring diagram for the TFT:
I figured the RS/DC is IO2 and CS is IO15.
There’s that pin labeled RESET
, but it seems to be hard-wired. Is that normal?
Regarding the BACKLIGHT, the screen seems to be lit up very bright (white). So at least I think it’s on by default.
There appears to be sample code here along with the wiring diagram I got here. (After translation, it says RESET is the LCD reset signal line. Because the GPIO on the start board is tight, it is connected to the RESET line of the system. Similarly, BL is the backlight control line of the LCD, which is also directly connected to 3.3V. – but I don’t know if that’s correct, or lost in translation. At least it would explain the backlight being always on.)
However, the sample code is very frustrating, because it uses macros like PIN_NUM_RST
, bit the headers that define those constants are not available – or at least I couldn’t figure out how to get them, even after having Google translate the page from Chinese.
Any suggestions?
For those interested in working with LVGL, I’ve successfully configured it using the following hardware setup:
Microcontroller: Lolin D32 PRO
Display: TFT 2.4 Touch Shield
TFT Driver: ILI9341
Touch Controller: XPT2046
Also notice the framework, not esp-idf but arduino did the trick for me.
esphome:
name: esp-display-lolin
friendly_name: ESP Display Lolin
platformio_options:
build_flags: "-DBOARD_HAS_PSRAM"
esp32:
board: lolin_d32_pro
framework:
type: arduino
external_components:
- source: github://clydebarrow/esphome@lvgl
components: [ lvgl ]
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret esphome_api
ota:
- platform: esphome
password: !secret esphome_ota
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
web_server:
local: true
captive_portal:
color:
- id: my_red
red: 100%
green: 0%
blue: 0%
- id: my_yellow
red: 100%
green: 100%
blue: 0%
- id: my_green
red: 0%
green: 100%
blue: 0%
- id: my_blue
red: 0%
green: 0%
blue: 100%
- id: my_gray
red: 50%
green: 50%
blue: 50%
- id: my_black
red: 0%
green: 0%
blue: 0%
- id: my_white
red: 100%
green: 100%
blue: 100%
font:
- file: "arial.ttf"
id: arial_48
size: 48
- file: "arial.ttf"
id: arial_36
size: 36
- file: "arial.ttf"
id: arial_24
size: 24
- file: "arial.ttf"
id: arial_12
size: 12
time:
- platform: homeassistant
id: esptime
sensor:
- platform: homeassistant
id: inside_temperature
entity_id: sensor.gw2000a_indoor_temperature
internal: true
- platform: homeassistant
id: outside_temperature
entity_id: sensor.gw2000a_temperature_1
internal: true
- platform: wifi_signal
name: "WiFi Signal Strength"
update_interval: 60s
spi:
clk_pin: 18
mosi_pin: 23
miso_pin: 19
touchscreen:
platform: xpt2046
id: touch_key1
cs_pin: 12
update_interval: 50ms
calibration:
x_min: 281
x_max: 3848
y_min: 347
y_max: 3878
transform:
mirror_x: false
mirror_y: false
swap_xy: false
lvgl:
displays:
- tft_ha_test
pages:
- id: main_page
widgets:
- label:
align: CENTER
text: 'Hello World!'
display:
- platform: ili9xxx
model: ili9341
cs_pin: 14
dc_pin: 27
reset_pin: 33
rotation: 90
auto_clear_enabled: false
invert_colors: false
show_test_card: false
id: tft_ha_test
I’m trying to get LVGL going on a Lanbon L8 but all I got was a blank screen UNTIL I removed the update_interval: never
line on the display. But I’m getting run-time errors:
[15:22:40][W][component:237]: Component display took a long time for an operation (72 ms).
[15:22:40][W][component:238]: Components should block for at most 30 ms.
[15:22:45][W][component:237]: Component display took a long time for an operation (72 ms).
[15:22:45][W][component:238]: Components should block for at most 30 ms.
Is the documentation wrong or am I doing something wrong?
Also, trying to test the touch screen by having a large checkable button in the middle of the screen. The label is there but not the button (it’s in the upper left) and it is TINY!
FYI, I’m familiar with LVGL using SquareLine Studio.
psram:
mode: octal
speed: 80MHz
spi:
clk_pin: GPIO19
mosi_pin: GPIO23
miso_pin: GPIO25
i2c:
sda: GPIO4
scl: GPIO0
font:
# gfonts://family[@weight]
- file: "gfonts://Roboto"
id: roboto_20
size: 20
display:
- id: langbon_L8
platform: st7789v
model: Custom
height: 320
width: 240
offset_height: 0
offset_width: 0
backlight_pin: GPIO5
cs_pin: GPIO22
dc_pin: GPIO21
reset_pin: GPIO18
auto_clear_enabled: false
touchscreen:
- platform: ft63x6
output:
- platform: ledc
pin: GPIO26
id: moodRed
- platform: ledc
pin: GPIO32
id: moodGreen
- platform: ledc
pin: GPIO33
id: moodBlue
- platform: gpio
pin: GPIO12
id: relay_1
- platform: gpio
pin: GPIO14
id: relay_2
- platform: gpio
pin: GPIO27
id: relay_3
light:
- platform: rgb
name: "Mood Light"
red: moodRed
green: moodGreen
blue: moodBlue
lvgl:
displays:
- langbon_L8
pages:
- id: main_page
widgets:
- button:
align: CENTER
height: 60
width: 200
checkable: true
bg_color: 0x0000FF
default:
bg_color: 0x00FF00
checked:
bg_color: 0xFF0000
- label:
text: "Click ME!"
align: CENTER
As per the docs, use the ili9xxx display component, not the deprecated st7789v component.
If you want the button to contain the label, it has to be a child of the button. See the example in the docs: LVGL Widgets — ESPHome
Switching to the ili9xxxx fixed the update issue and making the label a child of the button centered it on the button, but the button is still on the upper left and no sign that is is clickable.
display:
- id: langbon_L8
platform: ili9xxx
model: ST7789V
invert_colors: false
dimensions: 240x320
cs_pin: GPIO22
dc_pin: GPIO21
reset_pin: GPIO18
auto_clear_enabled: false
update_interval: never
...
lvgl:
pages:
- id: main_page
widgets:
- button:
x: 120
y: 120
height: 60
width: 150
checkable: true
default:
bg_color: 0x00FF00
checked:
bg_color: 0xFF0000
widgets:
- label:
text: "Click ME!"
align: CENTER
on_value:
then:
- logger.log:
format: "Button checked state: %d"
args: [ x ]
I can probably figure out the LGVL layout issues eventually (and how to manage the now-explicit backlight) but the lack of clicking needs help.
It is clickable (you will see it change when pressed) but the checkable
flag isn’t being set. Move the bg_color
setting out from default
to just under the button itself. Not sure why that affects it (could be a bug) but you never need to use the default
key anyway, since anything applied directly to the widget is the default.
Change
checkable: true
default:
bg_color: 0x00FF00
checked:
bg_color: 0xFF0000
to
checkable: true
bg_color: 0x00FF00
checked:
bg_color: 0xFF0000
just spent the weekend getting exactly this going!
here is my esphome config and it includes a display timeout and a clickable button that turns a homeassistant light entity on and off
spi:
clk_pin: GPIO19
mosi_pin: GPIO23
miso_pin: GPIO25
i2c:
sda: GPIO4
scl: GPIO0
display:
- platform: ili9xxx
model: ST7789V
cs_pin: GPIO22
dc_pin: GPIO21
reset_pin: GPIO18
invert_colors: false
auto_clear_enabled: false
update_interval: never
show_test_card: true
id: disp
rotation: 180
output:
- platform: ledc
pin: GPIO5
id: backlight_pwm
- platform: ledc
id: mood_red
pin: GPIO26
- platform: ledc
id: mood_green
pin: GPIO32
- platform: ledc
id: mood_blue
pin: GPIO33
light:
- platform: monochromatic
output: backlight_pwm
name: "Display Backlight"
id: backlight
restore_mode: ALWAYS_ON
- platform: rgb
name: "Moodlight"
red: mood_red
green: mood_green
blue: mood_blue
touchscreen:
platform: ft63x6
id: touch
display: disp
calibration:
x_min: 0
y_min: 0
x_max: 230
y_max: 312
on_touch:
- lambda: |-
ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
touch.x,
touch.y,
touch.x_raw,
touch.y_raw
);
on_release:
- if:
condition: lvgl.is_paused
then:
- logger.log: "LVGL resuming"
- lvgl.resume:
- lvgl.widget.redraw:
- light.turn_on: backlight
lvgl:
displays:
- disp
on_idle:
timeout: !lambda "return (id(display_timeout).state * 1000);"
then:
- logger.log: "LVGL is idle"
- light.turn_off: backlight
- lvgl.pause:
pages:
- id: main_page
widgets:
- button:
id: light_btn
align: CENTER
width: 140
height: 70
checkable: true
widgets:
- label:
align: CENTER
text: 'Lights'
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.bedroom_lights
- logger.log:
format: "Button checked"
switch:
- platform: gpio
pin: GPIO12
name: relay1
- platform: gpio
pin: GPIO14
name: relay2
- platform: gpio
pin: GPIO27
name: relay3
binary_sensor:
- platform: homeassistant
id: bedroom_light
entity_id: light.bedroom_lights
publish_initial_state: true
on_state:
then:
lvgl.widget.update:
id: light_btn
state:
checked: !lambda return x;
- platform: lvgl
name: button2
widget: light_btn
publish_initial_state: true
number:
- platform: template
name: LVGL Screen timeout
optimistic: true
id: display_timeout
unit_of_measurement: "s"
initial_value: 45
restore_value: true
min_value: 10
max_value: 180
step: 5
mode: box
captive_portal:
Good luck here is a basic button matrix that seems to work a bit better than single buttons.
I will keep uploading my latest configs to: GitHub - jtbnz/esphome_lanbonL8: ESphome config for a Lanbon L8 LCD switch
pages:
- id: main_page
widgets:
- buttonmatrix:
x: 5
y: 40
width: 230
items:
pressed:
bg_color: 0xFFFF00
id: matrix_id
rows:
- buttons:
- id: light_btn
control:
checkable: true
text: ‘Lights’
on_click:
- homeassistant.action:
action: light.toggle
data:
entity_id: light.bedroom_lights
- logger.log:
format: “Button pressed”
- buttons:
- id: relay1_btn
control:
checkable: true
text: ‘Relay1’
on_click:
- switch.toggle: relay1
- logger.log:
format: “Relay Button pressed”
I’ve submitted a PR to document the configuration for fully integrated hardware platform.