Difference between revisions of "STM32 Touch Sensors"

From Stm32World Wiki
Jump to navigation Jump to search
 
(6 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 17: Line 17:
  
 
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 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 27: 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.

STM32 Processors with Touch Sensors.png

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.

Schematic with touch sensors.png

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:

Touch PCB Layout.png

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:

Touch PCB.jpg

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.

TSC Pins.png

Under Middleware/Touchsensing:

Touch Mode and Configuration.png

Configuration parameters.png

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:

Touch output.png

Resources