ESP32-C3 with integrated GC9A01 - cheap touch controller

Cool. I actually would like to try to get this thing working under esphome using the esp-idf framework (instead of arduino) at some point in time as it’s more memory efficient so might leave more room to enable things like esp32_ble_tracker to work without causing the thing to randomly reboot due to low memory. As I have one now in pretty much every room it would be handy to have for presence tracking. Sadly I haven’t been able to get it to work without errors, albeit I will admit I didn’t spend a lot of time on it.

Hi, this configuration works for running lvgl. Does anyone know how to move between screens using lvgl?

# Display configuration
display:
  - platform: ili9xxx
    model: GC9A01A
    id: watchface
    reset_pin: $repin
    cs_pin: $cspin
    dc_pin:
      number: $dcpin
      ignore_strapping_warning: true
    invert_colors: True 
    auto_clear_enabled: False

# Touchscreen configuration
touchscreen:
  - platform: cst816
    id: my_touch_screen
    i2c_id: i2c_touch

# LVGL Configuration
lvgl:
  displays:
    - watchface
  touchscreens:
    - my_touch_screen
  pages:
    - id: main_page
      widgets:
        - label:
            align: CENTER
            text: 'Hello World!'
        - button:
            id: hello_button
            align: CENTER
            on_click:
              - lambda: |-
                  ESP_LOGI("Button", "Hola");
    - id: second_page
      widgets:
        - label:
            align: CENTER
            text: 'Esta es la Segunda Página'

# Gesture handling with touch events

text_sensor:


  - platform: CST816S_touchscreen
    id: my_touch_screenx
    on_value:
      then:
        - script.execute: screentime

Switching screens is in my example. Don’t use the whole YAML though as I need to share the updated version that works with newer ESPhome LVGL versions.

Put this at the bottom of your touchscreen section:

  on_touch:
    then:
      lvgl.page.next:

thank you!!!

As far as I can see, this thread is not only discussing one specific device but also anything similar :slight_smile: So, I’ll add my two cents.

Recently, for my DIY project, I purchased a round display with a rotary encoder based on the ESP32C3.

I liked it very much. The build and material quality are very high. It looks great, and the knob has satisfying tactile feedback. The display is bright with wide viewing angles. While this product does not have a touch screen, for such a compact size, it is not necessary, as the encoder knob is sufficient.

This display is available on AliExpress for about $20. It is based on the ESP32C3 chip and features a round IPS display with a 240x240 resolution, a GC9A01A display driver with LVGL support, PWM-controllable backlight, and an aluminum rotary encoder knob around the display with a push-button function. As far as I can tell, it uses a similar screen and display driver to the M5Dial, but with fewer peripheral components. However, it’s almost twice as cheap, has a more minimalist design, and can be used in projects where the M5Dial is not suitable due to its overly colorful and flashy appearance.

I created two templates for connecting it to ESPHome. The first template is basic, while the second one enables LVGL support.

I created a separate thread for this device, where you’ll find ready-made templates, a brief overview, and resource links:

Here’s a video with ESPHome & LVGL:

Link to the manufacturer’s store:

https://www.aliexpress.com/item/1005007045539218.html

2 Likes

Heh, thanks, I’ve bought the same one and I thought mine was bricked as well :smiley:

also, can I ask a stupid question? I’m now on this forum, is this your latest sample code version?

or rather this?

Both should be fine - I’ve tried to keep them updated. I have however just updated the code from one of my wall controllers. There was a minor breaking change that I just needed to allow for. :slight_smile:

I absolutely love this forum and its amazing community—almost as much as Home Assistant itself!

In just two hours, with no prior experience, I managed to display a sensor reading on one of these screens, all thanks to the incredible insights shared in this thread. I’m deeply grateful for the time, effort, and trial-and-error experiences documented here.

This achievement has solved a unique challenge in our household. We have a 4-year-old with diabetes who wears a CGM sensor, providing blood glucose readings every five minutes. While I had already integrated the sensor into Home Assistant, I struggled to find an effective way to display the data outside of using a phone. As parents of two small children, minimizing screen time—especially on phones—is a priority when they’re awake.

Thanks to this solution, I can now place an intuitive screen anywhere in the house, allowing us to monitor our child’s glucose levels without reaching for a phone. This small but powerful change will have a significant impact on our daily lives.

A heartfelt thank you to @zagnuts for your incredible contributions, and to everyone else who has helped build this thread. Your efforts are deeply appreciated!

2 Likes

I’m sure I’m speaking for everyone here that you are more than welcome, @lei-joh5959, and as a parent of three I am really chuffed that you’ve found such a novel use for the screen!

As a diabetic, I found it a great use! I have a screen which shows me similar stuff, but it could be repurposed and use this little device. Ill have to see if my old eyes can focus on the little screen at 2.30 am.

EDIT: @styphonthal Don’t suppose you’ve got the config for this one? I’ve tried updating the pins but the screen doesn’t come alive after flashing. Thanks

Ignore me I’ve since got it working, for anyone else with a ESP32-S3-Touch-LCD-1.28

ESP32-S3-Touch-LCD-1.28

esphome:
  name: esp32s3touchlcd128
  friendly_name: ESP32-S3-Touch-LCD-1.28
  platformio_options:
    board_build.flash_mode: dio

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  framework:
    type: arduino
  flash_size: 16MB

# Enable logging
logger:
  level: DEBUG

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

psram:
  mode: quad
  speed: 80MHz

external_components:
  - source: github://GadgetFactory/[email protected]
    
spi:
  clk_pin: GPIO10
  mosi_pin: GPIO11
  # interface: hardware

output:
  - platform: ledc
    pin:
      number: GPIO02
    id: backlight_output

light:
  - platform: monochromatic
    output: backlight_output
    name: LCD Backlight
    id: led
    restore_mode: ALWAYS_ON
    default_transition_length: 0s

display:
  - platform: ili9xxx
    model: GC9A01A
    id: lcd_display
    invert_colors: true
    data_rate: 80MHz
    cs_pin: GPIO09
    dc_pin: GPIO08
    reset_pin: GPIO14
    auto_clear_enabled: False

i2c:
  sda: GPIO06
  scl: GPIO07

touchscreen:
  platform: cst816
  id: my_touchscreen
  interrupt_pin: GPIO05
  reset_pin: GPIO13
  on_touch:
    then:
      lvgl.page.next:

lvgl:
  displays:
    - lcd_display
  touchscreens:
    - my_touchscreen
  pages:
    - id: display_1
      widgets:
        - label:
            align: CENTER
            text: 'Hello Beautiful!'
        - button:
            id: hello_button
            align: BOTTOM_MID
            on_click:
              - lambda: |-
                  ESP_LOGI("Button", "Hola");
    - id: display_2
      widgets:
        - label:
            align: CENTER
            text: 'This is another page'
    - id: meter_page
      widgets:
        - meter:
            align: CENTER
            height: 180
            width: 180
            scales:
              - range_from: -100 # scale for the needle value
                range_to: 400
                angle_range: 240
                rotation: 150
                indicators:
                  - line:
                      id: temperature_needle
                      width: 2
                      color: 0xFF0000
                      r_mod: -4
                  - tick_style:
                      start_value: -10
                      end_value: 40
                      color_start: 0x0000bd
                      color_end: 0xbd0000
                      width: 1
              - range_from: -10 # scale for the value labels
                range_to: 40
                angle_range: 240
                rotation: 150
                ticks:
                  width: 1
                  count: 51
                  length: 10
                  color: 0x000000
                  major:
                    stride: 5
                    width: 2
                    length: 10
                    color: 0x404040
                    label_gap: 10
            widgets:
              - label:
                  id: temperature_text
                  text: "-.-°C"
                  align: CENTER
                  y: 45
              - label:
                  text: "Outdoor"
                  align: CENTER
                  y: 65