Difference between revisions of "STM32 Touch Sensors"

From Stm32World Wiki
Jump to navigation Jump to search
Line 23: Line 23:
  
 
== Software ==  
 
== 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.
 
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.
Line 33: Line 35:
  
 
[[File:Configuration parameters.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>
  
 
== Resources ==  
 
== Resources ==  

Revision as of 05:34, 28 May 2021

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;
		}
	}
}

Resources