Crowpanel 1-28inch ESP32 rotary display with ESPHome

Has anyone managed to get one of these working with ESPHome? I bought one but I am struggling to get it to work. I can load the code but unable to get the display to work.

Your display GC9A01 and touch CST816D are both supported, so should be doable.

Also, have a look here:

1 Like

If someone has gotten this to work please post your code. I can get it to compile and upload but it would never fully boot if I remember correctly.

Hey, I got it to work finally. See the code below. still needs a bit of work but right now this is a basic clock that is displaying the correct time pulled from HA.

esphome:
  name: elecrowrotary128-inch
  platformio_options:
    build_flags: "-DBOARD_HAS_PSRAM"
    board_build.esp-idf.memory_type: qio_opi
    board_build.flash_mode: dio
  friendly_name: Rotary1.28-inch
  on_boot:
    priority: 800
    then:
      - logger.log: "Backlight ON"
      - output.turn_on: gpio_3_backlight_pwm
      - delay: 200ms
      - output.turn_off: power_light
      - output.turn_on: out1
      - output.turn_on: out2

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf
    version: recommended

# Enable logging
logger:
  level: VERY_VERBOSE

# Enable Home Assistant API
api:
  encryption:
    key: !secret encryption_key

ota:
  - platform: esphome
    password: !secret ota_key

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${friendly_name} Hotspot"
    password: "6T3RFWEF71"

psram:
  mode: octal
  speed: 80MHz 

time:
  - platform: homeassistant
    timezone: "Australia/Melbourne"
    id: esptime
    on_time_sync:
      - script.execute: time_update
    on_time:
      - minutes: '*'
        seconds: 0
        then:
          - script.execute: time_update

output:
  - platform: ledc
    pin: GPIO46
    id: gpio_3_backlight_pwm
  - platform: gpio
    id: power_light
    pin: GPIO40
    # inverted: true
  - platform: gpio
    id: out4
    pin: GPIO4
  - platform: gpio
    id: out12
    pin: GPIO12
  - platform: gpio
    id: out1
    pin: GPIO1
  - platform: gpio
    id: out2
    pin: GPIO2

light:
  - platform: monochromatic
    name: "Backlight"
    output: gpio_3_backlight_pwm
    id: back_light
    restore_mode: ALWAYS_ON

sensor:
  - platform: rotary_encoder
    id: knob
    name: "Encoder"
    pin_a:
      number: 45
      mode:
        input: true
        pullup: true
    pin_b:
      number: 42
      mode:
        input: true
        pullup: true
    resolution: 1
    min_value: -100000
    max_value:  100000

binary_sensor:
  - platform: touchscreen
    id: change_page # Name is not needed, ID is sufficient
    # This zone now covers the entire 240x240 screen
    x_min: 0
    y_min: 0
    x_max: 240
    y_max: 240
    on_press:
      - script.execute: screentime
  - platform: gpio
    pin: 41
    id: rotary_button

script:
  - id: screentime
    mode: restart
    then:
      - light.turn_on: back_light
      - delay: 1 min
      - light.turn_off: back_light
  - id: dim_screen
    then:
      - light.turn_on:
          id: back_light
          brightness: 30%
      - logger.log: "script: dim to 30%"
  - id: bright_screen
    then:
      - light.turn_on:
          id: back_light
          brightness: 100%
      - logger.log: "script: brightness to full"
  - id: time_update
    then:
      - lvgl.indicator.update:
          id: minute_hand
          value: !lambda |-
            return id(esptime).now().minute;
      - lvgl.indicator.update:
          id: hour_hand
          value: !lambda |-
            auto now = id(esptime).now();
            return std::fmod(now.hour, 12) * 60 + now.minute;
      - lvgl.label.update:
          id: date_label
          text: !lambda |-
            static const char * const mon_names[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
            static char date_buf[8];
            auto now = id(esptime).now();
            snprintf(date_buf, sizeof(date_buf), "%s %2d", mon_names[now.month-1], now.day_of_month);
            return date_buf;
      - lvgl.label.update:
          id: day_label
          text: !lambda |-
            static const char * const day_names[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
            return day_names[id(esptime).now().day_of_week - 1];

i2c:
  - id: i2c_touch
    setup_priority: 400
    sda: 6
    scl: 7
    scan: true
    frequency: 400kHz
  

touchscreen:
  platform: cst816
  id: touch
  address: 0x15
  interrupt_pin: 5
  reset_pin: 13
  i2c_id: i2c_touch
  transform:
    mirror_x: false
    mirror_y: true
    swap_xy: true


spi:
  id: spi_bus
  mosi_pin: 11
  clk_pin: 10

font:
  - file: "gfonts://Roboto"
    id: roboto16
    size: 16

display:
  - platform: ili9xxx
    id: round_display
    model: GC9A01A
    cs_pin: GPIO9
    dc_pin: GPIO3
    reset_pin: GPIO14
    invert_colors: true
    show_test_card: true 
    rotation: 0

      
#external_components:
#  - source: 
#      type: local
#      path: components
#    components: [gc9a01a_display]
lvgl:
  displays:
    - round_display
  default_font: roboto16
  disp_bg_color: black

  touchscreens:
    touchscreen_id: touch

  style_definitions:
    - id: date_style    
      text_font: unscii_8
      align: center
      text_color: 0x000000
      bg_opa: cover
      radius: 4
      pad_all: 2

  pages:
    - id: clock_page
      widgets:
        - obj: # clock container
            height: 240
            width: 240
            align: CENTER
            pad_all: 0
            border_width: 0
            bg_color: 0x000000 # black
            widgets:
              - meter: # clock face
                  height: 240
                  width: 240
                  align: CENTER
                  bg_opa: TRANSP
                  border_width: 0
                  text_color: 0xFFFFFF # white
                  scales:
                    - range_from: 0 # minutes scale
                      range_to: 60
                      angle_range: 360
                      rotation: 270
                      ticks:
                        width: 1
                        count: 61
                        length: 10
                        color: 0xFFFFFF # white
                      indicators:
                        - line:
                            id: minute_hand
                            width: 3
                            color: 0xFF0000 # Red
                            r_mod: -4
                            value: 0
                    - range_from: 1 # hours scale for labels
                      range_to: 12
                      angle_range: 330
                      rotation: 300
                      ticks:
                        width: 1
                        count: 12
                        length: 1
                        major:
                          stride: 1
                          width: 4
                          length: 10
                          color: 0xC0C0C0 # silver
                          label_gap: 12
                    - range_from: 0 # hi-res hours scale for hand
                      range_to: 720
                      angle_range: 360
                      rotation: 270
                      ticks:
                        count: 0
                      indicators:
                        - line:
                            id: hour_hand
                            width: 5
                            color: 0xFF0000 # Red
                            r_mod: -30
                            value: 0
              - label:
                  styles: date_style
                  id: day_label
                  y: -30
              - label:
                  id: date_label
                  styles: date_style
                  y: 30


captive_portal:

I’ll post back here as I get more of the functions to work.

Note for me the thing that got it working was holding down the boot button on the back while powering on. Before that I was having issues with boot loops.

1 Like

Where you able to upload using web.esphome.io interface? There instruction show using Arduino and I’ve not been able to connect using the ESP home web tool.