Difference between revisions of "STM32 Touch Sensors"
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | + | [[Category:STM32]][[Category:STM32 Development]][[Category:KiCAD]]{{metadesc|STM32 Touch Sensors - hardware and code}} | |
Only some STM32 processors have touch sensor circuitry built in, most noticeable the STM32Lxx series. | Only some STM32 processors have touch sensor circuitry built in, most noticeable the STM32Lxx series. | ||
Line 11: | Line 11: | ||
The circuitry involved in the touch sensing is the C5 and the actual touch pads J2, J3 and J4 and their accompanying resistors. | The circuitry involved in the touch sensing is the C5 and the actual touch pads J2, J3 and J4 and their accompanying resistors. | ||
+ | |||
+ | Layout wise I did two different approaches: | ||
+ | |||
+ | [[File:Touch PCB Layout.png|400px]] | ||
+ | |||
+ | The top and bottom touch pads are just big single sided SMD pads which is covered by soldermask. The center "hole" is a big through hole pad. | ||
+ | |||
+ | The gadget came out like this: | ||
+ | |||
+ | [[File:Touch PCB.jpg|400px]] | ||
+ | |||
+ | == Software == | ||
+ | |||
+ | === STM32CubeMX Configuration === | ||
+ | |||
+ | Messing around with this it turns out that the middle pad (the through hole one) is much to close to the neighbors, so in the software example I only deal with the two pads covered by soldermask. | ||
+ | |||
+ | [[File:TSC Pins.png|1000px]] | ||
+ | |||
+ | Under Middleware/Touchsensing: | ||
+ | |||
+ | [[File:Touch Mode and Configuration.png|600px]] | ||
+ | |||
+ | [[File:Configuration parameters.png|600px]] | ||
+ | |||
+ | === Code === | ||
+ | |||
+ | The touchsensing middleware will do all the heavy lifting and only a few lines of code is needed to use the touch sensors. | ||
+ | |||
+ | First of all, in the main program loop: | ||
+ | |||
+ | <pre> | ||
+ | /* Infinite loop */ | ||
+ | /* USER CODE BEGIN WHILE */ | ||
+ | |||
+ | uint32_t then = 0, now = 0; | ||
+ | |||
+ | for (;;) { | ||
+ | |||
+ | now = HAL_GetTick(); | ||
+ | if (now % 50 == 0 && now != then) { | ||
+ | |||
+ | tsl_user_Exec_IT(); | ||
+ | |||
+ | if (now % 1000 == 0) { | ||
+ | |||
+ | printf("Tick %5lu B0: %2d / %2d B1: %2d / %2d\n", now / 1000, | ||
+ | MyTKeys[0].p_Data->StateId, MyTKeys[0].p_ChD->Meas, | ||
+ | MyTKeys[1].p_Data->StateId, MyTKeys[1].p_ChD->Meas); | ||
+ | } | ||
+ | |||
+ | then = now; | ||
+ | } | ||
+ | |||
+ | /* USER CODE END WHILE */ | ||
+ | |||
+ | /* USER CODE BEGIN 3 */ | ||
+ | |||
+ | } | ||
+ | /* USER CODE END 3 */ | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | Essentially this will call the "tsl_user_Exec_IT()" function every 50 ms (20 times per second) and each second it will print out the status of the keys. | ||
+ | |||
+ | The interrupt handler callback is defined in tsl_user.c | ||
+ | |||
+ | <pre> | ||
+ | void HAL_TSC_ConvCpltCallback(TSC_HandleTypeDef* htsc) | ||
+ | { | ||
+ | /* USER CODE BEGIN HAL_TSC_ConvCpltCallback start*/ | ||
+ | |||
+ | /* USER CODE END HAL_TSC_ConvCpltCallback start*/ | ||
+ | TSL_acq_BankGetResult(idx_bank_it, 0, 0); | ||
+ | idx_bank_it++; | ||
+ | if (idx_bank_it > TSLPRM_TOTAL_BANKS-1) | ||
+ | { | ||
+ | // End of all banks acquisition, restart bank 0 in while(1) loop (This is a choice) | ||
+ | idx_bank_it=0; | ||
+ | acq_done_it++; | ||
+ | }else{ | ||
+ | // We restart next bank acquisition | ||
+ | TSL_acq_BankConfig(idx_bank_it); | ||
+ | TSL_acq_BankStartAcq_IT(); | ||
+ | } | ||
+ | /* USER CODE BEGIN HAL_TSC_ConvCpltCallback*/ | ||
+ | handle_touch(); | ||
+ | /* USER CODE END HAL_TSC_ConvCpltCallback*/ | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | All I do there is to call "handle_touch()" at the conclusion of each conversion. | ||
+ | |||
+ | The handle_touch() is defined like: | ||
+ | |||
+ | <pre> | ||
+ | // Called after touch keys have been measured | ||
+ | void handle_touch() { | ||
+ | uint32_t t = HAL_GetTick(); | ||
+ | for (int i = 0; i < 2; i++) { | ||
+ | TSL_StateId_enum_T state = MyTKeys[i].p_Data->StateId; | ||
+ | if (state != touch_state[i] && (state == TSL_STATEID_RELEASE || state == TSL_STATEID_DETECT)) { | ||
+ | printf("At tick %d Key %d changed - now = %d\n", t, i, MyTKeys[i].p_Data->StateId); | ||
+ | touch_state[i] = MyTKeys[i].p_Data->StateId; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | Touching each of the touchpads result in this output: | ||
+ | |||
+ | [[File:Touch output.png|600px]] | ||
== Resources == | == Resources == | ||
Line 21: | Line 133: | ||
* [https://www.st.com/content/ccc/resource/technical/document/application_note/28/4b/40/7c/e6/68/44/9c/DM00087593.pdf/files/DM00087593.pdf/jcr:content/translations/en.DM00087593.pdf Sampling capacitor selection guide for touch sensing applications on MCUs] | * [https://www.st.com/content/ccc/resource/technical/document/application_note/28/4b/40/7c/e6/68/44/9c/DM00087593.pdf/files/DM00087593.pdf/jcr:content/translations/en.DM00087593.pdf Sampling capacitor selection guide for touch sensing applications on MCUs] | ||
* [https://www.st.com/content/ccc/resource/technical/document/application_note/f4/7c/88/47/75/08/42/a8/DM00035396.pdf/files/DM00035396.pdf/jcr:content/translations/en.DM00035396.pdf ESD considerations for touch sensing applications on MCUs] | * [https://www.st.com/content/ccc/resource/technical/document/application_note/f4/7c/88/47/75/08/42/a8/DM00035396.pdf/files/DM00035396.pdf/jcr:content/translations/en.DM00035396.pdf ESD considerations for touch sensing applications on MCUs] | ||
+ | |||
+ | * [https://www.silabs.com/documents/public/application-notes/AN0040.pdf Hardware Design for Capacitive Touch] |
Latest revision as of 02:02, 18 July 2022
Only some STM32 processors have touch sensor circuitry built in, most noticeable the STM32Lxx series.
Hardware Example
As part of another project I was using an STM32L432 MCU and while doing that design I decided to add 3 touch sensors.
The circuitry involved in the touch sensing is the C5 and the actual touch pads J2, J3 and J4 and their accompanying resistors.
Layout wise I did two different approaches:
The top and bottom touch pads are just big single sided SMD pads which is covered by soldermask. The center "hole" is a big through hole pad.
The gadget came out like this:
Software
STM32CubeMX Configuration
Messing around with this it turns out that the middle pad (the through hole one) is much to close to the neighbors, so in the software example I only deal with the two pads covered by soldermask.
Under Middleware/Touchsensing:
Code
The touchsensing middleware will do all the heavy lifting and only a few lines of code is needed to use the touch sensors.
First of all, in the main program loop:
/* Infinite loop */ /* USER CODE BEGIN WHILE */ uint32_t then = 0, now = 0; for (;;) { now = HAL_GetTick(); if (now % 50 == 0 && now != then) { tsl_user_Exec_IT(); if (now % 1000 == 0) { printf("Tick %5lu B0: %2d / %2d B1: %2d / %2d\n", now / 1000, MyTKeys[0].p_Data->StateId, MyTKeys[0].p_ChD->Meas, MyTKeys[1].p_Data->StateId, MyTKeys[1].p_ChD->Meas); } then = now; } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
Essentially this will call the "tsl_user_Exec_IT()" function every 50 ms (20 times per second) and each second it will print out the status of the keys.
The interrupt handler callback is defined in tsl_user.c
void HAL_TSC_ConvCpltCallback(TSC_HandleTypeDef* htsc) { /* USER CODE BEGIN HAL_TSC_ConvCpltCallback start*/ /* USER CODE END HAL_TSC_ConvCpltCallback start*/ TSL_acq_BankGetResult(idx_bank_it, 0, 0); idx_bank_it++; if (idx_bank_it > TSLPRM_TOTAL_BANKS-1) { // End of all banks acquisition, restart bank 0 in while(1) loop (This is a choice) idx_bank_it=0; acq_done_it++; }else{ // We restart next bank acquisition TSL_acq_BankConfig(idx_bank_it); TSL_acq_BankStartAcq_IT(); } /* USER CODE BEGIN HAL_TSC_ConvCpltCallback*/ handle_touch(); /* USER CODE END HAL_TSC_ConvCpltCallback*/ }
All I do there is to call "handle_touch()" at the conclusion of each conversion.
The handle_touch() is defined like:
// Called after touch keys have been measured void handle_touch() { uint32_t t = HAL_GetTick(); for (int i = 0; i < 2; i++) { TSL_StateId_enum_T state = MyTKeys[i].p_Data->StateId; if (state != touch_state[i] && (state == TSL_STATEID_RELEASE || state == TSL_STATEID_DETECT)) { printf("At tick %d Key %d changed - now = %d\n", t, i, MyTKeys[i].p_Data->StateId); touch_state[i] = MyTKeys[i].p_Data->StateId; } } }
Touching each of the touchpads result in this output:
Resources
- Getting started with touch sensing control on STM32 microcontrollers
- Developing applications on STM32Cube with STMTouch touch sensing library
- Tuning a touch sensing application on MCUs
- Design with surface sensors for touch sensing applications on MCUs
- Improve conducted noise robustness for touch sensing applications on MCUs
- Sampling capacitor selection guide for touch sensing applications on MCUs
- ESD considerations for touch sensing applications on MCUs