跳转到内容

触摸屏组件

touchscreen 组件包含 ESPHome 中大多数触摸屏驱动组件的基础代码, 负责将触摸事件传递给具有 touchscreen 平台的 binary_sensors。LVGL 组件也使用它。

# Example touchscreen
touchscreen:
- platform: ...
display: display1
transform:
mirror_x: false
mirror_y: false
swap_xy: false
on_touch:
then:
...
on_update:
then:
...
on_release:
then:
...
  • display (必填, ID): 与此触摸屏一起使用的显示屏。

  • transform (可选): 使用硬件转换触摸屏显示。所有默认值均为 false。

    • swap_xy (可选, boolean): 如果为 true,则交换 x 和 y 轴。
    • mirror_x (可选, boolean): 如果为 true,则镜像 x 轴。
    • mirror_y (可选, boolean): 如果为 true,则镜像 y 轴。
  • update_interval (可选, Time): 触摸屏轮询间隔——仅在没有使用中断引脚时使用。默认为 50ms。

  • touch_timeout (可选, Time): 不报告触摸结束的触摸屏的超时。默认值因触摸屏而异。

  • calibration (可选): 某些触摸屏需要逐设备校准。

    • x_min (必填, int): 对应触摸屏左 (或顶部,如果指定了 swap_xy)边缘的原始值。请参阅 校准 了解校准触摸屏的过程。

    • x_max (必填, int): 对应触摸屏右 (或底部,如果指定了 swap_xy)边缘的原始值。

    • y_min (必填, int): 对应触摸屏顶部 (或左侧,如果指定了 swap_xy)边缘的原始值。

    • y_max (必填, int): 对应触摸屏底部 (或右侧,如果指定了 swap_xy)边缘的原始值。

  • on_touch (可选, Automation): 当触摸屏被触摸时执行的自动化。请参阅 on_touch 触发器。

  • on_update (可选, Automation): 当触摸屏被触摸时执行的自动化。请参阅 on_update 触发器。

  • on_release (可选, Automation): 当触摸屏不再被触摸时执行的自动化。请参阅 on_release 触发器。

on_touch 触发器 和 on_update 触发器 都有类型为 API 参考:touchscreen::TouchPoint 的参数, 在列表(on_update)中或作为 optional(on_touch)。

以下触摸位置的整数成员相对于显示屏的宽度和高度:

  • id 是触摸屏提供的用于在多触控屏幕上唯一标识触摸的数字。

  • state 指示触摸的状态。可以是 1,表示初始触摸,或 2 表示触摸位置已更改/移动。

  • x 和 y 是当前位置。

  • x_prev 和 y_prev 是上一个位置。

  • x_org 和 y_org 是首次检测到触摸时的位置。

  • x_raw 和 y_raw 用于相对于显示屏校准触摸屏。这替换了触摸屏类中同名的属性。

对于大多数触摸屏驱动,触摸屏的尺寸会自动从显示驱动程序设置以匹配屏幕尺寸。 在某些情况下,如 XPT2046(电阻式触摸屏),报告的值与实际屏幕尺寸无关。 可以使用 calibration 配置来手动校准触摸屏。

要将触摸点与显示坐标匹配,必须校准触摸屏。 触摸屏组件在校准范围内返回原始值。这些原始值可作为 x_raw 和 y_raw 成员变量使用。校准的目标是确定对应 于屏幕边缘的原始值。

校准假设显示屏以一种您将使用它的方式定向,即您的 显示渲染引擎 组件必须将 [0,0] 逻辑坐标放在左上角。

# Touchscreen
touchscreen:
platform: xpt2046
id: my_touchscreen
cs_pin: GPIOXX
on_touch:
- lambda: |-
ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
touch.x,
touch.y,
touch.x_raw,
touch.y_raw
);

获取触控笔或类似物体,运行项目并在屏幕的 边缘像素处触摸角落。重复几次并记录 x 和 y 的最小和最大原始值。

... top left ...
[21:07:48][I][cal:071]: x=217, y=34, x_raw=3718, y_raw=445
[21:07:49][I][cal:071]: x=222, y=32, x_raw=3804, y_raw=419
... top right ...
[21:07:52][I][cal:071]: x=19, y=36, x_raw=334, y_raw=370
[21:07:52][I][cal:071]: x=22, y=35, x_raw=386, y_raw=347
... bottom left ...
[21:08:00][I][cal:071]: x=224, y=299, x_raw=3836, y_raw=3835
[21:08:00][I][cal:071]: x=225, y=303, x_raw=3848, y_raw=3878
[21:08:01][I][cal:071]: x=223, y=299, x_raw=3807, y_raw=3829
... bottom right ...
[21:08:11][I][cal:071]: x=16, y=299, x_raw=281, y_raw=3839
[21:08:12][I][cal:071]: x=19, y=302, x_raw=328, y_raw=3866
[21:08:13][I][cal:071]: x=20, y=296, x_raw=358, y_raw=3799

这意味着最小原始 x 为 281,最大为 3848,最小 y 为 347,最大为 3878。

确定哪个原始值是显示屏的 x 方向,哪个是 y 方向。在我们的案例中 向右移动会减小 x 原始值,向下移动会增加 y 原始值,因此坐标轴 匹配,我们 不需要 使用 swap_xy。如果原始 x 是显示屏的 y, 请使用 swap_xy = true。

如果其中一个坐标朝”错误”方向移动,则需要反转。 通过设置 mirror_x 和/或 mirror_y 为 true 来执行反转。

touchscreen:
platform: xpt2046
calibration:
x_min: 281
x_max: 3848
y_min: 347
y_max: 3878
transform:
mirror_x: false
mirror_y: false
swap_xy: false

编译、运行并再次点击边缘。x 和 y 现在应该与 显示屏的坐标匹配。

[21:32:34][I][cal:071]: x=7, y=6, x_raw=3755, y_raw=407
[21:32:37][I][cal:071]: x=237, y=4, x_raw=313, y_raw=385
[21:32:43][I][cal:071]: x=239, y=318, x_raw=284, y_raw=3845
[21:33:05][I][cal:071]: x=2, y=313, x_raw=3821, y_raw=3793

注意,触摸屏并非极其精确,可能存在非线性 或类似错误,因此不要期望像素级精度。您可以使用类似以下的显示 lambda 来验证触摸点。

display:
- platform: ili9341
lambda: |-
auto touch = id(my_touchscreen)->get_touch();
if (touch) // or touch.has_value()
it.filled_circle(touch.value().x, touch.value().y, 10, RED);

准确地说,组件执行以下操作:

  • 读取原始 x 和 y,并使用(非反转的)最小值和最大值对其进行归一化
  • 如果需要,交换 x 和 y
  • 如果需要,进行反转
  • 缩放到显示屏尺寸

当触摸屏初始检测到触摸时,将触发此自动化;在所有触摸(对于支持多点触控的驱动程序)被释放之前,它将不会再次触发。

注意:此行为已更改(从 ESPHome 2023.11.6 开始)。要接收来自拖动的持续更新,请使用 on_update 触发器。

此触发器提供两个参数,名为 touch(类型为 touchpoint)和包含所有触摸列表的 touches。

当触摸屏检测到额外触摸或触摸在屏幕上移动时,将触发此新自动化。

此触发器提供一个名为 touches 的参数,类型为 API 参考:touchscreen::TouchPoints_t,它包含 TouchPoint 参数类型 的列表。

此触发器可用于检测在显示屏上滑动等手势。

例如,您可以执行以下操作:

on_update:
- lambda: |-
for (auto touch: touches) {
if (touch.state <= 2) {
ESP_LOGI("Touch points:", "id=%d x=%d, y=%d", touch.id, touch.x, touch.y);
}
}

请注意,每次都需要检查状态标志,以查看触摸是否仍然有效。

  • 状态值 0 表示触摸无效,因为不再检测到触摸。
  • 状态值 1 表示首次检测到。
  • 状态值 2 表示触摸仍然被检测到,但在屏幕上移动了。
  • 状态值 4 及更高表示检测到触摸释放。

当所有触摸从触摸屏上释放时,将触发此自动化。

此时它没有额外参数。

touchscreen 二进制传感器允许您在触摸屏上设置区域作为虚拟 按钮。

binary_sensor:
- platform: touchscreen
name: Top Left Touch Button
x_min: 0
x_max: 100
y_min: 0
y_max: 100
page_id: home_page_id
use_raw: true
  • touchscreen_id (可选, ID): 手动指定触摸屏的 ID。

  • x_min (必填, int): 被检测为虚拟按钮的屏幕区域的左坐标。

  • x_max (必填, int): 被检测为虚拟按钮的屏幕区域的右坐标。

  • y_min (必填, int): 被检测为虚拟按钮的屏幕区域的上坐标。

  • y_max (必填, int): 被检测为虚拟按钮的屏幕区域的下坐标。

  • page_id (可选, ID): 仅当显示屏显示此页面时才触发此二进制传感器。 不能与 pages 一起使用。

  • pages (可选, ID 列表): 仅当显示屏显示这些页面之一时才触发此二进制传感器。 不能与 page_id 一起使用。

  • use_raw (可选, boolean): 某些触摸屏大于底层屏幕,并使用此额外 区域作为触摸按钮。要允许传感器记录显示区域之外的触摸,请将其设置为 true。 如上所述的校准值应设置为显示屏边界。

  • 还包括 Binary Sensor 的所有其他选项。