Elecrow crowpanel 2.9 epaper

Hallo, hat hier jemand schon mal das crowpanel 2.9 epaper zum Laufen bekommen? Bekomme kein displayrefresh. Vermutlich ist der busygpin nicht richtige angesteuert aber ich weiß nicht wie ich es hinbekomme.

hier die test Yaml. Display bootet dann auch, macht aber keinen refresh.

Zusammenfassung

output:

  • platform: gpio

    pin: GPIO7

    id: epd_power

esphome:

name: eink_test

on_boot:

priority: 800

then:

  - output.turn_on: epd_power

  - delay: 200ms

esp32:

board: esp32-s3-devkitc1-n8r8

framework:

type: esp-idf

flash_size: 8MB

logger:

wifi:

ssid: !secret wifi_ssid

password: !secret wifi_password

font:

  • file: “gfonts://Roboto”

    id: font1

    size: 22

status_led:

pin: GPIO41

spi:

miso_pin: GPIO13

mosi_pin: GPIO40

clk_pin: GPIO39

display:

  • platform: waveshare_epaper

    id: eink_display

    cs_pin: GPIO10

    dc_pin: GPIO46

    reset_pin: GPIO47

    busy_pin:

    number: GPIO48

    inverted: true

    model: 2.90inv2-r2

    rotation: 90

    update_interval: 10s

    lambda: |-

    it.print(0, 10, id(font1), “TEST OK”);

Ich hab es mittlerweile zum laufen bekommen. ist als Müllkalender eingerichtet und aktualisiert sich alle 24std um 1:00 Uhr neu um die tage korrekt anzuzeigen. War viel hilfe von KI aber jetzt läufts.

muell-eink.yaml in ESPHome

globals:

  • id: is_update_mode
    type: bool
    restore_value: no
    initial_value: ‘false’

output:

  • platform: gpio
    pin: GPIO42
    id: sd_card_power

esphome:
name: eink-muell
on_boot:
priority: 900
then:
- output.turn_off: sd_card_power # Schaltet SD-Stromkreis ab
- delay: 1s
- switch.turn_on: display_power

  - lambda: |-
      if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT0) {
        ESP_LOGI("custom", "Manuelles Aufwachen per Knopf - Update-Modus aktiv!");
        id(is_update_mode) = true;
      }
  
  # WLAN-Verbindung abwarten
  - wait_until:
      condition:
        api.connected:
      timeout: 120s

  # Schritt 3. Update Display
  - delay: 2s
  - component.update: eink_display
  - delay: 15s 
  
  # Schritt 4: Schlafen legen mit Update-Pause
  - if:
      condition:
        lambda: 'return id(is_update_mode);'
      then:
        - logger.log: "Warte 4 Minuten auf OTA-Update..."
        - delay: 240s
  
  - if:
      condition:
        lambda: 'return id(ha_time).now().is_valid();'
      then:
        - deep_sleep.enter:
            id: deep_sleep_ctrl
            until: "01:00:00"
            time_id: ha_time
      else:
        - deep_sleep.enter:
            id: deep_sleep_ctrl
            sleep_duration: 1h

esp32:
board: esp32-s3-devkitc1-n8r8
framework:
type: arduino
flash_size: 8MB

switch:

  • platform: gpio
    pin: GPIO07
    id: display_power
    restore_mode: ALWAYS_ON

logger:

api:
encryption:
key: !secret muell_api_key

ota:

  • platform: esphome
    password: !secret muell_ota_password

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

font:

  • file: “gfonts://Oswald”
    id: font_big
    size: 28
    glyphs:
    • '!"%()+=,-_.:;? ’ # Die gängigsten Satzzeichen
    • ‘0123456789’ # Zahlen
    • ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’
    • ‘abcdefghijklmnopqrstuvwxyz’
    • ‘ÄÖÜäöüß’ # Deutsche Umlaute und das scharfe S
  • file: “gfonts://Oswald”
    id: font_small
    size: 20
    glyphs:
    • '!"%()+=,-_.:;? ’ # Die gängigsten Satzzeichen
    • ‘0123456789’ # Zahlen
    • ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’
    • ‘abcdefghijklmnopqrstuvwxyz’
    • ‘ÄÖÜäöüß’ # Deutsche Umlaute und das scharfe S
  • file: “gfonts://Roboto”
    id: font_tiny
    size: 10
    glyphs:
    • '!"%()+=,-_.:;? ’ # Die gängigsten Satzzeichen
    • ‘0123456789’ # Zahlen
    • ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’
    • ‘abcdefghijklmnopqrstuvwxyz’
    • ‘ÄÖÜäöüß’ # Deutsche Umlaute und das scharfe S
  • file: “https://github.com/Templarian/MaterialDesign-Webfont/raw/master/fonts/materialdesignicons-webfont.ttf
    id: icon_font
    size: 45
    glyphs:
    • “\U000F0A7A” # Restmüll (Trash Can)
    • “\U000F1CCC” # Papiertonne (Container/Box)
    • “\U000F044C” # Gelber Sack (Recycle-Variante)

sensor:

  • platform: homeassistant
    id: t0_tage
    entity_id: sensor.muell_termin_0_tage
  • platform: homeassistant
    id: t1_tage
    entity_id: sensor.muell_termin_1_tage
    time:
  • platform: homeassistant
    id: ha_time
    timezone: Europe/Berlin

text_sensor:

  • platform: homeassistant
    id: t0_name
    entity_id: sensor.muell_termin_0
  • platform: homeassistant
    id: t1_name
    entity_id: sensor.muell_termin_1

status_led:
pin: GPIO41

spi:
clk_pin: GPIO12
mosi_pin: GPIO11

display:

  • platform: waveshare_epaper
    id: eink_display
    cs_pin: GPIO45
    dc_pin: GPIO46
    reset_pin: GPIO47
    busy_pin: GPIO09
    model: 2.90inv2
    rotation: 270
    full_update_every: 10
    update_interval: never
    lambda: |-
    it.fill(Color::BLACK); // Hintergrund weiß (wegen Invertierung)

    // Header
    it.print(10, -3, id(font_big), Color::WHITE, “Müllabfuhr”);
    it.line(0, 35, 296, 35, Color::WHITE);

    // Icon-Logik Funktion
    auto get_icon = (std::string name) → const char* {
    // Wandelt Text in Kleinbuchstaben um für sicherere Suche
    std::transform(name.begin(), name.end(), name.begin(), ::tolower);

    if (name.find("haus") != std::string::npos)   return "\U000F0A7A";
    if (name.find("papier") != std::string::npos) return "\U000F1CCC";
    if (name.find("gelb") != std::string::npos)   return "\U000F044C";
    return "\U000F0A7A"; // Fallback
    

    };

    // Spalte 1: Nächster Termin
    int col1 = 15;
    if (id(t0_name).has_state()) {
    // Icon mittig über der Spalte
    it.print(74, 40, id(icon_font), Color::WHITE, TextAlign::TOP_CENTER, get_icon(id(t0_name).state));
    // Text-Infos
    it.print(74, 80, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, id(t0_name).state.c_str());

      if (id(t0_tage).state == 0) {
        it.print(74, 100, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, "HEUTE");
      } else if (id(t0_tage).state == 1) {
        it.print(74, 100, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, "MORGEN");
      } else {
        it.printf(74, 100, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, "In %.0f Tagen", id(t0_tage).state);
      }
    

    }

    // Spalte 2: Übernächster Termin (Zentriert bei 222px)
    if (id(t1_name).has_state()) {
    // Icon mittig
    it.print(222, 40, id(icon_font), Color::WHITE, TextAlign::TOP_CENTER, get_icon(id(t1_name).state));
    // Text-Infos
    it.print(222, 80, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, id(t1_name).state.c_str());

      if (id(t1_tage).state == 0) {
        it.print(222, 100, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, "HEUTE");
      } else if (id(t1_tage).state == 1) {
        it.print(222, 100, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, "MORGEN");
      } else {
        it.printf(222, 100, id(font_small), Color::WHITE, TextAlign::TOP_CENTER, "In %.0f Tagen", id(t1_tage).state);
      }
    

    }

    // — Zeitstempel —
    // Nutzt TextAlign::TOP_RIGHT, um bündig an der rechten Kante (290px) zu kleben
    it.strftime(290, 2, id(font_tiny), Color::WHITE, TextAlign::TOP_RIGHT, “Stand: %d.%m. %H:%M”, id(ha_time).now());

deep_sleep:
id: deep_sleep_ctrl
wakeup_pin:
number: GPIO2
mode: INPUT_PULLUP
inverted: true

sensor.yaml als sensoren für Waste Collection Schedule
  • platform: waste_collection_schedule
    name: muell_termin_0
    details_format: “upcoming”
    event_index: 0 # Der allernächste Termin
    value_template: ‘{{ value.types | join(", ") }}’ # Name der Tonne

  • platform: waste_collection_schedule
    name: muell_termin_0_tage
    details_format: “upcoming”
    event_index: 0
    value_template: ‘{{ value.daysTo }}’ # Tage bis dahin

  • platform: waste_collection_schedule
    name: muell_termin_1
    details_format: “upcoming”
    event_index: 1 # Der übernächste Termin
    value_template: ‘{{ value.types | join(", ") }}’

  • platform: waste_collection_schedule
    name: muell_termin_1_tage
    details_format: “upcoming”
    event_index: 1
    value_template: ‘{{ value.daysTo }}’

Waste Collection Schedule muss in der configuration.yaml mit dem lokalen Müllentsorger eingerichtet werden.