跳转到内容

Nextion TFT LCD 显示屏

nextion 显示平台允许您在 ESPHome 中使用 Nextion LCD 显示屏 (数据手册iTead)。

Nextion 显示屏

与 Nextion 显示屏的通信通过串行接口进行,因此您需要在配置中有一个 UART 总线,并配置好 rx_pintx_pin。这些引脚必须连接到显示屏上的相应引脚。

Nextion 显示屏默认使用 9600 的波特率。您可以通过在 Nextion Editor 中编辑 program.s 源文件来配置 Nextion 显示屏使用更高的速度。例如:

baud=115200 // 将波特率设置为 115200;其他支持的速率请参见 https://nextion.tech/instruction-set/
bkcmd=0 // 告诉 Nextion 不要发送命令响应。这是当前的默认值,但可以设置以防万一

这允许与 Nextion 显示屏进行更快的通信,强烈建议在使用 硬件 UART 时使用。

WARNING

我们强烈建议仅使用 硬件 UART 与 Nextion 显示屏。

使用软件 UART 已知会导致不可预测/不一致的行为。

如果您必须使用软件 UART,请注意大于 9600 的波特率极有可能导致问题。

简而言之,避免在 Nextion 显示屏上使用软件 UART。

# 示例配置条目
display:
- platform: nextion
id: nextion1
lambda: |-
it.set_component_value("gauge", 50);
it.set_component_text("textview", "Hello World!");
  • uart_id (可选, ID): 您希望用于此显示屏的 UART 总线 的 ID。当您有多个 UART 配置时指定此项。

  • brightness (可选, 百分比): 指定时,显示屏亮度将在启动时设置为此值。

  • lambda (可选, lambda): 用于在 Nextion 显示屏上渲染内容的 lambda。详见 渲染 Lambda。这通常为空。Nextion 的各个组件将处理更新显示元素所需的几乎所有功能。

  • update_interval (可选, 时间): 调用 lambda 更新显示屏的间隔。 默认为 5s

  • id (可选, ID): 手动指定用于代码生成的 ID。

  • tft_url (可选, 字符串): 用于显示屏固件更新(Nextion OTA)的 TFT 文件下载 URL。见 Nextion 上传

  • touch_sleep_timeout (可选, int): 设置内部无触摸休眠定时器(秒)。 范围:0(禁用)或 3-65535 秒(最大:约 18 小时)。值 1-2 会自动更正为 3。 设置后,Nextion 将在指定的无触摸活动时间后自动进入睡眠模式。 此设置持续有效,直到设备重启或重置。注意:显示屏只能通过重启或配置 auto_wake_on_touch: true 来唤醒。

  • start_up_page (可选, int): 设置 ESPHome 连接到 Nextion 时显示的页面。(Nextion 默认在启动时显示第 0 页)。

  • wake_up_page (可选, int): 设置唤醒后显示的页面

  • exit_reparse_on_start (可选, 布尔值): 在设置显示屏之前请求 Nextion 退出活动重解析模式。默认为 false

  • on_setup (可选, 动作): ESPHome 连接到 Nextion 后执行的动作。见 Nextion 自动化

  • on_sleep (可选, 动作): Nextion 进入睡眠时执行的动作。见 Nextion 自动化

  • on_wake (可选, 动作): Nextion 唤醒时执行的动作。见 Nextion 自动化

  • on_page (可选, 动作): 页面更改后执行的动作。见 Nextion 自动化

  • on_touch (可选, 动作): 触摸事件(按下或释放)后执行的动作。见 Nextion 自动化

  • auto_wake_on_touch (可选, 布尔值): 如果设置为 true,Nextion 将被配置为在触摸时从睡眠中唤醒。

  • max_queue_age (可选, 时间): 排队命令在被自动移除前的最大年龄(毫秒)。这有助于防止过期命令在延迟后执行。设置为 0 禁用基于年龄的移除(命令仅受队列大小限制)。注意: 非常低的值(例如 <50ms)可能导致命令在传输前被丢弃,因为 ESPHome 的循环时序(~16ms)。启用时建议最小值为 100ms。 范围:0-65535。默认为 8000(8 秒)。

  • startup_override_ms (可选, 时间): 如果显示屏未响应连接握手,在强制将显示屏标记为就绪之前等待的时间(毫秒)。设置为 0 禁用覆盖并无限期等待握手。这对于启动序列较慢的显示屏或强制执行严格握手要求很有用。 范围:0-65535。默认为 8000(8 秒)。

  • skip_connection_handshake (可选, 布尔值): 设置是否跳过初始显示屏连接握手过程。设置为 true 时,连接将在不执行握手的情况下建立。这在使用 Nextion 模拟器时很有用。默认为 false

  • on_buffer_overflow (可选, 动作): Nextion 报告缓冲区溢出时执行的动作。见 Nextion 自动化

  • command_spacing (可选, 时间): 设置发送到 Nextion 显示屏的命令之间的最小时间。 较高的值可以帮助防止缓冲区溢出,但会导致界面更新变慢。 范围是 0-255ms。默认为 0ms(禁用)。

  • max_commands_per_loop (可选, 整数): 限制每个循环周期处理的命令数量。 这有助于防止排队大量命令时发生堆栈溢出。 较低的值(例如 20)可能有助于在受限环境中提高稳定性。

  • max_queue_size (可选, 整数): 设置一次可以排队的最大命令数。 当达到限制时,新命令将被丢弃并记录警告。 这有助于防止在快速连续发出大量命令的复杂设置中发生内存溢出或启动时崩溃。如果未设置,队列大小无限制。

  • dump_device_info (可选, 布尔值): 在配置转储中显示设备信息(型号、固件版本、序列号、闪存大小)。 禁用时,设备信息仅在连接建立期间记录以节省内存。默认为 false

Nextion 显示屏内置了专用处理器来执行所有渲染。ESPHome 只需向显示屏发送指令,告诉它如何渲染某物和/或什么内容。

首先,您需要使用 Nextion Editor 创建一个”TFT”显示文件并”安装”到显示屏上,通常通过 SD 卡,您需要将”TFT”文件复制到 SD 卡上,然后插入显示屏进行安装/更新。然后,在渲染 lambda 中,您可以使用各种 API 调用来填充数据到显示屏:

display:
- platform: nextion
# ...
lambda: |-
// 设置组件的"value" - 值始终是整数
// 例如仪表使用 0 到 100 的整数表示其状态
it.set_component_value("gauge", 50);
// 设置组件的文本
it.set_component_text("textview", "Hello World!");
// 设置带格式的组件文本
it.set_component_text_printf("textview", "The uptime is: %.1f", id(uptime_sensor).state);

NOTE

虽然您可以使用渲染 lambda,但 Nextion 的大部分(如果不是全部)更新可以由各个 Nextion 组件/平台处理。见下文

有关 printf 格式规则的快速介绍,请参阅 格式化文本,有关 strftime 时间格式的介绍,请参阅 显示时间

lambdas 中可以使用多种方法;这些方法允许超出简单显示更新的高级功能。这里不一一列举;请参阅 API Reference: nextion.h 了解更多详情。下面的列表列出了一些常用的方法:

  • upload_tft : 启动向 Nextion 上传新 TFT 文件的过程;见下文 上传 TFT 文件
  • update_all_components() : 所有组件将发布其状态。
id(nextion1).update_all_components();
  • update_components_by_prefix(std::string page) : 这将发送匹配前缀的任何 component_name 的当前状态。一些设置如背景色需要在页面更改时重新发送;这是一个很好的钩子。
id(nextion1).update_components_by_prefix("page0.");
  • 设置各种传感器状态(见下文 队列类型):

    • set_nextion_sensor_state(NextionQueueType queue_type, std::string name, float state);
    • set_nextion_sensor_state(int queue_type, std::string name, float state);
    • set_nextion_text_state(std::string name, std::string state);

NOTE

下面的示例演示如何定义用户 API,以便 Home Assistant 可以通过代码向 Nextion 发送更新。

# 启用 Home Assistant API
api:
actions:
- action: set_nextion_sensor
variables:
nextion_type: int
name: string
state: float
then:
- lambda: |-
id(nextion1).set_nextion_sensor_state(nextion_type,name,state);
- action: set_nextion_text
variables:
name: string
state: string
then:
- lambda: |-
id(nextion1).set_nextion_text_state(name,state);
类型
SENSOR0
BINARY_SENSOR1
SWITCH2
TEXT_SENSOR3
WAVEFORM_SENSOR4
NO_RESULT5

Nextion 显示屏可以使用多种 触发器

此自动化将在与 Nextion 显示屏建立连接时触发。这发生在启动后,可能需要一些时间(几百毫秒)。它可用于在启动完成后更改某些显示元素。例如:

wifi:
ap: # 生成一个带有设备名称和 MAC 地址的无密码 AP
captive_portal:
display:
- platform: nextion
id: disp
on_setup:
then:
- lambda: |-
// 检查是否配置了 WiFi 热点
if (wifi::global_wifi_component->has_sta()) {
// 显示主页面
id(disp).goto_page("main_page");
} else {
// 显示 WiFi 接入点二维码用于 captive portal,见 https://qifi.org/
id(disp).goto_page("wifi_qr_page");
}

这些自动化将在睡眠或唤醒时触发(分别)。Nextion 在睡眠模式下不接受命令或更新;这些触发器可用于处理这种情况。例如,您可以使用它们来 强制更新,在唤醒时刷新显示屏内容。

此自动化在显示屏上更改页面时触发。这包括 ESPHome 发起的和 Nextion 发起的页面更改。ESPHome 通过调用 goto_page("page_name")goto_page(page_id) 函数来发起页面更改。Nextion 本身也可以作为对用户活动(触摸某些显示 UI 元素)的反应或使用定时器来更改页面。无论哪种情况,此自动化都可用于更新新显示页面的屏幕控件。

如果您完全拥有您的 Nextion HMI 设计,并遵循在 Nextion Editor 中为定义的 UI 组件将 vscope 设置为”global”的最佳实践,您可能永远不需要此触发器。但是,如果不是这种情况,并且您的部分/全部 UI 组件的 vscope 设置为”local”,on_page 将是您的解决方案——它使您能够发起相关组件的更新。

在更新组件之前,您需要知道 Nextion 正在显示哪个页面。x 参数将包含一个整数,表示当前页面 ID 号。

知道页面 ID 后,可以更新相应的组件。有两种可能的策略:

on_page:
then:
- lambda: |-
switch (x) {
case 0x02: // wifi_qr_page
// 在此手动触发第 0x02 页控件的更新
id(disp).set_component_text_printf("qr_wifi", "WIFI:T:nopass;S:%s;P:;;", wifi::global_wifi_component->get_ap().get_ssid().c_str());
break;
}

此自动化在 Nextion 显示屏上按下或释放组件时触发。

以下参数将可用:

  • page_id : 包含触摸发生的页面 ID(整数)。

  • component_id : 包含被触摸组件的 ID(整数)。您必须在 Nextion Editor 中的 HMI 配置中为 UI 元素的”Touch Press Event”和/或”Touch Release Event”启用”Send Component ID”。

  • touch_event : “press”事件为 true,“release”事件为 false

on_touch:
then:
- lambda: |-
ESP_LOGD("nextion.on_touch", "Nextion touch event detected!");
ESP_LOGD("nextion.on_touch", "Page ID: %i", page_id);
ESP_LOGD("nextion.on_touch", "Component ID: %i", component_id);
ESP_LOGD("nextion.on_touch", "Event type: %s", touch_event ? "Press" : "Release");

此自动化在 Nextion 显示屏报告串行缓冲区溢出时触发。发生这种情况时,Nextion 的缓冲区将继续接收新指令,但所有先前的指令都会丢失,Nextion 队列可能会不同步。

此自动化将允许您优雅地处理这种情况;例如,您可以向 Nextion 重复某些命令/更新或重启系统。

on_buffer_overflow:
then:
- lambda: |-
ESP_LOGW("nextion.on_buffer_overflow", "Nextion reported a buffer overflow event!");

您可以使用此 动作 设置 Nextion 背光的亮度。

on_...:
then:
- display.nextion.set_brightness: 50%

或者,如果您碰巧连接了多个 Nextion 显示屏,可能需要使用长格式:

on_...:
then:
- display.nextion.set_brightness:
id: nextion1
brightness: 50%

这将使用为 tft_url 指定的文件来更新(“OTA”)Nextion。

完成后,ESPHome 和 Nextion 都将重启。ESPHome 在上传过程中将无响应,不会发生日志记录或其他 自动化。此过程使用与 Nextion Editor 相同的协议,仅传输 TFT 文件的必要部分。

WARNING

使用软件 UART 已知会导致不可预测/不一致的行为,很可能导致更新过程失败。

如果您在更新过程中遇到问题并且正在使用软件 UART(例如在 ESP8266 上),您应该切换到具有更多可用 硬件 UART 的 ESP32 或支持的变体。

您可以使用 Home Assistant 本身或任何其他 Web 服务器来托管 TFT 文件。使用 HTTPS(通常推荐)时,您可能会注意到上传速度降低,因为加密消耗了微控制器上的更多资源。

我们建议使用 模板 来触发此过程。例如:

button:
- platform: template
id: update_nextion_button
name: Update Nextion
entity_category: diagnostic
on_press:
then:
- lambda: 'id(nextion1)->upload_tft();'

要从 Home Assistant 托管 TFT 文件,请在您的 config 目录中创建一个 www 目录(如果尚不存在)。如果您愿意,还可以为您的 TFT 文件创建一个子目录。

例如,如果文件位于您的配置目录 www/tft/default.tft,访问它的 URL 将是 http(s)://your_home_assistant_url:port/local/tft/default.tft

此库支持几种不同的组件,允许 Home Assistant、ESPHome 和 Nextion 之间的通信。

NOTE

如果 Nextion 正在睡眠或组件被设置为隐藏,即使发送更新,它也不会更新其组件。要解决此问题,在 Nextion 唤醒后,所有组件将其状态发送到 Nextion。

除了配置了 page_id /component_id 选项的 Nextion 外,下面的示例说明了:

  • 轮询 Nextion 以获取更新
  • 从 Nextion 发送到 ESPHome 的动态更新
sensor:
- platform: nextion
nextion_id: nextion1
name: "n0"
component_name: n0
- platform: nextion
id: current_page
name: "current_page"
variable_name: dp
update_interval: 1s

请注意,第一个需要在 Nextion 显示屏的 HMI 代码/配置中包含自定义协议。请参阅各个组件(链接如下)了解更多详情。