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);
}