ESPHome 实战手册:TRMNL 7.5" (OG) DIY Kit
本页是针对 TRMNL DIY Kit 的 ESPHome 实战手册。通用的基础内容——选择刷写路径、通用 YAML 模板、连接 Home Assistant——都在 Work with ESPHome 中。如果你是第一次在 Seeed 电子纸上使用 ESPHome,建议先快速浏览那一页。若你在寻找的是TRMNL 云端仪表盘工作流(无需 YAML、基于插件),请查看 Work with TRMNL。

Home Assistant 简介
Home Assistant 是一个功能强大的开源家庭自动化平台,可让你通过一个统一的界面控制和监控智能家居设备。它充当智能家居的中央枢纽,使你能够自动化日常流程、监控传感器,并打造更智能的居住空间。

为什么选择 Home Assistant?
-
本地控制:与许多基于云的解决方案不同,Home Assistant 在你的本地网络上运行,确保数据隐私,即使在没有互联网连接时,自动化也能正常工作。
-
广泛的设备支持:Home Assistant 可与数千种不同的智能家居设备和服务集成,具有极高的通用性和前瞻性。
-
强大的自动化能力:可以创建复杂的自动化规则,响应时间、设备状态、传感器读数等各种触发条件。
-
可自定义仪表盘:你可以自行设计用户界面,展示对你最重要的信息。
为什么将 TRMNL 7.5inch(OG) DIY Kit 与 Home Assistant 搭配使用?
TRMNL 7.5inch(OG) DIY Kit 是 Home Assistant 的绝佳搭档,原因包括:
-
高能效:电子纸显示屏仅在更新内容时消耗电能,非常适合显示天气预报、日历事件或系统状态等持久信息。
-
清晰可见性:与 LCD 屏不同,电子纸显示屏在任何光照条件下都易于阅读,包括直射阳光,非常适合作为壁挂式家庭控制面板。
-
超长续航:配合深度睡眠模式,显示屏在单次电池充电后即可运行数月,同时仍能一眼提供有价值的信息。
-
灵活集成:通过 ESPHome,显示屏可以与 Home Assistant 无缝集成,让你以优雅、始终可见的形式展示来自智能家居系统的任意数据。
这些优势使 TRMNL 7.5inch(OG) DIY Kit 成为为 Home Assistant 搭建节能、常亮信息显示屏的理想选择。
ESPHome 集成
ESPHome 是一个专为 ESP8266/ESP32 设备设计的开源固件生成工具。它允许你使用简单的 YAML 配置文件创建自定义固件,然后刷写到设备上。对于 TRMNL 7.5inch(OG) DIY Kit,ESPHome 充当关键的中间件,使设备能够与 Home Assistant 通信。
系统通过将 YAML 配置转换为在 ESP 设备上运行的完整固件来工作。该固件负责处理连接网络、与 Home Assistant 通信以及控制电子纸显示屏等所有复杂任务。结合 Home Assistant,ESPHome 为创建复杂的家庭自动化显示与控制界面提供了一个强大的平台。
下面我们来看看如何进行设置,并充分发挥这块多功能显示屏的潜力。
入门指南
在开始阅读本教程的具体内容之前,你需要准备好以下硬件。
所需材料
Home Assistant Green 是自动化家庭的最简单、最注重隐私的方式。它提供了极其简便的安装流程,并允许你通过一个系统控制所有智能设备,且所有数据默认都本地存储。该主板受益于蓬勃发展的 Home Assistant 生态系统,并将通过开源社区在每个月持续改进。
我们推荐在本教程中使用 Home Assistant Green 作为 Home Assistant 主机,当然你也可以使用任何带 Supervisor 的 Home Assistant 主机。
我们也为部分 Seeed Studio 产品编写了 Home Assistant 的安装教程,请参考以下内容。
- 在 ODYSSEY-X86 上使用 Home Assistant 入门
- 在 reTerminal 上使用 Home Assistant 入门
- 在 LinkStar H68K/reRouter CM4 上使用 Home Assistant 入门
如果你没有使用 Seeed Studio 的产品,也可以在 Home Assistant 官方网站上查看并学习其他产品的 Home Assistant 安装方法。
设备安装
步骤 1. 将显示屏连接到驱动板
将 FPC 线缆与 XIAO 电子纸显示板上的连接器对齐,然后扣上卡扣以确保连接牢固。
FPC 线缆的金属面应朝上,否则将不会显示任何内容。
请按照下面的安装教程操作,很多人都会装错。

步骤 2. 连接电池
将电池线缆连接到驱动板上的 JST 接口,确保极性正确(红线接 +,黑线接 -)。

步骤 3. 外壳组装(可选)
请注意,屏幕的软排线非常脆弱,操作时务必小心。如果损坏,整个屏幕将无法工作。
从 Resource part 打印开源外壳部件,并将组件装入其中。

首先,组装驱动板和电池。
测试 TRMNL 套件是否工作正常。
将屏幕插入外壳,并让 FPC 线缆能够伸出。
连接 FPC 延长线并组装整个外壳。
L 型外壳的组装方式也非常相似。
如果你的 TRMNL 套件离路由器较远,可以将天线移到外壳外面,这样性能会更好。
步骤 1. 安装 ESPHome
如果你已经安装了 ESPHome,可以跳过此步骤。
进入 Settings -> Add-ons -> ADD-ON STORE


搜索 ESPHome 并点击它。然后点击 INSTALL 和 START。
如果你在插件商店中找不到 ESPHome,请确保你使用的是支持插件的 Home Assistant 安装方式(例如 Home Assistant OS 或 supervised 安装)。对于其他安装类型(例如 Home Assistant Container),你可能需要使用 Docker 独立运行 ESPHome Device Builder。更多详情请参阅 官方 ESPHome 文档。

然后,ESPHome Builder 会出现在侧边栏。

步骤 2. 添加新设备
进入 ESPHome 并点击 NEW DEVICE。

给设备起一个你喜欢的名字,并选择 ESP32-S3 作为芯片类型,然后点击 SKIP。



创建新设备后,点击 EDIT。

在默认生成的代码中,esp32 的框架可能是 esp-idf,我们需要将其更改为 arduino。

步骤 3. 安装固件
这是一个非常基础的示例,会在屏幕上显示 “Hello World!”。
主要目的是向你展示将固件安装到设备的不同方式。
现在你可以复制下面的代码,并像下图所示粘贴到 captive_portal 之后。
# define font to display words
font:
- file: "gfonts://Inter@700"
id: font1
size: 24
# define SPI interface
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
update_interval: 30s
lambda: |-
it.print(0, 0, id(font1), "Hello World!");

点击 INSTALL 将代码安装到设备上,你会看到如下图所示的画面。
- Install through browser
- Install through host
- Install through Wi-Fi
如果你的 Home Assistant 主机(Raspberry PI/Green/Yellow 等)离你比较远,我们推荐使用这种方式。你可以使用手边的电脑来安装。
首先,你需要点击 Manual download 下载编译好的固件。

打开这个网站,我们将在这里把固件上传到 ePaper 面板。

回到 ESPHome 下载固件。

选择 Factory 格式。

使用 USB 线 将 ePaper 面板连接到你的电脑,然后点击 CONNECT。

选择 usbmodemxxx(Windows 为 COMxxx)并点击连接。遇到问题?点击这里。

点击 INSTALL 并选择你刚刚下载的固件。

稍等片刻,你会在屏幕上看到 “Hello world!” ~


如果你的 Home Assistant 主机(Raspberry PI/Green/Yellow 等)就在附近,我们推荐使用这种方式,因为更简单。
在你将代码安装到设备之前,需要使用 USB 线 将此设备连接到运行 Home Assistant 的 Raspberry Pi 或 HA Green(Yellow) 等主机。
按照下图所示的选项点击,将代码安装到设备上。在设备处于深度睡眠模式时没有找到端口?


稍等片刻,你会看到如下图所示的反馈。这意味着代码已成功运行。


这是最简单的方式,但前提是首次安装程序时,你需要先使用左侧的方法将程序上传到 ePaper 面板。之后,你就可以通过 Wi-Fi 上传。同时,请确保你的 YAML 配置中包含正确配置的 ota 和 api 部分,并带有有效的加密密钥,才能使此方法生效。
通过这种方式,你不需要将 ePaper 面板连接到任何设备,只需确保它在线即可。
点击该选项,固件就会自动安装到 ePaper 面板上。

稍等片刻,你会看到如下图所示的反馈。如果失败,可能是信号较弱。请将设备移近路由器。遇到问题?点击这里。


基本用法
1. 显示图形
此示例会在屏幕上显示图形。
你可以复制下面的代码,并像下图所示粘贴到 captive_portal 部分。
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
update_interval: 5min
lambda: |-
it.rectangle(10, 10, 100, 50);
it.rectangle(150, 10, 50, 50);
it.circle(250, 35, 25);
it.filled_rectangle(10, 80, 100, 50);
it.filled_rectangle(150, 80, 50, 50);
it.filled_circle(250, 105, 25);
当你看到如下图所示的反馈时,说明代码已成功运行。
你也可以点击这里查看更多用法。

2. 在 HA 中显示信息
此示例会在屏幕上显示 HA 中的信息。
首先,你需要将此设备添加到 HA。否则,你无法从 HA 获取信息。
如果 HA 没有显示该设备,你应该先运行上面的示例。运行上述示例后,你就可以在 HA 中看到该设备。


然后,点击 SUBMIT 和 FINISH。


安装好 ESPHome 并添加新设备后,你可以复制下面的代码,并按照下图所示粘贴到 captive_portal 之后。
# Define font to show info
font:
- file: "gfonts://Inter@700"
id: myFont
size: 24
# Get info from HA, as string format
text_sensor:
- platform: homeassistant
entity_id: weather.forecast_home
id: myWeather
internal: true
- platform: homeassistant
entity_id: weather.forecast_home
id: myTemperature
attribute: "temperature"
internal: true
# Get info from HA, as float format
sensor:
- platform: homeassistant
entity_id: weather.forecast_home
id: myPressure
attribute: "pressure"
internal: true
# Display info via SPI
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
update_interval: 30s
lambda: |-
//print info in log
ESP_LOGD("epaper", "weather: %s", id(myWeather).state.c_str());
ESP_LOGD("epaper", "temperature: %s", id(myTemperature).state.c_str());
ESP_LOGD("epaper", "pressure: %.1f", id(myPressure).state);
//display info in epaper screen
it.printf(100, 100, id(myFont), "%s", id(myWeather).state.c_str());
it.printf(100, 150, id(myFont), "%s", id(myTemperature).state.c_str());
it.printf(100, 200, id(myFont), "%.1f", id(myPressure).state);
将这些代码烧录到你的设备中。

这段代码的功能是从 HA 获取天气、温度和气压,并将它们显示在屏幕上。

如果你发现你的 Home Assistant 中没有与天气相关的组件,可以在集成中下载一个名为 Open-Meteo 的集成。

当你看到如下图所示的反馈时,说明代码已成功运行。


3. 显示图标
本示例将在屏幕上显示图标。
首先,我们需要安装一个文件编辑器附加组件。搜索 Studio Code Server 并点击它。点击 INSTALL 和 START。


接着然后,创建一个名为 fonts 的新文件夹,下载此文件并将其放入 fonts 文件夹中。

你可以复制下面的代码,并按照下图所示粘贴到 captive_portal 之后。
font:
- file: 'fonts/materialdesignicons-webfont.ttf' #here is the directory to save ttf file
id: font_mdi_large
size: 200 # big size icon
glyphs: &mdi-weather-glyphs
- "\U000F0595" # weather cloudy
- "\U000F0592" # weather hail
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_mdi_medium # small size icon
size: 40
glyphs: *mdi-weather-glyphs
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
update_interval: 30s
lambda: |-
it.printf(100, 200, id(font_mdi_medium), TextAlign::CENTER, "\U000F0595");
it.printf(400, 200, id(font_mdi_large), TextAlign::CENTER, "\U000F0592");
当你看到如下图所示的反馈时,说明代码已成功运行。

如果你想使用其他图标,可以点击下面的按钮查看更多。
选择一个你想要的图标。

复制代码并将其粘贴到 captive_portal 部分,如下图所示。


4. 显示图片
本示例将在屏幕上显示任意你喜欢的图片。
与上一个示例类似,我们需要安装 Studio Code Server 并创建一个名为 image 的新文件夹来保存图片。
然后将一张图片放入 image 文件夹。你可以点击下面的按钮下载一张图片来试一试。

你可以复制下面的代码,并按照下图所示粘贴到 captive_portal 之后。
image:
- file: /config/esphome/image/wifi.jpg # the path where you save the image, png or jpg format
id: myImage
type: BINARY
resize: 800x480 # how big you want to show, the biggest size should be as same as ePaper Penal pixel(800x480)
invert_alpha: true # invert color
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
update_interval: 30s
lambda: |-
it.image(0, 0, id(myImage));
当你看到如下图所示的反馈时,说明代码已成功运行。

示例 1. 将 Home Assistant 仪表盘截图显示出来
本示例将在屏幕上显示 HA 的截图。
首先,你需要安装一个截图附加组件 Puppet,点击此处安装。

请注意版本应当高于或等于 1.11.4。安装完成后,进入 Configuration page。我们需要为这个附加组件创建一个 access_token。

请参照下一步创建一个 token 并粘贴到这里。

进入Security page页面底部创建一个 token,然后将其复制并粘贴到 Puppet 插件中。

记得重启 Puppet 插件。

启动插件后,会在端口 10000 上启动一个新服务器。你请求的任何路径都会返回该页面的截图。你需要指定想要的视口大小。
例如,要获取默认仪表盘 1000px x 1000px 的截图,请访问:
# http://192.168.1.191:10000/lovelace/0?viewport=1000x1000(My address)
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000
为了减少 E Ink® 显示屏的颜色数量,你可以添加 eink 参数。该值表示要使用的颜色数量(包括黑色)。例如,对于 2 色 E Ink® 显示屏:
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2
如果你使用 eink=2,还可以通过添加 invert 参数来反转颜色:
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2&invert
此外,你也可以截取其他页面的截图,例如 HA 中的 To-do lists 页面:
http://192.168.1.191:10000/todo?viewport=800x480&eink=2&invert
你可以在浏览器中输入这个链接来查看截图效果。

复制下面的代码,并将其粘贴到 esp32 后面:
# Enable PSRAM support since online_image requires more than the available RAM capacity
psram:
mode: octal
speed: 80MHz
你可以复制下面的代码,并按照如下所示粘贴到 captive_portal 后面。
http_request:
verify_ssl: false
timeout: 10s
watchdog_timeout: 15s
online_image:
- id: dashboard_image
format: PNG
type: BINARY
buffer_size: 30000
url: http://192.168.1.191:10000/todo?viewport=800x480&eink=2&invert #change this link to your screenshot link
update_interval: 30s
on_download_finished:
- delay: 0ms
- component.update: main_display
spi:
clk_pin: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
id: main_display
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
update_interval: never
lambda: |-
it.image(0, 0, id(dashboard_image));
当你看到如下图所示的反馈时,表示代码已成功运行。

示例 2. 深度睡眠模式
在深度睡眠模式下,你无法直接向设备上传代码。你需要进入下载模式。点击此处跳转到 Q3。
本示例将展示如何使用深度睡眠模式来节省电量。每 6 小时更新一次信息。
你可以复制下面的代码,并按照如下所示粘贴到 captive_portal 后面。
globals:
- id: sleep_counter
type: int
restore_value: yes # key parameter, to use RTC storage
initial_value: '0'
# Here is deep sleep part
deep_sleep:
id: deep_sleep_1
run_duration: 30s # Device wake up and run 30s (enough to display)
sleep_duration: 3min # deep sleep for 3min
interval:
- interval: 29s # run this command before the end of run_duration
then:
- logger.log: "Entering deep sleep now..."
font:
- file: "gfonts://Inter@700"
id: font1
size: 24
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
update_interval: 3min
lambda: |-
id(sleep_counter) += 1;
ESP_LOGD("main", "Wakeup count: %d", id(sleep_counter));
it.printf(100, 100, id(font1), "Wakeup count: %d", id(sleep_counter));
你会看到一个计数器。每次设备唤醒时,它都会加一。

示例 3. 综合示例
为了让你更好地理解,我们强烈建议你先运行上面的基础用法示例。
本示例展示了适用于 TRMNL 7.5 英寸电子纸 DIY 套件的完整 ESPHome 配置。该 YAML 代码集成了多种功能,用于创建一个与 Home Assistant 无缝协作的智能交互式显示面板。
目的与功能:
-
该配置使设备能够连接到 Wi-Fi 和 Home Assistant,并支持 API 和 OTA 更新,便于管理。
-
它将电子纸显示屏设置为通过物理按键控制的两个可切换页面,用于显示不同类型的信息。
-
设备读取电池电压,计算电池电量百分比,并显示相应的电池图标和数值。
-
从 Home Assistant 获取天气状况和温度,并以合适的图标和单位进行显示。
-
同时显示当前时间和日期,并与 Home Assistant 保持同步。
本示例展示了如何结合传感器读数、Home Assistant 数据和用户输入,使用 ESPHome 和 TRMNL 7.5 英寸电子纸套件构建一个功能丰富、始终在线的智能显示屏。
点击此处预览完整代码
esphome:
name: obdy
friendly_name: obdy
on_boot:
priority: 600
then:
- output.turn_on: bsp_battery_enable
- delay: 200ms
- component.update: battery_voltage
- component.update: battery_level
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Enable PSRAM support since online_image requires more than the available RAM capacity
psram:
mode: octal
speed: 80MHz
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "j0V30kuJ6Zdij9SU6Ee+7ruwid+7SQOxtinjld2PRc0="
ota:
- platform: esphome
password: "db786195ae6f9748f5b57ea9bd1d4161"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Obdy Fallback Hotspot"
password: "IOfapF7hXq55"
captive_portal:
# Deep-sleep, wake by GPIO4
# deep_sleep:
# id: deep_sleep_1
# run_duration: 1min
# sleep_duration: 60min
# wakeup_pin: GPIO4
# wakeup_pin_mode: INVERT_WAKEUP
spi:
clk_pin: GPIO7
mosi_pin: GPIO9
# Fonts
font:
- file: "gfonts://Inter@700"
id: small_font
size: 24
- file: "gfonts://Inter@700"
id: mid_font
size: 36
- file: "gfonts://Inter@700"
id: big_font
size: 180
- file: "gfonts://Inter@700"
id: time_font
size: 96 # for the big time display
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_bat_icon
size: 24
glyphs:
- "\U000F007A" # mdi-battery-10
- "\U000F007B" # mdi-battery-20
- "\U000F007C" # mdi-battery-30
- "\U000F007D" # mdi-battery-40
- "\U000F007E" # mdi-battery-50
- "\U000F007F" # mdi-battery-60
- "\U000F0080" # mdi-battery-70
- "\U000F0081" # mdi-battery-80
- "\U000F0082" # mdi-battery-90
- "\U000F0079" # mdi-battery
- file: "fonts/materialdesignicons-webfont.ttf" # <-- 替换成你的字体文件路径
id: weather_icon_font
size: 100
glyphs:
- "\U000F0599" # weather-sunny
- "\U000F0595" # weather-partly-cloudy
- "\U000F0F2F" # weather-cloudy
- "\U000F0597" # weather-rainy
- "\U000F0598" # weather-snowy
- "\U000F059B" # weather-windy
- "\U000F0594" # weather-fog
- "\U000F0596" # weather-lightning
globals:
- id: page_index
type: int
restore_value: true
initial_value: '0'
- id: battery_glyph
type: std::string
restore_value: no
initial_value: "\"\\U000F0079\"" # default full battery
sensor:
- platform: adc
pin: GPIO1
name: "Battery Voltage"
id: battery_voltage
update_interval: 60s
attenuation: 12db
filters:
- multiply: 2.0
- platform: template
name: "Battery Level"
id: battery_level
unit_of_measurement: "%"
icon: "mdi:battery"
device_class: battery
state_class: measurement
lambda: 'return id(battery_voltage).state;'
update_interval: 60s
on_value:
then:
- lambda: |-
int pct = int(x);
if (pct <= 10) id(battery_glyph) = "\U000F007A";
else if (pct <= 20) id(battery_glyph) = "\U000F007B";
else if (pct <= 30) id(battery_glyph) = "\U000F007C";
else if (pct <= 40) id(battery_glyph) = "\U000F007D";
else if (pct <= 50) id(battery_glyph) = "\U000F007E";
else if (pct <= 60) id(battery_glyph) = "\U000F007F";
else if (pct <= 70) id(battery_glyph) = "\U000F0080";
else if (pct <= 80) id(battery_glyph) = "\U000F0081";
else if (pct <= 90) id(battery_glyph) = "\U000F0082";
else id(battery_glyph) = "\U000F0079";
filters:
- calibrate_linear:
- 4.15 -> 100.0
- 3.96 -> 90.0
- 3.91 -> 80.0
- 3.85 -> 70.0
- 3.80 -> 60.0
- 3.75 -> 50.0
- 3.68 -> 40.0
- 3.58 -> 30.0
- 3.49 -> 20.0
- 3.41 -> 10.0
- 3.30 -> 5.0
- 3.27 -> 0.0
- clamp:
min_value: 0
max_value: 100
output:
- platform: gpio
pin: GPIO6
id: bsp_battery_enable
binary_sensor:
- platform: gpio # Next page KEY1
pin:
number: GPIO2
mode: INPUT_PULLUP
inverted: true
id: key1
name: "Key1"
on_press:
then:
- lambda: |-
id(page_index) = (id(page_index) + 1) % 2;
id(epaper_display).update();
- platform: gpio # Prev page KEY2
pin:
number: GPIO3
mode: INPUT_PULLUP
inverted: true
id: key2
name: "Key2"
on_press:
then:
- lambda: |-
id(page_index) = (id(page_index) - 1 + 2) % 2;
id(epaper_display).update();
# - platform: gpio
# pin:
# number: GPIO5 # KEY3
# mode: INPUT_PULLUP
# inverted: true
# id: key2
# name: "Key2"
# on_press:
# then:
# Home Assistant time
time:
- platform: homeassistant
id: ha_time
text_sensor:
- platform: homeassistant
entity_id: weather.home
id: myWeather
- platform: homeassistant
entity_id: weather.home
id: temp
attribute: "temperature"
display:
- platform: waveshare_epaper
id: epaper_display
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
update_interval: never
lambda: |-
// ---------- PAGE 0 ----------
if (id(page_index) == 0) {
// Screen dimension constants for easy adjustment
const int scr_w = 800;
const int scr_h = 480;
const int center_x = scr_w / 2; // Center X-coordinate of the screen (400)
// --- Top-right: Battery Info ---
// Display the battery icon using an icon font
it.printf(scr_w - 130, 13, id(font_bat_icon), "%s", id(battery_glyph).c_str());
// Display the battery percentage text
it.printf(scr_w - 100, 10, id(small_font), "%.0f%%", id(battery_level).state);
// --- Draw the vertical separator line ---
// Draw a vertical line in the middle to separate left and right areas
it.filled_rectangle(center_x, 100, 2, 280);
// ==================================================
// LEFT AREA: WEATHER INFO
// ==================================================
// Calculate the center X-coordinate of the left area for alignment
const int left_center_x = center_x / 2; // 200
// 1. Display the title "Weather" at the top of the left area
it.printf(left_center_x, 110, id(mid_font), TextAlign::TOP_CENTER, "Weather");
// 2. Get the weather condition and select the corresponding icon
std::string weather_condition = id(myWeather).state;
std::string weather_icon = "\U000F0599"; // Default icon (sunny), as a fallback for unknown states
if (weather_condition == "partlycloudy") {
weather_icon = "\U000F0595"; // weather-partly-cloudy
} else if (weather_condition == "cloudy") {
weather_icon = "\U000F0F2F"; // weather-cloudy
} else if (weather_condition == "rainy") {
weather_icon = "\U000F0597"; // weather-rainy
} else if (weather_condition == "snowy") {
weather_icon = "\U000F0598"; // weather-snowy
} else if (weather_condition == "windy") {
weather_icon = "\U000F059B"; // weather-windy
} else if (weather_condition == "fog") {
weather_icon = "\U000F0594"; // weather-fog
} else if (weather_condition == "lightning") {
weather_icon = "\U000F0596"; // weather-lightning
}
// Display the weather icon in the center of the left area
it.printf(left_center_x, 240, id(weather_icon_font), TextAlign::CENTER, "%s", weather_icon.c_str());
// 3. Display the weather condition text below the icon
it.printf(left_center_x, 400, id(mid_font), TextAlign::BOTTOM_CENTER, "%s", weather_condition.c_str());
// ==================================================
// RIGHT AREA: TEMPERATURE INFO
// ==================================================
// Calculate the center X-coordinate of the right area for alignment
const int right_center_x = center_x + (center_x / 2); // 600
// 1. Display the title "Temperature" at the top of the right area
it.printf(right_center_x, 110, id(mid_font), TextAlign::TOP_CENTER, "Temperature");
// 3. Display the temperature reading below the icon, with one decimal place
float temp_c = stof(id(temp).state);
double temp_f = temp_c * 9.0 / 5.0 + 32.0;
it.printf(right_center_x, 250, id(mid_font), TextAlign::CENTER, "%.0f°F", temp_f);
it.printf(right_center_x, 380, id(mid_font), TextAlign::CENTER, "%.1f°C", temp_c);
}
// ---------- PAGE 1 ----------
else{
// Battery top-right
it.printf(670, 13, id(font_bat_icon), "%s", id(battery_glyph).c_str());
it.printf(700, 10, id(small_font), "%.0f%%", id(battery_level).state);
auto now = id(ha_time).now();
struct tm timeinfo = now.to_c_tm();
// centering time HH:MM
char timeStr[6];
strftime(timeStr, sizeof(timeStr), "%H:%M", &timeinfo);
it.printf(400, 180, id(time_font), TextAlign::CENTER, timeStr);
// Date: Day of week
const char *weekday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
const char *wday = weekday[timeinfo.tm_wday];
// Date: month - day
char dateStr[12];
strftime(dateStr, sizeof(dateStr), "%b %d", &timeinfo); // e.g. Jun 15
// Day of the week + date below the time
it.printf(400, 280, id(mid_font), TextAlign::CENTER, "%s, %s", wday, dateStr);
}
当你看到如下图所示的反馈时,表示代码已成功运行。

常见问题
Q1:为什么没有数据?
在这种情况下,你需要前往 Settings -> Devices & Services -> Integrations 来**重新配置(RECONGFIGURE)**设备。还没有找到你的 ePaper Penal?尝试重启 HA。

Q2:为什么我在 Home Assistant 中获取不到这些数据?
在这种情况下,你需要前往 Settings -> Devices & Services -> Integrations,将你的设备**添加(ADD)**到 HA 中。

Q3:设备处于深度睡眠模式时,如何上传新程序?


当设备处于深度睡眠模式时,你无法直接上传新程序。
-
首先,确保设备已开启。然后,按住位于 XIAO ESP32-S3 Plus 上 USB-C 接口旁边的 Boot 按钮。
-
在按住 Boot 按钮的同时,按一下 Reset 按钮,然后松开 Boot 按钮。
-
之后,关闭电池开关并拔掉电源线。
-
最后,重新插上电源线并上传新程序。
Q4:TRMNL 7.5inch(OG) DIY Kit 无法连接到你的电脑?

尝试多次拔插,或者根据提示安装驱动程序。
Q5:通过 Wi-Fi 上传程序失败?

在这种情况下,你的 epaper penal 处于离线或深度睡眠模式。请让它重新上线或将其唤醒。
技术支持与产品讨论
感谢你选择我们的产品!我们将为你提供多种支持,以确保你在使用我们产品的过程中尽可能顺利。我们提供多种沟通渠道,以满足不同的偏好和需求。

