跳转到内容

触摸屏组件

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

# 触摸屏示例
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 (可选, 布尔值):如果为 true,交换 x 和 y 轴。
    • mirror_x (可选, 布尔值):如果为 true,镜像 x 轴。
    • mirror_y (可选, 布尔值):如果为 true,镜像 y 轴。
  • update_interval (可选, 时间):触摸屏轮询间隔 - 仅在不使用中断引脚时使用。默认为 50ms

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

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

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

    • x_max (**必填”, int):对应于触摸屏右边缘(如果指定了 swap_xy 则为下边缘)的原始值。

    • y_min (**必填”, int):对应于触摸屏上边缘(如果指定了 swap_xy 则为左边缘)的原始值。

    • y_max (**必填”, int):对应于触摸屏下边缘(如果指定了 swap_xy 则为右边缘)的原始值。

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

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

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

on_touch 触发器on_update 触发器 都有一个 API Reference: touchscreen::TouchPoint 类型的参数,在列表中(on_update)或作为 optionalon_touch)。

下面的触摸位置整数成员与显示屏宽度和高度相关:

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

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

  • xy 是当前位置。

  • x_prevy_prev 是前一位置。

  • x_orgy_org 是首次检测到触摸时的位置。

  • x_rawy_raw 用于相对于显示屏校准触摸屏。这取代了触摸屏类中同名的属性。

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

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

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

# 触摸屏
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 原始值。

... 左上 ...
[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
... 右上 ...
[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
... 左下 ...
[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
... 右下 ...
[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) // 或 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 Reference: 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 (可选, 布尔值):某些触摸屏比底层屏幕大,并使用此额外区域作为触摸按钮。要允许传感器在显示区域外注册触摸,请将此设置为 true。上述校准值应设置为显示边界。

  • 所有其他选项来自 二进制传感器