Unable to switch pages using a Tactile switch and lvgl component

Hi,
I’m trying to switch between two pages (main_page and page_1), defined in the LGVL, with a tactile switch. I’m not able to get this working. Tried different ways, but always end up with compile errors. I’m using a gc9a01 display.

I’m new to using displays in esphome…
What am I doing wring here? (this can’t be that hard… I guess…)

##############################################
# Include all required packages / functions
##############################################
packages:
  base: !include common/base.yaml
  hass: !include common/home_assistant.yaml
  board: !include common/board_esp32_s2_mini.yaml
  wifi: !include common/wifi.yaml
  display: !include common/display_gc9a01a_lvgl.yaml
...
...
...
binary_sensor:
  - platform: gpio
    pin: GPIO18  
    name: "Page Switch"
    id: page_switch
    on_press:
     - lambda: |-
          static bool is_main_page = true;
          is_main_page = !is_main_page;
          if (is_main_page) {
            lv_scr_load(main_page);  // Verwijst naar de object ID for main_page
          } else {
            lv_scr_load(page_1);  // Verwijst naar de object ID for Page_1
          }

Display.yaml:

# GC9A01 round Display 240x240
# initial version: 16022025

font:
  - file: "fonts/Roboto-Medium.ttf"
    id: roboto_medium
    size: 56 # Increased from 24 to 48
    extras:
      - file: "fonts/materialdesignicons-webfont.ttf"
        glyphs: [
            "\U000F07E4", # mdi-molecule-co2
            "\U000F0F55", # mdi-home-thermometer-outline
          ]
  - file: "fonts/ds-digi.ttf"
    id: font_digital
    size: 72 # Increased from 12 to 20

# # SPI-bus voor het GC9A01-display
spi:
  clk_pin: 11 #5 # SCL
  mosi_pin: 9 #3  #SDA

display:
  - platform: ili9xxx
    model: GC9A01A
    id: my_display
    dimensions:
      height: 240
      width: 240
    cs_pin: 5 #7
    dc_pin: 7 #9
    reset_pin: 3 #11
    invert_colors: true
    rotation: 0
    auto_clear_enabled: false
    update_interval: never
    data_rate: 40MHz

lvgl:
  log_level: INFO
  color_depth: 16
  bg_color: 0x000000
  align: center
  pad_all: 5

  pages:
    - id: main_page
      widgets:
        - meter:
            height: 240
            width: 240
            align: center
            text_font: montserrat_14
            bg_opa: TRANSP
            text_color: 0x999999
            border_width: 0
            pad_all: 4

            scales:
              - ticks:
                  width: 2
                  count: 21
                  length: 15
                  color: 0x000000
                  major:
                    stride: 5
                    width: 6
                    length: 20
                    color: 0xFFFFFF
                    label_gap: 20
                range_from: 300
                range_to: 2300
                angle_range: 270
                rotation: 135

                indicators:
                  - line:
                      id: co2_needle
                      width: 8
                      color: 0xFF0000
                      r_mod: -5
                  - arc: # GREEN
                      color: 0x00FF00
                      width: 12
                      start_value: 300
                      end_value: 800
                  - arc: #YELLOW
                      color: 0xFFDE21
                      width: 12
                      start_value: 800
                      end_value: 1299
                  - arc: # ORANGE
                      color: 0xFF7518
                      width: 12
                      start_value: 1300
                      end_value: 1799
                  - arc: #RED
                      color: 0xF44336
                      width: 12
                      start_value: 1800
                      end_value: 2300

        - obj:
            # to cover the middle part of meter indicator line
            height: 118
            width: 118
            radius: 73
            align: CENTER
            border_width: 0
            bg_color: 0x000000
            pad_all: 0

        - label:
            id: co2_text
            text_font: roboto_medium
            align: center
            text_color: 0x999999
            bg_opa: TRANSP
            y: -35
            recolor: true
            text: "\U000F07E4"
        - label:
            id: co2value
            text_font: font_digital
            align: center
            text_color: 0xFFFFFF
            bg_opa: TRANSP
            y: +12
            text: "---"
        - label:
            id: ppm_text
            text_font: montserrat_24
            align: center
            text_color: 0x999999
            bg_opa: TRANSP
            y: +90
            text: "PPM"

    - id: page_1
      widgets:
        - obj:
            # to cover the middle part of meter indicator line
            height: 118
            width: 118
            radius: 73
            align: CENTER
            border_width: 0
            bg_color: 0x000000
            pad_all: 5
        - label:
            id: temperature
            text_font: montserrat_14
            align: top_left
            text_color: 0x0000FF
            bg_opa: TRANSP
            y: -60
            text: "---°C"
        - label:
            id: humidity
            text_font: montserrat_14
            align: top_right
            text_color: 0x0000FF
            bg_opa: TRANSP
            y: -60
            text: "---% RH"

  top_layer:
    widgets:
      - obj: # make sure it's the last one in this list:
          id: boot_screen
          x: 0
          y: 0
          width: 100%
          height: 100%
          bg_color: 0xffffff
          bg_opa: COVER
          radius: 0
          pad_all: 0
          border_width: 0
          widgets:
            - image:
                align: CENTER
                src: boot_logo
                y: -40
            - spinner:
                align: CENTER
                y: 95
                height: 50
                width: 50
                spin_time: 1s
                arc_length: 60deg
                arc_width: 8
                indicator:
                  arc_color: 0x18bcf2
                  arc_width: 8
          on_press:
            - lvgl.widget.hide: boot_screen

You forgot to post them.
And tell what Esp board you have.

Sorry. You’re completely right. My apologises.
Using an ESP32S2-mini

Compile error:

INFO ESPHome 2025.2.0
INFO Reading configuration /config/esphome/airmon2.yaml...
INFO Detected timezone 'Europe/Amsterdam'
INFO Generating C++ source...
INFO Compiling app...
Processing airmon2 (board: esp32-s2-saola-1; framework: arduino; platform: platformio/[email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32S2 240MHz, 320KB RAM, 4MB Flash
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5 
 - toolchain-xtensa-esp32s2 @ 8.4.0+2021r2-patch5
Dependency Graph
|-- AsyncTCP-esphome @ 2.1.4
|-- WiFi @ 2.0.0
|-- FS @ 2.0.0
|-- Update @ 2.0.0
|-- ESPAsyncWebServer-esphome @ 3.2.2
|-- ESPmDNS @ 2.0.0
|-- noise-c @ 0.1.6
|-- SPI @ 2.0.0
|-- Wire @ 2.0.0
|-- ArduinoJson @ 6.18.5
|-- lvgl @ 8.4.0
Compiling .pioenvs/airmon2/src/main.cpp.o
/config/esphome/airmon2.yaml:47:34: error: stray '#' in program
             lv_scr_load(main_page);  # Verwijst naar de object ID voor de hoofdpagina
                                  ^
/config/esphome/airmon2.yaml:49:31: error: stray '#' in program
             lv_scr_load(page_1);  # Verwijst naar de object ID voor de tweede pagina
                               ^
/config/esphome/airmon2.yaml: In lambda function:
/config/esphome/airmon2.yaml:47:21: error: cannot convert 'esphome::lvgl::LvPageType*' to 'lv_obj_t*' {aka '_lv_obj_t*'}
             lv_scr_load(main_page);  # Verwijst naar de object ID voor de hoofdpagina
                     ^~~~~~~~~
In file included from .piolibdeps/airmon2/lvgl/lvgl.h:39,
                 from src/esphome/components/lvgl/lvgl_proxy.h:13,
                 from src/esphome/components/image/image.h:6,
                 from src/esphome.h:37,
                 from src/main.cpp:3:
.piolibdeps/airmon2/lvgl/src/core/lv_disp.h:205:43: note:   initializing argument 1 of 'void lv_scr_load(lv_obj_t*)'
 static inline void lv_scr_load(lv_obj_t * scr)
                                ~~~~~~~~~~~^~~
/config/esphome/airmon2.yaml:47:36: error: 'Verwijst' was not declared in this scope
             lv_scr_load(main_page);  # Verwijst naar de object ID voor de hoofdpagina
                                    ^~~~~~~~
/config/esphome/airmon2.yaml:49:21: error: cannot convert 'esphome::lvgl::LvPageType*' to 'lv_obj_t*' {aka '_lv_obj_t*'}
             lv_scr_load(page_1);  # Verwijst naar de object ID voor de tweede pagina
                     ^~~~~~
In file included from .piolibdeps/airmon2/lvgl/lvgl.h:39,
                 from src/esphome/components/lvgl/lvgl_proxy.h:13,
                 from src/esphome/components/image/image.h:6,
                 from src/esphome.h:37,
                 from src/main.cpp:3:
.piolibdeps/airmon2/lvgl/src/core/lv_disp.h:205:43: note:   initializing argument 1 of 'void lv_scr_load(lv_obj_t*)'
 static inline void lv_scr_load(lv_obj_t * scr)
                                ~~~~~~~~~~~^~~
/config/esphome/airmon2.yaml:49:33: error: 'Verwijst' was not declared in this scope
             lv_scr_load(page_1);  # Verwijst naar de object ID voor de tweede pagina
                                 ^~~~~~~~
*** [.pioenvs/airmon2/src/main.cpp.o] Error 1

Lambda is C++, the hash symbol is used for comments for yaml, not C++. Use double slash, like:

            lv_scr_load(main_page);  // Verwijst naar de object ID voor de hoofdpagina
1 Like

thx, you’re right. I changed it:

binary_sensor:
  - platform: gpio
    pin: GPIO18 
    name: "Page Switch"
    id: page_switch
    on_press:
     - lambda: |-
          static bool is_main_page = true;
          is_main_page = !is_main_page;
          if (is_main_page) {
            lv_scr_load(main_page);  // Verwijst naar de object ID voor de hoofdpagina
          } else {
            lv_scr_load(page_1);  // Verwijst naar de object ID voor de tweede pagina
          }

the compiler fails:

Compiling .pioenvs/airmon2/src/main.cpp.o
/config/esphome/airmon2.yaml: In lambda function:
/config/esphome/airmon2.yaml:47:21: error: cannot convert 'esphome::lvgl::LvPageType*' to 'lv_obj_t*' {aka '_lv_obj_t*'}
             lv_scr_load(main_page);  // Verwijst naar de object ID voor de hoofdpagina
                     ^~~~~~~~~
In file included from .piolibdeps/airmon2/lvgl/lvgl.h:39,
                 from src/esphome/components/lvgl/lvgl_proxy.h:13,
                 from src/esphome/components/image/image.h:6,
                 from src/esphome.h:37,
                 from src/main.cpp:3:
.piolibdeps/airmon2/lvgl/src/core/lv_disp.h:205:43: note:   initializing argument 1 of 'void lv_scr_load(lv_obj_t*)'
 static inline void lv_scr_load(lv_obj_t * scr)
                                ~~~~~~~~~~~^~~
/config/esphome/airmon2.yaml:49:21: error: cannot convert 'esphome::lvgl::LvPageType*' to 'lv_obj_t*' {aka '_lv_obj_t*'}
             lv_scr_load(page_1);  // Verwijst naar de object ID voor de tweede pagina
                     ^~~~~~
In file included from .piolibdeps/airmon2/lvgl/lvgl.h:39,
                 from src/esphome/components/lvgl/lvgl_proxy.h:13,
                 from src/esphome/components/image/image.h:6,
                 from src/esphome.h:37,
                 from src/main.cpp:3:
.piolibdeps/airmon2/lvgl/src/core/lv_disp.h:205:43: note:   initializing argument 1 of 'void lv_scr_load(lv_obj_t*)'
 static inline void lv_scr_load(lv_obj_t * scr)
                                ~~~~~~~~~~~^~~
*** [.pioenvs/airmon2/src/main.cpp.o] Error 1

Not sure where you got the page switch code from…

Why not use the documented methods:

on_press:
  then:
    - if:
        condition:
          lvgl.page.is_showing: main_page
        then:
          - lvgl.page.show:
              id: page_1
        else:
          - lvgl.page.show:
              id: main_page

 

thx again for the reply. I did not use that while (as I understood) would only work with a touchscreen. meaning it had to be defined within lvgl…
What you just sent, worked as I expected and hoped (nice and simple).

I flag your reply as the solution :slight_smile:

(Got another issue now, since the sensor is not giving me any data anymore…but that’s for another day… goodnight from the Netherlands)

1 Like

This is sufficient:

on_press:
  lvgl.page.next:

Yep - know that - just didn’t want to assume he only had 2 pages :smiley:

Well, that’s what his yaml had :slight_smile:

1 Like

Ok - I’ll pay that… :laughing:

thx both.
I’m new to the LVGL and trying to learn (that’s the reason for starting with just 2 pages). So thx for the tips and explanations.

LVGL Graphics — ESPHome is why I thought/understood, it was not possible that way.