ESP32-2432S028R (Sunton 2.8" / CYD) Config

Just wanted to share a basic working config for this device (ESP32-2432S028R) :slight_smile:

Heads-up: I try to keep the configs in these posts updated but sometimes the configs in my repo are more up-to-date!

Here are the device-specific bits of the config separated out from everything else:

esp32:
  board: esp32dev
  framework:
    type: arduino

i2c:
  - sda: 27
    scl: 22
    scan: true

spi:
  - id: tft
    clk_pin: 14
    mosi_pin: 13
    miso_pin:
      number: 12
      ignore_strapping_warning: true
  - id: touch
    clk_pin: 25
    mosi_pin: 32
    miso_pin: 39

output:
  - id: backlight_pwm
    platform: ledc
    pin: 21
  - id: output_red
    platform: ledc
    pin: 4
    inverted: true
  - id: output_green
    platform: ledc
    pin: 16
    inverted: true
  - id: output_blue
    platform: ledc
    pin: 17
    inverted: true

light:
  - id: backlight
    platform: monochromatic
    output: backlight_pwm
    name: Display Backlight
    restore_mode: ALWAYS_ON
  - id: led
    platform: rgb
    red: output_red
    green: output_green
    blue: output_blue
    restore_mode: ALWAYS_OFF

# sensor:
#   - platform: adc
#     pin: 34
#     name: "Brightness"
#     update_interval: 60s

display:
  - id: main_display
    platform: ili9xxx
    model: ILI9341
    spi_id: tft
    cs_pin:
      number: 15
      ignore_strapping_warning: true
    dc_pin:
      number:  2
      ignore_strapping_warning: true
    invert_colors: false
    update_interval: never
    auto_clear_enabled: false

touchscreen:
  - id: main_touchscreen
    platform: xpt2046
    spi_id: touch
    cs_pin: 33
    interrupt_pin: 36
    threshold: 400
    calibration:
      x_min: 280
      x_max: 3860
      y_min: 340
      y_max: 3860
    transform:
      mirror_x: true
    # 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
    #         );

lvgl:
  buffer_size: 25%

I like to keep device-specific code like that its own file separate from everything else so that I can use the Packages component to import it into multiple relevant projects, rather than duplicate the whole thing into each one. In my case I save it into a file called templates/ESP32-2432S028R.yaml.

In the spirit of not duplicating code into multiple projects, I create another file that is not device-specific but is common/repetitive among all my projects. In my case I chose to call it templates/common.yaml and it has code like so:

esphome:
  name: "${device_name}"
  friendly_name: "${friendly_name}"

logger:
  level: INFO

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

web_server:
  port: 80

ota:
  - platform: esphome

api:

Finally, this is how I use both of the above files together in a project.:

substitutions:
  device_name: sunton-28-test-device
  friendly_name: Sunton 2.8 Test Device

packages:
  common: !include templates/common.yaml
  device: !include templates/ESP32-2432S028R.yaml
  # dashboard: !include templates/dashboard_320x240.yaml

#sensor: ...

Note: The contents of the dashboard package referenced above aren’t in this post but I have it in the example to illustrate the power of setting up a config this way. In my case templates/dashboard_320x240.yaml is a file that I’ve created with HA sensors and LVGL pages in it, and it can be reused on any of my devices that support the same resolution as this one.

If someone wants to help get this device listed on devices.esphome.io then be my guest! I was too lazy to dig into that but hopefully posting here is just as helpful.

Concerns / Potential Improvements

  • Touch gestures such as scrolling in LVGL don’t seem to work very well, but I haven’t spent any time figuring it out as basic touches and holds work fine.

Some things to consider before purchasing

  • There’s no PSRAM which might limit use of images.
  • The display has satisfactory viewing angles despite being a TN panel.
  • The resistive touch is surprisingly okay, but not great.
  • Micro-B Cables are very fragile and don’t provide a great connection, especially if ever bumped or bent.

More in my GitHub repo

1 Like

Does the calibration of the touchscreen change at all if I use the display rotated 270 degrees ? I was testing some code last night and put a rectangle on the screen and configured the touch part to the same coordinates, and the touch was only activated when I pressed a different part of the screen.

I’m wondering if the rotation means I need something like a

mirror_x: true

(I also cant get my head around why min x has a value larger than max x, or does that effectively do the mirror thing ?)

And a good idea to organise your command and device specific stuff like that.

I just did a quick test and added rotation: 270 to the display block and I can still tap everything in my UI without issues.

Since this has a resistive screen, the calibration values may differ per-device slightly, but I have a bunch and they all seem to be fine with the ones in the code above. It might be worth you trying this: Touchscreen Components — ESPHome

I’ll have to test again later.
Do you know why the minx and maxx seem the wrong way around ?

I got the link for the calibration from another thread and will see what that shows later.

I’ve honestly never looked at the touch values before to notice, sorry

So for calibration, I am assuming that in the orientation i have on the screen, top leftshould be x=0,y=0 and bottom right x=max and y=max.

Solved. If you rotate the display 90 or 270 you have to use more settings to keep the orientation and size of the display axis the same.

This is my display and touch screen settings for the display rotated 270 degrees, so thats landscape, with the usb ports to the left as you look at the screen.

Display section:-

  - platform: ili9xxx
    update_interval: 60s
    invert_colors: false
    id: esp_display
USB ports
    model: ILI9341
    spi_id: spi_tft
    cs_pin: GPIO15
    dc_pin: GPIO2
    transform:
      swap_xy: true
      mirror_x: true
      mirror_y: true
    dimensions:
      height: 240
      width: 320

You can use rotation: 270 instead of transform, but that does it in software, where transform does it in hardware. Its also vital to flip the display dimensions otherwise the long side is limited to 240 pixels.

And the touchscreen config looks like this:-

touchscreen:
  platform: xpt2046
  id: esp_touchscreen
  spi_id: spi_touch
  cs_pin: GPIO33
  interrupt_pin: GPIO36
  update_interval: 50ms
  threshold: 400
  calibration:
    x_min: 3860
    x_max: 360
    y_min: 280
    y_max: 3860

  transform:
    swap_xy: true
    mirror_y: true

So I now have working coordinates, with top left as x-0,y=0 and bottom right as x=320,y=240.

Interesting - so just rotation: 270 works but you’re saying it’s less efficient as it’s done in software rather than hardware? What is the benefit of doing it in hardware? I assume it’s more efficient but is it something that I can notice easily?

I stumbled over it on this page:-

There is a section part way down with a note that says this:-

Note

The rotation variable will do a software based rotation. It is better to use the transform option to rotate the display in hardware. Use one of the following combinations: - 90 degrees - use swap_xy with mirror_x - 180 degrees - use mirror_x with mirror_y - 270 degrees - use swap_xy with mirror_y

With 90 and 270 rotations you will also need to swap the height and width in dimensions (see example below.

The text is slightly wrong, because at 270 you need mirror_x as well.

Not necessarily - it varies from display to display, so that may be true with your display but is not true in general.

Some of the display models in the ili9xxx driver have a default mirror setting because of the way the LCD is wired to the driver chip. If you override the default with transform then for those displays you will need a “non-standard” configuration of swap/mirror, which is likely the case with your display.

Good to know. I also noticed I needed mirror_x for the display not to be flipped, but I didnt need to do that with the touchscreen config. Weird.

Yes, some of the boards don’t natively configure the touchscreen with the same geometry as the display they’re attached to. That’s why the touchscreen doesn’t automatically copy the display transform.

So, after I got my device working when rotated 270, I decided that I actually wanted it rotated 90. The display settings were simple, but the touch screen not so much.

My current settings are:-

swap_xy: true
mirror_y: false
mirror_x: (see below)

swap xy correctly changes the orientation, all good here.

Now that the axis are swapped, the mirror commands are also swapped, and I found that:-

mirror_y: corrects the x axis so x it is increasing from left to right

However, irrespective of whether or not I put true or false for mirror_x:, y never never changes. Y is always high top left.

@RyanEwen - As you were so helpful last time, any thoughts ?

My full touch screen config is below:-

touchscreen:
  platform: xpt2046
  id: esp_touchscreen
  spi_id: spi_touch
  cs_pin: GPIO33
  interrupt_pin: GPIO36
  update_interval: 50ms
  threshold: 400
  calibration:
    x_min: 3860
    x_max: 280 
    y_min: 340
    y_max: 3860

  transform:
   swap_xy: true
   mirror_x: true
   mirror_y: false

  on_touch: #left on for debugging.
    - lambda: |-
        ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%d", touch.x, touch.y, touch.x_raw, touch.y_raw);

I wonder if the above has anything to do with it.

I haven’t made the move from rotation to transform so I’m not of much help here. rotation just works for me but when I have time to play around I might try switching over and see if I can help

At a guess, I suspect you need to switch the calibration values to reflect the transformations.

Personally I would never choose a board with a resistive touchscreen. There’s a reason they often ship them with a stylus :slight_smile:

The raw calibration values dont change when you set various parameters like swap_xy and mirrors, so I don’t think its that. I’m only using the CYD as a test, a better device is on its way :wink:

Seems its a bug in esphome… I just stumbled over this thread which is exactly the issue I am facing:-

1 Like

I think I just ran into a similar issue with this device: DIS05035H (Elecrow CrowPanel 3.5") Config

By-default that device is in landscape with the USB port on the right, and touch seems to be rotated -90 degrees from the display (top left came through at bottom left, middle left came through at bottom center, bottom left came through at bottom right). Setting rotation: 90 rotates the display so that it’s in portrait with the USB port at the bottom and touch, but touch is still -90 from the display.

Rather than use rotation I tried using transform, but it wasn’t quite what the docs said it would be. To rotate 90 degrees using transform on that particular device, I had to swap the dimensions and only set mirror_x: true (docs say to also use swap_xy). To get the touch to match, I had to swap the mins and maxes.

That would indicate that the init sequence already included axis swapping, which you have now overwritten with an explicit transform. It also sounds like the display has the x-axis drivers in reverse order, i.e. the hardware has a built-in x-mirror. This is the kind of stuff that makes experimentation necessary much of the time.

1 Like