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.

Hi, curious if you got any further. Thinking about getting one of these as wel…

Hi,

there are some esphome example configs in the official elecrow GitHub repo: