Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Lilygo T5-4.7 inch ESP32-S3 (aka "plus"/V2.3) e-paper module #1960

Open
nickolay opened this issue Nov 15, 2022 · 41 comments
Open

Comments

@nickolay
Copy link

There's #1109 open for the original T5-4.7 module. This year the vendor introduced a new version of the module, which they call "T5 4.7 Inch E-paper V2.3" or "T5-4.7 Plus".

The vendor advertises the new ESP32-S3 chip and TF-card reader as the major new features, but there are multiple other differences as well. The pinout is incompatible, so any attempts to blindly run examples from #1109 on the new board without first figuring out the differences will fail.

I'll copy the description from the original feature request verbatim, as only the internals of the board are different; the use-case is the same:

Describe the problem you have/What new integration you would like
The Lyligo T5-4.7inch is a great e-paper module based on an ESP32. It has a resolution of 960*540, 16 gray level and support partial refresh. I would be great to have it integrated in ESPHome the same / similar way Waveshare e-paper screens and modules are.

Please describe your use case for this integration and alternatives you've tried:
To date there is no support for this module in ESPHome. The only support given by the maker is through Arduino IDE

Additional context
This is the maker's GitHub for this product: https://github.com/Xinyuan-LilyGO/LilyGo-EPD47

@nickolay
Copy link
Author

nickolay commented Nov 15, 2022

So far I managed to get esphome run to flash the chip, based on vendor's demo:

esphome:
  name: lilygo
  platformio_options:
    upload_speed: 921600
    monitor_speed: 115200
    board_build.mcu: esp32s3
    board_build.f_cpu: 240000000L
    #uncommenting the following causes: .platformio/packages/framework-arduinoespressif32/tools/sdk/esp32s3/include/newlib/platform_include/assert.h:20:10: fatal error: sdkconfig.h: No such file or directory
    # board_build.arduino.memory_type: qspi_opi
    board_build.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.flash_type: qspi
    board_build.psram_type: opi
    board_build.memory_type: qspi_opi
    board_build.boot_freq: 80m

esp32:
  variant: esp32s3
  board: esp32-s3-devkitc-1

  framework:
    type: arduino
    version: 2.0.3
    platform_version: 5.1.1

With the above, basic ESP32 functionality like OTA updates work normally.
It's easy to detect physical button presses:

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO21 #was GPIO39 on the previous board
      inverted: true
    name: "Button 1"
    on_press:
      - logger.log: PhysButton Pressed

Hopefully someone will have time to adapt the screen library.

Update: there are three implementations for the original board discussed in #1109:

There's some work happening over at vroland/epdiy#203 for supporting ESP32-S3 in general and the new T5-4.7 in particular, but it's currently a bit too experimental for my taste, so I'm toying with approach similar to the one taken by tiaanv...

@nickolay
Copy link
Author

nickolay commented Dec 3, 2022

I'm toying with approach similar to the one taken by tiaanv...

OK, the screen appears to work for me: https://github.com/nickolay/esphome-lilygo-t547plus

@besanur
Copy link

besanur commented Feb 10, 2023

How did you flash, i was not able to flash it via esphome web. Only worked with esptool. I have a basic configuration to display the time, but it shows a wrong time, hour is alwas at 01:XX.
And if a look at esphome web ui in home-assistant the devices is not connected, but after i connect it to my computer and read logs via them after that it is connected the wifi.

My config:

esphome:
  name: lilygo
  platformio_options:
    # Unless noted otherwise, based on https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/1eb6119fc31fcff7a6bafecb09f4225313859fc5/examples/demo/platformio.ini#L37
    upload_speed: 921600
    monitor_speed: 115200
    board_build.mcu: esp32s3
    board_build.f_cpu: 240000000L
    board_build.arduino.memory_type: qspi_opi
    board_build.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.flash_type: qspi
    board_build.psram_type: opi
    board_build.memory_type: qspi_opi
    board_build.boot_freq: 80m
    build_flags: # the first three defines are required for the screen library to function.
      - "-DBOARD_HAS_PSRAM"
      - "-DARDUINO_RUNNING_CORE=0" # TODO: this conflicts with the value from platformio's idedata, spewing a lot of warnings during the build.
      - "-DARDUINO_EVENT_RUNNING_CORE=0" # and this too
      # In addition to lilygo's settings:
      # To enable reading logs over USB until `hardware_uart: USB_CDC` support
      # is added to `logger:`, as detailed in <https://github.com/esphome/feature-requests/issues/1906>:
      - "-DARDUINO_USB_MODE=1"
      - "-DARDUINO_USB_CDC_ON_BOOT=1"

esp32:
  variant: esp32s3
  board: esp32-s3-devkitc-1

  framework:
    type: arduino
    # Just like in <https://community.home-assistant.io/t/enable-usb-cdc-to-log-hello-world-to-esp32-s3-dev-board-for-esphome/463164/10>
    # I had problems with newer versions; the following combination happens to work, so using it for now.
    version: 2.0.3
    platform_version: 5.1.1

logger:
  level: VERBOSE
  # hardware_uart: USB_CDC  # see note about <https://github.com/esphome/feature-requests/issues/1906> above

# Enable Home Assistant API
api:
  encryption:
    key: "rZjS7VS1G5PPFc7JLfwWYGMZ8LVg81Mokz9UUoCel00="

ota:
  password: "6903efa08992bfb72e6e2545357799ae"
  
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
    # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lilygo-T5 Fallback Hotspot"
    password: "xHMGPUOTHBjX"

captive_portal:

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO21 #was GPIO39 on the previous board
      inverted: true
    name: "Button 1"
    on_press:
      - logger.log: PhysButton Pressed

external_components:
  source:
    type: local
    path: esphome-lilygo-t547plus/components/
  components: ["t547"]

time:
  - platform: homeassistant
    id: esptime

font: 
  - file: "fonts/Roboto-Regular.ttf"
    id: font_clock
    size: 78
    glyphs: [':', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

display:
  - platform: t547
    # rotation: 180
    update_interval: 30s
    lambda: |-
      it.strftime(it.get_width()/2, it.get_height()/2, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(esptime).now());

@lehovec
Copy link

lehovec commented Feb 10, 2023

You can add platformio board configuration from LilyGo-EPD47 GitHub repository to esphome. I added lilygo-t5-74-plus.json file to /config/esphome/.esphome/build/[your-esphome-device]/boards and I am am able to flash without problems.

esphome:
  name: liligo-t5-47-epaper-plus
  platformio_options:
    board_dir: boards
    #include https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/master/platformio/boards/lilygo-t5-47-plus.json as custom board
    board: lilygo-t5-47-plus

esp32:
  variant: esp32s3
  board: lilygo-t5-47-plus

  framework:
    type: arduino
    # You don't need to specify version and platform_version

i2c:
  sda: GPIO17
  scl: GPIO18
  # There is some problems with i2c scan so turn scan off if problem appear on your board
  scan: false
  id: bus_a

external_components:
  - source: github://nickolay/esphome-lilygo-t547plus
    components: ["t547"]

display:
- platform: t547
  id: t5_display
  update_interval: 30s

@nickolay
Copy link
Author

i was not able to flash it via esphome web. Only worked with esptool

I'm not sure how you can provide the necessary platformio_options via esphome web, so I'm flashing using the CLI (esphome run basic.yaml), as noted in the readme.

I'm always flashing over USB to be able to see the logs from the first startup, which are very useful to troubleshoot the occasional problems, like the device booting into safe mode (i.e. ignoring most of the config). I've also added the device to Home assistant manually.

You can add platformio board configuration from LilyGo-EPD47 GitHub repository to esphome

Cool tip, thanks!

@besanur
Copy link

besanur commented Feb 10, 2023

You can add platformio board configuration from LilyGo-EPD47 GitHub repository to esphome. I added lilygo-t5-74-plus.json file to /config/esphome/.esphome/build/[your-esphome-device]/boards and I am am able to flash without problems.

esphome:
  name: liligo-t5-47-epaper-plus
  platformio_options:
    board_dir: boards
    #include https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/master/platformio/boards/lilygo-t5-47-plus.json as custom board
    board: lilygo-t5-47-plus

esp32:
  variant: esp32s3
  board: lilygo-t5-47-plus

  framework:
    type: arduino
    # You don't need to specify version and platform_version

i2c:
  sda: GPIO17
  scl: GPIO18
  # There is some problems with i2c scan so turn scan off if problem appear on your board
  scan: false
  id: bus_a

external_components:
  - source: github://nickolay/esphome-lilygo-t547plus
    components: ["t547"]

display:
- platform: t547
  id: t5_display
  update_interval: 30s

with this solution it works much better and without problems.. thank you

@kaeltis
Copy link

kaeltis commented Apr 6, 2023

Has anyone figured out how to read the battery voltage? According to https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/master/schematic/T5-4.7-Plus.pdf the pin should be GPIO14, but there I'm getting ESP32S3 doesn't support ADC on this pin.

@nickolay
Copy link
Author

nickolay commented Apr 6, 2023

@kaeltis see Xinyuan-LilyGO/LilyGo-EPD47#87 for a C example, which seems to work okay. Didn’t try to use it from esphome yet.

@kaeltis
Copy link

kaeltis commented Apr 6, 2023

Thanks, I've forked an existing module that solved this for the old board revision and it seems to work.
I have pretty much no idea what I'm doing so this definitely needs improvements: https://github.com/kaeltis/esphome-lilygo-t547plus

@startQ341
Copy link

startQ341 commented May 9, 2023

You can add platformio board configuration from LilyGo-EPD47 GitHub repository to esphome. I added lilygo-t5-74-plus.json file to /config/esphome/.esphome/build/[your-esphome-device]/boards and I am am able to flash without problems.

esphome:
  name: liligo-t5-47-epaper-plus
  platformio_options:
    board_dir: boards
    #include https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/master/platformio/boards/lilygo-t5-47-plus.json as custom board
    board: lilygo-t5-47-plus

esp32:
  variant: esp32s3
  board: lilygo-t5-47-plus

  framework:
    type: arduino
    # You don't need to specify version and platform_version

i2c:
  sda: GPIO17
  scl: GPIO18
  # There is some problems with i2c scan so turn scan off if problem appear on your board
  scan: false
  id: bus_a

external_components:
  - source: github://nickolay/esphome-lilygo-t547plus
    components: ["t547"]

display:
- platform: t547
  id: t5_display
  update_interval: 30s

a try your code but have a error code a try change jason file but same problem thanks for help

Processing obrazovka (board: lilygo-t5-47-plus; framework: arduino; platform: platformio/espressif32 @ 5.3.0)

Error: Could not load broken JSON: /config/esphome/.esphome/build/obrazovka/boards/lilygo-t5-47-plus.json

@lehovec
Copy link

lehovec commented May 9, 2023

@startQ341 error indicate that lilygo-t5-47-plus.json file is somehow corrupted. Try to download it from source repository again or check in some online json validator what is problem with that file.

@startQ341
Copy link

@lehovec
thank you for your help browser corrupted data while downloading

@zagnuts
Copy link

zagnuts commented Jul 4, 2023

Thanks guys for this - it's working perfectly for me now, both screen and battery estimate. Only minor hassle is the lack of partial refresh support but hopefully that will become available eventually. Oh, and it would be nice to be able to disable that blinding blue light with something civilised like

status_led:
  pin:
    number: GPIO05
    inverted: True

rather than having to contemplate crushing it with pliers! (FWIW it can be done via epd_poweroff_all() apparently)

@petrhod
Copy link

petrhod commented Jul 16, 2023

Please help me compile for Lilygo 4.7 pro.
I am able to program with the arduino ino and Lily works. I am not able to display anything in esphome. I always get an error message:
Tool Manager: Installing espressif/toolchain-riscv32-esp @ 8.4.0+2021r2-patch3 INFO Installing espressif/toolchain-riscv32-esp @ 8.4.0+2021r2-patch3 Error: Could not find the package with 'espressif/toolchain-riscv32-esp @ 8.4.0+2021r2-patch3' requirements for your system 'linux_x86_64'
My code is based on the above:

esphome:
  name: lilygo
  platformio_options:
    # Unless noted otherwise, based on https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/1eb6119fc31fcff7a6bafecb09f4225313859fc5/examples/demo/platformio.ini#L37
    upload_speed: 921600
    monitor_speed: 115200
    board_build.mcu: esp32s3
    board_build.f_cpu: 240000000L
    board_build.arduino.memory_type: qspi_opi
    board_build.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.flash_type: qspi
    board_build.psram_type: opi
    board_build.memory_type: qspi_opi
    board_build.boot_freq: 80m
    build_flags:  # the first three defines are required for the screen library to function.
      - "-DBOARD_HAS_PSRAM"
      - "-DARDUINO_RUNNING_CORE=0"  # TODO: this conflicts with the value from platformio's idedata, spewing a lot of warnings during the build.
      - "-DARDUINO_EVENT_RUNNING_CORE=0"  # and this too
      # In addition to lilygo's settings:
      # To enable reading logs over USB until `hardware_uart: USB_CDC` support
      # is added to `logger:`, as detailed in <https://github.com/esphome/feature-requests/issues/1906>:
      - "-DARDUINO_USB_MODE=1"
      - "-DARDUINO_USB_CDC_ON_BOOT=1"
 esp32:

  board: esp32-s3-devkitc-1
  framework:
    type: arduino
    version: 2.1.1
    platform_version: 5.1.1

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "maXDU+zyImnTxgTD60TgWY0WUMoNS/ToE97w8WBGVPk="

ota:
  password: "92d1d4c3224f0fc6e118bffe0d4b8834"

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

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

captive_portal:

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO21 #was GPIO39 on the previous board
      inverted: true
    name: "Button 1"
    on_press:
      - logger.log: PhysButton Pressed

external_components:
  source:
    type: local
    path: components/
  components: ["t547"]

font: 
  - file: "Google_Sans_Bold.ttf"
    id: font_clock
    size: 78
    glyphs: [':', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

time:
  - platform: homeassistant
    id: esptime

display:
  - platform: t547
    # rotation: 180
    update_interval: 30s
    lambda: |-
      it.strftime(it.get_width()/2, it.get_height()/2, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(esptime).now());** 

@special-k-uk
Copy link

special-k-uk commented Jul 25, 2023

I managed to get it compiled and flashed with the below. I saved the JSON locally into /.esphome/build/test

esphome:
  name: test
  friendly_name: test
  platformio_options:
    board_dir: boards
    #include https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/master/platformio/boards/lilygo-t5-47-plus.json as custom board
    board: lilygo-t5-47-plus

esp32:
  variant: esp32s3
  board: lilygo-t5-47-plus

  framework:
    type: arduino
    # version: 2.0.8
    # You don't need to specify version and platform_version

# Enable logging
logger:
  level: VERBOSE

# Enable Home Assistant API
api:
  encryption:
    key: "secret"

ota:
  password: "secret"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
    
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Test Fallback Hotspot"
    password: "GGH2cv2rqbUL"

captive_portal:

i2c:
  sda: GPIO18
  scl: GPIO17
  # There is some problems with i2c scan so turn scan off if problem appear on your board
  scan: true
  id: bus_a

external_components:
  - source: github://nickolay/esphome-lilygo-t547plus
    components: ["t547"]

touchscreen:
  - platform: lilygo_t5_47
    id: lilygo_touchscreen
    interrupt_pin: GPIO09
    address: 0x5A
    setup_priority: -100
    on_touch:
      then:
        - display.page.show_next: 't5_display'
        - component.update: 't5_display'

@special-k-uk
Copy link

Has anyone managed to get the Touchscreen component working with this board?

I've been using this touch panel on the older v3 boards and I'd like to continue using it on the newer S3 based boards.

Unfortunately the interrupt_pin has changed from GPIO13 on the older v3 to GPIO9 on the newer S3 board, and it looks like the Touchscreen Component is fixed at GPIO13, although it requires you to specify the pin in yaml.

I've logged an bug report here, just wondering if anyone has found a way to use touch?

@htitze
Copy link

htitze commented Aug 16, 2023

Please help me compile for Lilygo 4.7 pro. I am able to program with the arduino ino and Lily works. I am not able to display anything in esphome. I always get an error message: Tool Manager: Installing espressif/toolchain-riscv32-esp @ 8.4.0+2021r2-patch3 INFO Installing espressif/toolchain-riscv32-esp @ 8.4.0+2021r2-patch3 Error: Could not find the package with 'espressif/toolchain-riscv32-esp @ 8.4.0+2021r2-patch3' requirements for your system 'linux_x86_64' My code is based on the above:

esphome:
  name: lilygo
  platformio_options:
    # Unless noted otherwise, based on https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/1eb6119fc31fcff7a6bafecb09f4225313859fc5/examples/demo/platformio.ini#L37
    upload_speed: 921600
    monitor_speed: 115200
    board_build.mcu: esp32s3
    board_build.f_cpu: 240000000L
    board_build.arduino.memory_type: qspi_opi
    board_build.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.flash_type: qspi
    board_build.psram_type: opi
    board_build.memory_type: qspi_opi
    board_build.boot_freq: 80m
    build_flags:  # the first three defines are required for the screen library to function.
      - "-DBOARD_HAS_PSRAM"
      - "-DARDUINO_RUNNING_CORE=0"  # TODO: this conflicts with the value from platformio's idedata, spewing a lot of warnings during the build.
      - "-DARDUINO_EVENT_RUNNING_CORE=0"  # and this too
      # In addition to lilygo's settings:
      # To enable reading logs over USB until `hardware_uart: USB_CDC` support
      # is added to `logger:`, as detailed in <https://github.com/esphome/feature-requests/issues/1906>:
      - "-DARDUINO_USB_MODE=1"
      - "-DARDUINO_USB_CDC_ON_BOOT=1"
 esp32:

  board: esp32-s3-devkitc-1
  framework:
    type: arduino
    version: 2.1.1
    platform_version: 5.1.1

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "maXDU+zyImnTxgTD60TgWY0WUMoNS/ToE97w8WBGVPk="

ota:
  password: "92d1d4c3224f0fc6e118bffe0d4b8834"

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

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

captive_portal:

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO21 #was GPIO39 on the previous board
      inverted: true
    name: "Button 1"
    on_press:
      - logger.log: PhysButton Pressed

external_components:
  source:
    type: local
    path: components/
  components: ["t547"]

font: 
  - file: "Google_Sans_Bold.ttf"
    id: font_clock
    size: 78
    glyphs: [':', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

time:
  - platform: homeassistant
    id: esptime

display:
  - platform: t547
    # rotation: 180
    update_interval: 30s
    lambda: |-
      it.strftime(it.get_width()/2, it.get_height()/2, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(esptime).now());** 

Same problem for me...

@Fabian-Schmidt
Copy link

Hi,

I got the display working with the following config:
Still having issues with logging and display is not perfect.

esphome:
  name: esp-t5-s3
  friendly_name: "T5 S3"
  platformio_options:
    board_build.f_flash: 80000000L
    board_upload.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.psram_type: opi
    board_build.partitions: default_16MB.csv
    board_build.arduino.memory_type: qio_opi
  on_boot:
    then:
      # read time from external source (connected via I2C)
      - pcf85063.read_time

external_components:  - source: github://Fabian-Schmidt/esphome-lilygo_t5_47_display
    components: ["lilygo_t5_47_s3_display"]
    refresh: 0s
  - source: github://Fabian-Schmidt/esphome@jesserockz-2023-136-Fabian-Schmidt
    components: [ logger ]

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: arduino
    version: latest

logger:
  hardware_uart: USB_CDC # USB_CDC # USB_SERIAL_JTAG

i2c:
  sda: 18
  scl: 17
  frequency: 10kHz
  scan: false
  id: i2c_bus_a

time:
  - platform: pcf85063
    id: esptime
    update_interval: never

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO21
      inverted: true
    name: "Button 1"
    on_press:
    - lambda:
        // Code here

sensor:
  - platform: internal_temperature
    id: esptemp
    name: "Internal Temperature"
    update_interval: 1s

font:
  - file: Google_Sans_Bold.ttf
    id: font_name
    size: 38

display:
- platform: lilygo_t5_47_s3_display
  update_interval: 10s
  # rotation: 180
  # clear: false
  full_update_every: 6
  # power_off_delay_enabled: false
  lambda: 
    it.printf(100, 100, id(font_name), TextAlign::BASELINE_CENTER, "Hello World");

@petrhod
Copy link

petrhod commented Aug 19, 2023

Hi, for my i ok this ....


esphome:
  name: esp-t5-s3
  friendly_name: "T5 S3"
  platformio_options:
    board_build.f_flash: 80000000L
    board_upload.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.psram_type: opi
    board_build.partitions: default_16MB.csv
    board_build.arduino.memory_type: qio_opi
  on_boot:
    then:
      # read time from external source (connected via I2C)
      # - pcf85063.read_time

external_components:
  - source: github://nickolay/esphome-lilygo-t547plus
    components: ["t547"]

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: arduino
    version: latest

# Enable Home Assistant API
api:
  encryption:
    key: "2DvwSZRhQbXP3y1jVlTR5wg9FBPCrbMVVmKikLNFcXw="

ota:
  password: "0b4f13991d00618a668dbc3d78fa09ac"

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

#i2c:
#  sda: 18
#  scl: 17
#  frequency: 10kHz
#  scan: false
#  id: i2c_bus_a

#deep_sleep:
#  run_duration: 30s
#  sleep_duration: 1min

time:
  - platform: homeassistant
    id: homeassistant_time

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO21
      inverted: true
    name: "Button 1"
    on_press:
    - lambda:
        // Code here

#sensor:
#  - platform: internal_temperature
#    id: esptemp
#    name: "Internal Temperature"
#    update_interval: 1s

font:
  - file: Google_Sans_Bold.ttf
    id: font_1
    size: 45
  - file: Google_Sans_Bold.ttf
    id: font_2
    size: 150

display:
- platform: t547
  update_interval: 60s
  # rotation: 180
  #clear: true
  #full_update_every: 3
  #power_off_delay_enabled: true
  lambda: 
    it.printf(10, 100, id(font_1), " Hello World");
 
  
    ```

@VladimirV01
Copy link

VladimirV01 commented Nov 11, 2023

Hello Guys, I wanted to say thanks to everybody who provided help in this thread.
It was very helpful and helped me get my Lilygo T5 Plus going.

However, no matter how hard I tried, I could not manage to establish the connection with the RTC.
Has anyone succeeded with this task?

@special-k-uk
Copy link

special-k-uk commented Nov 14, 2023

Hello Guys, I wanted to say thanks to everybody who provided help in this thread. It was very helpful and helped me get my Lilygo T5 Plus going.

However, no matter how hard I tried, I could not manage to establish the connection with the RTC. Has anyone succeeded with this task?

Hey @VladimirV01
The PCF8563 is a core component now , although I think the hardware itself might be a bit flakey as it works 90% of the time for me. The other 10% of the time it will throw an error on boot that it's unable to connect.

Here's what I have

esphome:
  name: barn-blind-controller
  friendly_name: barn-blind-controller
  platformio_options:
    board_build.f_flash: 80000000L
    board_upload.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.psram_type: opi
    board_build.partitions: default_16MB.csv
    board_build.arduino.memory_type: qio_opi 
  on_boot:
    priority: -100
    then:
      - pcf8563.read_time

then

i2c:
  - id: bus_a
    sda: GPIO18
    scl: GPIO17
    # There is some problems with i2c scan so turn scan off if problem appear on your board
    scan: False
    frequency: 100khz

time:
  - platform: pcf8563
    id: internal_clock
    address: 0x51  
    i2c_id: bus_a
  - platform: homeassistant
    id: external_clock
    on_time_sync:
      then:
        - pcf8563.write_time

I hope that helps?

@VladimirV01
Copy link

Hello Guys, I wanted to say thanks to everybody who provided help in this thread. It was very helpful and helped me get my Lilygo T5 Plus going.
However, no matter how hard I tried, I could not manage to establish the connection with the RTC. Has anyone succeeded with this task?

Hey @VladimirV01 The PCF8563 is a core component now , although I think the hardware itself might be a bit flakey as it works 90% of the time for me. The other 10% of the time it will throw an error on boot that it's unable to connect.

Here's what I have

esphome:
  name: barn-blind-controller
  friendly_name: barn-blind-controller
  platformio_options:
    board_build.f_flash: 80000000L
    board_upload.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.psram_type: opi
    board_build.partitions: default_16MB.csv
    board_build.arduino.memory_type: qio_opi 
  on_boot:
    priority: -100
    then:
      - pcf8563.read_time

then

i2c:
  - id: bus_a
    sda: GPIO18
    scl: GPIO17
    # There is some problems with i2c scan so turn scan off if problem appear on your board
    scan: False
    frequency: 100khz

time:
  - platform: pcf8563
    id: internal_clock
    address: 0x51  
    i2c_id: bus_a
  - platform: homeassistant
    id: external_clock
    on_time_sync:
      then:
        - pcf8563.write_time

I hope that helps?

Hello @special-k-uk !

Thank you very much for taking the time to check this issue and write an answer.

I have followed your advice and checked your configuration.
After changing the frequency to 100KHz and setting the address manually to 0x51 as advised by you, I don't see the initialization error on boot of the integrated RTC anymore!

Now I see that it syncs the RTC on time sync with homeassistant, therefore I can be sure it works.

@ex-nerd
Copy link

ex-nerd commented Nov 18, 2023

I managed to piece together a working config for my new board that includes a bunch of the changes, including the display code from @nickolay and battery stuff from @kaeltis (you two should consider merging your work for nickolay/esphome-lilygo-t547plus#3). I also activated the internal temp sensor, and set things to read/write with the internal clock. So far, everything is working great for me with an old LiPo battery I had sitting around (battery sensor is reading 4.5V, which lines up with what it did with the LilyGo firmware).

Anyway, here it is for posterity (along with some notes since I just copy/pasted my yaml file here)

# See: https://github.com/esphome/feature-requests/issues/1960
# See for older hardware: https://github.com/esphome/feature-requests/issues/1109

esphome:
  name: lilygo-t5-eink
  friendly_name: LilyGo T5 eInk
  platformio_options:
    board_build.f_flash: 80000000L
    board_upload.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.psram_type: opi
    board_build.partitions: default_16MB.csv
    board_build.arduino.memory_type: qio_opi
  on_boot:
    priority: -100
    then:
      - pcf8563.read_time

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: arduino
    version: latest

# Enable logging
logger:

# Enable Home Assistant API (API password is deprecated in favor of encryption key)
# https://esphome.io/components/api.html
api:
  encryption:
    key: !secret home_assistant_encryption_key

ota:
  password: !secret ota_password

wifi:
  networks:
    - ssid: !secret wifi_ssid
      password: !secret wifi_password
  reboot_timeout: 15min

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lilygo-T5-Eink Fallback Hotspot"
    password: !secret fallback_ssid_password

captive_portal:

external_components:
  # https://github.com/nickolay/esphome-lilygo-t547plus
  - source: github://nickolay/esphome-lilygo-t547plus
    components: ["t547"]
  # https://github.com/kaeltis/esphome-lilygo-t547plus
  - source: github://kaeltis/esphome-lilygo-t547plus
    components: ["lilygo_t5_47_battery"]

#deep_sleep:
#  run_duration: 30s
#  sleep_duration: 1min

i2c:
  - id: bus_a
    sda: GPIO18
    scl: GPIO17
    frequency: 100khz
    # There is some problems with i2c scan so turn scan off if problem appear on your board
    scan: False

time:
  - platform: pcf8563
    id: internal_clock
    address: 0x51  
    i2c_id: bus_a
  - platform: homeassistant
    id: ha_time
    on_time_sync:
      then:
        - pcf8563.write_time

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO21 #was GPIO39 on the previous board
      inverted: true
    name: "Button 1"
    on_press:
      - logger.log: PhysButton Pressed

sensor:
  - platform: internal_temperature
    id: esptemp
    name: "Internal Temperature"
    update_interval: 1s

  - platform: lilygo_t5_47_battery
    id: battery_voltage
    voltage:
      name: "Battery Voltage"

  - platform: template
    name: "Battery Percentage"
    id: battery_percentage
    lambda: |-
      // tweak values in mapping for calibration
      // 4.1 = max voltage
      // 3.3 = min voltage
      float y = (id(battery_voltage).voltage->state - 3.3) * 100.0 / (4.1 - 3.3);
      if (y < 100.0) { return y; } else { return 100.0; };

font:
  # https://github.com/hprobotic/Google-Sans-Font/blob/master/
  - file: fonts/GoogleSans-Bold.ttf
    id: font_1
    size: 45
  - file: fonts/GoogleSans-Bold.ttf
    id: font_2
    size: 150
  - file: "fonts/GoogleSans-Bold.ttf"
    id: font_clock
    size: 300
    glyphs: [':', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

display:
- platform: t547
  update_interval: 60s
  # rotation: 180
  #clear: true
  #full_update_every: 3
  #power_off_delay_enabled: true
  lambda: |-
    it.printf(10, 50, id(font_1), "Battery: %.1f% (%.1fV)", id(battery_percentage).state, id(battery_voltage).voltage->state);
    // https://esphome.io/cookbook/display_time_temp_oled.html 
    it.printf(10, 100, id(font_1), "Internal Temp: %.1f°C", id(esptemp).state);

    it.strftime(it.get_width()/2, it.get_height()/2-150, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(ha_time).now());

@ThierryDi
Copy link

Hello,
Thanks a lot to all this threads' participants for their work which helped me piece together my own config. (I won't post my code as it doesn't bring anything new to the table ;-))
I was wondering if any of you managed to print in grayscale ?
Cheers

@PabloFFF93
Copy link

Has anyone had such a problem

`INFO ESPHome 2023.11.6
INFO Reading configuration /config/esphome/test.yaml...
WARNING The selected Arduino framework version is not the recommended one. If there are connectivity or build issues please remove the manual version.
Failed config

esp32: None

Please specify flash_size within esp32 configuration only.
board: esp32-s3-devkitc-1
framework:
version: 2.0.9
source: ~3.20009.0
platform_version: platformio/espressif32@5.4.0
type: arduino
flash_size: 4MB
variant: ESP32S3`

@zagnuts
Copy link

zagnuts commented Dec 14, 2023

Has anyone had such a problem
Failed config
Please specify flash_size within esp32 configuration only.

Try commenting out "board_upload.flash_size" from within the platformio_options section. It will use the default, which should be fine. :-)

@PabloFFF93
Copy link

PabloFFF93 commented Dec 20, 2023

There is some progress...
It is installed.

It doesn't start, the USB logs show this:
image

And the browser is not responding

@Januznl
Copy link

Januznl commented Dec 26, 2023

There is some progress... It is installed.

It doesn't start, the USB logs show this: image

And the browser is not responding

Have you tried ESPHome version: 2023.12.5?
I had the same issues, but since i've updated to the latest version its working.

Steps i took:

  • click on Install (plug into this computer (usb)
  • Use esphome web to flash
  • i had to bring the arduino in boot mode by holding the button "STR_100" and press the button "REST"
  • after flashing i presses "REST" again and the board started the esphome firmware.

I'm currently creating a repo with working clock example and steps to take to get the S3 Plus running.
See https://github.com/Januznl/esphome-lilygo-t5-s3-plus

@PabloFFF93
Copy link

PabloFFF93 commented Dec 28, 2023

yeah! Your way works! now my entities are available on eink!
Uploading 20231228_031042.jpg…

@Januznl
Copy link

Januznl commented Dec 28, 2023

@PabloFFF93 did you use the guide? or upgrading and the boot steps?

@PabloFFF93
Copy link

I used the guide. I didn't really need to special boot ESP by key.. Everything became clear after using the new board and uploading your yaml ESPHOME: and ESP32: conf. I think this was the problem.

I have a similar problem in esp32 by wroover. I have to click boot to initialize the boot

@Januznl
Copy link

Januznl commented Dec 28, 2023

I used the guide. I didn't really need to special boot ESP by key.. Everything became clear after using the new board and uploading your yaml ESPHOME: and ESP32: conf. I think this was the problem.

I have a similar problem in esp32 by wroover. I have to click boot to initialize the boot

nice, good news its working!

@nickolay
Copy link
Author

You can add platformio board configuration from LilyGo-EPD47 GitHub repository to esphome. I added lilygo-t5-74-plus.json file to /config/esphome/.esphome/build/[your-esphome-device]/boards and I am am able to flash without problems.

esphome:
  name: liligo-t5-47-epaper-plus
  platformio_options:
    board_dir: boards
    #include https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/master/platformio/boards/lilygo-t5-47-plus.json as custom board
    board: lilygo-t5-47-plus

esp32:
  variant: esp32s3
  board: lilygo-t5-47-plus

I finally looked into how this works, because I couldn't understand why I can't use an absolute path for the esphome.platformio_options.board_dir. Turns out if you're using the custom board json, the remaining platformio_options do not have any effect and can be dropped.

Details for the curious:

In other news:

@dxdr
Copy link

dxdr commented Mar 11, 2024

Thank you everyone for your help getting this set up... one thing that I can't seem to figure out is how to set up external buttons. I was able to get one set up on GPIO 15 using the pins in the molex connector, but can't seem to get another working on any of the other pins. The FAQ says that 12, 13, 14 and 15 should be available if not using the touch screen, but I can't seem to figure out how to physically connect the button to the board. I thought I could use the 40 pin connector, but I tested each pin and none seem to produce a response when I use:
`

  • platform: gpio
    pin:
    number: GPIO13
    inverted: false
    mode:
    input: true
    pullup: true
    name: "${esp_name} Button 13"
    id: button13
    on_click:
    then:
    - logger.log: "Button 13 Pressed..."
    `

I'm sure I'm missing something simple, but if anyone has an idea I would appreciate it.

@husnainali09
Copy link

Trying to get homeassistant dashboard working on T5 ESP32-3. Keep getting esptime error. Anyone know how to fix this ?

  name: esphome-web-60e604
  friendly_name: Lilygodash

esphome:
  name: lilygodash
  platformio_options:
    # Include https://github.com/Xinyuan-LilyGO/LilyGo-EPD47/blob/master/platformio/boards/lilygo-t5-47-plus.json as custom board
    board: lilygo-t5-47-plus
    # Directory where the lilygo-t5-47-plus.json file can be found
    board_dir: boards
#  on_boot:
#    priority: -100
#    then:
#      - pcf8563.read_time
  # custom build path, so we can save the lilygo-t5-47-plus.json file in the sub-folder "boards"
  build_path: /config/esphome/.esphome/basic-clock/
  includes:
    - common.h

esp32:
  variant: esp32s3
  board: lilygo-t5-47-plus
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "B1DK4ps4YiUJ0Vit1S4jFxalSAOwZjNvr6QhFeWjngI="

ota:
  password: "B1DK4ps4YiUJ0Vit1S4jFxalSAOwZjNvr6QhFeWjngI="

## External components for T5 support ##
external_components:
  # https://github.com/nickolay/esphome-lilygo-t547plus
  - source: github://nickolay/esphome-lilygo-t547plus
    components: ["t547"]
  # https://github.com/kaeltis/esphome-lilygo-t547plus
  - source: github://kaeltis/esphome-lilygo-t547plus
    components: ["lilygo_t5_47_battery"]

## -- ##

## Only needed if powered via battery ##
#deep_sleep:
#  run_duration: ${run_time}
#  sleep_duration: ${sleep_time}
#  id: deep_sleep_1
#  esp32_ext1_wakeup:
#    pins: GPIO39
#    mode: ALL_LOW
#    allow_other_uses: true
## -- ##

wifi:
  networks:
    - ssid: NETGEAR08_IoT
      password: abbaabba12
  reboot_timeout: 15min
  use_address: 192.168.1.245

web_server:
  port: 80
  include_internal: true 

sun:
  latitude: 45.817900°
  longitude: 15.963196°


time:
  - platform: homeassistant
    id: ntp
#    timezone: Australia/Brisbane
    on_time_sync:
      - then:
        - component.update: sunrise
        - component.update: sunset
  - platform: pcf8563
    id: internal_clock
    address: 0x51  
    i2c_id: bus_a


i2c:
  - id: bus_a
    sda: GPIO18
    scl: GPIO17
    frequency: 100khz
    # There are some problems with i2c scan, so turn scan off if problems appear on your board
    scan: False

#time:
#  - platform: pcf8563
#    id: internal_clock
#    address: 0x51  
#    i2c_id: bus_a
#  - platform: homeassistant
#    id: ha_time
#    on_time_sync:
#      then:
#        - pcf8563.write_time


script:
  - id: all_data_received
    then:
      - component.update: t5_display
#      - component.update: batt_volt
#      - component.update: batt

sensor:
  - platform: lilygo_t5_47_battery
    id: battery_voltage
    voltage:
      name: "Battery Voltage"

  - platform: template
    name: "Battery Percentage"
    id: battery_percentage
    lambda: |-
      // tweak values in mapping for calibration
      // 4.1 = max voltage
      // 3.3 = min voltage
      float y = (id(battery_voltage).voltage->state - 3.3) * 100.0 / (4.1 - 3.3);
      if (y < 100.0) { return y; } else { return 100.0; };

  # weather
  - platform: homeassistant
    entity_id: sensor.accuweather_apparent_temperature
    id: temperature
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_realfeel_temperature_min_1d
    id: day1_min
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_realfeel_temperature_max_1d
    id: day1_max
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_thunderstorm_probability_day_1d
    id: day1_storm
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_realfeel_temperature_min_2d
    id: day2_min
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_realfeel_temperature_max_2d
    id: day2_max
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_thunderstorm_probability_day_2d
    id: day2_storm
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_realfeel_temperature_min_3d
    id: day3_min
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_realfeel_temperature_max_3d
    id: day3_max
    internal: true
  - platform: homeassistant
    entity_id: sensor.accuweather_thunderstorm_probability_day_3d
    id: day3_storm
    internal: true
  # temperature/humidity sensors
  - platform: homeassistant
    entity_id: sensor.bedroom_temperature_2
    id: temp_bedroom
    internal: true
  - platform: homeassistant
    entity_id: sensor.bedroom_humidity
    id: humidity_bedroom
    internal: true
  - platform: homeassistant
    entity_id: sensor.living_room_temperature
    id: temp_living
    internal: true
  - platform: homeassistant
    entity_id: sensor.living_room_humidity
    id: humidity_living
    internal: true
  - platform: homeassistant
    entity_id: sensor.zita_room_temperature
    id: temp_zita
    internal: true
  - platform: homeassistant
    entity_id: sensor.zita_room_temperature_2_humidity
    id: humidity_zita
    internal: true
  - platform: homeassistant
    entity_id: sensor.luka_room_temperature
    id: temp_luka
    internal: true
  - platform: homeassistant
    entity_id: sensor.luka_room_humidity
    id: humidity_luka
    internal: true

## Battery ##
#  - platform: lilygo_t5_47_battery
#    update_interval: 60s
#    id: batt_volt
#    voltage:
#      name: "Battery Voltage"
#  - platform: template
#    name: "e-ink Dashboard Battery"
#    id: batt
#    unit_of_measurement: "%"
#    accuracy_decimals: 0
#    device_class: battery
#    lambda: |-
#      int y = (1-(4.1-id(batt_volt).voltage->state)/(4.1-3.3))*100;
#      if (y < 100) {return y;} else {return 100;};
## -- ##

binary_sensor:
#  - platform: gpio
#    pin: 
#      number: GPIO39
#      inverted: true
#      allow_other_uses: true
#    name: "lilygo-t5 Button 1"
#    on_press:
#      then:
#        - component.update: t5_display
  - platform: gpio
    pin: 
      number: GPIO21 #was GPIO39 on the previous board
      inverted: true
    name: "Button 1"
    on_press:
      - logger.log: PhysButton Pressed
  - platform: homeassistant
    entity_id: binary_sensor.balcony_temp_falling
    id: temp_falling
    internal: true
  - platform: homeassistant
    entity_id: binary_sensor.balcony_temp_rising
    id: temp_rising
    internal: true

text_sensor:

  # sun/moon
  - platform: sun
    id: sunrise
    name: Sun Next Sunrise
    type: sunrise
    format: "%H:%M"
    internal: true
  - platform: sun
    id: sunset
    name: Sun Next Sunset
    type: sunset
    format: "%H:%M"    
    internal: true
  - platform: homeassistant
    entity_id: sun.sun
    id: hasun
    internal: true
  - platform: homeassistant
    entity_id: sensor.moon
    id: moon
    internal: true
## NOT used but required later ##
  - platform: homeassistant
    entity_id: sensor.idokep_condition
    id: condition
    internal: true
  - platform: homeassistant
    entity_id: sensor.idokep_day1_dow
    id: day1_dow
    internal: true
  - platform: homeassistant
    entity_id: sensor.idokep_day1_condition
    id: day1_condition
    internal: true
  - platform: homeassistant
    entity_id: sensor.idokep_day2_dow
    id: day2_dow
    internal: true
  - platform: homeassistant
    entity_id: sensor.idokep_day2_condition
    id: day2_condition
    internal: true
  - platform: homeassistant
    entity_id: sensor.idokep_day3_dow
    id: day3_dow
    internal: true
  - platform: homeassistant
    entity_id: sensor.idokep_day3_condition
    id: day3_condition
    internal: true
## -- ##

  # calendar
  - platform: homeassistant
    entity_id: calendar.krscanski_blagdani
    attribute: message
    id: nevnap
    internal: true
  - platform: homeassistant
    entity_id: calendar.zita_school
    attribute: message
    id: calendar_message
    internal: true
  - platform: homeassistant
    entity_id: calendar.zita_school
    attribute: start_time
    id: calendar_start
    internal: true    
    on_value: # Actions to perform once data for the last sensor has been received
      then:
        - script.execute: all_data_received

  # zone tracking
  - platform: homeassistant
    entity_id: device_tracker.pixel_7_pro
    id: andrej_location
    internal: true
  - platform: homeassistant
    entity_id: sensor.andrej_distance
    id: andrej_distance
    internal: true
  - platform: homeassistant
    entity_id: device_tracker.oppo
    id: mirta_location
    internal: true
  - platform: homeassistant
    entity_id: sensor.mirta_distance
    id: mirta_distance
    internal: true
    on_value: # Actions to perform once data for the last sensor has been received
      then:
        - script.execute: all_data_received  

## Fonts used on display##
# Google Sans Medium
# Google Sans Bold
# https://github.com/sahibjotsaggu/Google-Sans-Fonts
# Check that filename matches name below
# Material UI Icons - https://pictogrammers.github.io/@mdi/font/5.3.45/ 
# https://github.com/Templarian/MaterialDesign-Webfont/blob/master/fonts/materialdesignicons-webfont.ttf
## -- ##
font:
  - file: "Google_Sans_Medium.ttf"
    id: font_small
    size: 28    
    glyphs: |-
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'/&|ÁÉÍÓÖŐÚÜŰáéíóöőúüű
  - file: "Google_Sans_Medium.ttf"
    id: font_medium
    size: 38
    glyphs: |-
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'/&|ÁÉÍÓÖŐÚÜŰáéíóöőúüű
  - file: "Google_Sans_Bold.ttf"
    id: font_medium_bold
    size: 38
    glyphs: |-
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'/&|ÁÉÍÓÖŐÚÜŰáéíóöőúüű
  - file: "Google_Sans_Medium.ttf"
    id: font_big
    size: 48
    glyphs: |-
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'/&|ÁÉÍÓÖŐÚÜŰáéíóöőúüű
  - file: "Google_Sans_Medium.ttf"
    id: font_large
    size: 56
    glyphs: |-
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'/&|ÁÉÍÓÖŐÚÜŰáéíóöőúüű
  - file: "Google_Sans_Bold.ttf"
    id: font_xlarge_bold
    size: 72
    glyphs: |-
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'/&|ÁÉÍÓÖŐÚÜŰáéíóöőúüű
  # material UI icons - from https://pictogrammers.github.io/@mdi/font/5.3.45/
  - file: 'materialdesignicons-webfont.ttf'
    id: font_icons
    size: 130
    glyphs:
      - "\U000F0594" # clear-night
      - "\U000F0590" # cloudy
      - "\U000F0591" # fog
      - "\U000F0592" # hail
      - "\U000F0593" # lightning
      - "\U000F067E" # lightning-rainy
      - "\U000F0F31" # night-partly-cloudy
      - "\U000F0595" # partly-cloudy
      - "\U000F0596" # pouring
      - "\U000F0597" # rainy
      - "\U000F0F36" # snowy
      - "\U000F067F" # snowy-rainy
      - "\U000F0599" # sunny
      - "\U000F059D" # windy
      - "\U000F059E" # windy-variant
      - "\U000F0F38" # exCentereptional
  - file: 'materialdesignicons-webfont.ttf'
    id: font_icons_small
    size: 56
    glyphs:
      # weather
      - "\U000F0594" # clear-night
      - "\U000F0590" # cloudy
      - "\U000F0591" # fog
      - "\U000F0592" # hail
      - "\U000F0593" # lightning
      - "\U000F067E" # lightning-rainy
      - "\U000F0F31" # night-partly-cloudy
      - "\U000F0595" # partly-cloudy
      - "\U000F0596" # pouring
      - "\U000F0597" # rainy
      - "\U000F0F36" # snowy
      - "\U000F067F" # snowy-rainy
      - "\U000F0599" # sunny
      - "\U000F059D" # windy
      - "\U000F059E" # windy-variant
      - "\U000F0F38" # exceptional
      # moon phases
      - "\U000F0F61" # moon-first-quarter
      - "\U000F0F62" # moon-full
      - "\U000F0F63" # moon-last-quarter
      - "\U000F0F64" # moon-new
      - "\U000F0F65" # moon-waning-crescent
      - "\U000F0F66" # moon-waning-gibbous
      - "\U000F0F67" # moon-waxing-crescent
      - "\U000F0F68" # moon-waxing-gibbous
      # other icons
      - "\U000F10C2" # Temperature High
      - "\U000F10C3" # Temperature Low
      - "\U000F054B" # umbrella
      - "\U000F02E3" # Bed
      - "\U000F064D" # human-male
      - "\U000F0649" # human-female
      - "\U000F0C0D" # L circle
      - "\U000F0C37" # Z circle      
      - "\U000F04B9" # sofa
      - "\U000F04DB" # stop
      - "\U000F040A" # play
      - "\U000F03E4" # pause
      - "\U000F0643" # man
      - "\U000F1078" # woman
      - "\U000F00ED" # calendar
  - file: 'materialdesignicons-webfont.ttf'
    id: font_icons_tiny
    size: 32
    glyphs:
      - "\U000F005E" # arrow-up-thick
      - "\U000F0046" # arrow-down-thick
      - "\U000F059C" # Sunrise
      - "\U000F059B" # Sunset

display:
-   platform: t547
    update_interval: 10s
    #cycles_render: 20    # optional (default: 20): higher number -> less ghosting, crisper image, more time
    #cycles_invert: 20    # optional (default: 20): higher number -> more timef or full update, but mor burn-in protection
    id: t5_display
    rotation: 0
    lambda: |-
      // icon constants
      #define ICON_temp_high        "\U000F10C2"
      #define ICON_temp_low         "\U000F10C3"
      #define ICON_umbrella         "\U000F054B"
      #define ICON_bed              "\U000F02E3"
      #define ICON_human_male       "\U000F064D"
      #define ICON_human_female     "\U000F0649"
      #define ICON_alpha_l_circle   "\U000F0C0D"     
      #define ICON_alpha_z_circle   "\U000F0C37"      
      #define ICON_sofa             "\U000F04B9"
      #define ICON_man              "\U000F0643"
      #define ICON_woman            "\U000F1078"
      #define ICON_up               "\U000F005E"
      #define ICON_down             "\U000F0046"
      #define ICON_sunrise          "\U000F059C"
      #define ICON_sunset           "\U000F059B"
      #define ICON_calendar         "\U000F00ED"
      // positioning constants
      #define xRes 960
      #define yRes 540
      #define xCenter (xRes/2 + 40) // X position center
      #define pad 10
      #define celsiusSuperscript 12
      #define rowHeight 75
      #define temperatureCol 195
      #define humidityCol 300
      #define weatherCol 120
      #define weatherTempCorr 15

      // helper variables
      int y = 0;

      // === Date ===

      // time
      auto time = id(ntp).now();
      auto dayTime = id(hasun).state == "above_horizon";
      it.strftime(pad, 0, id(font_xlarge_bold), TextAlign::TOP_LEFT, "%H:%M", time);
      // date + nameday
      std::string dateFormat = generateDateFormat(time, id(nevnap).state);
      it.strftime(xRes - pad - 55, pad, id(font_medium_bold), TextAlign::TOP_RIGHT, dateFormat.c_str(), time);
      // moon phase
      auto moonIcon = moonToIcon(id(moon).state);
      it.printf(xRes - pad/2, pad, id(font_icons_small), TextAlign::TOP_RIGHT, moonIcon.c_str()); 

      // === LEFT - Calendar ===
      y = 150;
      it.printf(pad, y, id(font_icons_small), TextAlign::CENTER_LEFT, ICON_calendar); 
      if(id(calendar_message).state.length() > 0) {
        std::string start = id(calendar_start).state;
        struct tm tp;
        strptime(start.c_str(), "%Y-%m-%d %H:%M:%S", &tp);
        tp.tm_isdst = 0; // TODO: Day light saving.. will this need to be handled once the daylight saving goes off?
        time_t c_t = mktime(&tp);
        auto t = time::ha_time::from_c_tm(&tp, c_t);
        if (t.timestamp < time.timestamp + (86400*7) )  {
          it.strftime(77+10, y-15, id(font_medium), TextAlign::CENTER_LEFT, "%a", t);
          it.strftime(77+0, y+15, id(font_medium), TextAlign::CENTER_LEFT, "%H:%M", t);
          it.printf(77 + 109, y, id(font_big), TextAlign::CENTER_LEFT, "%.35s", id(calendar_message).state.c_str());
        } else {
          it.printf(77, y, id(font_big), TextAlign::CENTER_LEFT, "No events in 7 days");
        }
      }

      // === RIGHT - Weather ===

      y = 135;
      // current temperature
      if (!isnan(id(temperature).state)) {
        it.printf(xRes - 210, y, id(font_xlarge_bold), TextAlign::CENTER_RIGHT, "%.0f", id(temperature).state);
        it.printf(xRes - 210, y - celsiusSuperscript, id(font_large), TextAlign::CENTER_LEFT, "°C");
        if (id(temp_rising).state) {
          it.printf(xRes - 210, y + 3, id(font_icons_tiny), TextAlign::TOP_LEFT, ICON_up);
        }
        else if (id(temp_falling).state) {
          it.printf(xRes - 210, y + 3, id(font_icons_tiny), TextAlign::TOP_LEFT, ICON_down);
        }
      }
      // current condition icon
      auto conditionIcon = conditionToIcon(id(condition).state, dayTime);
      it.printf(xRes - pad, y, id(font_icons), TextAlign::CENTER_RIGHT, conditionIcon.c_str());
      y = 200;
      it.printf(xCenter + weatherCol, y, id(font_icons_tiny), TextAlign::BASELINE_RIGHT, ICON_sunrise);
      it.printf(xCenter + weatherCol, y, id(font_small), TextAlign::BASELINE_LEFT, "%s", id(sunrise).state.c_str());      
      it.printf(xCenter + weatherCol*2, y, id(font_icons_tiny), TextAlign::BASELINE_RIGHT, ICON_sunset);
      it.printf(xCenter + weatherCol*2, y, id(font_small), TextAlign::BASELINE_LEFT, "%s", id(sunset).state.c_str());  

      // === LEFT - room info ===
      
      // Living room / Nappali
      y = 290;
      it.printf(pad, y, id(font_icons_small), TextAlign::BASELINE_LEFT, ICON_sofa); 
      if (!isnan(id(temp_living).state)) {
        it.printf(temperatureCol, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.1f", id(temp_living).state);
        it.printf(temperatureCol, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(humidity_living).state)) {
        it.printf(humidityCol, y, id(font_medium), TextAlign::BASELINE_RIGHT, "%.0f", id(humidity_living).state);
        it.printf(humidityCol, y, id(font_small), TextAlign::BASELINE_LEFT, "%%");
      }
      // Bedroom / Háló
      y += rowHeight; // 350
      it.printf(pad, y, id(font_icons_small), TextAlign::BASELINE_LEFT, ICON_bed); 
      if (!isnan(id(temp_bedroom).state)) {
        it.printf(temperatureCol, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.1f", id(temp_bedroom).state);
        it.printf(temperatureCol, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(humidity_bedroom).state)) {
        it.printf(humidityCol, y, id(font_medium), TextAlign::BASELINE_RIGHT, "%.0f", id(humidity_bedroom).state);
        it.printf(humidityCol, y, id(font_small), TextAlign::BASELINE_LEFT, "%%");
      }
      // Kid 1 / Zita
      y += rowHeight; // 425
      it.printf(pad, y, id(font_icons_small), TextAlign::BASELINE_LEFT, ICON_alpha_z_circle); 
      if (!isnan(id(temp_zita).state)) {
        it.printf(temperatureCol, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.1f", id(temp_zita).state);
        it.printf(temperatureCol, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(humidity_zita).state)) {
        it.printf(humidityCol, y, id(font_medium), TextAlign::BASELINE_RIGHT, "%.0f", id(humidity_zita).state);
        it.printf(humidityCol, y, id(font_small), TextAlign::BASELINE_LEFT, "%%");
      }
      // Kid 2 / Luka
      y += rowHeight; // 500
      it.printf(pad, y, id(font_icons_small), TextAlign::BASELINE_LEFT, ICON_alpha_l_circle); 
      if (!isnan(id(temp_luka).state)) {
        it.printf(temperatureCol, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.1f", id(temp_luka).state);
        it.printf(temperatureCol, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(humidity_luka).state)) {
        it.printf(humidityCol, y, id(font_medium), TextAlign::BASELINE_RIGHT, "%.0f", id(humidity_luka).state);
        it.printf(humidityCol, y, id(font_small), TextAlign::BASELINE_LEFT, "%%");
      }

      // === MIDDLE - Locations ===

      it.line(humidityCol + 40, 220, humidityCol + 40, yRes);

      auto centerCol = (humidityCol + 40 + xCenter - 10) / 2;
      y = 290;
      it.printf(centerCol, y + rowHeight/4, id(font_icons_small), TextAlign::BASELINE_CENTER, ICON_man);
      y += rowHeight; // 350
      auto gaborLocationText = locationToHungarian(id(andrej_location).state, id(andrej_distance).state);
      it.printf(centerCol, y - rowHeight/4, id(font_medium), TextAlign::BASELINE_CENTER, "%s", gaborLocationText.c_str());
      y += rowHeight; // 425
      it.printf(centerCol, y + rowHeight/4, id(font_icons_small), TextAlign::BASELINE_CENTER, ICON_woman);
      y += rowHeight; // 500
      auto verusLocationText = locationToHungarian(id(mirta_location).state, id(mirta_distance).state);
      it.printf(centerCol, y - rowHeight/4, id(font_medium), TextAlign::BASELINE_CENTER, "%s", verusLocationText.c_str());

      it.line(xCenter - 10, 220, xCenter - 10, yRes);

      // === RIGHT - Forecast ===

      // Day of week
      y = 240;
      it.printf(xCenter + weatherCol, y, id(font_medium), TextAlign::BASELINE_CENTER, "%s", id(day1_dow).state.c_str());
      it.printf(xCenter + weatherCol*2, y, id(font_medium), TextAlign::BASELINE_CENTER, "%s", id(day2_dow).state.c_str());
      it.printf(xCenter + weatherCol*3, y, id(font_medium), TextAlign::BASELINE_CENTER, "%s", id(day3_dow).state.c_str());

      // Condition
      //y += 65; // 295
      //auto day1Icon = conditionToIcon(id(day1_condition).state, dayTime);
      //auto day2Icon = conditionToIcon(id(day2_condition).state, dayTime);
      //auto day3Icon = conditionToIcon(id(day3_condition).state, dayTime);
      //it.printf(xCenter + weatherCol, y, id(font_icons_small), TextAlign::BASELINE_CENTER, day1Icon.c_str());
      //it.printf(xCenter + weatherCol*2, y, id(font_icons_small), TextAlign::BASELINE_CENTER, day2Icon.c_str());
      //it.printf(xCenter + weatherCol*3, y, id(font_icons_small), TextAlign::BASELINE_CENTER, day3Icon.c_str());

      // High/low temperature
      y += 60; // 350
      it.printf(xCenter, y, id(font_icons_small), TextAlign::BASELINE_LEFT, ICON_temp_high);
      if (!isnan(id(day1_max).state)) {
        it.printf(xCenter + weatherCol + weatherTempCorr, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.0f", id(day1_max).state);
        it.printf(xCenter + weatherCol + weatherTempCorr, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(day2_max).state)) {
        it.printf(xCenter + weatherCol*2 + weatherTempCorr, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.0f", id(day2_max).state);
        it.printf(xCenter + weatherCol*2 + weatherTempCorr, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(day3_max).state)) {
        it.printf(xCenter + weatherCol*3 + weatherTempCorr, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.0f", id(day3_max).state);
        it.printf(xCenter + weatherCol*3 + weatherTempCorr, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      y += rowHeight; // 425
      it.printf(xCenter, y, id(font_icons_small), TextAlign::BASELINE_LEFT, ICON_temp_low);
      if (!isnan(id(day1_min).state)) {
        it.printf(xCenter + weatherCol + weatherTempCorr, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.0f", id(day1_min).state);
        it.printf(xCenter + weatherCol + weatherTempCorr, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(day2_min).state)) {
        it.printf(xCenter + weatherCol*2 + weatherTempCorr, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.0f", id(day2_min).state);
        it.printf(xCenter + weatherCol*2 + weatherTempCorr, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }
      if (!isnan(id(day3_min).state)) {
        it.printf(xCenter + weatherCol*3 + weatherTempCorr, y, id(font_large), TextAlign::BASELINE_RIGHT, "%.0f", id(day3_min).state);
        it.printf(xCenter + weatherCol*3 + weatherTempCorr, y - celsiusSuperscript, id(font_medium), TextAlign::BASELINE_LEFT, "°C");
      }

      // Thunder probability
      y += rowHeight; // 425
      it.printf(xCenter, y, id(font_icons_small), TextAlign::BASELINE_LEFT, ICON_storm);
      // 20mm precipitation is using the max bar height, which is 25px
      if (!isnan(id(day1_storm).state)) {
        auto prec1size = max(min(id(day1_storm).state * 25.0 / 20.0, 25.0), 1.0);
        it.filled_rectangle(xCenter + weatherCol - 45, y - prec1size, weatherCol - pad*2, prec1size);
        if (id(day1_storm).state > 1) {
          it.printf(xCenter + weatherCol + 3, y-prec1size-pad/2, id(font_medium), TextAlign::BASELINE_RIGHT, "%.0f", id(day1_storm).state);
          it.printf(xCenter + weatherCol + 3, y-prec1size-pad/2, id(font_small), TextAlign::BASELINE_LEFT, "%");
        } else if (id(day1_storm).state > 0) {
          it.printf(xCenter + weatherCol + 3, y-prec1size-pad/2, id(font_medium), TextAlign::BASELINE_CENTER, ". . .");
        }
      }
      if (!isnan(id(day2_storm).state)) {
        auto prec2size = max(min(id(day2_storm).state * 25.0 / 20.0, 25.0), 1.0);
        it.filled_rectangle(xCenter + weatherCol*2 - 45, y - prec2size, weatherCol - pad*2, prec2size);
        if (id(day2_storm).state > 1) {
          it.printf(xCenter + weatherCol*2 + 3, y-prec2size-pad/2, id(font_medium), TextAlign::BASELINE_RIGHT, "%.0f", id(day2_storm).state);
          it.printf(xCenter + weatherCol*2 + 3, y-prec2size-pad/2, id(font_small), TextAlign::BASELINE_LEFT, "%");
        } else if (id(day2_storm).state > 0) {
          it.printf(xCenter + weatherCol*2 + 3, y-prec2size-pad/2, id(font_medium), TextAlign::BASELINE_CENTER, ". . .");
        }
      }
      if (!isnan(id(day3_storm).state)) {
        auto prec3size = max(min(id(day3_storm).state * 25.0 / 20.0, 25.0), 1.0);
        it.filled_rectangle(xCenter + weatherCol*3 - 45, y - prec3size, weatherCol - pad*2, prec3size);
        if (id(day3_storm).state > 1) {
          it.printf(xCenter + weatherCol*3 + 3, y-prec3size-pad/2, id(font_medium), TextAlign::BASELINE_RIGHT, "%.0f", id(day3_storm).state);
          it.printf(xCenter + weatherCol*3 + 3, y-prec3size-pad/2, id(font_small), TextAlign::BASELINE_LEFT, "%");
        } else if (id(day3_storm).state > 0) {
          it.printf(xCenter + weatherCol*3 + 3, y-prec3size-pad/2, id(font_medium), TextAlign::BASELINE_CENTER, ". . .");
        }
      }

      // === Footer/debug ===

      //it.printf(xRes - pad, yRes - pad/2, id(font_small), TextAlign::BASELINE_RIGHT, "%.2fV/%.0f%%", id(batt_volt).voltage->state, id(batt).state);
      //it.printf(pad, yRes - pad/2, id(font_small), TextAlign::BASELINE_LEFT, "%s", icon);```

Error Log

```INFO ESPHome 2024.3.1
INFO Reading configuration /config/esphome/esphome-web-60e604.yaml...
INFO Detected timezone 'Australia/Brisbane'
INFO Detected timezone 'Australia/Brisbane'
INFO Generating C++ source...
INFO Compiling app...
Processing lilygodash (board: lilygo-t5-47-plus; framework: arduino; platform: platformio/espressif32@5.4.0)
--------------------------------------------------------------------------------
Library Manager: Installing Wire
INFO Installing Wire
HARDWARE: ESP32S3 240MHz, 320KB RAM, 16MB Flash
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5 
 - toolchain-xtensa-esp32s3 @ 8.4.0+2021r2-patch5
Dependency Graph
|-- AsyncTCP-esphome @ 2.1.3
|-- WiFi @ 2.0.0
|-- FS @ 2.0.0
|-- Update @ 2.0.0
|-- ESPAsyncWebServer-esphome @ 3.1.0
|-- ESPmDNS @ 2.0.0
|-- noise-c @ 0.1.4
|-- ArduinoJson @ 6.18.5
|-- Wire @ 2.0.0
|-- LilyGoEPD47 @ 0.3.0+sha.0f31685
Compiling .pioenvs/lilygodash/src/main.cpp.o
Compiling .pioenvs/lilygodash/lib64d/WiFi/WiFiGeneric.cpp.o
In file included from src/main.cpp:104:
src/common.h:4:47: error: 'ESPTime' is not a member of 'esphome::time'
 std::string generateDateFormat(esphome::time::ESPTime time, std::string nameday) {
                                               ^~~~~~~
src/common.h:4:47: note: suggested alternative:
In file included from src/esphome/components/display/display.h:10,
                 from src/esphome.h:18,
                 from src/main.cpp:3:
src/esphome/core/time.h:17:8: note:   'esphome::ESPTime'
 struct ESPTime {
        ^~~~~~~
In file included from src/main.cpp:104:
src/common.h:4:73: error: expected primary-expression before 'nameday'
 std::string generateDateFormat(esphome::time::ESPTime time, std::string nameday) {
                                                                         ^~~~~~~
src/common.h:4:82: error: expected ',' or ';' before '{' token
 std::string generateDateFormat(esphome::time::ESPTime time, std::string nameday) {
                                                                                  ^
Compiling .pioenvs/lilygodash/lib64d/WiFi/WiFiMulti.cpp.o
/config/esphome/esphome-web-60e604.yaml: In lambda function:
/config/esphome/esphome-web-60e604.yaml:506:70: error: no match for call to '(std::__cxx11::string {aka std::__cxx11::basic_string<char>}) (esphome::ESPTime&, std::__cxx11::string&)'
       std::string dateFormat = generateDateFormat(time, id(nevnap).state);
                                                                      ^
/config/esphome/esphome-web-60e604.yaml:521:24: error: 'esphome::time::ha_time' has not been declared
         auto t = time::ha_time::from_c_tm(&tp, c_t);
                        ^~~~~~~
*** [.pioenvs/lilygodash/src/main.cpp.o] Error 1
========================== [FAILED] Took 2.95 seconds ==========================```

@zagnuts
Copy link

zagnuts commented Apr 8, 2024

Is it possible that the bit that goes:

  build_path: /config/esphome/.esphome/basic-clock/
  includes:
    - common.h

Is throwing the proverbial wrench in the gears? Not sure if this is of any help, but the following works for me:

esphome:
  name: ${esp_hostname}
  friendly_name: ${esp_hostname}
  platformio_options:
    board_build.f_flash: 80000000L
#    board_upload.flash_size: 16MB
    board_build.flash_mode: qio
    board_build.psram_type: opi
    board_build.partitions: default_16MB.csv
    board_build.arduino.memory_type: qio_opi
  on_boot:
    priority: -100
    then:
      - pcf8563.read_time

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: arduino
    version: latest

Cheers

@xxLeoxx93
Copy link

Did anyone get the touchscreen to work?
Used this but no luck so far:

touchscreen:
  - platform: lilygo_t5_47
    id: lilygo_touchscreen
    interrupt_pin: GPIO47
    address: 0x5A

and

  - platform: touchscreen
    name: Top Left Touch Button
    x_min: 0
    x_max: 1000
    y_min: 0
    y_max: 1000
    on_press:
      - logger.log: Touch1 Pressed

@alexwide
Copy link

@xxLeoxx93 i foud a working solution for the touchscreen

touchscreen:
  - platform: gt911
    id: lilygo_touchscreen
    interrupt_pin: GPIO47
    address: 0x5D
    i2c_id: bus_a
    setup_priority: -100
    on_touch:
      then:
        - component.update: t5_display

@xxLeoxx93
Copy link

@alexwide
Thank you so much! Works perfectly!
How dod you find the platform: gt911 part?
I also tried the same adress and everything but i was missing the correct platform.
Thanks again!

@PabloFFF93
Copy link

PabloFFF93 commented May 7, 2024

Hi,
For a while everything worked fine.
I wanted to upload the change and now this appears:

INFO Compiling app...
Processing t5lily (board: lilygo_t_display_s3; framework: arduino; platform: platformio/espressif32@5.4.0)

UnknownBoard: Unknown board ID 'lilygo_t_display_s3'

What to do now?

@ex-nerd
Copy link

ex-nerd commented May 9, 2024

one thing that I can't seem to figure out is how to set up external buttons

@dxdr You're doing better than me. Can you share an image of how you hooked things up to the molex connector? I was trying for capacitive touch that the S3 is supposed to support (I got as far as filing a bug: Xinyuan-LilyGO/LilyGo-EPD47#113) but at this point I'd love even a single external button.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests