ARM单片机触摸传感器原理和应用(4)

续ARM单片机触摸传感器原理和应用(3)

使用以下这类代码序列计算三个频率

for(int f=0; f<FREQ_VALUES;f++)

{

        if(f!=0){

                if(OptimunTscCfgCTPH+1<=16 && OptimunTscCfgCTPL+1<=16){

                        OptimunTscCfgCTPH++;

                        OptimunTscCfgCTPL++;

                }else{

// 假设 CTPH<= CTPL

                        OptimunTscCfgDIV *= 2;

                        OptimunTscCfgCTPH = 1 + (OptimunTscCfgCTPH/2);

                        OptimunTscCfgCTPL = 1 + (OptimunTscCfgCTPL/2);

                }

        }

        FreqHopp[f].div = OptimunTscCfgDIV;

        FreqHopp[f].ctph = OptimunTscCfgCTPH;

        FreqHopp[f].ctpl = OptimunTscCfgCTPL;

}

主循环调用

while (1)

{

        // Process TSC acquisition

        if(TSCAcqDone != 0){

                TSCAcqDone = 0;

                // Get TSC/TSL keys status

                TSL_obj_GroupProcess(&MyObjGroup);

        // Process DXS …

        // Process ECS algo …

        // activate led if key is press …

        //FTB, or Fast Transient Burst immunity: wait for 15ms …

        // We move to next frequency

        MoveToNextFreq();

        // After last bank acquisition we restart all bank acquisition

        TSCidxGroup = 0;

        TSCAcqDone = 0;

        TSL_acq_BankConfig(TSCidxGroup);

        TSL_acq_BankStartAcq_IT();

        }else{

        __WFI();

        }

}

用于在每次采集后改变频率的API

* Api

void MoveToNextFreq(void)

{

        static int f=0;

        f++;

        f %= FREQ_VALUES; // Change TSC frequency DIV divider         htsc.Init.PulseGeneratorPrescaler = INT_TO_PRESC(FreqHopp[f].div);         htsc.Init.CTPulseHighLength = INT_TO_CTPH(FreqHopp[f].ctph);         htsc.Init.CTPulseLowLength = INT_TO_CTPL(FreqHopp[f].ctpl);

        // Re Init TSC IP with New parameters... HAL_TSC_Init(&htsc);

        return;

}

注意:

• 当使用所有频率时,所有传感器上的测量值必须相等:在从频率F0变化到频率F1时,从测量的角度来看,任何传感器都不应观察到变化。

• 所选频率必须足够远离彼此,不能是简单的倍数关系。

• 在每个频率下必须执行相同数量的采集。建议使用四个样本来验证触摸检测,而不是三个样本。在两个频率下各执行两次采集。 

4.2.8 优化采样电容Cs和串联电阻Rs

增加采样电容Cs会延长采集时间,但可以减少传导噪声的影响。 配置Rskey = 10 kΩ和Cskey = 47 nF可以在传导噪声的免疫力上取得良好的效果。 

4.2.9 在VDD上的噪声或纹波测量

在使用MCU通用目的ADC的应用中,可以测量VIN的纹波,并由用户决定是否停止触摸传感采集。同样的测量也可以在VDD侧进行(见下图)。

图25. 在VDD上的VIN纹波测量

 关于VDD去耦,可以使用额外的10纳法拉(nF)和1纳法拉(nF)电容器。这种去耦方法分散了去耦电容的阻抗,并扩大了去耦噪声的抑制范围。

图26. VDD上的去耦电容器

4.3  应用层提升可靠性

4.3.1 使用DXS(检测排除系统)

在触摸传感系统中,多重检测指的是系统对单一触摸事件的多次识别,这可能会导致误操作或系统响应的混乱。检测排除系统(DXS)是一种功能,用于确保对触摸事件只进行一次检测,从而提高系统的稳定性和用户交互的准确性。

在触摸系统的编程过程中,应提供了一种避免多重检测的方法。并通过设置USE_DXS来激活:

/*=======================================================================*/ /* Detection Exclusion System (DXS) */ /*=======================================================================*/ /** @defgroup Common_Parameters_DXS 12 - DXS *

@{ */

/** Detection Exclusion System (0=No, 1=Yes) */

#define TSLPRM_USE_DXS (1)

/** @} Common_Parameters_DXS */  

4.3.2 确认传感器状态

通常所有传感器都处于TSL_STATEID_RELEASE状态。当一个传感器被按下时,其状态变为TSL_STATEID_DETECT。

用户可以使用如下所示的SensorNbInStateId API检测系统的行为。

/**

* @brief Count Sensor in stateId

* @param StateId Sensor state id, can NOT be OR-ed.

* @retval Sensor number in StateId state

*/

int SensorNbInState(TSL_StateId_enum_T StateId){

        int cntStateId=0,cntTKey=0;

        // Parse TKey sensors

        #if TSLPRM_TOTAL_TOUCHKEYS > 0

        for (cntTKey=0;cntTKey<TSLPRM_TOTAL_TOUCHKEYS;cntTKey++){                 if(MyTKeys[cntTKey].p_Data->StateId == StateId){

                        cntStateId++;

                }

        } #endif // Parse LinRots sensors

        #if TSLPRM_TOTAL_LINROTS > 0

                for (cntTKey=0;cntTKey<TSLPRM_TOTAL_LINROTS;cntTKey++){                         if(MyLinRots[cntTKey].p_Data->StateId == StateId){

                        cntStateId++;

                        }

                }

        #endif

return cntStateId;

}

在主循环中,不在RELEASE(释放)状态的传感器数量被计数,如果超过n个传感器不在稳定状态,则停止采集。这可能会在有噪声干扰或当手同时触摸所有传感器时发生。

 下面详细说明的加上DXS(检测排除系统)算法,提高了系统的噪声免疫力。

#define NOISE_COMPUTE_WINDOWS 10 /* Use to monitor noise */

#define NOISE_COMPUTE_THRESHOLD 20 /* Threshold level to decide when noise is too high */

#define NOISE_SUSPEND_DELAY 5000 /* Suspend delay when we detect noise (5s) */

#define NOISE_SENSOR_NOT_IN_RELEASE 3 /* Suspend acquisition when sensors are not in release state */

while (1)

{

        if(TSCAcqDone != 0 && WaitEndOfNoiseDuration == 0){

                TSCAcqDone = 0;

                // Get TSC/TSL keys status

                TSL_obj_GroupProcess(&MyObjGroup);

                // Point to DXS first object

                // Process ECS algo // Application sensor processing

                // For FTB test, wait for 15ms // Handle Frequency Hopping

                // Handle noise on application level

                nbSensorInRelease = SensorNumberInState(TSL_STATEID_RELEASE);

                // Handle next acquisition                 if((((TSLPRM_TOTAL_TOUCHKEYS+TSLPRM_TOTAL_LINROTS)-                                                nbSensorInRelease) >= NOISE_SENSOR_NOT_IN_RELEASE)){

                        // Noise detect, we suspend sensors acquisition

                        WaitEndOfNoiseDuration = NOISE_SUSPEND_DELAY;

                        }else{

                         // After last bank acquisition we restart all bank acquisition

                        TSCidxGroup = 0;

                        TSCAcqDone = 0;

                        TSL_acq_BankConfig(TSCidxGroup);

                        TSL_acq_BankStartAcq_IT();

                }

        }else{

        __WFI();

        // We assume only 1ms tick interrupt occurs

        if(WaitEndOfNoiseDuration > 0) {

                WaitEndOfNoiseDuration--;

                if(WaitEndOfNoiseDuration==0){

                        nbSensorInRelease = 0;

                        WaitEndOfNoiseDuration = 0;

                        // We restart all acquisition

                        TSCidxGroup = 0;

                        TSCAcqDone = 0;

                        TSL_acq_BankConfig(TSCidxGroup);

                        TSL_acq_BankStartAcq_IT();

                }

        }

4.2.10 使用噪声水平测量的差异值

/**

* @brief Get noise level

* @param None

* @retval mean noise level

*/

int phaseMeasurementNoise=0;

int GetNoiseLevel(void)

{

        int meanNoiseLevel=0,

        noiseLevelTKEYS=0,

        noiseLevelLROT=0;

        uint32_t id = 0, channel=0, div=0; //Reset array

        if(phaseMeasurementNoise==0){

        #if TSLPRM_TOTAL_TOUCHKEYS > 0

        for (channel=0;channel<TSLPRM_TOTAL_TOUCHKEYS;channel++){ 

                for (id=0;id<NOISE_COMPUTE_WINDOWS;id++){ NoiseTKEYS[channel][id] = 0;

                }

        }

#endif

#if TSLPRM_TOTAL_LINROTS > 0

                for (channel=0;channel<TSLPRM_TOTAL_LINROTS;channel++){

                        for (id=0;id<NOISE_COMPUTE_WINDOWS;id++){

                                NoiseLROT[channel][id] = 0;

                        }

                }

#endif

}

        phaseMeasurementNoise++;

//Start to measure noise, level.....

#if TSLPRM_TOTAL_TOUCHKEYS > 0

// Parse TKey sensors

        for (channel=0;channel<TSLPRM_TOTAL_TOUCHKEYS;channel++){

                 NoiseTKEYS[channel][phaseMeasurementNoise%NOISE_COMPUTE_WINDOWS] =MyTKeys[channel].p_ChD->Delta; }

#endif

#if TSLPRM_TOTAL_LINROTS > 0

// Parse LinRots sensors

        for (channel=0;channel<TSLPRM_TOTAL_LINROTS;channel++){

                NoiseLROT[channel][phaseMeasurementNoise%NOISE_COMPUTE_WINDOWS] =MyLinRots[channel].p_ChD->Delta; }

#endif

// Compute noise inside the rolling windows

#if TSLPRM_TOTAL_TOUCHKEYS > 0

        for (channel=0;channel<TSLPRM_TOTAL_TOUCHKEYS;channel++){

                for (id=0;id<NOISE_COMPUTE_WINDOWS;id++){

                        noiseLevelTKEYS += NoiseTKEYS[channel][id];

                }

        }

        noiseLevelTKEYS = abs(noiseLevelTKEYS);

        noiseLevelTKEYS /= NOISE_COMPUTE_WINDOWS;

        div += TSLPRM_TOTAL_TOUCHKEYS;

// Will be used to compute noise mean level

#endif

#if TSLPRM_TOTAL_LINROTS > 0

        for (channel=0;channel<TSLPRM_TOTAL_LINROTS;channel++){

                for (id=0;id<NOISE_COMPUTE_WINDOWS;id++){

                        noiseLevelLROT += NoiseLROT[channel][id];

                }

        }

        noiseLevelLROT = abs(noiseLevelLROT);

        noiseLevelLROT /= NOISE_COMPUTE_WINDOWS;

        div += TSLPRM_TOTAL_LINROTS; // Will be used to compute noise mean level

#endif

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MUKAMO

你的鼓励是我们创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值