Use ESPHome with e-ink Displays to blend in with your home decor!

Yeah, thanks! It’s great, but how could I miss that all so far…? :thinking:

Hello to all,

I’m having an issue with my e-paper display. I’m using the 2.7" Waveshare E-paper hat compatible with a Pi. The back is marked rev2.2. 264x176, 2.7inch E-Ink display HAT for Raspberry Pi, SPI interface | WF10190CZ22

I can display text just fine. However, the text and the alignment (default Left) are mirrored for some reason. I can’t seem to find a mirror option in display component or waveshare driver components.


display:
  - platform: waveshare_epaper
    id: eink_display
    cs_pin: GPIO15
    dc_pin: GPIO13
    # busy_pin: D4
    reset_pin: GPIO12
    model: 2.70inv2
    update_interval: never
    # rotation: 90
    
    lambda: |-
          it.printf(65, 10, id(font1), TextAlign::TOP_LEFT, "%s", "4 juli 2024");

Any ideas?

Edit: attached a picture, it says more than a thousand words :smile:
Edit: My other display (a larger 7.5" v3) works just fine with the same lambda… :unamused:

Have you tried to set a value for the rotation?
In your config it seems to be commented out.

Thanks for the guide, this is my version and so for its working great!

I have one issue through, and its the power. Now I´m powering it witha Power bank hidden behind the frame. It works, but after some 12-15 hourers the power bank stop to output power (but it isn´t empty). If reconnect the cord to the power bank it start to work again.

Anyone have a solution for this?

1 Like

Hi!

I’m struggling with my own e-ink D. version.
I’m able to display text, but only FIXED text; each time I try to show a variable, text sensor for example, it doesn’t appear.

configuration.yaml

  - trigger:
      - platform: event #update at startup#
        event_type: homeassistant_started
      - platform: time_pattern
        hours: "/4"
    action:
      - service: weather.get_forecasts
        data:
          type: daily
        target:
          entity_id: weather.forecast_casa
        response_variable: daily
      - variables:
          today: "{{ daily['weather.forecast_casa'].forecast[0] }}"
    sensor:
      - name: "Weather Today Temp"
        unique_id: forecasted_high_temp
        icon: mdi:thermometer-low
        state: "{{ today.temperature }}"
        unit_of_measurement: °C
      - name: "Weather Today Lower Temp"
        unique_id: forecasted_low_temp
        icon: mdi:thermometer-minus
        state: "{{ today.templow }}"
        unit_of_measurement: °C
      - name: "Weather Today Rain Chance"
        unique_id: forecasted_ran_chance
        icon: mdi:cloud-percent
        state: "{{ today.precipitation }}"
        unit_of_measurement: "%"
      - name: "Weather Today Condition"
        unique_id: forecasted_condition
        icon: mdi:weather-partly-cloudy
        state: "{{ today.condition }}"

einkdisplayone.yaml

esphome:
  name: "einkdisplayone"
  friendly_name: EinkDisplayOne
  on_boot:
      priority: 200.0
      then:
        - component.update: eink_display
        - wait_until:
            condition:
              lambda: 'return id(data_updated) == true;'
              # Wait a bit longer so all the items are received
        - delay: 5s
        - logger.log: "Initial sensor data received: Refreshing display..."
        - lambda: 'id(initial_data_received) = true;'
        - script.execute: update_screen

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "VLbw/7BICoq9bIIWfOx33vvepdmUQ+zgGzipi4goInk="

ota:
  - platform: esphome
    password: "88ab2520c9fc5c1b652b15db2612011b"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true
  manual_ip:
    static_ip: 192.168.1.145
    gateway: 192.168.1.1
    subnet: 255.255.255.0

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

web_server:
  port: 80
  include_internal: true

captive_portal:

# Global variables for detecting if the display needs to be refreshed. (Thanks @paviro!)
globals:
  - id: data_updated
    type: bool
    restore_value: no
    initial_value: 'false'
  - id: initial_data_received
    type: bool
    restore_value: no
    initial_value: 'false'
  - id: recorded_display_refresh
    type: int
    restore_value: yes
    initial_value: '0'
 

time:
  - platform: homeassistant
    id: homeassistant_time
    on_time:
      - seconds: 0
        minutes: /1
        then:
          - if:
              condition:
                lambda: 'return id(data_updated) == true;'
              then:
                - if:
                    condition:
                      binary_sensor.is_on: motion_detected
                    then:
                      - logger.log: "Sensor data updated and activity in home detected: Refreshing display..."
                      - script.execute: update_screen
                    else:
                      - logger.log: "Sensor data updated but no activity in home - skipping display refresh."
              else:
                - logger.log: "No sensors updated - skipping display refresh."

# Script for updating screen - Refresh display and publish refresh count and time. (Thanks @paviro!)
script:
  - id: update_screen
    then:
      - lambda: 'id(data_updated) = false;'
      - component.update: eink_display
      - lambda: 'id(recorded_display_refresh) += 1;'
      #- lambda: 'id(display_last_update).publish_state(id(homeassistant_time).now().timestamp);'



font:
  - file: "gfonts://Inter@900"
    id: big
    size: 60
  - file: "gfonts://Inter@900"
    id: medium
    size: 30
  - file: "gfonts://Inter@700"
    id: small
    size: 20
  - file: "gfonts://Inter@700"
    id: tiny
    size: 14

  # Include Material Design Icons font
  # Thanks to https://community.home-assistant.io/t/display-materialdesign-icons-on-esphome-attached-to-screen/199790/16
  - file: 'fonts/materialdesignicons-webfont.ttf'
    id: font_mdi_large
    size: 96
    glyphs: &mdi-weather-glyphs
      - "\U000F0590" # mdi-weather-cloudy
      - "\U000F0F2F" # mdi-weather-cloudy-alert
      - "\U000F0E6E" # mdi-weather-cloudy-arrow-right
      - "\U000F0591" # mdi-weather-fog
      - "\U000F0592" # mdi-weather-hail
      - "\U000F0F30" # mdi-weather-hazy
      - "\U000F0898" # mdi-weather-hurricane
      - "\U000F0593" # mdi-weather-lightning
      - "\U000F067E" # mdi-weather-lightning-rainy
      - "\U000F0594" # mdi-weather-night
      - "\U000F0F31" # mdi-weather-night-partly-cloudy
      - "\U000F0595" # mdi-weather-partly-cloudy
      - "\U000F0F32" # mdi-weather-partly-lightning
      - "\U000F0F33" # mdi-weather-partly-rainy
      - "\U000F0F34" # mdi-weather-partly-snowy
      - "\U000F0F35" # mdi-weather-partly-snowy-rainy
      - "\U000F0596" # mdi-weather-pouring
      - "\U000F0597" # mdi-weather-rainy
      - "\U000F0598" # mdi-weather-snowy
      - "\U000F0F36" # mdi-weather-snowy-heavy
      - "\U000F067F" # mdi-weather-snowy-rainy
      - "\U000F0599" # mdi-weather-sunny
      - "\U000F0F37" # mdi-weather-sunny-alert
      - "\U000F14E4" # mdi-weather-sunny-off
      - "\U000F059A" # mdi-weather-sunset
      - "\U000F059B" # mdi-weather-sunset-down
      - "\U000F059C" # mdi-weather-sunset-up
      - "\U000F0F38" # mdi-weather-tornado
      - "\U000F059D" # mdi-weather-windy
      - "\U000F059E" # mdi-weather-windy-variant
      - "\U000F1508" # mdi-water-off-outline
      - "\U000F0E0A" # mdi-water-outline
      - "\U000F1503" # mdi-water-alert-outline 
      - "\U000F081D" # mdi-fan-off 
      - "\U000F1B5A" # mdi-weather-dust                
      - "\U000F02D6" # mdi-help   
      - "\U000F0717" # mdi-snowflake  
      - "\U000F0F29" # mdi-snowflake-alert          
 
  - file: 'fonts/materialdesignicons-webfont.ttf'
    id: font_mdi_medium
    size: 36
    glyphs: *mdi-weather-glyphs


#********************************** Create sensors **********************************

# Check if motion is detected to switch on the screen
binary_sensor:
  - platform: homeassistant
    entity_id: binary_sensor.weatherman_motion_detected
    id: motion_detected

sensor:
  - platform: homeassistant
    id: eink_forecasted_temperature
    entity_id: sensor.forecasted_high_temp
#  - platform: template
#    name: "Weatherman - Display Last Update"
#    device_class: timestamp
#    entity_category: "diagnostic"
#    id: display_last_update

text_sensor:
  - platform: homeassistant
    id: eink_forecasted_condition           #id sensor to be used here in the display section
    entity_id: sensor.forecasted_condition  #id sensor from configutaion.yaml

  - platform: homeassistant
    id: eink_portone_status      
    entity_id: sensor.sensor_contact_portone_contact

#********************************** ePaper ESP Board **********************************

# Pins for Waveshare ePaper ESP Board
spi:
  clk_pin: GPIO13
  mosi_pin: GPIO14

# Now render everything on the ePaper screen.
display:
  - platform: waveshare_epaper
    id: eink_display
    cs_pin: GPIO15
    dc_pin: GPIO27
    busy_pin: GPIO25
    reset_pin: GPIO26
    reset_duration: 2ms
    #model: 7.50inV2
    model: 7.50in-bV2
    update_interval: never
    rotation: 270°
    lambda: |-
      // Map weather states to MDI characters.
      std::map<std::string, std::string> weather_icon_map
        {
          {"cloudy", "\U000F0590"},
          {"cloudy-alert", "\U000F0F2F"},
          {"cloudy-arrow-right", "\U000F0E6E"},
          {"fog", "\U000F0591"},
          {"hail", "\U000F0592"},
          {"hazy", "\U000F0F30"},
          {"hurricane", "\U000F0898"},
          {"lightning", "\U000F0593"},
          {"lightning-rainy", "\U000F067E"},
          {"night", "\U000F0594"},
          {"night-partly-cloudy", "\U000F0F31"},
          {"partlycloudy", "\U000F0595"},
          {"partly-lightning", "\U000F0F32"},
          {"partly-rainy", "\U000F0F33"},
          {"partly-snowy", "\U000F0F34"},
          {"partly-snowy-rainy", "\U000F0F35"},
          {"pouring", "\U000F0596"},
          {"rainy", "\U000F0597"},
          {"snowy", "\U000F0598"},
          {"snowy-heavy", "\U000F0F36"},
          {"snowy-rainy", "\U000F067F"},
          {"sunny", "\U000F0599"},
          {"sunny-alert", "\U000F0F37"},
          {"sunny-off", "\U000F14E4"},
          {"sunset", "\U000F059A"},
          {"sunset-down", "\U000F059B"},
          {"sunset-up", "\U000F059C"},
          {"tornado", "\U000F0F38"},
          {"windy", "\U000F059D"},
          {"windy-variant", "\U000F059E"},
          {"fan-off", "\U000F081D"},    
          {"weather-windy", "\U000F059D"},  
          {"weather-hurricane", "\U000F0898"},          
          {"weather-dust", "\U000F1B5A"},
          {"help", "\U000F02D6"},   
          {"water-off-outline", "\U000F1508"}, 
          {"water-outline", "\U000F0E0A"}, 
          {"water-alert-outline", "\U000F1503"},     
          {"snowflake", "\U000F0717"}, 
          {"snowflake-alert", "\U000F0F29"},                                                                      
        };

      it.line(20, 20, 600, 20);

      it.strftime(240, 50, id(medium), TextAlign::CENTER_HORIZONTAL, "%A %B %d, %Y", id(homeassistant_time).now());   //Date 
      //it.strftime(240, 90, id(big), TextAlign::CENTER_HORIZONTAL, "%I:%M%p", id(homeassistant_time).now());         //Time

      it.printf(240, 290, id(small), TextAlign::TOP_CENTER, "...FIXED TEXT...");

      it.printf(240, 390, id(small), TextAlign::TOP_CENTER, "Text sensor: %s", id(eink_forecasted_condition).state.c_str());
      
      it.printf(240, 440, id(medium), TextAlign::CENTER_HORIZONTAL,"%s",weather_icon_map[id(eink_forecasted_condition).state.c_str()].c_str());

      it.printf(240, 480, id(small), TextAlign::TOP_CENTER, "Sensor: %s", id(eink_portone_status).state.c_str());

      it.printf(240, 700, id(tiny), TextAlign::TOP_CENTER, "%.0°", id(eink_forecasted_temperature).state);

Variables eink_forecasted_condition, eink_forecasted_temperature, eink_portone_status are not shown, neither as icon or text.
(homeassistant_time).now() is the only variable that actually is shown.

These sensors work properly in HA dashboard.

I’m clearly using wrong some home assistant basics sensor configuration.

If some one can help on my issue I’ll very appreciate!

Would you be comfortable sharing your code? This looks excellent…!

curious how you implemented the epaper days operating on battery in HA ?

As a Formula 1 enthusiast, I decided to set up a second E-ink display at home that shows information about the next race and upcoming races.

What I’ve noticed is that, since it only updates once a day, the image can sometimes appear a bit “grainy.” This could likely be resolved by updating the screen more frequently, but I haven’t felt the need for it, and the screen will last longer this way.

2 Likes

Is anyone using the 3d printed battery and board holder that @jjansen85 kindly provided a link to? Im trying to find a suitable lipo battery while ordering the hardware to make one of these displays, but as i havent had the holder printed yet (don’t own a 3d printer) I don’t know what lipo battery to order. Are the additional 4 standoffs within the holder design for a battery holder of some sort? I can see 4 of them must be for mounting the Firebeetle esp32 board. Are the other 4 for mounting the waveshare epaper driver board? Does the lipo battery just sit in with the boards without being fixed in place?Any pictures of the internals would be a help, thanks!

1 Like

Correct, 4 standoffs for mounting the firebeetle and 4 for mounting the waveshare driver.

I just used double sided tape to fix the battery inside the enclosure.
I used a 3700mAh battery of 10cm long and 3.3cm wide
https://www.amazon.nl/dp/B08215B4KK

Great, thank you for the quick reply! Out of interest, how many days of runtime did you get from the battery in the end?

Not sure, but around 9 months

1 Like

@jjansen85, if you don’t mind me asking are you connecting the waveshare driver to the GDI on the firebeetle? If yes, what are you using for that connection? :slight_smile:

No, connected according GitHub - lmarzen/esp32-weather-epd: A low-power E-Paper weather display powered by an ESP32 microcontroller. Utilizes the OpenWeatherMap API.

1 Like

Really? I had a much bigger usb powerbank that run out in days. How many refreses a day (rough estimate) did you have? May also be that the 3 color version I have is more power hungry though. It has a really long refresh cycle.

One update every hour. Update takes about 30 seconds.
During the night it does sleep for 7 hours (no screen updates)

I have 5 min updates (if needed, with more changing data that is often needed) and sleeping at night, so that is already accounting for a 12x increase.

Hi, is there a method to connect firebeetle 2 to Esphome? I want to switch from a waveshare to firebeetle but I can’t do it

Hi

I just bought the Waveshare e-ink and a Waveshare ESP32

I read this thread and it says “Upload files” but how does one actually do this.

I connected it to my computer, it pops up a new serial Port COM5, if i connect to this with Putty and 115200 as the speed, all i get is dots like this …

I need to be able to access and change parameters for it to connect to my wifi, i guess, when it is connected to my wifi i can do FTP or something into it to change files ?

Can someone throw me a lifeline and point me in the right direction :slight_smile:

You really need to read up on how ESPHome works but the initial flash of your device can be done from https://web.esphome.io - assuming you have the right driver installed for it to work. There’s tons of tutorials on this but outside the scope of this thread which is far more specific.

1 Like