TRMNL Screen Not Refreshing

Recently got my TRMNL screen and had it running with HA for about a month. I then noticed that the content on the screen was not updating. I checked the logs on ESPHome and noticed the following. Just not sure if I got a defective screen or what could have gone wrong. Any suggestions are appreciated.

[22:24:51][D][sensor:131]: 'dishwasher_power': Sending state 71.43000  with 1 decimals of accuracy
[22:24:52][I][waveshare_epaper:3965]: Power on the display and hat
[22:25:02][E][waveshare_epaper:3910]: Timeout while displaying image!
[22:25:13][E][waveshare_epaper:3910]: Timeout while displaying image!
[22:25:24][E][waveshare_epaper:3910]: Timeout while displaying image!
[22:25:34][E][waveshare_epaper:3910]: Timeout while displaying image!
[22:25:34][D][homeassistant.sensor:024]: 'sensor.furnace_washer_channel_1_power': Got state 104.54

Here is the YML file:

esphome:
  name: trmnl-screen
  friendly_name: TRMNL Screen

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  framework:
    type: arduino

logger:

api:
  encryption:
    key: "#######################"

ota:
  - platform: esphome
    password: "#####################"

wifi:
  ssid: "#######"
  password: "###########"
  power_save_mode: NONE
  fast_connect: true
  ap:
    ssid: "TRMNL Fallback"
    password: "#########"

captive_portal:

web_server:
  port: 80

# ---- Fonts ----
font:
  - file: "fonts/materialdesignicons-webfont.ttf"
    id: mdi_header
    size: 100
    bpp: 1
    ignore_missing_glyphs: true
    glyphs: ["\U000F1903"]   # mdi:home-lightning-bolt

  - file: "fonts/materialdesignicons-webfont.ttf"
    id: mdi_pod
    size: 42
    bpp: 1
    ignore_missing_glyphs: true
    glyphs:
      - "\U000F0D3E"   # transmission-tower
      - "\U000F1A73"   # solar-power-variant
      - "\U000F1A58"   # meter-electric-outline
      - "\U000F05A9"   # wifi

  - file: "gfonts://Inter@700"
    id: font_big
    size: 42
    glyphs: ["0123456789.- kWhdBm…"]

  - file: "gfonts://Inter@700"
    id: font_pod_value
    size: 26
    glyphs: ["0123456789.- WdBm…"]

  - file: "gfonts://Inter@700"
    id: font_title
    size: 32
    glyphs: ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-() ."]

  - file: "gfonts://Inter@400"
    id: font_body
    size: 24
    glyphs: ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-() ."]

  - file: "gfonts://Inter@700"
    id: font_body_bold
    size: 24
    glyphs: ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-() ."]

  - file: "gfonts://Inter@700"
    id: font_small
    size: 20
    glyphs: ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-() ."]

# ---- Time ----
time:
  - platform: sntp
    id: sntp_time
    timezone: "America/Denver"

# ---- Home Assistant sensors ----
sensor:
  - platform: homeassistant
    id: net_power
    entity_id: sensor.ted_net_meter
    internal: true

  - platform: homeassistant
    id: grid_power
    entity_id: sensor.ted_total_meter
    internal: true

  - platform: homeassistant
    id: solar_power
    entity_id: sensor.ted_solar_meter
    internal: true

  - platform: homeassistant
    id: energy_used_daily
    entity_id: sensor.energy_used_daily
    internal: true

  - platform: homeassistant
    id: solar_generated_daily
    entity_id: sensor.solar_generated_daily
    internal: true

  - platform: template
    id: net_daily_kwh
    unit_of_measurement: "kWh"
    accuracy_decimals: 2
    update_interval: 60s
    lambda: |-
      if (!id(energy_used_daily).has_state() || !id(solar_generated_daily).has_state()) return NAN;
      if (isnan(id(energy_used_daily).state) || isnan(id(solar_generated_daily).state)) return NAN;
      return id(energy_used_daily).state - id(solar_generated_daily).state;

  - platform: homeassistant
    id: ac_power
    entity_id: sensor.ac_channel_1_power
    internal: true
  - platform: homeassistant
    id: furnace_fan_power
    entity_id: sensor.furnace_washer_channel_1_power
    internal: true
  - platform: homeassistant
    id: washer_power
    entity_id: sensor.furnace_washer_channel_2_power
    internal: true
  - platform: homeassistant
    id: dryer_power
    entity_id: sensor.shellyem_bcff4dfd04c6_channel_1_power
    internal: true
  - platform: homeassistant
    id: karina_room_power
    entity_id: sensor.ne_room_light_fan_controls_electric_consumption_w
    internal: true
  - platform: homeassistant
    id: office_power
    entity_id: sensor.nw_room_light_fan_controls_electric_consumption_w
    internal: true
  - platform: homeassistant
    id: ev_power
    entity_id: sensor.chargepoint_1_power
    internal: true
  - platform: homeassistant
    id: plex_power
    entity_id: sensor.shellyem_bcff4dfcfac5_channel_1_power
    internal: true
  - platform: homeassistant
    id: dishwasher_power
    entity_id: sensor.shellyem_bcff4dfcfac5_channel_2_power
    internal: true
  - platform: homeassistant
    id: family_room_power
    entity_id: sensor.family_rooms_channel_2_power
    internal: true
  - platform: homeassistant
    id: game_room_power
    entity_id: sensor.family_rooms_channel_1_power
    internal: true

  - platform: wifi_signal
    id: wifi_rssi
    name: "TRMNL WiFi RSSI"
    update_interval: 60s

# ---- Display ----
spi:
  clk_pin: GPIO7
  mosi_pin: GPIO9

display:
  - platform: waveshare_epaper
    model: 7.50inv2
    cs_pin: GPIO44
    dc_pin: GPIO10
    reset_pin: GPIO38
    busy_pin:
      number: GPIO4
      inverted: true
    rotation: 0
    update_interval: 3min
    lambda: |-
      using namespace esphome::display;

      const int W = 800, H = 480;
      const int COL_SPLIT_X = 420;
      const int L_LEFT  = 24;
      const int L_RIGHT = COL_SPLIT_X + 16;
      const int LEFT_CX = (L_LEFT + COL_SPLIT_X) / 2;
      const int RIGHT_VALUE_X = W - 24;

      // ==== Header: Daily Net ====
      const int HEADER_Y = 26;
      const int ICON_W = 100;
      const int VALUE_H = 42;
      const int spacing = 14;

      char dn_buf[32];
      if (id(net_daily_kwh).has_state() && !isnan(id(net_daily_kwh).state)) {
        snprintf(dn_buf, sizeof(dn_buf), "%.2f kWh", id(net_daily_kwh).state);
      } else {
        snprintf(dn_buf, sizeof(dn_buf), "… kWh");
      }

      const int text_width_est = 220;
      const int total_w = ICON_W + spacing + text_width_est;
      const int left_edge = LEFT_CX - total_w/2;

      it.printf(left_edge + ICON_W/2, HEADER_Y, id(mdi_header), TextAlign::TOP_CENTER, "\U000F1903");
      const int value_y = HEADER_Y + (ICON_W - VALUE_H)/2 + 2;
      it.printf(left_edge + ICON_W + spacing, value_y, id(font_big), TextAlign::TOP_LEFT, "%s", dn_buf);

      // ==== Pods (2x2) ====
      const int LEFT_AREA_W = COL_SPLIT_X - L_LEFT;
      const int POD_GAP = 24;
      const int POD_W = (LEFT_AREA_W - POD_GAP) / 2;
      const int POD_H = 86;
      const int POD_TOP = 152;
      const int POD_ROW2_Y = POD_TOP + POD_H + POD_GAP;
      const int BORDER_THICKNESS = 3;

      auto pod_box = [&](int x, int y) {
        for (int i = 0; i < BORDER_THICKNESS; i++) {
          it.rectangle(x - i, y - i, POD_W + 2*i, POD_H + 2*i);
        }
      };

      auto pod_icon_value = [&](int x, int y, const char* icon_utf, float value, const char* unit, bool signed_val) {
        it.printf(x + 12, y + 8, id(mdi_pod), TextAlign::TOP_LEFT, "%s", icon_utf);
        char buf[32];
        if (isnan(value)) {
          snprintf(buf, sizeof(buf), "…");
        } else if (signed_val) {
          snprintf(buf, sizeof(buf), "%.0f %s", value, unit);
        } else {
          snprintf(buf, sizeof(buf), "%.0f %s", fabsf(value), unit);
        }
        int value_x = x + POD_W * 0.65;   // shifted right
        int value_y = y + POD_H/2 - 6;
        it.printf(value_x, value_y, id(font_pod_value), TextAlign::CENTER, "%s", buf);
      };

      const int POD1_X = L_LEFT;
      const int POD2_X = L_LEFT + POD_W + POD_GAP;

      // Pod 1: Grid
      float v_grid = (id(grid_power).has_state() && !isnan(id(grid_power).state)) ? id(grid_power).state : NAN;
      pod_box(POD1_X, POD_TOP);
      pod_icon_value(POD1_X, POD_TOP, "\U000F0D3E", v_grid, "W", false);

      // Pod 2: Solar
      float v_solar = (id(solar_power).has_state() && !isnan(id(solar_power).state)) ? -fabsf(id(solar_power).state) : NAN;
      pod_box(POD2_X, POD_TOP);
      pod_icon_value(POD2_X, POD_TOP, "\U000F1A73", v_solar, "W", true);

      // Pod 3: Net
      float v_net = (id(net_power).has_state() && !isnan(id(net_power).state)) ? id(net_power).state : NAN;
      pod_box(POD1_X, POD_ROW2_Y);
      pod_icon_value(POD1_X, POD_ROW2_Y, "\U000F1A58", v_net, "W", true);

      // Pod 4: Wi-Fi
      float v_wifi = (id(wifi_rssi).has_state() && !isnan(id(wifi_rssi).state)) ? id(wifi_rssi).state : NAN;
      pod_box(POD2_X, POD_ROW2_Y);
      pod_icon_value(POD2_X, POD_ROW2_Y, "\U000F05A9", v_wifi, "dBm", true);

      // ==== Right column: sorted non-zero loads ====
      struct Item { const char* name; float value; bool valid; };
      Item items[] = {
        {"AC", id(ac_power).state, id(ac_power).has_state() && !isnan(id(ac_power).state)},
        {"Furnace Fan", id(furnace_fan_power).state, id(furnace_fan_power).has_state() && !isnan(id(furnace_fan_power).state)},
        {"Washer", id(washer_power).state, id(washer_power).has_state() && !isnan(id(washer_power).state)},
        {"Dryer", id(dryer_power).state, id(dryer_power).has_state() && !isnan(id(dryer_power).state)},
        {"Karina Room", id(karina_room_power).state, id(karina_room_power).has_state() && !isnan(id(karina_room_power).state)},
        {"Office", id(office_power).state, id(office_power).has_state() && !isnan(id(office_power).state)},
        {"EV", id(ev_power).state, id(ev_power).has_state() && !isnan(id(ev_power).state)},
        {"Plex", id(plex_power).state, id(plex_power).has_state() && !isnan(id(plex_power).state)},
        {"Dishwasher", id(dishwasher_power).state, id(dishwasher_power).has_state() && !isnan(id(dishwasher_power).state)},
        {"Family Room", id(family_room_power).state, id(family_room_power).has_state() && !isnan(id(family_room_power).state)},
        {"Game Room", id(game_room_power).state, id(game_room_power).has_state() && !isnan(id(game_room_power).state)}
      };
      const int N = sizeof(items)/sizeof(items[0]);
      for (int i = 0; i < N; i++) {
        if (!items[i].valid || fabsf(items[i].value) < 0.5f) {
          items[i].valid = false;
          items[i].value = -1e9f;
        }
      }
      for (int i = 0; i < N - 1; i++) {
        int m = i;
        for (int j = i + 1; j < N; j++) if (items[j].value > items[m].value) m = j;
        if (m != i) { Item t = items[i]; items[i] = items[m]; items[m] = t; }
      }
      int y = 80, STEP = 28;
      for (int i = 0; i < N; i++) {
        const Item &r = items[i];
        if (!r.valid) continue;
        it.printf(L_RIGHT, y, id(font_small), "%s", r.name);
        it.printf(RIGHT_VALUE_X, y - 8, id(font_body), TextAlign::TOP_RIGHT, "%.0f W", r.value);
        y += STEP;
        if (y > (H - 60)) break;
      }

      // ==== Footer ====
      const int CENTER_X = W / 2;
      if (id(sntp_time).now().is_valid()) {
        auto t = id(sntp_time).now();
        char buf[32];
        t.strftime(buf, sizeof(buf), "%I:%M:%S %p");
        it.printf(CENTER_X, H - 32, id(font_body), TextAlign::TOP_CENTER, "Updated: %s", buf);
      }