This post was last edited by dirty on 2024-2-22 09:38
The development board FM33FT056A MCU integrates the touch detection function. The official provides a complete TSI touch solution with advantages such as preventing false liquid touches, suppressing electromagnetic interference, supporting overlay touches, and automatic tuning algorithms. Through the collaboration of software and hardware, it can be applied in the field of automotive electronic touch, such as touch applications for windows, lights, and central control panels. This article describes the implementation of TSI button touch and slider touch and position functions.
1. Hardware Principle
The development board has two touch buttons BT0 and BT1 and a touch slider SLDER. The schematic diagram and hardware are as follows
Figure 1: Touch buttons and sliders
The TSI module uses the self-capacitance method to detect touch behavior. Fudan Micro has a complete introduction to TSI. It integrates its own algorithm and is equipped with a debugging tool TSITuner. On the one hand, it saves costs, and on the other hand, it completes the closed loop in the solution application. This is a good job.
2. Code Preparation
The official provides TSIDemo, here are some interpretations, improvements, modifications and applications.
1. About TSI Software Library
(1). tsi.c, tsi.h: Contains the library's operation control functions (start, stop, etc.);
(2). tsi_baseline.c, tsi_baseline.h: Contains the baseline algorithm implementation;
(3). tsi_calibration.c, tsi_calibration.h: Contains the touch hardware parameter automatic calibration algorithm implementation;
(4). tsi_conf.h: User configuration file, some configurable parameters of the TSI software library are listed here. We only provide the template tsi_conf_template.h corresponding to this file. Users can modify it and rename it to tsi_conf.h for use.
(5). tsi_def.h: Contains some definitions required by the library, including some definitions of optional configuration parameter values.
(6). tsi_filter.c, tsi_filter.h: Contains the implementation of the RawCount filter.
(7). tsi_interrupt.c: Contains the interrupt service routine of the TSI module.
(8). tsi_objects.c, tsi_objects.h: tsi_objects.c contains all TSI module control definitions and parameters ( touch pins TSI_Pins and channel TSI_ChannelSensorMap, etc. ), tsi_objects.h contains all TSI software library data structure definitions. tsi_objects.c We only provide the corresponding template tsi_objects_template.c. Users can modify it and rename it to tsi_objects.h for use.
(9). tsi_sensor.c, tsi_sensor.h: Contains the configuration, initialization, and status update functions used by the sensor;
(10). tsi_widget.c, tsi_widget.h: Contains the configuration, initialization, and status update functions used by the widget;
2. Code modification
(1) Remove TSI_DEBUG_xxx from the main function, add the debug serial port printing mentioned above , and add buttons, slider touch and position detection . The code is as follows
int main(void)
{
/* 使能IWDT */
IWDT_Init(FL_IWDT_PERIOD_4000MS);
/* Init FL driver library */
FL_Init();
/* 使能SVD, 阈?.157V(falling)~4.257V(rising) */
SVD_Init(SVD_MONTIOR_VDD, FL_SVD_WARNING_THRESHOLD_GROUP11, FL_SVD_REFERENCE_1P0V);
/* 确认SVD监测结果是否高于阈值,如否则持续等?*/
while(false == SVD_Result_Confirmed(SVD_HIGHER_THRESHOLD, 2000U/*us*/));
/* 使能BOR */
RMU_BOR_Init(FL_RMU_BOR_THRESHOLD_2P00V);
/* Init system clock */
SystemClockInit();
/* USER CODES AREA 1 BEGIN */
/* USER CODES AREA 1 END */
MF_Config_Init();
/* Init TSI */
TSI_Init();
printf("TSI Init \r\n");
/* Enable all widgets */
TSI_Widget_EnableAll();
/* Feed watchdog */
FL_IWDT_ReloadCounter(IWDT);
/* Start TSI */
TSI_Start();
printf("TSI Start \r\n");
/* Feed watchdog */
FL_IWDT_ReloadCounter(IWDT);
/* Init and start TSI debug */
// TSI_Debug_Init();
// TSI_Debug_Start();
/* USER CODES AREA 2 BEGIN */
/* USER CODES AREA 2 END */
while(1)
{
/* USER CODES AREA 3 BEGIN */
/* USER CODES AREA 3 END */
/* Feed watchdog */
FL_IWDT_ReloadCounter(IWDT);
/* 电源掉电监测处理 */
PowerDownMonitoring();
/* Handle debug event */
TSI_Debug_Handler();
/* USER CODES AREA 4 BEGIN */
/* USER CODES AREA 4 END */
/* Wait until a scan sequence has completed */
if(TSI_GETSTAT_SCAN_CPLT())
{
TSI_CLRSTAT_SCAN_CPLT();
/* Update all widgets */
TSI_Widget_UpdateAll();
if(TSI_WidgetList.bt0.buttonStatus==1)
{
printf("bt0 is touched\r\n");
}
if(TSI_WidgetList.bt1.buttonStatus==1)
{
printf("bt1 is touched\r\n");
}
if(TSI_WidgetList.slider.sliderStatus==1)
{
printf("silder is touched,position:%d--[range:0-255]\n",TSI_WidgetList.slider.centerPos);
}
/* Update debug interface trace buffer */
// TSI_Debug_UpdateTrace();
/* USER CODES AREA 5 BEGIN */
/* USER CODES AREA 5 END */
}
/* USER CODES AREA 6 BEGIN */
/* USER CODES AREA 6 END */
}
}
(2) When debugging the simulation, it was found that the slider trigger status was not set. The official code has a bug. Modify TSI_Widget_UpdateSlider and add sliderWidget->sliderStatus=sliderWidget->base.status; the complete function is as follows:
void TSI_Widget_UpdateSlider(TSI_SliderWidgetTypeDef* sliderWidget)
{
if(sliderWidget->base.status == 1U)
{
int i;
uint8_t peakIndex = 0U;
uint16_t peakSignalVal = 0U;
uint16_t centroidCalcData[3];
uint16_t threshold = sliderWidget->base.activeTh - sliderWidget->base.activeHys;
int32_t centroid;
const TSI_MetaWidgetTypeDef *metaWidget = sliderWidget->base.meta;
TSI_SensorTypeDef* sensor = metaWidget->sensors;
int32_t mul = (TSI_SLIDER_RESOLUTION / (metaWidget->sensorCnt - 1)) << 8U;
/*
Calculate the slider postion using centroid algorithm:
1. Find the sensor X with the highest signal, which is the center of the touched area;
2. Calcuate centroid using X's neighbour sensor;
*/
/* Find peak value and corresponding sensor */
for (i = 0; i < metaWidget->sensorCnt; i++)
{
if(sensor->diffCount > threshold && sensor->diffCount > peakSignalVal)
{
peakIndex = i+1;
peakSignalVal = sensor->diffCount;
}
sensor++;
}
if(peakIndex != 0)
{
/* Get neighbour sensors signal value */
sensor = metaWidget->sensors;
if(peakIndex == 1)
{
centroidCalcData[0] = 0;
centroidCalcData[1] = peakSignalVal;
centroidCalcData[2] = (int32_t)sensor[1].diffCount;
}
else if(peakIndex == metaWidget->sensorCnt)
{
centroidCalcData[0] = sensor[peakIndex-2].diffCount;
centroidCalcData[1] = peakSignalVal;
centroidCalcData[2] = 0;
}
else
{
centroidCalcData[0] = sensor[peakIndex-2].diffCount;
centroidCalcData[1] = peakSignalVal;
centroidCalcData[2] = sensor[peakIndex].diffCount;
}
/* Calculate centroid */
centroid = ((int32_t)centroidCalcData[2]
- (int32_t)centroidCalcData[0]) * mul /
((int32_t)centroidCalcData[0]
+ (int32_t)centroidCalcData[1]
+ (int32_t)centroidCalcData[2]);
centroid += (peakIndex-1) * mul;
centroid >>= 8U;
sliderWidget->centerPos = centroid;
}
}
//fix bug:sliderStatus not setted when touched or released
sliderWidget->sliderStatus=sliderWidget->base.status;
}
The code is ready, compile and burn.
3. Test
Open the serial port, touch BT0, BT1 to see the touch button is triggered; the slider position from right to left (USB TYPE-C facing left) is 0-255, you can touch or slide. The complete log is as follows
Figure 2: Touch log
At this point, the touch function has been implemented, the effect is good, the touch is sensitive and the slider position is accurate.