AnsweredAssumed Answered

Need help with a linear touch sensor which uses 5 ios

Question asked by Davis.John.004 on Apr 5, 2017

This markup tool does not work well.  The post is repeated on stack overflow.  You can read below, but its easier to follow on  this link http://stackoverflow.com/questions/43240218/stmicro-stmtouch-driver-usage-of-a-5-channel-mono-electrode-design-for-linear-se

 

 

I'm working with a custom board which has 8 channels consisting of three touchkey and 1 linear sensor.

There are 8 channel IOs, three sampling IOs and no shield configs. Three of the channels are for the three touchkeys. Five of the channels are for the linear sensor.

I have worked with the STM3270B Discovery board where it has three channels setup in a Half-Ended electrode design (LIN_H). I've worked through the example provided by this board for a non interrupt implementation.

I have worked with the STM3207 Eval board where it has two channels setup as two touchkeys.

On my custom board the touchkeys work flawlessly. The five channel linear sensor does not work completely. All five pads do indeed detect a touch but as far as data position goes, it fails. The example has all the ios in a single channel. There isn't an example I know of which uses 5 channels split across two TSC groups. Its mentioned in the STMTouch Driver User Manual, but I'll have to look again for a code sample.

The problem is that the macro which determines the value of the sensor LINEAR_POSITION = MyLinRots[0].p_Data->Position has two results. If either of the two pads associated with the group 1 IOs is touched the DETECT macro fires correctly but the LINEAR_POSITION value is 0x2. Likewise if the three pads associated with the group 2 IOS is touched DETECT macro fires correctly but the LINEAR_POSITION value is 0xC.

I thought the value would vary between 0 and 255 split 5 ways for each pad. I've looked at the raw position instead of the scaled position but it behaves similarly.

Here is my layout of the channels, banks, touchkeys, linear/rotary and objects split across the header file and source file.

The header:

 

/* Channel IOs definition */ // The three touchkey channels #define CHANNEL_0_IO_MSK    (TSC_GROUP6_IO2) #define CHANNEL_0_GRP_MSK   (TSC_GROUP6) #define CHANNEL_0_SRC       (TSC_GROUP6_IDX) /* Index in source register (TSC->IOGXCR[]) */ #define CHANNEL_0_DEST      (0) /* Index in destination result array */  #define CHANNEL_1_IO_MSK    (TSC_GROUP6_IO3) #define CHANNEL_1_GRP_MSK   (TSC_GROUP6) #define CHANNEL_1_SRC       (TSC_GROUP6_IDX) #define CHANNEL_1_DEST      (1)  #define CHANNEL_2_IO_MSK    (TSC_GROUP6_IO4) #define CHANNEL_2_GRP_MSK   (TSC_GROUP6) #define CHANNEL_2_SRC       (TSC_GROUP6_IDX) #define CHANNEL_2_DEST      (2)  // The five linrot channels #define CHANNEL_3_IO_MSK    (TSC_GROUP1_IO3) #define CHANNEL_3_GRP_MSK   (TSC_GROUP1) #define CHANNEL_3_SRC       (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */ #define CHANNEL_3_DEST      (3) /* Index in destination result array */  #define CHANNEL_4_IO_MSK    (TSC_GROUP1_IO4) #define CHANNEL_4_GRP_MSK   (TSC_GROUP1) #define CHANNEL_4_SRC       (TSC_GROUP1_IDX) /* Index in source register (TSC->IOGXCR[]) */ #define CHANNEL_4_DEST      (4) /* Index in destination result array */  #define CHANNEL_5_IO_MSK    (TSC_GROUP2_IO2) #define CHANNEL_5_GRP_MSK   (TSC_GROUP2) #define CHANNEL_5_SRC       (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */ #define CHANNEL_5_DEST      (5) /* Index in destination result array */  #define CHANNEL_6_IO_MSK    (TSC_GROUP2_IO3) #define CHANNEL_6_GRP_MSK   (TSC_GROUP2) #define CHANNEL_6_SRC       (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */ #define CHANNEL_6_DEST      (6) /* Index in destination result array */  #define CHANNEL_7_IO_MSK    (TSC_GROUP2_IO4) #define CHANNEL_7_GRP_MSK   (TSC_GROUP2) #define CHANNEL_7_SRC       (TSC_GROUP2_IDX) /* Index in source register (TSC->IOGXCR[]) */ #define CHANNEL_7_DEST      (7) /* Index in destination result array */    /* Shield IOs definition */ #define SHIELD_IO_MSK       (0) // orig (TSC_GROUP7_IO3)  we dont have a shield  /* Banks definition */ // The touch key bank #define BANK_0_NBCHANNELS    (1) #define BANK_0_MSK_CHANNELS  (CHANNEL_0_IO_MSK | SHIELD_IO_MSK) #define BANK_0_MSK_GROUPS    (CHANNEL_0_GRP_MSK)  #define BANK_1_NBCHANNELS    (1) #define BANK_1_MSK_CHANNELS  (CHANNEL_1_IO_MSK | SHIELD_IO_MSK) #define BANK_1_MSK_GROUPS    (CHANNEL_1_GRP_MSK)  #define BANK_2_NBCHANNELS    (1) #define BANK_2_MSK_CHANNELS  (CHANNEL_2_IO_MSK | SHIELD_IO_MSK) #define BANK_2_MSK_GROUPS    (CHANNEL_2_GRP_MSK)   // The linrot bank #define BANK_3_NBCHANNELS    (5) #define BANK_3_MSK_CHANNELS  (CHANNEL_3_IO_MSK | CHANNEL_4_IO_MSK | CHANNEL_5_IO_MSK | CHANNEL_6_IO_MSK| CHANNEL_7_IO_MSK | SHIELD_IO_MSK) #define BANK_3_MSK_GROUPS    (CHANNEL_3_GRP_MSK | CHANNEL_4_GRP_MSK | CHANNEL_5_GRP_MSK | CHANNEL_6_GRP_MSK | CHANNEL_7_GRP_MSK )

The source

/* define for the linear */ #define LINEAR_DETECT ((MyLinRots[0].p_Data->StateId == TSL_STATEID_DETECT) || \                        (MyLinRots[0].p_Data->StateId == TSL_STATEID_DEB_RELEASE_DETECT)) #define LINEAR_POSITION (MyLinRots[0].p_Data->Position)   /*============================================================================*/ /* Channels                                                                   */ /*============================================================================*/  /* Source and Configuration (ROM) */ CONST TSL_ChannelSrc_T MyChannels_Src[TSLPRM_TOTAL_CHANNELS] = {  // The three touchkey channels     { CHANNEL_0_SRC, CHANNEL_0_IO_MSK, CHANNEL_0_GRP_MSK },   { CHANNEL_1_SRC, CHANNEL_1_IO_MSK, CHANNEL_1_GRP_MSK },   { CHANNEL_2_SRC, CHANNEL_2_IO_MSK, CHANNEL_2_GRP_MSK }, // The five linrot channels   { CHANNEL_3_SRC, CHANNEL_3_IO_MSK, CHANNEL_3_GRP_MSK },   { CHANNEL_4_SRC, CHANNEL_4_IO_MSK, CHANNEL_4_GRP_MSK },   { CHANNEL_5_SRC, CHANNEL_5_IO_MSK, CHANNEL_5_GRP_MSK },   { CHANNEL_6_SRC, CHANNEL_6_IO_MSK, CHANNEL_6_GRP_MSK },   { CHANNEL_7_SRC, CHANNEL_7_IO_MSK, CHANNEL_7_GRP_MSK }  };  /* Destination (ROM) */ CONST TSL_ChannelDest_T MyChannels_Dest[TSLPRM_TOTAL_CHANNELS] = { // The three touchkey channels   { CHANNEL_0_DEST },   { CHANNEL_1_DEST },   { CHANNEL_2_DEST }, // The five linrot channels   { CHANNEL_3_DEST },   { CHANNEL_4_DEST },   { CHANNEL_5_DEST },   { CHANNEL_6_DEST },   { CHANNEL_7_DEST }, };  /* Data (RAM) */ TSL_ChannelData_T MyChannels_Data[TSLPRM_TOTAL_CHANNELS];  /*============================================================================*/ /* Banks                                                                      */ /*============================================================================*/  /* List (ROM) */ CONST TSL_Bank_T MyBanks[TSLPRM_TOTAL_BANKS] = {   // The three touchkey bankss   {&MyChannels_Src[0], &MyChannels_Dest[0], MyChannels_Data, BANK_0_NBCHANNELS, BANK_0_MSK_CHANNELS, BANK_0_MSK_GROUPS},   {&MyChannels_Src[1], &MyChannels_Dest[1], MyChannels_Data, BANK_1_NBCHANNELS, BANK_1_MSK_CHANNELS, BANK_1_MSK_GROUPS},   {&MyChannels_Src[2], &MyChannels_Dest[2], MyChannels_Data, BANK_2_NBCHANNELS, BANK_2_MSK_CHANNELS, BANK_2_MSK_GROUPS},   // The one linrot bank   {&MyChannels_Src[3], &MyChannels_Dest[3], MyChannels_Data, BANK_3_NBCHANNELS, BANK_3_MSK_CHANNELS, BANK_3_MSK_GROUPS} };  /*============================================================================*/ /* Touchkey sensors                                                           */ /*============================================================================*/  /* Data (RAM) */ TSL_TouchKeyData_T MyTKeys_Data[TSLPRM_TOTAL_TKEYS];  /* Parameters (RAM) */ TSL_TouchKeyParam_T MyTKeys_Param[TSLPRM_TOTAL_TKEYS];  /* State Machine (ROM) */  void MyTKeys_ErrorStateProcess(void); void MyTKeys_OffStateProcess(void);  CONST TSL_State_T MyTKeys_StateMachine[] = {   /* Calibration states */   /*  0 */ { TSL_STATEMASK_CALIB,              TSL_tkey_CalibrationStateProcess },   /*  1 */ { TSL_STATEMASK_DEB_CALIB,          TSL_tkey_DebCalibrationStateProcess },   /* Release states */   /*  2 */ { TSL_STATEMASK_RELEASE,            TSL_tkey_ReleaseStateProcess }, #if TSLPRM_USE_PROX > 0   /*  3 */ { TSL_STATEMASK_DEB_RELEASE_PROX,   TSL_tkey_DebReleaseProxStateProcess }, #else   /*  3 */ { TSL_STATEMASK_DEB_RELEASE_PROX,   0 }, #endif   /*  4 */ { TSL_STATEMASK_DEB_RELEASE_DETECT, TSL_tkey_DebReleaseDetectStateProcess },   /*  5 */ { TSL_STATEMASK_DEB_RELEASE_TOUCH,  TSL_tkey_DebReleaseTouchStateProcess }, #if TSLPRM_USE_PROX > 0   /* Proximity states */   /*  6 */ { TSL_STATEMASK_PROX,               TSL_tkey_ProxStateProcess },   /*  7 */ { TSL_STATEMASK_DEB_PROX,           TSL_tkey_DebProxStateProcess },   /*  8 */ { TSL_STATEMASK_DEB_PROX_DETECT,    TSL_tkey_DebProxDetectStateProcess },   /*  9 */ { TSL_STATEMASK_DEB_PROX_TOUCH,     TSL_tkey_DebProxTouchStateProcess },   #else   /*  6 */ { TSL_STATEMASK_PROX,               0 },   /*  7 */ { TSL_STATEMASK_DEB_PROX,           0 },   /*  8 */ { TSL_STATEMASK_DEB_PROX_DETECT,    0 },   /*  9 */ { TSL_STATEMASK_DEB_PROX_TOUCH,     0 }, #endif   /* Detect states */   /* 10 */ { TSL_STATEMASK_DETECT,             TSL_tkey_DetectStateProcess },   /* 11 */ { TSL_STATEMASK_DEB_DETECT,         TSL_tkey_DebDetectStateProcess },   /* Touch state */   /* 12 */ { TSL_STATEMASK_TOUCH,              TSL_tkey_TouchStateProcess },   /* Error states */   /* 13 */ { TSL_STATEMASK_ERROR,              MyTKeys_ErrorStateProcess },   /* 14 */ { TSL_STATEMASK_DEB_ERROR_CALIB,    TSL_tkey_DebErrorStateProcess },   /* 15 */ { TSL_STATEMASK_DEB_ERROR_RELEASE,  TSL_tkey_DebErrorStateProcess },   /* 16 */ { TSL_STATEMASK_DEB_ERROR_PROX,     TSL_tkey_DebErrorStateProcess },   /* 17 */ { TSL_STATEMASK_DEB_ERROR_DETECT,   TSL_tkey_DebErrorStateProcess },   /* 18 */ { TSL_STATEMASK_DEB_ERROR_TOUCH,    TSL_tkey_DebErrorStateProcess },   /* Other states */   /* 19 */ { TSL_STATEMASK_OFF,                MyTKeys_OffStateProcess } };   /* Methods for "extended" type (ROM) */ CONST TSL_TouchKeyMethods_T MyTKeys_Methods = {   TSL_tkey_Init,   TSL_tkey_Process };  /* TouchKeys list (ROM) */ CONST TSL_TouchKey_T MyTKeys[TSLPRM_TOTAL_TKEYS] = {   { &MyTKeys_Data[0], &MyTKeys_Param[0], &MyChannels_Data[CHANNEL_0_DEST], MyTKeys_StateMachine, &MyTKeys_Methods },   { &MyTKeys_Data[1], &MyTKeys_Param[1], &MyChannels_Data[CHANNEL_1_DEST], MyTKeys_StateMachine, &MyTKeys_Methods },   { &MyTKeys_Data[2], &MyTKeys_Param[2], &MyChannels_Data[CHANNEL_2_DEST], MyTKeys_StateMachine, &MyTKeys_Methods } };  /*============================================================================*/ /* Linear and Rotary sensors                                                  */ /*============================================================================*/  /* Data (RAM) */ TSL_LinRotData_T MyLinRots_Data[TSLPRM_TOTAL_LINROTS];  /* Parameters (RAM) */ TSL_LinRotParam_T MyLinRots_Param[TSLPRM_TOTAL_LINROTS];  /* State Machine (ROM) */  void MyLinRots_ErrorStateProcess(void); void MyLinRots_OffStateProcess(void);     CONST TSL_State_T MyLinRots_StateMachine[] = {   /* Calibration states */   /*  0 */ { TSL_STATEMASK_CALIB,              TSL_linrot_CalibrationStateProcess },   /*  1 */ { TSL_STATEMASK_DEB_CALIB,          TSL_linrot_DebCalibrationStateProcess },   /* Release states */   /*  2 */ { TSL_STATEMASK_RELEASE,            TSL_linrot_ReleaseStateProcess }, #if TSLPRM_USE_PROX > 0   /*  3 */ { TSL_STATEMASK_DEB_RELEASE_PROX,   TSL_linrot_DebReleaseProxStateProcess }, #else   /*  3 */ { TSL_STATEMASK_DEB_RELEASE_PROX,   0 }, #endif   /*  4 */ { TSL_STATEMASK_DEB_RELEASE_DETECT, TSL_linrot_DebReleaseDetectStateProcess },   /*  5 */ { TSL_STATEMASK_DEB_RELEASE_TOUCH,  TSL_linrot_DebReleaseTouchStateProcess }, #if TSLPRM_USE_PROX > 0   /* Proximity states */   /*  6 */ { TSL_STATEMASK_PROX,               TSL_linrot_ProxStateProcess },   /*  7 */ { TSL_STATEMASK_DEB_PROX,           TSL_linrot_DebProxStateProcess },   /*  8 */ { TSL_STATEMASK_DEB_PROX_DETECT,    TSL_linrot_DebProxDetectStateProcess },   /*  9 */ { TSL_STATEMASK_DEB_PROX_TOUCH,     TSL_linrot_DebProxTouchStateProcess }, #else   /*  6 */ { TSL_STATEMASK_PROX,               0 },   /*  7 */ { TSL_STATEMASK_DEB_PROX,           0 },   /*  8 */ { TSL_STATEMASK_DEB_PROX_DETECT,    0 },   /*  9 */ { TSL_STATEMASK_DEB_PROX_TOUCH,     0 }, #endif   /* Detect states */   /* 10 */ { TSL_STATEMASK_DETECT,             TSL_linrot_DetectStateProcess },   /* 11 */ { TSL_STATEMASK_DEB_DETECT,         TSL_linrot_DebDetectStateProcess },   /* Touch state */   /* 12 */ { TSL_STATEMASK_TOUCH,              TSL_linrot_TouchStateProcess },   /* Error states */   /* 13 */ { TSL_STATEMASK_ERROR,              MyLinRots_ErrorStateProcess },   /* 14 */ { TSL_STATEMASK_DEB_ERROR_CALIB,    TSL_linrot_DebErrorStateProcess },   /* 15 */ { TSL_STATEMASK_DEB_ERROR_RELEASE,  TSL_linrot_DebErrorStateProcess },   /* 16 */ { TSL_STATEMASK_DEB_ERROR_PROX,     TSL_linrot_DebErrorStateProcess },   /* 17 */ { TSL_STATEMASK_DEB_ERROR_DETECT,   TSL_linrot_DebErrorStateProcess },   /* 18 */ { TSL_STATEMASK_DEB_ERROR_TOUCH,    TSL_linrot_DebErrorStateProcess },   /* Other states */   /* 19 */ { TSL_STATEMASK_OFF,                MyLinRots_OffStateProcess } };    /* Methods for "extended" type (ROM) */ CONST TSL_LinRotMethods_T MyLinRots_Methods = {   TSL_linrot_Init,   TSL_linrot_Process,   TSL_linrot_CalcPos };  /* Delta Normalization Process    The MSB is the integer part, the LSB is the real part    Examples:    - To apply a factor 1.10:      0x01 to the MSB      0x1A to the LSB (0.10 x 256 = 25.6 -> rounded to 26 = 0x1A)    - To apply a factor 0.90:      0x00 to the MSB      0xE6 to the LSB (0.90 x 256 = 230.4 -> rounded to 230 = 0xE6) */ CONST uint16_t MyLinRot0_DeltaCoeff[3] = {0x0100, 0x0100, 0x0100};  /* LinRots list (ROM)*/ CONST TSL_LinRot_T MyLinRots[TSLPRM_TOTAL_LINROTS] = {   {     /* LinRot sensor 0 = S1 */     &MyLinRots_Data[0],     &MyLinRots_Param[0],     &MyChannels_Data[CHANNEL_3_DEST], // first channel data     5, /* Number of channels */  //      MyLinRot0_DeltaCoeff, // discovery     //    (TSL_tsignPosition_T *)TSL_POSOFF_3CH_LIN_H, // GP board         (TSL_tsignPosition_T *)TSL_POSOFF_5CH_LIN_M1,  // Discovery     //    TSL_SCTCOMP_3CH_LIN_H, // GP board         TSL_SCTCOMP_5CH_LIN_M1, // Discovery     //    TSL_POSCORR_3CH_LIN_H, // GP board         TSL_POSCORR_5CH_LIN_M1,     MyLinRots_StateMachine,     &MyLinRots_Methods     } };   /*============================================================================*/ /* Generic Objects                                                            */ /*============================================================================*/  /* List (ROM) */ CONST TSL_Object_T MyObjects[TSLPRM_TOTAL_OBJECTS] = {   // touchkeys   { TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[0] },   { TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[1] },   { TSL_OBJ_TOUCHKEY, (TSL_TouchKey_T *)&MyTKeys[2] },   // lin rot   { TSL_OBJ_LINEAR, (TSL_LinRot_T *)&MyLinRots[0] }  };  /* Group (RAM) */ TSL_ObjectGroup_T MyObjGroup = {   &MyObjects[0],        /* First object */   TSLPRM_TOTAL_OBJECTS, /* Number of objects */   0x00,                 /* State mask reset value */   TSL_STATE_NOT_CHANGED /* Current state */ };  /*============================================================================*/ /* TSL Common Parameters placed in RAM or ROM                                 */ /* --> external declaration in tsl_conf.h                                     */ /*============================================================================*/  TSL_Params_T TSL_Params = {   TSLPRM_ACQ_MIN,   TSLPRM_ACQ_MAX,   TSLPRM_CALIB_SAMPLES,   TSLPRM_DTO, #if TSLPRM_TOTAL_TKEYS > 0     MyTKeys_StateMachine,   /* Default state machine for TKeys */   &MyTKeys_Methods,       /* Default methods for TKeys */ #endif #if TSLPRM_TOTAL_LNRTS > 0   MyLinRots_StateMachine, /* Default state machine for LinRots */   &MyLinRots_Methods      /* Default methods for LinRots */ #endif };  /* Private functions prototype -----------------------------------------------*/  /* Global variables ----------------------------------------------------------*/  __IO TSL_tTick_ms_T ECSLastTick; /* Hold the last time value for ECS */  /**   * @brief  Initialize the STMTouch Driver   * @param  None   * @retval None   */ void tsl_user_Init(void) {    TSL_obj_GroupInit(&MyObjGroup); /* Init Objects */    TSL_Init(MyBanks); /* Init acquisition module */    tsl_user_SetThresholds(); /* Init thresholds for each object individually (optional) */ }   /**   * @brief  Execute STMTouch Driver main State machine   * @param  None   * @retval status Return TSL_STATUS_OK if the acquisition is done   */ tsl_user_status_t tsl_user_Exec(void) {   static uint32_t idx_bank = 0;   static uint32_t config_done = 0;   tsl_user_status_t status = TSL_USER_STATUS_BUSY;    /* Configure and start bank acquisition */   if (!config_done)   {     TSL_acq_BankConfig(idx_bank);     TSL_acq_BankStartAcq();     config_done = 1;   }    /* Check end of acquisition (polling mode) and read result */   if (TSL_acq_BankWaitEOC() == TSL_STATUS_OK)  {     TSL_acq_BankGetResult(idx_bank, 0, 0);     idx_bank++; /* Next bank */     config_done = 0;   }    /* Process objects, DxS and ECS      Check if all banks have been acquired   */   if (idx_bank > TSLPRM_TOTAL_BANKS-1)   {     /* Reset flags for next banks acquisition */     idx_bank = 0;     config_done = 0;      /* Process Objects */     TSL_obj_GroupProcess(&MyObjGroup);      /* DxS processing (if TSLPRM_USE_DXS option is set) */     TSL_dxs_FirstObj(&MyObjGroup);      /* ECS every 100ms */     if (TSL_tim_CheckDelay_ms(100, &ECSLastTick) == TSL_STATUS_OK)     {       if (TSL_ecs_Process(&MyObjGroup) == TSL_STATUS_OK)       {         status = TSL_USER_STATUS_OK_ECS_ON;       }       else       {         status = TSL_USER_STATUS_OK_ECS_OFF;       }     }     else     {       status = TSL_USER_STATUS_OK_NO_ECS;     }   }   else   {     status = TSL_USER_STATUS_BUSY;   }    return status; }  /**   * @brief  Set thresholds for each object (optional).   * @param  None   * @retval None   */ void tsl_user_SetThresholds(void) {   /* Example: Decrease the Detect thresholds for the TKEY 0   MyTKeys_Param[0].DetectInTh -= 10;   MyTKeys_Param[0].DetectOutTh -= 10;   */ }  /**   * @brief  Executed when a sensor is in Error state   * @param  None   * @retval None   */ void MyTKeys_ErrorStateProcess(void) {   /* Add here your own processing when a sensor is in Error state */ }   /**   * @brief  Executed when a sensor is in Off state   * @param  None   * @retval None   */ void MyTKeys_OffStateProcess(void) {   /* Add here your own processing when a sensor is in Off state */ }  /**   * @brief  Executed when a sensor is in Error state   * @param  None   * @retval None   */ void MyLinRots_ErrorStateProcess(void) {   /* Add here your own processing when a sensor is in Error state */ }   /**   * @brief  Executed when a sensor is in Off state   * @param  None   * @retval None   */ void MyLinRots_OffStateProcess(void) {   /* Add here your own processing when a sensor is in Off state */ }   /**   * @brief  This function handles a tick.   * @param  None   * @retval None   */ void User_Tick_Management(void) {     // tick counters set to zero first time this routine is called   static uint32_t tempo_50ms=0;     static uint32_t tempo_100ms=0;   static uint32_t tempo_200ms=0;   static uint32_t tempo_300ms=0;   static uint32_t tempo_400ms=0;   static uint32_t tempo_500ms=0;    // increment each counter, but bound to max count for each   tempo_50ms++;   tempo_100ms++;   tempo_200ms++;   tempo_300ms++;   tempo_400ms++;   tempo_500ms++;   tempo_50ms%=50;   tempo_100ms%=100;   tempo_200ms%=200;   tempo_300ms%=300;   tempo_400ms%=400;   tempo_500ms%=500;    // LINEAR_POSITION = MyLinRots[0].p_Data->Position   // above is a "scaled" position   // MyLinRots[0].p_Data->RawPosition   if (LINEAR_DETECT) {     // Now we just adjust when we are touching.     if (LINEAR_POSITION < 4) {       if (tempo_500ms==0) {         BSP_LED_Toggle(LED2);       }     } else if (LINEAR_POSITION < 8) {       if (tempo_300ms==0) {         BSP_LED_Toggle(LED2);       }     } else if (LINEAR_POSITION < 12) {       if (tempo_100ms==0) {         BSP_LED_Toggle(LED2);       }     } else {  // pos >= 12       if (tempo_50ms==0) {         BSP_LED_Toggle(LED2);       }     }    }   } /**   * @brief  Display sensors information on LEDs and LCD   * @param  status TSL user status   * @retval None   */ void Process_Sensors(tsl_user_status_t status) {    /* LED1 is ON when TS1 on board is touched */   if (MyTKeys[0].p_Data->StateId == TSL_STATEID_DETECT){     BSP_LED_On(LED3);   } else {     BSP_LED_Off(LED3);   }    /* LED2 is ON when TS2 on board is touched */   if (MyTKeys[1].p_Data->StateId == TSL_STATEID_DETECT) {     BSP_LED_On(LED4);   } else {     BSP_LED_Off(LED4);   }     /* LED3 is ON when TS3 on board is touched */   if (MyTKeys[2].p_Data->StateId == TSL_STATEID_DETECT) {     BSP_LED_On(LED5);   } else {     BSP_LED_Off(LED5);   }   #ifdef isthisused     /* ECS information */   switch (status){     case TSL_USER_STATUS_OK_ECS_OFF:       BSP_LED_Off(LED5);       break;     case TSL_USER_STATUS_OK_ECS_ON:       BSP_LED_Toggle(LED5);       break;     default:       break;   } #endif       if (LINEAR_DETECT) {     BSP_LED_On(LED1);   } else{     BSP_LED_Off(LED1);   }  }

Outcomes