Trying to use a Adafruit Feather ESP32 V2 and 3.5" 480x320 TFT FeatherWing V2

Hi!

I’ve been trying this for weeks now (on the weekends, I do have a day job :slight_smile: ) and can’t seem to get anywhere.

I have a number of Feather ESP32 V2s running various ESPhome tasks strewn about the house. So, I know that they work well with ESPhome.

I’d love to use the FeatherWing TFT as a display/control interface for Home Assistant.

I believe this should work, as the HX8357 chipset is supported by ESPhome’s display module, no?

This is what I’ve come up with through furious googling and experimentation:

esphome:
  name: featherwingtft
  friendly_name: FeatherWingTFT

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "..."

ota:
  - platform: esphome
    password: "..."

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Featherwingtft Fallback Hotspot"
    password: "6hRYLr7djERW"

captive_portal:

psram:

spi:
  clk_pin: GPIO05
  mosi_pin: GPIO19
  miso_pin: GPIO21

time:
  - platform: homeassistant
    timezone: UTC-01:00    # Change your timezone here
    id: esptime 

font:
  - file:
      type: gfonts
      family: Lato
      weight: 400
    id: lato
    size: 20
  - file:
      type: gfonts
      family: Lato
      weight: 900
    id: latoblack
    size: 30
  - file:
      type: gfonts
      family: Lato
      weight: 900
    id: latoblackheading1
    size: 50

color:
  - id: RED
    red: 100%
    green: 0%
    blue: 0%
  - id: GREEN
    red: 0%
    green: 100%
    blue: 0%
  - id: BLUE
    red: 0%
    green: 0%
    blue: 100%
  - id: YELLOW
    red: 100%
    green: 100%
    blue: 0%
  - id: WHITE
    red: 100%
    green: 100%
    blue: 100%
  - id: ORANGE
    red: 100%
    green: 67%
    blue: 20%

display:
  - platform: ili9xxx
    model: ili9341
    dc_pin: GPIO10
#    reset_pin: GPIO00
    invert_colors: false
    update_interval: 1s
    id: my_display
    pages:                # Define the pages
      - id: showtime
        lambda: |-
          it.strftime(45, 20, id(latoblack), "%d-%m-%Y", id(esptime).now());
          it.strftime(25, 55, id(latoblackheading1), "%H:%M:%S", id(esptime).now());

The output is:

[17:29:11][I][logger:171]: Log initialized
[17:29:11][C][safe_mode:079]: There have been 8 suspected unsuccessful boot attempts
[17:29:11][D][esp32.preferences:114]: Saving 1 preferences to flash...
[17:29:11][D][esp32.preferences:143]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[17:29:11][I][app:029]: Running through setup()...
[17:29:11][D][spi:039]: Setting up SPI bus...
[17:29:11][D][ili9xxx:034]: Setting up ILI9xxx
[17:29:11][D][spi_device:381]: mode 0, data_rate 40000kHz
[17:29:12][D][ili9xxx:030]: Wrote MADCTL 0x48
[17:29:12][C][wifi:048]: Setting up WiFi...
[17:29:12][C][wifi:061]: Starting WiFi...
[17:29:12][C][wifi:062]:   Local MAC: E8:9F:6D:30:E2:84
[17:29:12][D][wifi:482]: Starting scan...
[17:29:12]Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
[17:29:12]
[17:29:12]Core  1 register dump:
[17:29:12]PC      : 0x40092db5  PS      : 0x00060930  A0      : 0x80093642  A1      : 0x3ffb2490  
[17:29:12]A2      : 0xbbbbbbbb  A3      : 0xffffffff  A4      : 0x00000000  A5      : 0x00000001  
[17:29:12]A6      : 0x00060320  A7      : 0x00000001  A8      : 0x00000006  A9      : 0x0000000b  
[17:29:12]A10     : 0xbbbbbbf7  A11     : 0x0002580c  A12     : 0x0000000e  A13     : 0x3ffcedbc  
[17:29:12]A14     : 0x007ba744  A15     : 0x003fffff  SAR     : 0x0000000c  EXCCAUSE: 0x0000001c  
[17:29:12]EXCVADDR: 0xbbbbbbfb  LBEG    : 0x40085985  LEND    : 0x4008598d  LCOUNT  : 0x00000027  
[17:29:12]
[17:29:12]
[17:29:12]Backtrace:0x40092db2:0x3ffb24900x4009363f:0x3ffb24b0 0x400938c0:0x3ffb24d0 0x40083e0a:0x3ffb24f0 0x40083e1d:0x3ffb2520 0x400d8341:0x3ffb2540 0x400d9de0:0x3ffb2560 0x400d9e0f:0x3ffb2580 0x400d9f45:0x3ffb25a0 0x400d7d2a:0x3ffb25c0 0x400d81f1:0x3ffb25e0 0x400da455:0x3ffb2600 0x40172e5d:0x3ffb2620 0x400e1f23:0x3ffb2640 0x400e0df2:0x3ffb2690 0x400e2a46:0x3ffb26c0 0x400eebc6:0x3ffb2820 
[17:29:12]
[17:29:12]
[17:29:12]
[17:29:12]
[17:29:12]ELF file SHA256: 0000000000000000
[17:29:12]
[17:29:12]Rebooting...
[17:29:12]ets Jul 29 2019 12:21:46
[17:29:12]
[17:29:12]rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
[17:29:12]configsip: 271414342, SPIWP:0xee
[17:29:12]clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
[17:29:12]mode:DIO, clock div:2
[17:29:12]load:0x3fff0030,len:1184
[17:29:12]load:0x40078000,len:13132
[17:29:12]load:0x40080400,len:3036
[17:29:12]entry 0x400805e4

Am I doing something wrong?

Best regards,
Andrew

Doesn’t even have Gpio10 pin.
And it’s internally connected to flash memory, so it would cause problems.

Also, you could use
board = adafruit_feather_esp32_v2
so you get correct flash memory etc.

Hello Karosm,

Thanks for the pointer… I got the DC GPIO from the TFT’s Pinout:

  • DC - This is the display SPI data/command selector pin. By default, it is connected to pin 10. To change this, cut the jumper. Then, connect the signal pad (closest to the label on the board silk) to one of the available and compatible GPIO pads.

https://learn.adafruit.com/adafruit-3-5-tft-featherwing/pinouts-v2

Not sure where that lands when the Feather ESP32 V2 is connected. Not sure if I’m being dense or if it is just poorly described.

I’m away for the next few weeks, so I won’t be able to follow-up on this until then. I will update if I figure anything out.

Thanks again!

Adafruit writes:
On the ESP32 , TFT_CS is pin #15, TFT_DC is pin #33
I would inspect visually though…

Hi!

Finally had a chance to revisit this…

If I use this in my yaml file:

esphome:
  name: featherwingtft
  friendly_name: FeatherWingTFT

esp32:
  board: adafruit_feather_esp32_v2
  framework:
    type: arduino

logger:

api:

ota:
  - platform: esphome

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

ap:
    ssid: "Featherwingtft Fallback Hotspot"
    password: "6hRYLr7djERW"

captive_portal:

psram:

spi:
  clk_pin: GPIO05
  mosi_pin: GPIO19
  miso_pin: GPIO21

display:
  - platform: ili9xxx
    model: ili9341
    dc_pin: GPIO33
    cs_pin: GPIO15
#    reset_pin: GPIO00
    invert_colors: false
    update_interval: 1s
    id: my_display
    pages:                # Define the pages
      - id: showtime
        lambda: |-
          it.strftime(45, 20, id(latoblack), "%d-%m-%Y", id(esptime).now());
          it.strftime(25, 55, id(latoblackheading1), "%H:%M:%S", id(esptime).now());

The log shows:

[09:46:26][C][ili9xxx:091]: ili9xxx
[09:46:26][C][ili9xxx:091]: Rotations: 0 °
[09:46:26][C][ili9xxx:091]: Dimensions: 240px x 320px
[09:46:26][C][ili9xxx:092]: Width Offset: 0
[09:46:26][C][ili9xxx:093]: Height Offset: 0
[09:46:26][C][ili9xxx:099]: Color mode: 16bit
[09:46:26][C][ili9xxx:108]: Data rate: 40MHz
[09:46:26][C][ili9xxx:111]: CS Pin: GPIO15
[09:46:26][C][ili9xxx:112]: DC Pin: GPIO33
[09:46:26][C][ili9xxx:114]: Color order: BGR
[09:46:26][C][ili9xxx:115]: Swap_xy: NO
[09:46:26][C][ili9xxx:116]: Mirror_x: YES
[09:46:26][C][ili9xxx:117]: Mirror_y: NO
[09:46:26][C][ili9xxx:118]: Invert colors: NO
[09:46:26][C][ili9xxx:123]: Update Interval: 1.0s

(Previously, I saw error messages regarding the display here…)

Followed by endless messages reading

[09:46:27][W][component:239]: Component display took a long time for an operation (65 ms).
[09:46:27][W][component:240]: Components should block for at most 30 ms.

The screen is blank showing a just a white background.

I feel like I’m getting closer, but don’t know what to try next. Any additional help would be greatly appreciated.

Thanks!

Best regards,
Andrew

Your log doesn’t mention showtime, I would try without pages.
Actually, just add this to your display:
show_test_card: true

Hi!

I replaced pages with the test card:

display:
  - platform: ili9xxx
    model: ili9341
    dc_pin: GPIO33
    cs_pin: GPIO15
#    reset_pin: GPIO00
    invert_colors: false
    update_interval: 1s
    id: my_display
    show_test_card: true
#    pages:                # Define the pages
#      - id: showtime
#        lambda: |-
#          it.strftime(45, 20, id(latoblack), "%d-%m-%Y", id(esptime).now());
#          it.strftime(25, 55, id(latoblackheading1), "%H:%M:%S", id(esptime).now());

Now the error messages are gone, but the screen is still just showing a blank white background…

I had a look at the documentation, but it’s little bit confusing.
So you have both Esp board V2 and Wing V2, right?


So your pins are correct.
Driver is HX8357-D, so try with other models like 9481, 9488 …
Play with display options and try some different SPI data rate as well.

Hello!

Ok, thanks a million! Yes, I am using the ESP32 V2 and the Wing V2…

I started going through the models listed here:
https://esphome.io/components/display/ili9xxx.html

And it turned out that this model works:

ILI9481

I saw the test card… When I switch back to the pages:

    pages:                # Define the pages
      - id: showtime
        lambda: |-
          it.strftime(45, 20, id(latoblack), "%d-%m-%Y", id(esptime).now());
          it.strftime(25, 55, id(latoblackheading1), "%H:%M:%S", id(esptime).now());

I see the date and time displayed on the screen, but the constant…

[19:01:44][W][component:239]: Component display took a long time for an operation (117 ms).
[19:01:44][W][component:240]: Components should block for at most 30 ms.

… are back. Not sure if that is something I should worry about.

Nice!

Not really, it’s very common warning, and your time is not ridiculous long.
Maybe because of esptime.
What if you just print static “hello word” without pages?

    lambda: |-
      // Print the string "Hello World!" at [0,10]
      it.print(0, 10, id(latoblack), "Hello World!");

I tried that… This was the result (basically the same):

[19:41:23][W][component:239]: Component display took a long time for an operation (109 ms).
[19:41:23][W][component:240]: Components should block for at most 30 ms.

… I’ll just ignore it.

Thanks!

Last thing: … any idea if it is possible to adjust the display’s brightness (or turn it off and on)? I tried using:

light:
  - platform: monochromatic
    name: "OLED Display"
    output: awtd_output
    id: oled
    on_turn_on:
      then: 
      - display.page.show: page1  
      - component.update: display1
    on_turn_off:
      then:
      - display.page.show: page2   # a empty page....
      - component.update: display1

output:
  - platform: template
    id: awtd_output
    type: float
    write_action:
      then:
      - lambda: id(display1).set_contrast(state);

… but I gather that only works for OLED displays.

… I need to pull this pad low:

  • LITE - This is the TFT backlight pad, located between the Feather headers and the TFT ribbon cable towards the top of the board. It is not connected to any pins by default. Pull this pin low to turn off the backlight.

Or control it with LEDC output.

Ok. Yes, thanks. Using (e.g.) PIN 14 on the ESP32 Feather V2 connected to the “LITE” pad (some quick soldering required) allows driving the display’s brightness.

For anyone else looking for this solution, here’s the basic code I came up with so far:

esphome:
  name: featherwingtft
  friendly_name: FeatherWingTFT

esp32:
  board: adafruit_feather_esp32_v2
  framework:
    type: arduino

ota:
  - platform: esphome

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

  ap:
    ssid: "Featherwingtft Fallback Hotspot"
    password: "6hRYLr7djERW"

api:
web_server:
captive_portal:
psram:
logger:

spi:
  clk_pin: GPIO05
  mosi_pin: GPIO19
  miso_pin: GPIO21

i2c:
  sda: GPIO22
  scl: GPIO20
  scan: true
  frequency: 400kHz

time:
  - platform: homeassistant
    timezone: UTC-02:00    # Change your timezone here
    id: esptime 

font:
  - file:
      type: gfonts
      family: Lato
      weight: 400
    id: lato
    size: 20
  - file:
      type: gfonts
      family: Lato
      weight: 900
    id: latoblack
    size: 30
  - file:
      type: gfonts
      family: Lato
      weight: 900
    id: latoblackheading1
    size: 50

color:
  - id: RED
    red: 100%
    green: 0%
    blue: 0%
  - id: GREEN
    red: 0%
    green: 100%
    blue: 0%
  - id: BLUE
    red: 0%
    green: 0%
    blue: 100%
  - id: YELLOW
    red: 100%
    green: 100%
    blue: 0%
  - id: WHITE
    red: 100%
    green: 100%
    blue: 100%
  - id: ORANGE
    red: 100%
    green: 67%
    blue: 20%

output:
  - platform: ledc
    pin: GPIO14
    id: gpio_14

number:
  - platform: template
    name: pwm_change
    optimistic: true
    initial_value: 200000
    min_value: 100000
    max_value: 200000
    step: 500
    mode: slider
    on_value:
      - output.ledc.set_frequency:
          id: gpio_14
          frequency: !lambda |-
            return x;

light:
  - platform: monochromatic
    output: gpio_14
    name: "FeatherWingBrightness"

# TSC2007 touchscreen configuration
external_components:
  source:
    type: git
    url: http://github.com/rgregg/esphome-components/
  components: tsc2007

touchscreen:
  - platform: tsc2007
    id: my_touchscreen
    display: my_display
    address: 0x48
    calibration:
      x_min: 366  
      x_max: 3649
      y_min: 208
      y_max: 3808
    transform:
      mirror_x: false
      mirror_y: true
      swap_xy: 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
              );    
    on_release:
      then:
        - logger.log: "Touch Released"

binary_sensor:
  - platform: touchscreen
    name: Top Left Touch Button
    x_min: 0
    x_max: 150
    y_min: 25
    y_max: 75
 #   page_id: page
    use_raw: false

display:
  - platform: ili9xxx
    model: ILI9481
    dc_pin: GPIO33
    cs_pin: GPIO15
    invert_colors: false
    update_interval: 1s
    id: my_display
    pages:
      - id: showtime
        lambda: |-
          it.strftime(45, 20, id(latoblack),  "%Y-%m-%d", id(esptime).now());
          it.strftime(25, 55, id(latoblackheading1), "%H:%M:%S", id(esptime).now());

This includes use of the touchscreen. I think all the building blocks are in place for making an interface for displaying information and/or controlling items (lights, shades, etc.).

Thanks again for all your help!

Best regards,
Andrew

How is the frequency change between 100kHz and 200kHz effecting the backlight?

I couldn’t figure that out exactly. The example code I found for controlling the display brightness used different values. I played around until I found something that seemed to work… The slider in HA turns the light off at 10% … at 11% it is very dim and goes up to full brightness at 100%.

I didn’t ask about light brightness. I mean that template number for frequency…

Sorry, … I thought the template number controls the brightness… that’s why I rambled on about it.

Different frequency doesn’t change brightness, different duty cycle does.
I wouldn’t offer solution for others if you don’t know what your code does…