touch_element.rst 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. 触摸元件
  2. =============
  3. :link_to_translation:`en:[English]`
  4. 概述
  5. --------
  6. 触摸元件库是基于触摸传感器驱动设计的高度抽象的元件库,该库提供了统一且友好的软件接口,可以快速构建电容式触摸传感器的应用。有关触摸传感器驱动 API 的更多信息,请参阅 :doc:`../peripherals/touch_pad`。
  7. 架构
  8. ^^^^^^^^^^^^
  9. 触摸元件库通过触摸传感器驱动程序配置触摸传感器外设。使用时,部分必要的硬件参数需要传递给函数 :cpp:func:`touch_element_install`,但只有在调用 :cpp:func:`touch_element_start` 函数后,才会自动配置这些参数。这些参数配置会对实时系统产生很大的影响,因此步骤顺序很重要,必须在调用启动函数之后进行配置,确保系统正常运行。
  10. 上述参数包括触摸通道阈值、防水屏蔽传感器驱动级别等。触摸元件库会设置触摸传感器中断和 esp_timer 例程,并在触摸传感器中断服务例程中获取触摸传感器的硬件信息(通道状态、通道编号)。当特定通道事件发生时,硬件信息将传递给 esp_timer 回调例程,esp_timer 回调例程将触摸传感器通道信息分配给触摸元件(例如按键、滑条等)。随后,触摸元件库运行特定算法,更新触摸元件状态或计算其位置,并将结果分派给相应的处理程序。
  11. 因此,在使用触摸元件库时,你无需关注触摸传感器外设的工作细节,该库会处理大部分硬件信息,并将更有意义的信息传递给事件处理程序。
  12. 下图展示了触摸元件库的工作流程。
  13. .. figure:: /../_static/touch_element/te_architecture.svg
  14. :scale: 100 %
  15. :align: center
  16. 触摸元件库架构
  17. 下表展示了 {IDF_TARGET_NAME} 中与触摸元件库有关的功能。
  18. .. list-table::
  19. :header-rows: 1
  20. :widths: 70 30
  21. :align: center
  22. * - 功能
  23. - ESP32S2
  24. * - 防水
  25. - ✔
  26. * - 按键
  27. - ✔
  28. * - 触摸滑条
  29. - ✔
  30. * - 矩阵按键
  31. - ✔
  32. 外设
  33. ^^^^^^^^^^
  34. {IDF_TARGET_NAME} 集成了一个触摸传感器外设,具有多个物理通道。
  35. .. only:: esp32s2 or esp32s3
  36. - 14 个物理电容触摸通道
  37. - 定时器或软件 FSM 触发模式
  38. - 高达 5 种中断(高阈值和低阈值中断、测量单通道完成和测量所有通道完成中断、测量超时中断)
  39. - 睡眠模式唤醒源
  40. - 硬件内置降噪
  41. - 硬件滤波器
  42. - 硬件防水传感器
  43. - 硬件近场感应传感器
  44. 这些通道的具体位置如下:
  45. .. list-table::
  46. :header-rows: 1
  47. :widths: 50 50
  48. :align: center
  49. * - 通道
  50. - {IDF_TARGET_NAME}
  51. * - **通道 0**
  52. - **GPIO 0(保留)**
  53. * - **通道 1**
  54. - **GPIO 1**
  55. * - **通道 2**
  56. - **GPIO 2**
  57. * - **通道 3**
  58. - **GPIO 3**
  59. * - **通道 4**
  60. - **GPIO 4**
  61. * - **通道 5**
  62. - **GPIO 5**
  63. * - **通道 6**
  64. - **GPIO 6**
  65. * - **通道 7**
  66. - **GPIO 7**
  67. * - **通道 8**
  68. - **GPIO 8**
  69. * - **通道 9**
  70. - **GPIO 9**
  71. * - **通道 10**
  72. - **GPIO 10**
  73. * - **通道 11**
  74. - **GPIO 11**
  75. * - **通道 12**
  76. - **GPIO 12**
  77. * - **通道 13**
  78. - **GPIO 13**
  79. * - **通道 14**
  80. - **GPIO 14**
  81. .. only:: esp32
  82. - 10 个物理电容触摸通道
  83. - 定时器或软件 FSM 触发模式
  84. - 2 种中断(超过阈值和低于阈值中断)
  85. - 睡眠模式唤醒源
  86. 这些通道的具体位置如下:
  87. .. list-table::
  88. :header-rows: 1
  89. :widths: 50 50
  90. :align: center
  91. * - 通道
  92. - {IDF_TARGET_NAME}
  93. * - **通道 0**
  94. - **GPIO 0(有效)**
  95. * - **通道 1**
  96. - **GPIO 1**
  97. * - **通道 2**
  98. - **GPIO 2**
  99. * - **通道 3**
  100. - **GPIO 3**
  101. * - **通道 4**
  102. - **GPIO 4**
  103. * - **通道 5**
  104. - **GPIO 5**
  105. * - **通道 6**
  106. - **GPIO 6**
  107. * - **通道 7**
  108. - **GPIO 7**
  109. * - **通道 8**
  110. - **GPIO 8**
  111. * - **通道 9**
  112. - **GPIO 9**
  113. 术语
  114. -----------
  115. 触摸元件库的有关术语如下:
  116. .. list-table::
  117. :header-rows: 1
  118. :widths: 50 50
  119. :align: center
  120. * - 术语
  121. - 定义
  122. * - **触摸传感器 (touch sensor)**
  123. - 芯片内部的触摸传感器外设
  124. * - **触摸通道 (touch channel)**
  125. - 触摸传感器外设内的触摸通道
  126. * - **触摸焊盘 (touch pad)**
  127. - 外部物理触摸焊盘,通常位于 PCB 内部
  128. * - **降噪通道 (de-noise channel)**
  129. - 内部降噪通道,始终为通道 0 且已预留
  130. * - **屏蔽传感器 (shield sensor)**
  131. - 防水传感器之一,用于小面积的水滴检测,并补偿水滴对读数的影响
  132. * - **防护传感器 (guard sensor)**
  133. - 防水传感器之一,用于大面积的涉水检测,并临时禁用触摸传感器
  134. * - **屏蔽通道 (shield channel)**
  135. - 防水屏蔽传感器连接的通道,始终为通道 14
  136. * - **防护通道 (guard channel)**
  137. - 防水防护传感器连接的通道
  138. * - **屏蔽焊盘 (shield pad)**
  139. - 外部物理屏蔽焊盘,通常是网格状,与防水传感器相连
  140. * - **防护焊盘 (guard pad)**
  141. - 外部物理防护焊盘,通常是环状,与防护传感器相连
  142. .. figure:: /../_static/touch_element/te_component.svg
  143. :scale: 100 %
  144. :align: center
  145. 触摸传感器应用程序系统组件
  146. 触摸传感器信号
  147. ^^^^^^^^^^^^^^^^^^^
  148. 触摸传感器可提供以下信号:
  149. - 原始信号:从触摸传感器获取、未经滤波的信号。
  150. - 平滑信号:原始信号通过内部硬件滤波器滤波后的信号。
  151. - 基准信号:经过滤波的信号,已过滤极低频噪声。
  152. 以上信号均可通过触摸传感器驱动程序 API 获取。
  153. .. figure:: /../_static/touch_element/te_signal.png
  154. :scale: 40 %
  155. :align: center
  156. 触摸传感器信号
  157. 触摸传感器信号阈值
  158. ^^^^^^^^^^^^^^^^^^^^^^
  159. 触摸传感器阈值支持重新配置,可用于确定触摸传感器状态。当平滑信号和基准信号间的差值大于阈值,即 ``(平滑信号 - 基准信号)> 信号阈值`` 时,触摸通道状态改变,并触发触摸中断。
  160. .. figure:: /../_static/touch_element/te_threshold.svg
  161. :scale: 40 %
  162. :align: center
  163. 触摸传感器信号阈值
  164. 灵敏度
  165. ^^^^^^^^^^^^^^^^
  166. 触摸传感器的一个重要性能参数,该值越大,表明触摸传感器越灵敏。可以通过以下公式计算:
  167. .. math::
  168. Sensitivity = \frac{Signal_{press} - Signal_{release}}{Signal_{release}} = \frac{Signal_{delta}}{Signal_{benchmark}}
  169. 防水性能
  170. ^^^^^^^^^^^^^^^^^^
  171. 防水性能是触摸传感器的硬件功能,包括防护传感器和屏蔽传感器(始终连接到通道 14),可以抵御一定程度的水滴影响,并检测水流。
  172. 触摸按键
  173. ^^^^^^^^^^^^^^^^^^
  174. 触摸按键占用触摸传感器的一个通道,外观如下图所示:
  175. .. figure:: /../_static/touch_element/te_button.svg
  176. :scale: 100 %
  177. :align: center
  178. 触摸按键
  179. 触摸滑条
  180. ^^^^^^^^^^^^^^^^^^
  181. 触摸滑条占用触摸传感器的多个通道(至少三个),占用的通道越多,滑条的采样分辨率和准确度越高。触摸滑条外观如下图所示:
  182. .. figure:: /../_static/touch_element/te_slider.svg
  183. :scale: 100 %
  184. :align: center
  185. 触摸滑条
  186. 触摸矩阵
  187. ^^^^^^^^^^^^^^^^^^
  188. 触摸矩阵按键占用触摸传感器的多个通道(至少 2 + 2 = 4 个通道),它支持通过较少通道获取更多按键。{IDF_TARGET_NAME} 最多支持 49 个按键。触摸矩阵按键外观如下图所示:
  189. .. figure:: /../_static/touch_element/te_matrix.svg
  190. :scale: 100 %
  191. :align: center
  192. 触摸矩阵
  193. 使用触摸元件库
  194. --------------
  195. 使用触摸元件库时,请遵循以下初始化流程:
  196. 1. 调用 :cpp:func:`touch_element_install`,初始化触摸元件库。
  197. 2. 调用 :cpp:func:`touch_xxxx_install`,初始化触摸元件(按键、滑条等)。
  198. 3. 调用 :cpp:func:`touch_xxxx_create`,创建新元件实例。
  199. 4. 调用 :cpp:func:`touch_xxxx_subscribe_event`,订阅事件通知。
  200. 5. 调用 :cpp:func:`touch_xxxx_set_dispatch_method`,选择事件通知的传递方式。
  201. 6. 选择使用回调函数传递事件通知时,调用 :cpp:func:`touch_xxxx_set_callback`,设置事件处理函数。
  202. 7. 调用 :cpp:func:`touch_element_start`,启用触摸元件库。
  203. 8. 选择使用回调函数传递事件通知时,若事件发生,驱动核心会调用回调函数,你无需做任何处理;选择使用事件任务传递事件通知时,你需要创建一个事件任务,并调用 :cpp:func:`touch_element_message_receive`,循环获取信息。
  204. 9. (可选)如果要暂停触摸元件的实时系统,或因某种原因无法获取触摸元件信息,应调用 :cpp:func:`touch_element_stop`,暂停触摸元件系统,然后再次调用 :cpp:func:`touch_element_start` 恢复系统。
  205. 上述流程代码如下所示:
  206. .. code-block:: c
  207. static touch_xxx_handle_t element_handle; //声明一个触摸元件句柄
  208. //定义订阅的事件处理函数
  209. void event_handler(touch_xxx_handle_t out_handle, touch_xxx_message_t out_message, void *arg)
  210. {
  211. //事件处理逻辑
  212. }
  213. void app_main()
  214. {
  215. //使用默认初始化器配置触摸元件库
  216. touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
  217. touch_element_install(&global_config);
  218. //使用默认初始化器配置触摸元件
  219. touch_xxx_global_config_t elem_global_config = TOUCH_XXXX_GLOBAL_DEFAULT_CONFIG();
  220. touch_xxx_install(&elem_global_config);
  221. //创建新的实例
  222. touch_xxx_config_t element_config = {
  223. ...
  224. ...
  225. };
  226. touch_xxx_create(&element_config, &element_handle);
  227. //通过事件掩码订阅特定事件
  228. touch_xxx_subscribe_event(element_handle, TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE, NULL);
  229. //选择使用回调函数传递事件通知
  230. touch_xxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK);
  231. //注册回调函数
  232. touch_xxx_set_callback(element_handle, event_handler);
  233. //启用触摸元件库处理
  234. touch_element_start();
  235. }
  236. 初始化
  237. ^^^^^^^^^^^^^^
  238. 1. 要初始化触摸元件库,请调用 :cpp:func:`touch_element_install` 函数,并传递一个 :cpp:type:`touch_elem_global_config_t` 类型的实例作为参数,以配置触摸传感器外设和触摸元件库。默认初始化器位于 :cpp:func:`TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG` 中,此默认配置适用于多数常见应用场景。建议在充分了解触摸传感器外设前,不要更改默认配置,以免影响系统。
  239. 2. 要初始化特定的触摸元件,需要调用其构造函数 :cpp:func:`touch_xxxx_install`。在调用此构造函数前,所有触摸元件都不会工作,以节省内存。因此,若要设置所需元件,需要为每个要使用的触摸元件分别调用构造函数。
  240. 启动触摸元件实例
  241. ^^^^^^^^^^^^^^^^
  242. 1. 要创建新的触摸元件实例,请调用 :cpp:func:`touch_xxxx_create`,选择一个通道,并将其 `灵敏度`_ 传递给新的元件实例。
  243. 2. 要订阅事件通知,请调用 :cpp:func:`touch_xxxx_subscribe_event`。触摸元件库提供了多个事件,事件掩码存放在 :idf_file:`components/touch_element/include/touch_element/touch_element.h` 中。通过使用这些事件掩码,可以订阅单个特定事件,或将单个事件组合在一起,订阅多个事件。
  244. 3. 要配置传递事件通知的方式,请调用 :cpp:func:`touch_xxxx_subscribe_event`。触摸元件库提供了两种方式: :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT` 和 :cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK`,支持以不同方式获取并处理触摸元件信息。
  245. 事件处理
  246. ^^^^^^^^^^^^^^^^^
  247. 如果配置的是 :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT`,需要启用一个事件处理任务获取触摸元件信息。调用 :cpp:func:`touch_element_message_receive` 可以获取所有元件的原始信息,随后通过调用相应的信息解码器 :cpp:func:`touch_xxxx_get_message`,提取特定类型元件的信息,获取有关触摸操作的详细数据。如果配置的是 :cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK`,在触摸元件开始工作之前,需要调用 :cpp:func:`touch_xxxx_set_callback`,传递一个事件处理函数,有关触摸操作的详细数据都会传递到该事件处理函数。
  248. .. warning::
  249. 由于事件处理函数在元件库的核心运行,即在 esp-timer 回调中运行,请避免执行可能导致阻塞或延迟的操作,如调用 :cpp:func:`vTaskDelay`。
  250. 事件处理过程代码如下所示:
  251. .. code-block:: c
  252. /* ---------------------------------------------- TOUCH_ELEM_DISP_EVENT ----------------------------------------------- */
  253. void element_handler_task(void *arg)
  254. {
  255. touch_elem_message_t element_message;
  256. while(1) {
  257. if (touch_element_message_receive(&element_message, Timeout) == ESP_OK) {
  258. const touch_xxxx_message_t *extracted_message = touch_xxxx_get_message(&element_message); //信息解码
  259. ... //事件处理逻辑
  260. }
  261. }
  262. }
  263. void app_main()
  264. {
  265. ...
  266. touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_EVENT); //设置以 TOUCH_ELEM_DISP_EVENT 传递事件通知
  267. xTaskCreate(&element_handler_task, "element_handler_task", 2048, NULL, 5, NULL); //创建一个事件处理任务
  268. ...
  269. }
  270. /* -------------------------------------------------------------------------------------------------------------- */
  271. ...
  272. /* ---------------------------------------------- TOUCH_ELEM_DISP_CALLBACK ----------------------------------------------- */
  273. void element_handler(touch_xxxx_handle_t out_handle, touch_xxxx_message_t out_message, void *arg)
  274. {
  275. //事件处理逻辑
  276. }
  277. void app_main()
  278. {
  279. ...
  280. touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK); //设置以 ``TOUCH_ELEM_DISP_CALLBACK`` 传递事件通知
  281. touch_xxxx_set_callback(element_handle, element_handler); //注册事件处理函数
  282. ...
  283. }
  284. /* -------------------------------------------------------------------------------------------------------------- */
  285. 使用防水功能
  286. ^^^^^^^^^^^^^^^^
  287. 1. 一旦初始化触摸元件的防水功能,防水屏蔽传感器会始终处于开启状态。防水屏蔽传感器为可选项,如果不需要,可以通过配置结构体,将 ``TOUCH_WATERPROOF_GUARD_NOUSE`` 传递给 :cpp:func:`touch_element_waterproof_install`。
  288. 2. 要关联触摸元件与防护传感器,请调用 :cpp:func:`touch_element_waterproof_add`,将触摸元件句柄添加到触摸元件防水功能的掩码列表中。触摸元件与防护传感器关联后,水流触发防护传感器时会关闭触摸元件,为其提供保护。
  289. 查看使用触摸元件防水功能的示例代码,请前往 ESP-IDF 示例的 :example:`peripherals/touch_sensor/touch_element/touch_element_waterproof` 目录。
  290. 配置防水功能的代码如下所示:
  291. .. code-block:: c
  292. void app_main()
  293. {
  294. ...
  295. touch_xxxx_install(); //初始化实例(按键、滑条等)
  296. touch_xxxx_create(&element_handle); //创建新的触摸元件
  297. ...
  298. touch_element_waterproof_install(); //初始化触摸元件防水功能
  299. touch_element_waterproof_add(element_handle); //关联触摸元件与防护传感器
  300. ...
  301. }
  302. 从 Light/Deep-sleep 模式唤醒
  303. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  304. 仅触摸按键可配置为唤醒源。
  305. 使用触摸传感器,可以唤醒从 Light-sleep 或 Deep-sleep 模式中唤醒芯片。在 Light-sleep 模式下,任何已安装的触摸按键都可以唤醒芯片。但在 Deep-sleep 模式下,只有睡眠按键可以唤醒芯片,触摸传感器还会立即进行校准。如果手指没有及时离开,可能导致校准参考值出错。尽管在手指离开后,校准参考值会自行恢复,不会影响驱动逻辑,但如果你不想在从 Deep-sleep 模式唤醒时看到错误的校准参考值,可以调用 :cpp:func:`touch_element_sleep_enable_wakeup_calibration`,禁用唤醒校准功能。
  306. 查看使用触摸元件唤醒芯片的示例代码,请前往 ESP-IDF 示例的 :example:`system/light_sleep` 目录。
  307. .. code-block:: c
  308. void app_main()
  309. {
  310. ...
  311. touch_element_install();
  312. touch_button_install(); //初始化触摸按键
  313. touch_button_create(&element_handle); //创建新的触摸元件
  314. ...
  315. // ESP_ERROR_CHECK(touch_element_enable_light_sleep(&sleep_config));
  316. ESP_ERROR_CHECK(touch_element_enable_deep_sleep(button_handle[0], &sleep_config));
  317. // ESP_ERROR_CHECK(touch_element_sleep_enable_wakeup_calibration(button_handle[0], false)); //(可选)禁用唤醒校准,防止基准值更新为错误值
  318. touch_element_start();
  319. ...
  320. }
  321. 应用示例
  322. -------------------
  323. 查看使用触摸元件库的示例代码,请前往 ESP-IDF 示例的 :example:`peripherals/touch_sensor/touch_element` 目录。
  324. API 参考 - 触摸元件核心
  325. ----------------------------------
  326. .. include-build-file:: inc/touch_element.inc
  327. API 参考 - 触摸按键
  328. ----------------------------------
  329. .. include-build-file:: inc/touch_button.inc
  330. API 参考 - 触摸滑条
  331. ----------------------------------
  332. .. include-build-file:: inc/touch_slider.inc
  333. API 参考 - 触摸矩阵
  334. ----------------------------------
  335. .. include-build-file:: inc/touch_matrix.inc