Using TTGO epaper display with ESPHome

I am something of a newb in the world of Home Assistant, ESPHome and ePaper displays. I thought it might be useful to share my experiences, since my project is now running nicely and doing what I wanted it to do.

The display in question is the LILYGO® TTGO T5 V2.2 ESP32 2.9" EPaper. There is information about the exact model at which is of some use, but please note that the Pin Reference Description seems to be largely erroneous. If you are thinking of using the ESP 32 on board for an additional purpose, such as a temperature sensor, and need to know the GPIO pin numbers, you would be advised to consult the schematic at

My starting point was the very helpful description of the Waveshare epaper display at As a newb I was puzzled by the mention of 4-wire SPI, and I spent some time trying to find out whether the GPIO pins on my model were the same. It could be that this does not matter, because the pins are assigned by the code, but I inferred that on my device the CLK pin was 18 and the MOSI 23. This seems to work perfectly well for me.

The next question was which ESP32 borad to select when setting up the ESPHome yaml. I have tried both the esp32dev and the ttgo-t1 and they both worked perfectly well.

I set up the yaml with a basic display, with a lot of excellent help from, uploaded it, and had a good OTA set-up. The main challenge for me was to use states from Home Assistant which were strings rather than values. Initially I went down the MQTT route (see, and created an automation in Home Asssistant to publish to MQTT. This worked, but it was laborious and seemed to work against the principles of ESPHome! My son pointed out that in fact it is simple: use the Home Assistant API and then platform: homeassistant within the relevant text sensor statement. This is much cleaner and neater.

My project was to build a display which would give basic weather data plus indoor temperature. My ESPHome code is as follows:

  name: epaper2
  platform: ESP32
  board: esp32dev

  ssid: "MY_SSID"
  password: "MY PASSWORD"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
    ssid: "Epaper2 Fallback Hotspot"
    password: "xxxxxxxxxx"


# Enable logging

# Enable Home Assistant API
  password: "PASSWORD"

  password: "PASSWORD"

  clk_pin: 18
  mosi_pin: 23

  - file: "Ldfcomicsans-jj7l.ttf"
    id: font_cs
    size: 20
  - file: "arial_th.ttf"
    id: font_arth
    size: 16

  - platform: homeassistant
    entity_id: sensor.sn1_temperature
    id: kit_temp
  - platform: homeassistant
    entity_id: sensor.weathermet_temperature
    id: out_temp
  - platform: homeassistant
    entity_id: sensor.weathermet_feels_like_temperature
    id: feels_like
  - platform: homeassistant
    entity_id: sensor.weathermet_wind_speed
    id: wind_speed
  - platform: homeassistant
    entity_id: sensor.weathermet_wind_gust
    id: wind_gust

  - platform: dht
    pin: 26
    model: "DHT22"
      name: "ePaper Temperature"
      id: eptem
      name: "ePaper Humidity"
      id: ephu
    update_interval: 60s

  - platform: homeassistant
    entity_id:  sensor.weathermet_wind_direction
    id: wind_dir

  - platform: waveshare_epaper
    cs_pin: 5
    dc_pin: 19
    busy_pin: 4
    reset_pin: 12
    model: 2.90in
    full_update_every: 180
    rotation: 270
    lambda: |-
      it.print(0, 0, id(font_cs), "Conditions:");
      it.printf(0, 42, id(font_arth), "Inside:");
      it.printf(55, 40, id(font_cs), "%.1fc", id(eptem).state);
      it.printf(120, 42, id(font_arth), "Outside:");
      it.printf(170, 40, id(font_cs), "%.1fc", id(out_temp).state);
      it.printf(120, 68, id(font_arth), "feels like:");
      it.printf(178, 68, id(font_arth), "%.1fc", id(feels_like).state);
      it.printf(0, 102, id(font_arth), "Wind kph:");
      it.printf(75, 100, id(font_cs), "%.1f", id(wind_speed).state);
      it.printf(105, 100, id(font_arth), " - ");
      it.printf(118, 102, id(font_arth), "%.1f", id(wind_gust).state);
      it.printf(165, 100, id(font_cs), "%s", id(wind_dir).state.c_str());

You will see that I have also included a local temperature/humidity sensor, using the ESP 32. This is a simple DHT22 sensor, using pin 26 (which shows on the manufacturer’s description as IO13 for some reason).

Finally, I housed the display in a freeform stand which I made from thermoplastic and four screws. My only tip to pass on here is that I have found that it helps to put the thermosplastic in the freezer for 15 minutes or so before drilling holes. The drill bit works more cleanly if the material is as rigid as possible.

epaper (2)

That’s it. I hope this can help other newbs like myself, and of course I am more than happy to listen to any suggestions for improvements.


Hi, I have the T5 V2.3 and get esphome to work with WLAN, Bluetooth etc, the only exception is the Display :frowning:

I adapted the pins as per your first link, and simplified the Display output to just draw a line or say Hello World as per ESPhome sample, but no reaction of the Display after uploading.

Would you have any hint or tip how to check further?

Hi. Can you show us your ESPHome code?

Nice to see someone else has integrated that as well. I put that (V2.2) as temperature display, works quite well! I designed / printed 3D case and tried to get it working with battery (makes no sense, i think) so then I had to route little cable for power input.


That looks pretty cool, Tommi Savikko . Does the graphic change depending on conditions?

Yep, penguin gets scarf when it is cold, removes when it is little warmer and sunglasses when it is summer :slight_smile:

Reason for the graphic is that there was empty slot and it needed to be filled :stuck_out_tongue:

There are few things I’m planning to add there (for example work shifts from google calendar) but currently it serves the purpose very well.

I just uploaded case design to Thingiverse:


Hello there,

Could you share a bit more than just this picture ? :sweat_smile:

I would love to see your code even if not ready to be shared on your github…

Thanks !


Here you go:


Thanks, that’s amazing :slight_smile:
i was “worried” to fry my TTGO display since official doc doesn’t mention the 2.9 size for that brand…

That full example will help so much !
Thanks !

1 Like

One observation, i had this display on semi direct sunlight. Display seems to fade, have to move display somewhere else.

1 Like

This is maybe off topic but still you guys might have solved connecting your ESP to a Mac using a
USB-C —> USB-C cable.

I am running OSX 10.15.4, The Silicon Laboratories drivers are installed, and ESPHomeFlasher is working, recognizing a regular USB-connection to the ESP via an USB-C —> USB adaptor.

Still the USB-C —> USB-C connection does not recognize this USB-C connected ESP.
I have tested three different cables with no luck.
I am out of ideas!

Because of the sun i had to relocate display and turn it in portrait mode. Seems to be quite nice on that orientation as well:


I’ve just got one of the T5 V2.3 boards as well.

Its partially working with the pins from this guide:

  - platform: waveshare_epaper
    model: "2.13in-ttgo"
    cs_pin: 5
    dc_pin: 17
    busy_pin: 4
    reset_pin: 16

But the background is almost completely black, which makes the text almost completely illegible:

I’m assuming there’s some setting I’m missing or have wrong, does anyone have any suggestions of what it might be?

I just realised now that it only managed to print Hello World! to the screen once and after changing the lambda to something else, its no longer updating.

And success!

After digging around the esphome repo on github, I noticed that there’s another model of this display, 2.13in-ttgo-b73.

The final working config is:

  - platform: waveshare_epaper
    model: 2.13in-ttgo-b73
    cs_pin: 5
    dc_pin: 17
    busy_pin: 4
    reset_pin: 16

Thanks @davewongillies for your posts. I am glad you got the display to work.

I have a 2.13in display which uses the b73 variant. It works perfectly well in terms of displaying the data it should be displaying (ignore the nan in the pic, just a non-connected sensor), but the display itself is not very clear and shows traces of data which were displayed months ago in an earlier version. It is almost as though the refresh function does not work properly. Either that,or the unit is defective. I’m posting this here in case anyone else has encountered the same problem or can offer a solution?


My working config is as follows:

  - platform: waveshare_epaper
    cs_pin: 5
    dc_pin: 17
    busy_pin: 4
    reset_pin: 16
    model: 2.13in-ttgo-b73
    update_interval: 60min
    full_update_every: 2
    rotation: 270
    id: my_display

I have played around with the ‘update_interval’ and ‘full_update_every’ parameters, but have found no settings which corrrect the problem.

I have the same unit and problem. I stopped working on mine some time ago. The display came with an image on it that erased easily. But my updates kinda burnt-in. My guess was that I was continually updating the screen causing the ink to become more and more heavily plastered to some points.

I noticed the same problem with the ‘burn in’. I think the page re-fresh caused by the code doesn’t fully re-fresh the page. Hitting the the reset button seems to clear it out again.

There seems to be a bug on the 2.13in-ttgo-b73 code on esphome which causes burn in. Please refer to this bug report

Seems that esphome is not powering off the display after refreshing, which is known to cause burn in in this device.

1 Like

Did anyone succeed in the workaround for the 2.13 inch version which was posted there?

I have changed the code as mentioned in the waveshare_epaper.cpp but that didn’t change the problem for me.

EDIT: It does work for me now, I had to make the waveshare_epaper.cpp read only after changing it otherwise it would get overwritten.