【嵌入式底层知识修炼】高性能的ADC一阶滞后滤波算法

文章目录

  • 01 - 一阶滞后滤波算法简介
  • 02 - 硬件低通滤波器
  • 03 - 稳定滤波的原理
  • 04 - 实际应用与变形
  • 05 - 滤波效果展示
  • 06 - 高性能的表现
  • 07 - 总结


越有魅力的事物,往往存在一种“反差”,即其存在两个相互关联的特性,但是各自表现得十分不同

————小白


  一阶滞后滤波又称作RC低通滤波、一阶滤波、一阶惯性滤波、一阶低通滤波等,下文统一称为一阶滞后滤波。

01 - 一阶滞后滤波算法简介

  嵌入式中的ADC数字滤波算法有很多,搜索一下会有常用的10种算法,一阶滞后滤波是其中一种,也是大名鼎鼎的一种,在这10种算法中,虽然一直有人评论其各有优缺点,各有使用场合,但是如果在条件十分受限的实际嵌入式项目中让我选择一种,即使知道或不知道数据源的特性,我都会毫不犹豫地选择一阶滞后滤波算法,数学算法公式为:
Y n = α X n + ( 1 − α ) Y n − 1 (1) Y_{n} = α X_{n} + (1 - α) Y_{n-1} \tag{1} Yn=αXn+(1α)Yn1(1)
  式中: Y n Y_{n} Yn是本次滤波输出值, α α α是滤波系数, X n X_{n} Xn是本次采样, Y n − 1 Y_{n-1} Yn1是上一次滤波输出。
  公式十分简单,只有乘、加的操作并且只有一条计算公式,没有额外的数据计算。

02 - 硬件低通滤波器

  下图为一阶滞后滤波所对应的硬件低通滤波器等效电路,其中:

  • Input相当于于 X n X_{n} Xn:作为信号源的输入
  • Output相当于 Y n Y_{n} Yn:作为目标信号的输出
  • 电阻相当于 α α α:作为滤波系统,设计实验测试阶段可调
  • 电容相当于 Y n − 1 Y_{n-1} Yn1:用于储存上一次的输出值

在这里插入图片描述
  如果在原理图中看到类似的结构,可以认为添加了硬件低通滤波器,此等效电路算是比较简单的一种,还有比较复杂的需要有三极管等电子元件。

03 - 稳定滤波的原理

  滤波的目标是过滤掉数据的各种干扰,得到期望的稳定值,使得系统收敛。下面用坐标轴对公式作一个解释, x x x轴作为时间Time, y y y轴作为AD值Value,AD采集过程中我们能够得到一段采集的数据输入输出记录:
【嵌入式底层知识修炼】高性能的ADC一阶滞后滤波算法_第1张图片
  就 x x x轴某一个时刻 T T T而言,我们只能得到当前时刻 T T T的输入值Input和前面时刻的 ( T − 1 , T − 2 , … … 1 ) (T-1,T-2,……1) (T1T21)输出值Output,我们把当前时刻得到的输入值记为 X n X_{n} Xn,紧挨着的上一个时刻的输出值记为 Y n − 1 Y_{n-1} Yn1。滤波的目标是得到一个稳定值,何为稳定?什么样的值是稳定的?在不同时刻是否不同?根据一阶滞后滤波算法,如果要回答这些问题,无论如何我们只能假设在上一个时刻的输出值 Y n − 1 Y_{n-1} Yn1是稳定值

因为除开第一个数据,所有数据都有前驱,当前值的滤波与前驱有关,那么随着时间的推移,所有的数据历史会形成一个链条,相邻的项是有联系的,因此只要某个时刻的值发生了变化,那么后面的值都会随之变化,如果我们限定了这些变化的敏感度(与α有关),比如降低敏感度,那么在一个有限的波形内由于变化不敏感,就会过滤掉波动的数据,得到一个认为是收敛的值

  根据假设,因为 Y n − 1 Y_{n-1} Yn1是稳定值,所以 X n X_{n} Xn与它存在一个误差 e e e,也就是:
X n = Y n − 1 + e (2) X_{n} = Y_{n-1} + e \tag{2} Xn=Yn1+e(2)
  其中 e e e可正可负,我们代入公式(1)得到:
Y n = α X n + ( 1 − α ) Y n − 1 = α ( Y n − 1 + e ) + ( 1 − α ) Y n − 1 = α Y n − 1 + α e + Y n − 1 − α Y n − 1 = α e + Y n − 1 (3) \begin{aligned} Y_{n} =& α X_{n} + (1 - α) Y_{n-1} \tag{3} \\ =& α(Y_{n-1} + e) + (1 - α) Y_{n-1}\\ =& αY_{n-1} + αe + Y_{n-1} - α Y_{n-1}\\ =& αe + Y_{n-1} \end{aligned} Yn====αXn+(1α)Yn1α(Yn1+e)+(1α)Yn1αYn1+αe+Yn1αYn1αe+Yn1(3)
  原理就在这个公式里面,因为我们假设 Y n − 1 Y_{n-1} Yn1是稳定值,因此当前时刻 T T T的输出 Y n Y_{n} Yn就取决于滤波系数 α α α和误差 e e e,而滤波系数 α α α一般为固定值:
  当趋向于0, α → 0 α\rightarrow 0 α0 Y n = e ⋅ O ( 0 ) + Y n − 1 Y_{n} =e\cdot O(0) + Y_{n-1} Yn=eO(0)+Yn1 ,多数情况下 α ⋅ ∣ e ∣ ≤ 0.5 α\cdot|e| \leq 0.5 αe0.5,根据C语言的四舍五入,这个误差会被忽略,这就是降低敏感度,稳定数据,系统收敛性明显,但是数据的变化会滞后,因为需要一个较大的误差才能让 Y n Y_{n} Yn发生变化。
【嵌入式底层知识修炼】高性能的ADC一阶滞后滤波算法_第2张图片
  当趋向于1, α → 1 α\rightarrow 1 α1 Y n = e ⋅ O ( 1 ) + Y n − 1 Y_{n} =e\cdot O(1) + Y_{n-1} Yn=eO(1)+Yn1,多数情况下 α ⋅ ∣ e ∣ ≥ 0.5 α\cdot|e| \geq 0.5 αe0.5,根据C语言的四舍五入,这个误差会被记录并且马上反应,这就是升高敏感度,实时反映数据波动,系统收敛性不明显,数据并不稳定。
【嵌入式底层知识修炼】高性能的ADC一阶滞后滤波算法_第3张图片
  由C语言中四舍五入可知,需要 α ⋅ ∣ e ∣ ≥ 1 2 α\cdot|e| \geq \frac{1}{2} αe21的时候, Y n Y_{n} Yn才会变化,也就是当 α ⋅ ∣ e ∣ < 0.5 α\cdot|e| < 0.5 αe<0.5的时候不变化,解不等式得到 e ∈ ( − 1 2 a , 1 2 a ) e \in (-\frac{1}{2a},\frac{1}{2a}) e(2a12a1),代入(2)式,得到AD值的稳定和变化范围
Y n = { Y n − 1 : ( Y n − 1 − 1 2 a ) < X n < ( Y n − 1 + 1 2 a ) X n + [ α ⋅ e ] : X n ∈ Others , [ x ] 代 表 对 x 四 舍 五 入 (4) Y_{n} = \left\{ \begin{array}{lr} Y_{n-1} &: & (Y_{n-1} - \frac{1}{2a}) < X_{n} < (Y_{n-1} + \frac{1}{2a})& \tag{4}\\ X_{n}+[α\cdot e] &:& X_{n} \in \text{Others} ,[x]代表对x四舍五入& \end{array} \right. Yn={Yn1Xn+[αe]::(Yn12a1)<Xn<(Yn1+2a1)XnOthers[x]x(4)
  对于一个上一次的输出值 Y n − 1 Y_{n-1} Yn1,如果当前时刻的输入值 X n ∈ ( Y n − 1 − 1 2 a , Y n − 1 + 1 2 a ) X_{n} \in(Y_{n-1} - \frac{1}{2a},Y_{n-1} + \frac{1}{2a}) XnYn12a1Yn1+2a1,都将都被认为是 Y n − 1 Y_{n-1} Yn1,必须有一个较大的误差 e e e才能让 Y n Y_{n} Yn发生变化,这就是滞后的意思

04 - 实际应用与变形

  嵌入式的实际应用会根据实际情况作相应的变形和改变,以下只举一个例子,体验一阶滞后滤波的实际应用。
  场景:一个电控盆栽,有ARM逻辑主板+8051辅助板,8051系列的单片机作为盆栽的辅助板,需要采集温度传感器的AD值,反馈给主板作处理。
【嵌入式底层知识修炼】高性能的ADC一阶滞后滤波算法_第4张图片
  分析:盆栽一般放置在家庭中,环境温度在一大段时间内一般都是稳定的(比如上午、下午、晚上),而且温度是线性变换的,不会出现突变的情况,因此系统需要的是一个稳定的AD值,不允许环境温度没有有效变化的时候AD值却在波动,因此降低滤波系数 α α α,降低敏感度,使得系统收敛,稳定数据。
  问题:8051系统的芯片处理浮点数非常吃力,不能让系统浪费在这些时间上。
  解决:不作浮点数处理,把滤波系数 α α α平移到整数范围内,也就是扩大 K K K倍,整个公式变形为:
原来 : Y n = α X n + ( 1 − α ) Y n − 1 变形 : Y n = α X n + ( K − α ) Y n − 1 K (6) \begin{aligned} \text{原来}: Y_{n} =& α X_{n} + (1 - α) Y_{n-1}\\ \text{变形}: Y_{n} =& \frac{α X_{n} + (K - α) Y_{n-1} }{K}\tag{6} \end{aligned} 原来Yn=变形Yn=αXn+(1α)Yn1KαXn+(Kα)Yn1(6)
  除法也是会占用很多CPU资源,不过我们可以把 K K K定为2的幂次方,除法就可以轻松转成位移运算
Y ( n ) = ( α X n + ( K − α ) Y n − 1 ) > > l o g 2 K (7) Y(n) = (α X_{n} + (K - α) Y_{n-1})>> log_2{K}\tag{7} Y(n)=αXn+(Kα)Yn1>>log2K(7)
  (7)式就是最终公式,定好 K K K α α α后,就可以编程实现了,比如 K = 128 , α = 8 K=128,α = 8 K=128α=8,那么:
Y n = ( 8 ⋅ X n + 120 ⋅ Y n − 1 ) > > 7 Y_{n}= (8 \cdot X_{n} + 120 \cdot Y_{n-1} )>> 7 Yn=8Xn+120Yn1>>7
  对应的编程代码:

extern uint32_t LastValue;
uint32_t ADC_filter(uint32_t CurrValue)
{
	uint32_t tmp = (8 * CurrValue + 120 * LastValue) >> 7;
	LastValue = tmp;
	return LastValue;
}

  公式只有整数的乘法、加法和位移运算,这些运算在8051单片机系列中的消耗是可以接受的(不到万不得已,不会用浮点数和除法运算)。

05 - 滤波效果展示

  选取上述公式,并代入随机值,这些随机值都认为是各种干扰因素造成的波动,也就是实际的ADC数据理应不变:
Y n = ( 8 ⋅ X n + 120 ⋅ Y n − 1 ) > > 7 Y_{n}= (8 \cdot X_{n} + 120 \cdot Y_{n-1} )>> 7 Yn=8Xn+120Yn1>>7
【嵌入式底层知识修炼】高性能的ADC一阶滞后滤波算法_第5张图片
  系列1蓝色线为随机值,模拟干扰因素的波动,系列2红色线为滤波后的数据,能够观察到,因为我们定的滤波系数 α α α较小,因此会降低敏感度,在源数据从64突然跳变到70的时候,滤波得到的值也是不变的,可以稍微提高滤波系数,比如 α = 32 α = 32 α=32,再看一下滤波效果:
【嵌入式底层知识修炼】高性能的ADC一阶滞后滤波算法_第6张图片
  在这个实验中,充分能够看到一阶滞后滤波中滞后的过程,在源数据蓝色线波动后,滤波结果红色线并不是马上跟随波动,而是滞后一段时间,需要源数据和上一次的滤波输出值有较大差别的时候才进行变化。

06 - 高性能的表现

  一阶滞后滤波的高性能表现在:

  • 易于实现:2-3句代码就能实现。
  • 适应性强:公式变形简单,可应用在很多场合内。
  • 运算简单:一条公式,几个基本运算符,计算速度也快。
  • 可调属性:能够轻易调整收敛速度和敏感性,而且调节的范围参考。

  以上4点可以作为和其它滤波算法作比较的点,对比的实验会在另一篇博客中,期待下一篇。

07 - 总结

  • 一阶滞后滤波公式: Y n = α X n + ( 1 − α ) Y n − 1 Y_{n} = α X_{n} + (1 - α) Y_{n-1} Yn=αXn+(1α)Yn1,可适当变形
  • AD值的稳定和变化范围:
    Y n = { Y n − 1 : ( Y n − 1 − 1 2 a ) < X n < ( Y n − 1 + 1 2 a ) X n + [ α ⋅ e ] : X n ∈ Others , [ x ] 代 表 对 x 四 舍 五 入 Y_{n} = \left\{ \begin{array}{lr} Y_{n-1} &: & (Y_{n-1} - \frac{1}{2a}) < X_{n} < (Y_{n-1} + \frac{1}{2a})& \\ X_{n}+[α\cdot e] &:& X_{n} \in \text{Others} ,[x]代表对x四舍五入& \end{array} \right. Yn={Yn1Xn+[αe]::(Yn12a1)<Xn<(Yn1+2a1)XnOthers[x]x
  • 高性能的表现在:易于实现、适应性强、运算简单、可调属性

你可能感兴趣的:(一阶滞后滤波,低通滤波,ADC滤波,#,嵌入式底层知识修炼)