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…!