原理分析
关于这个偏差的问题在上一篇博客中已经进行了介绍,这里就先从相序检测的过程本身进行分析,相序检测过程的直接目的是通过对两路DI(分别时UV和VW)的输入边沿进行检测,通过计算两个有效下降沿的时间差来判定其结果是正常、逆相,还是缺相。
大体的执行过程如下:
外部启动相序检测功能;
相序检测系统(任务中执行)在识别到启动请求后,切换状态机为采集状态,然后立刻启动延时功能(延时2ms开启输入捕获/外部输入中断,并在中断中切换状态机);
采集过程中,如果识别到上升沿,则不计入统计,且启动延时(先关闭输入中断,延时3ms),如果是下降沿则计入统计,并且丢弃第一个下降沿,在第二个下降沿开始计时;
当识别到第二个下降沿时记下此时的计数器的数值,并切换通道为VW通道,启动延时功能(延时2ms开启中断);
当识别到第三个下降沿时,记下此时的计数器数值,和前一个记录的计数器数值进行差值计算得到两个的时间差;
(注:以上过程中如果遇到上升沿,统一按照3ms延时,切换通道时延时2ms)
以上是正确的执行过程,结合本次问题,整理易错点如下:
在任务中启动延时;
延时的精度;
边沿的识别;
结果的可靠性;
问题分析
前面已经提到了4个易错点,接下来逐个进行介绍。
1.任务中延时
前面已经提到,在整个相序检测系统中,有如下几个部分组成:
相序检测服务(主状态机)任务;
延时定时器(是硬件TIM实现);
外部输入中断;
当然,整个系统还有其它各种任务在运行,而相序检测任务的优先级必然不是最高的,而且我们这里实现的延时又是异步的,因为其延时执行的动作是在定时器回调中执行的,因此,我们理想的状态是,开启延时后,其延时后面的代码也应先执行完(毕竟后面仅有一行代码,不至于耗时超过1ms),定时器才会执行。
出现问题时,我们切换通道还是仅延时1ms,这里抛开精度,作为任务,由于存在更高优先级的任务,所以必然会发生抢占的情况,而抢占的发生时机也是不确定的,如果恰好在延时开启之后被抢占,那么其被挂起的时间也必然会超过1ms,由于延时是通过TIM实现的,所以被抢占的这段时间TIM先到时间于是立刻执行了里面的逻辑,而回到任务时,才继续执行下一行代码。
之前出现问题时,我们状态机切换是放在了延时后面,我们的目的可以理解为:
状态1-->启动延时,切换为状态2-->在定时器中执行状态切换为3
如果出现了前面的问题,那么就会导致切换顺序如下:
状态1-->启动延时-->定时器先执行状态切换为3-->回到任务执行,状态切换为2
由于在状态机中,状态2是要通过延时切换的,所以这也就会导致状态机一直卡在状态2而不会往下执行。
2.延时的精度
我们虽然使用的是TIM实现的延时,但是由于系统中需要使用TIM来进行延时的地方太多,所以我们只能共享TIM,那么就意味着他们是通过TIM中的计数值来进行延时判断,由于TIM的时基是1ms,因此,当我们要延时1ms时,实际上有可能是0~1ms。
3.边沿的识别
这里使用的是外部输入中断,中断中是通过对输入引脚的电平进行判断,当为高电平时则认为是上升沿,如果是低电平则认为是下降沿,那么如果外部输入信号的质量比较差,如存在边沿的抖动,那么必然会导致可能是以下降沿进来的中断,但是经过判断识别成了上升沿。
但是我们又要通过这种方式来减少干扰,毕竟抖动的发生一般发生在边沿,因此,该点易错点的风险比较小,也是不太好通过软件去处理的。
4.结果的可靠性
我们前面能够做的仅是边沿的简单滤波,但是对于一些偶发的异常,如电平稳定过程中的波动,以及连续的电平波动还是存在计算偏差较大的情况,因此,为了保证结果的可靠性,我们还需要对结果进行过滤处理,大体方法如下:
a.采集多组时间差;
b.对时间差进行排序;
c.将结果三等分,去除两端的结果,剩下的中间部分取均值,作为最终的结果;
3.问题总结
相序检测逻辑中的问题可以归结为如下:
执行路径异常,结果延时先执行;
延时的效果存在1ms的偏差;
边沿的识别比较依赖电平判断,对外部的输入信号的波动比较敏感;
单次采集不可靠,所以多次采集剔值求均值;