嵌入式开发中的硬件滤波器设计和软件滤波设计

滤波有哪几种?

答:在微机控制系统的模拟输入信号中,一般均含有各种噪声和干扰,他们来自被测信号源本身、传感器、外接干扰等。为了进行准确测量和控制,必须消除被测信号中的噪声和干扰:

滤波分为硬件滤波和软件滤波:

l 硬件滤波:运用一定规格的电阻、电容组成的RC滤波器或者采用电感、电容组成的LC滤波器等模拟滤波器进行滤波;

l 软件滤波:也成为数字滤波,通过一定的计算或判断程序减少或削弱噪声影响。1.滤波有哪几种?

答:在微机控制系统的模拟输入信号中,一般均含有各种噪声和干扰,他们来自被测信号源本身、传感器、外接干扰等。为了进行准确测量和控制,必须消除被测信号中的噪声和干扰:

滤波分为硬件滤波和软件滤波:

l 硬件滤波:运用一定规格的电阻、电容组成的RC滤波器或者采用电感、电容组成的LC滤波器等模拟滤波器进行滤波;

l 软件滤波:也成为数字滤波,通过一定的计算或判断程序减少或削弱噪声影响。

硬件滤波

什么是滤波器?

各种传感器信号多多少少会携带一些噪声信号,那么通过滤波器就能够更好的降低和去除噪声,还原真实有用信号。

滤波器是一个电路,其去除或“过滤掉”频率分量的特定范围。换句话说,它将信号的频谱分离为将要通过的频率分量和将被阻隔的频率分量。

如果您对频域分析没有太多经验,您可能仍然不确定这些频率成分是什么,以及它们如何在不能同时具有多个电压值的信号中共存。让我们看一个有助于澄清这个概念的简短例子。

假设我们有一个由完美的5kHz正弦波组成的音频信号。我们知道时域中的正弦波是什么样的,在频域中我们只能看到5kHz的频率“尖峰”。现在让我们假设我们激活一个500kHz振荡器,将高频噪声引入音频信号。

在示波器上看到的信号仍然只是一个电压序列,每个时刻有一个值,但信号看起来会有所不同,因为它的时域变化现在必须反映5kHz正弦波和高频噪音波动。

然而,在频域中,正弦波和噪声是在一个信号中同时存在的单独的频率分量。正弦波和噪声占据了信号频域表示的不同部分,这意味着我们可以通过将信号引导通过低频并阻挡高频的电路来滤除噪声。正弦波和噪声信号频域的不同部分分布示意图,如下。

图片

滤波器的类型

滤波器可以放在与滤波器频率响应的一般特征相对应的广泛类别中。如果滤波器通过低频并阻止高频,则称为低通滤波器;如果它阻挡低频并通过高频,它就是一个高通滤波器。还有带通滤波器,其仅通过相对窄的频率范围,以及带阻滤波器,其仅阻挡相对窄的频率范围。各滤波器频域表示,如下图所示。

图片

还可以根据用于实现电路的组件类型对滤波器进行分类。无源滤波器使用电阻器,电容器和电感器,这些组件不具备提供放大的能力,因此无源滤波器只能维持或减小输入信号的幅度。另一方面,有源滤波器既可以滤波信号又可以应用增益,因为它包括有源元件,如晶体管或运算放大器,如下图。

图片

这种有源低通滤波器基于流行的Sallen-Key拓扑结构,相关文章移步此处:Sallen-Key 有源滤波器

RC低通滤波器

为了创建无源低通滤波器,我们需要将电阻元件与电抗元件组合在一起。换句话说,我们需要一个由电阻器和电容器或电感器组成的电路。从理论上讲,电阻—电感(RL)低通拓扑在滤波能力方面与电阻—电容(RC)低通拓扑相当。但实际上,电阻—电容方案更为常见,因此本文的其余部分将重点介绍RC低通滤波器。RC低通滤波器示意图如下。

图片

如图所示,通过将一个电阻与信号路径串联,并将一个电容与负载并联,可以产生RC低通响应。在图中,负载是单个组件,但在实际电路中,它可能更复杂,例如模数转换器,放大器或示波器的输入级,用于测量滤波器的响应。

如果我们认识到电阻器和电容器形成与频率相关的分压器,就可以直观地分析RC低通拓扑的滤波动作。重新绘制RC低通滤波器,使其看起来像分压器,如下图。

图片

当输入信号的频率低时,电容器的阻抗相对于电阻器的阻抗高;因此,大部分输入电压在电容器上(和负载两端,与电容器并联)下降。当输入频率较高时,电容器的阻抗相对于电阻器的阻抗较低,这意味着电阻器上的电压降低,并且较少的电压传输到负载。因此,低频通过并且高频被阻挡。

RC低通功能的这种定性解释是重要的第一步,但是当我们需要实际设计电路时它并不是很有用,因为术语“高频”和“低频”非常模糊。工程师需要创建通过并阻止特定频率的电路。例如,在上述音频系统中,我们希望保留5kHz信号并抑制500kHz信号。这意味着我们需要一个滤波器,从5kHz到500kHz之间的传递过渡到阻塞。

RC滤波器截止频率

滤波器不会引起显著衰减的频率范围称为通带,滤波器确实导致显着衰减的频率范围称为阻带。模拟滤波器,例如RC低通滤波器,总是从通带逐渐过渡到阻带。这意味着无法识别滤波器停止传递信号并开始阻塞信号的一个频率。然而,工程师需要一种方便,简洁地总结滤波器频率响应的方法,这就是截止频率概念发挥作用的地方。

当您查看RC滤波器的频率响应图时,您会注意到术语“截止频率”不是很准确。信号光谱被“切割”成两半的图像,其中一个被保留而其中一个被丢弃,不适用,因为随着频率从截止点下方移动到截止值以上,衰减逐渐增加。

RC低通滤波器的截止频率实际上是输入信号幅度降低3dB的频率(选择该值是因为幅度降低3dB对应于功率降低50%)。因此,截止频率也称为-3dB频率,实际上该名称更准确且信息量更大。术语带宽是指滤波器通带的宽度,在低通滤波器的情况下,带宽等于-3dB频率,如下图所示。

图片

上图表示RC低通滤波器的频率响应的一般特性,带宽等于-3dB频率。

如上所述,RC滤波器的低通行为是由电阻器的频率无关阻抗与电容器的频率相关阻抗之间的相互作用引起的。为了确定滤波器频率响应的细节,我们需要在数学上分析电阻(R)和电容(C)之间的关系,我们还可以操纵这些值,以设计满足精确规格的滤波器。RC低通滤波器的截止频率(fC)计算如下:

图片

来看一个简单的设计实例。电容值比电阻值更具限制性,因此我们将从常见的电容值(例如10nF)开始,然后我们将使用该公式来确定所需的电阻值。目标是设计一个滤波器,它将保留5kHz音频波形并抑制500kHz噪声波形。我们将尝试100kHz的截止频率,稍后在文章中我们将更仔细地分析此滤波器对两个频率分量的影响,公式如下。

图片

因此,160Ω电阻与10nF电容相结合,将为我们提供一个非常接近所需频率响应的滤波器。

滤波器响应可视化

评估滤波器对信号影响的最方便方法是检查滤波器频率响应的图。这些图形通常称为波德图,在垂直轴上具有幅度(以分贝为单位),在水平轴上具有频率;水平轴通常具有对数标度,使得1Hz和10Hz之间的物理距离与10Hz和100Hz之间,100Hz和1kHz之间的物理距离相同等等。这种配置使我们能够快速准确地评估滤波器在很大频率范围内的行为。如下图,是频率响应图的一个例子。

图片

曲线上的每个点表示如果输入信号的幅度为1V且频率等于水平轴上的相应值,则输出信号将具有的幅度。例如,当输入频率为1MHz时,输出幅度(假设输入幅度为1V)将为0.1V(因为-20dB对应于十倍减少因子)。

当您花费更多时间使用滤波器电路时,此频率响应曲线的一般形状将变得非常熟悉。通带中的曲线几乎完全平坦,然后随着输入频率接近截止频率,它开始下降得更快。最终,衰减的变化率(称为滚降)稳定在20dB/decade-即,输入频率每增加十倍,输出信号的幅度降低20dB。

评估低通滤波器性能

如果我们仔细绘制我们在本文前面设计的滤波器的频率响应,我们将看到5kHz时的幅度响应基本上是0dB(即几乎为零衰减),500kHz时的幅度响应约为-14dB(对应于0.2的增益)。这些值与我们在上一节中执行的计算结果一致。

由于RC滤波器总是从通带到阻带逐渐过渡,并且因为衰减永远不会达到无穷大,我们无法设计出“完美”的滤波器—即对正弦波没有影响并完全消除噪声的滤波器。相反,我们总是需要权衡。如果我们将截止频率移近5kHz,我们将有更多的噪声衰减,但我们想要发送到扬声器的正弦波也会衰减更多。如果我们将截止频率移近500kHz,我们在正弦波频率下的衰减会减少,但噪声频率下的衰减也会减少。

前面我们已经讨论了滤波器修改信号中各种频率分量振幅的方式。然而,除了振幅效应之外,电抗性电路元件总是引入相移。

低通滤波器相移

相位的概念是指周期内特定时刻的周期信号的值。因此,当我们说电路引起相移时,我们的意思是它会在输入信号和输出信号之间产生偏差:输入和输出信号不再在同一时刻开始和结束它们的周期。相移值(例如45°或90°)表示产生的偏差量。

电路中的每个电抗元件都会引入90°的相移,但这种相移不会同时发生。输出信号的相位与输出信号的振幅一样,随着输入频率的增加而逐渐变化。RC低通滤波器中有一个电抗元件(电容器),因而电路最终也会引入90°的相移。

与振幅响应一样,通过检查水平轴表示对数频率的曲线图,可以最容易地评估相位响应。以下描述表示了一般模式,查看下图可以进一步了解详细信息。

  • 相移最初为0°
  • 相移逐渐增加,直到在截止频率处达到45°,在这部分响应期间,变化率逐渐增加
  • 在截止频率之后,相移继续增加,但变化率逐渐降低
  • 随着相移逐渐接近90°,变化率变得非常小

图片

实线是振幅响应,虚线是相位响应。截止频率为100kHz。注意,截止频率下的相移为45°。

二阶低通滤波器

到目前为止,我们假设RC低通滤波器由一个电阻器和一个电容器组成。这种配置是一阶滤波器。相关推荐:

无源滤波器的“阶数”由电路中电抗元件(即电容器或电感器)的数量决定。高阶滤波器具有更多的无功元件,会产生更多的相移和更陡的滚降,而后者是增加滤波器阶数的主要动机。

向滤波器添加一个电抗元件,例如,从一阶到二阶或二阶到三阶,便可将最大滚降增加20dB/十倍。

二阶滤波器通常围绕由电感器和电容器组成的谐振电路构建,这种拓扑结构称为RLC(Resistor-Inductor-Capacitor)。但是,也可以创建二阶RC滤波器。如下图所示,我们需要做的就是将两个一阶RC滤波器级联起来。

图片

虽然这种拓扑肯定会产生二阶响应,但它没有被广泛使用,其频率响应通常不如二阶有源滤波器或二阶RLC滤波器。

二阶RC滤波器的频率响应

我们可以尝试根据所需的截止频率设计一阶滤波器,然后从中选择两个串联连接来,从而构成二阶RC低通滤波器。此举确实可以使滤波器表示出类似的总频率响应,最大滚降为40dB/decade而不是20dB/decade。

但是,如果我们更仔细地观察响应,我们会发现-3dB频率出现降低。二阶RC滤波器的行为不符合预期,因为两个滤波阶段不是独立的,因此不能简单地将这两个滤波器连接在一起,并将电路分析为一阶低通滤波器叠加一个相同的一阶低通过滤。

此外,即使我们在两级之间插入缓冲器,使得第一阶RC和第二阶RC可以用作独立滤波器,此时原始截止频率处的衰减将是6dB而不是3dB。这恰恰是因为两阶独立工作而导致的。第一个滤波器在截止频率处具有3dB的衰减,而第二个滤波器加上了另外3dB的衰减,如下图。

图片

二阶RC低通滤波器的基本限制是设计人员无法通过调整滤波器的Q因子来微调从通带到阻带的转换;此参数表示频率响应的阻尼程度。如果将两个相同的RC低通滤波器级联,则整体传递函数对应于二阶响应,但Q因子始终为0.5。当Q=0.5时,滤波器处于过阻尼的边界,这会导致频率响应在过渡区域中“下垂”。二阶有源滤波器和二阶谐振滤波器没有这一限制;设计人员可以控制Q因子,从而微调过渡区域的频率响应。

总结

所有电信号都混合了所需频率分量和不需要的频率分量。不需要的频率分量通常由噪声和干扰引起,并且在某些情况下会对系统的性能产生负面影响。

滤波器是以不同方式对信号频谱的不同部分作出反应的电路。低通滤波器旨在让低频分量通过,同时阻止高频分量。

低通滤波器的截止频率表示滤波器从低衰减变为显著衰减的频率区域。

RC低通滤波器的输出电压可以通过将电路视为由(频率无关)电阻和(频率相关)电抗组成的分压器来计算。

振幅(以dB为单位,在垂直轴上)与对数频率(以赫兹为单位,在水平轴上)的曲线图是检查滤波器理论行为的方便有效的方法,还可以使用相位与对数频率的关系图来确定将要应用于输入信号的相移量。

二阶滤波器的滚降更陡峭;当信号不能在所需频率分量和不需要的频率分量之间提供宽带分离时,这种二阶响应比较有用。

可以通过构建两个相同的一阶RC低通滤波器,然后将一个的输出连接到另一个的输入来创建二阶RC低通滤波器,但最终整体的-3dB频率将低于预期。

软件滤波

滤波方式方法优点缺点复杂度
限幅滤波法根据经验判断,确定两次采样允许的最大偏差值设为A ,每次检测到新值时判断;如果本次值与上次值之差<=A,则有效;如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值能有效克服因偶然因素引起的脉冲干扰无法抑制周期性干扰,平滑度差尚未计算
中位值滤波法连续采样N次(N取奇数),把N次采样值按大小排列,取中间值作为本次有效值能有效克服因偶然因素引起的波动干扰,对温度、液位的变化缓慢的被测参数有良好的滤波效果对流量、速度等快速变化的参数不适宜
算术平均滤波法连续采样N个值进行算术平均计算;N值较大时:信号平滑度较高,但灵敏度较低;N值较小时:信号平滑度较低,但灵敏度高;N值的选取:一般流量,N = 12;压力:N= 4适用于对一般具有随机干扰的信号进行滤波,这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动对于测量速度较慢或要求数据计算速度较快的试试控制不适用,比较浪费RAM
递推平均滤波法把连续取N个采样值看成一个队列;队列的长度固定为N;每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出);把队列中的N个数据进行算术平均计算,就可得到新的滤波结果;N值得选取:流量:N = 12;压力:N = 4;液面:N = 4-12;温度:N = 1-4对周期性干扰有良好的抑制作用,平滑度高,适用于高频震荡的系统灵敏度低,对偶然出现的脉冲式干扰的抑制作用较差,不易消除由于脉冲干扰引起的采样值偏差,不适用于脉冲干扰比较严重的场合,比较浪费RAM
中位值平均滤波法相当于“中位值滤波法 + 算术平均滤波法”,连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2个数据的算术平均值,N = 3-14融合了两种滤波的优点,可消除对于偶然出现的脉冲性滤波干扰 所引起的采样值偏差测量速度较慢,和算术平均值滤波一样,比较浪费RAM
限幅平均滤波法相当于“限幅两部分 + 递推平均滤波法”,每次采样到的新数据先进行限幅处理,再送入队列进行递推平均滤波处理融合了两种滤波的优点,可消除对于偶然出现的脉冲性滤波干扰 所引起的采样值偏差比较浪费RAM
一阶滞后滤波法取a = 0-1,(1-a)本次采样值+a上次滤波结果对于周期性干扰有良好的抑制作用,适用于波动频率较高的场合相位滞后,灵敏度低,滞后程度取决于a的大小,不能消除滤波频率高于采样频率的1/2的干扰信号
加权递推平均滤波法是对递推平均滤波法的改进,即不同时刻的数据加以不同的权,通常是,越接近现时刻的数据,权取得越大。给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低适用于有较大纯滞后时间常数的系统对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号,不能迅速反应系统当前所受干扰的严重程度,滤波效果差
消抖滤波法设置一个滤波计数器,将每次采样值与当前有效值比较:如果采样值 = 当前有效值,则计数器清零;如果采样值</>当前有效值,则计数器+1,并判断计数器是否>=上限N(溢出);如果计数器溢出,则将本次值替换当前有效值,并清计数器对于变化缓慢的被测参数由较好的滤波效果,可避免在临界值附近控制器的反复开/关跳动或显示器上数值抖动对于快速变化的参数不适宜,如果在计数器溢出的那一次采样值恰好是干扰值,则会将干扰值当做有效值导入系统
限幅消抖滤波法相当于“限幅滤波法 + 消抖滤波法” ,先限幅,后消抖继承了限幅和消抖的优点,改进了消抖滤波法中的缺陷,避免将干扰值导入系统不适合快速变化的参数
巴特沃斯滤波法适用于ad采样,会出现周期性的脉冲波动占用过多的RAM,计算时间较长,不适宜快速变化的参数

已剪辑自: https://www.jianshu.com/p/38ed6ff1b8c0

姓名:王柯祎

学号:20021110373T

转自 :http://www.wtoutiao.com/p/1fe9dPI.html

【嵌牛导读】总结常用的一些数字滤波算法的特点和适用范围。

【嵌牛鼻子】1、克服大脉冲干扰的数字滤波法;2、抑制小幅度高频噪声的平均滤波法;3、复合滤波法

【嵌牛正文】

数字滤波(digital filtering):用数字设备,通过一定的算法,对信号进行处理,将某个频段的信号进行滤除,得到新的信号的这一过程叫做数字滤波。

数字滤波器可以分为两大部分:即经典滤波器和现代滤波器。经典滤波器就是假定输入信号x(n)中的有用成分和希望滤除成分分别位于不同的频带,因而我们通过一个线性系统就可以对噪声进行滤除,如果噪声和信号的频谱相互混叠,则经典滤波器得不到滤波的要求。通常有高通滤波器,低通滤波器,带通滤波器,带阻滤波器。现代滤波器是从含有噪声的信号估计出有用的信号和噪声信号。这种方法是把信号和噪声本身都视为随机信号,利用其统计特征,如自相关函数,互相关函数,自功率谱,互功率谱等引导出信号的估计算法,然后利用数字设备实现。目前主要有维纳滤波,卡尔曼滤波,自适应滤波等数字滤波器。

下面介绍常用的8种滤波方法:

(一)克服大脉冲干扰的数字滤波法:

克服由仪器外部环境偶然因素引起的突变性扰动或仪器内部不稳定引起误码等造成的尖脉冲干扰,是仪器数据处理的第一步。通常采用简单的非线性滤波法。

1、限幅滤波法(又称程序判断滤波法)限幅滤波是通过程序判断被测信号的变化幅度,从而消除缓变信号中的尖脉冲干扰。

A、方法:根据经验判断,确定两次采样允许的最大偏差值(设为A)每次检测到新值时判断:如果本次值与上次值之差A,则本次值无效,放弃本次值,用上次值代替本次值

B、优点:能有效克服因偶然因素引起的脉冲干扰。缺点:无法抑制那种周期性的干扰平滑度差。

C、适用范围:变化比较缓慢的被测量值

2、中位值滤波法

中位值滤波是一种典型的非线性滤波器,它运算简单,在滤除脉冲噪声的同时可以很好地保护信号的细节信息。

A、方法:连续采样N次(N取奇数)把N次采样值按大小排列(多采用冒泡法)取中间值为本次有效值

B、优点:能有效克服因偶然因素引起的波动(脉冲)干扰。缺点:对流量、速度等快速变化的参数不宜。

C、适用范围:对温度、液位的变化缓慢的被测参数有良好的滤波效果

(二)抑制小幅度高频噪声的平均滤波法

小幅度高频电子噪声:电子器件热噪声、A/D量化噪声等。通常采用具有低通特性的线性滤波器:算数平均滤波法、加权平均滤波法、滑动加权平均滤波法一阶滞后滤波法等。

3、算术平均滤波法算术平均滤波法是对N个连续采样值相加,然后取其算术平均值作为本次测量的滤波值。

A、方法:连续取N个采样值进行算术平均运算N值较大时:信号平滑度较高,但灵敏度较低N值较小时:信号平滑度较低,但灵敏度较高N值的选取:一般流量,N=12;压力:N=4

B、优点:对滤除混杂在被测信号上的随机干扰信号非常有效。被测信号的特点是有一个平均值,信号在某一数值范围附近上下波动。缺点:不易消除脉冲干扰引起的误差。对于采样速度较慢或要求数据更新率较高的实时系统,算术平均滤法无法使用的。比较浪费RAM

4、递推平均滤波法(又称滑动平均滤波法)

对于采样速度较慢或要求数据更新率较高的实时系统,算术平均滤法无法使用的。滑动平均滤波法把N个测量数据看成一个队列,队列的长度固定为N,每进行一次新的采样,把测量结果放入队尾,而去掉原来队首的一个数据,这样在队列中始终有N个“最新”的数据。

A、方法:把连续取N个采样值看成一个队列,队列的长度固定为N,每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)把队列中的N个数据进行算术平均运算,就可获得新的滤波结果N值的选取:流量,N=12;压力:N=4;液面,N=412;温度,N=14

B、优点:对周期性干扰有良好的抑制作用,平滑度高适用于高频振荡的系统。缺点:灵敏度低对偶然出现的脉冲性干扰的抑制作用较差不易消除由于脉冲干扰所引起的采样值偏差不适用于脉冲干扰比较严重的场合比较浪费RAM

5、加权递推平均滤波法

A、方法:是对递推平均滤波法的改进,即不同时刻的数据加以不同的权通常是,越接近现时刻的数据,权取得越大。给予新采样值的权系数越大,则灵敏度越高,但信号平滑度低

B、优点:适用于有较大纯滞后时间常数的对象和采样周期较短的系统。缺点:对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号不能迅速反应系统当前所受干扰的严重程度,滤波效果差

6、一阶滞后滤波法一阶低通数字滤波器是用软件的方法实现硬件的RC滤波,以抑制干扰信号。在模拟量输入通道中,常用一阶滞后RC模拟滤波器来抑制干扰。

用此种方法来实现对低频干扰时,首先遇到的问题是要求滤波器有大的时间常数(时间常数=RC)和高精度的RC网络。时间常数越大,要求RC值越大,其漏电流也必然增大,从而使RC网络精度下降。采用一阶滞后的数字滤波方法,能很好的克服这种模拟量滤波器的缺点,在滤波常数要求较大的场合,此法更适合。

A、方法:a=Tf/(Tf+T)Tf为滤波时间常数。T为采样周期本次滤波结果=(1-a)本次采样值+a上次滤波结果

B、优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合。缺点:相位滞后,灵敏度低滞后程度取决于a值大小不能消除滤波频率高于采样频率的1/2的干扰信号

(三)复合滤波法

在实际应用中,有时既要消除大幅度的脉冲干扰,有要做到数据平滑。因此常把前面介绍的两种以上的方法结合起来使用,形成复合滤波。去极值平均滤波算法:先用中值滤波算法滤除采样值中的脉冲性干扰,然后把剩余的各采样值进行平均滤波。连续采样N次,剔除其最大值和最小值,再求余下N-2个采样的平均值。显然,这种方法既能抑制随机干扰,又能滤除明显的脉冲干扰。

7、中位值平均滤波法(又称防脉冲干扰平均滤法)

中位值平均滤波法相当于“中位值滤波法”+“算术平均滤波法”。

A、方法:连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2个数据的算术平均值N值的选取:3~14

B、优点:融合了两种滤波法的优点这种方法既能抑制随机干扰,又能滤除明显的脉冲干扰。缺点:测量速度较慢,和算术平均滤波法一样比较浪费RAM

8、限幅平均滤波法

在脉冲干扰较严重的场合,如采用一般的平均值法,则干扰会平均到结果中去。限幅平均滤波法相当于“限幅滤波法”+“递推平均滤波法”

A、方法:每次采样到的新数据先进行限幅处理,再送入队列进行递推平均滤波处理

B、优点:融合了两种滤波法的优点,对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差。缺点:比较浪费RAM

C、适用范围:缓变信号已剪辑自: https://www.jianshu.com/p/38ed6ff1b8c0

姓名:王柯祎

学号:20021110373T

转自 :http://www.wtoutiao.com/p/1fe9dPI.html

【嵌牛导读】总结常用的一些数字滤波算法的特点和适用范围。

【嵌牛鼻子】1、克服大脉冲干扰的数字滤波法;2、抑制小幅度高频噪声的平均滤波法;3、复合滤波法

【嵌牛正文】

数字滤波(digital filtering):用数字设备,通过一定的算法,对信号进行处理,将某个频段的信号进行滤除,得到新的信号的这一过程叫做数字滤波。

数字滤波器可以分为两大部分:即经典滤波器和现代滤波器。经典滤波器就是假定输入信号x(n)中的有用成分和希望滤除成分分别位于不同的频带,因而我们通过一个线性系统就可以对噪声进行滤除,如果噪声和信号的频谱相互混叠,则经典滤波器得不到滤波的要求。通常有高通滤波器,低通滤波器,带通滤波器,带阻滤波器。现代滤波器是从含有噪声的信号估计出有用的信号和噪声信号。这种方法是把信号和噪声本身都视为随机信号,利用其统计特征,如自相关函数,互相关函数,自功率谱,互功率谱等引导出信号的估计算法,然后利用数字设备实现。目前主要有维纳滤波,卡尔曼滤波,自适应滤波等数字滤波器。

下面介绍常用的8种滤波方法:

(一)克服大脉冲干扰的数字滤波法:

克服由仪器外部环境偶然因素引起的突变性扰动或仪器内部不稳定引起误码等造成的尖脉冲干扰,是仪器数据处理的第一步。通常采用简单的非线性滤波法。

1、限幅滤波法(又称程序判断滤波法)限幅滤波是通过程序判断被测信号的变化幅度,从而消除缓变信号中的尖脉冲干扰。

A、方法:根据经验判断,确定两次采样允许的最大偏差值(设为A)每次检测到新值时判断:如果本次值与上次值之差A,则本次值无效,放弃本次值,用上次值代替本次值

B、优点:能有效克服因偶然因素引起的脉冲干扰。缺点:无法抑制那种周期性的干扰平滑度差。

C、适用范围:变化比较缓慢的被测量值

2、中位值滤波法

中位值滤波是一种典型的非线性滤波器,它运算简单,在滤除脉冲噪声的同时可以很好地保护信号的细节信息。

A、方法:连续采样N次(N取奇数)把N次采样值按大小排列(多采用冒泡法)取中间值为本次有效值

B、优点:能有效克服因偶然因素引起的波动(脉冲)干扰。缺点:对流量、速度等快速变化的参数不宜。

C、适用范围:对温度、液位的变化缓慢的被测参数有良好的滤波效果

(二)抑制小幅度高频噪声的平均滤波法

小幅度高频电子噪声:电子器件热噪声、A/D量化噪声等。通常采用具有低通特性的线性滤波器:算数平均滤波法、加权平均滤波法、滑动加权平均滤波法一阶滞后滤波法等。

3、算术平均滤波法算术平均滤波法是对N个连续采样值相加,然后取其算术平均值作为本次测量的滤波值。

A、方法:连续取N个采样值进行算术平均运算N值较大时:信号平滑度较高,但灵敏度较低N值较小时:信号平滑度较低,但灵敏度较高N值的选取:一般流量,N=12;压力:N=4

B、优点:对滤除混杂在被测信号上的随机干扰信号非常有效。被测信号的特点是有一个平均值,信号在某一数值范围附近上下波动。缺点:不易消除脉冲干扰引起的误差。对于采样速度较慢或要求数据更新率较高的实时系统,算术平均滤法无法使用的。比较浪费RAM

4、递推平均滤波法(又称滑动平均滤波法)

对于采样速度较慢或要求数据更新率较高的实时系统,算术平均滤法无法使用的。滑动平均滤波法把N个测量数据看成一个队列,队列的长度固定为N,每进行一次新的采样,把测量结果放入队尾,而去掉原来队首的一个数据,这样在队列中始终有N个“最新”的数据。

A、方法:把连续取N个采样值看成一个队列,队列的长度固定为N,每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)把队列中的N个数据进行算术平均运算,就可获得新的滤波结果N值的选取:流量,N=12;压力:N=4;液面,N=412;温度,N=14

B、优点:对周期性干扰有良好的抑制作用,平滑度高适用于高频振荡的系统。缺点:灵敏度低对偶然出现的脉冲性干扰的抑制作用较差不易消除由于脉冲干扰所引起的采样值偏差不适用于脉冲干扰比较严重的场合比较浪费RAM

5、加权递推平均滤波法

A、方法:是对递推平均滤波法的改进,即不同时刻的数据加以不同的权通常是,越接近现时刻的数据,权取得越大。给予新采样值的权系数越大,则灵敏度越高,但信号平滑度低

B、优点:适用于有较大纯滞后时间常数的对象和采样周期较短的系统。缺点:对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号不能迅速反应系统当前所受干扰的严重程度,滤波效果差

6、一阶滞后滤波法一阶低通数字滤波器是用软件的方法实现硬件的RC滤波,以抑制干扰信号。在模拟量输入通道中,常用一阶滞后RC模拟滤波器来抑制干扰。

用此种方法来实现对低频干扰时,首先遇到的问题是要求滤波器有大的时间常数(时间常数=RC)和高精度的RC网络。时间常数越大,要求RC值越大,其漏电流也必然增大,从而使RC网络精度下降。采用一阶滞后的数字滤波方法,能很好的克服这种模拟量滤波器的缺点,在滤波常数要求较大的场合,此法更适合。

A、方法:a=Tf/(Tf+T)Tf为滤波时间常数。T为采样周期本次滤波结果=(1-a)本次采样值+a上次滤波结果

B、优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合。缺点:相位滞后,灵敏度低滞后程度取决于a值大小不能消除滤波频率高于采样频率的1/2的干扰信号

(三)复合滤波法

在实际应用中,有时既要消除大幅度的脉冲干扰,有要做到数据平滑。因此常把前面介绍的两种以上的方法结合起来使用,形成复合滤波。去极值平均滤波算法:先用中值滤波算法滤除采样值中的脉冲性干扰,然后把剩余的各采样值进行平均滤波。连续采样N次,剔除其最大值和最小值,再求余下N-2个采样的平均值。显然,这种方法既能抑制随机干扰,又能滤除明显的脉冲干扰。

7、中位值平均滤波法(又称防脉冲干扰平均滤法)

中位值平均滤波法相当于“中位值滤波法”+“算术平均滤波法”。

A、方法:连续采样N个数据,去掉一个最大值和一个最小值然后计算N-2个数据的算术平均值N值的选取:3~14

B、优点:融合了两种滤波法的优点这种方法既能抑制随机干扰,又能滤除明显的脉冲干扰。缺点:测量速度较慢,和算术平均滤波法一样比较浪费RAM

8、限幅平均滤波法

在脉冲干扰较严重的场合,如采用一般的平均值法,则干扰会平均到结果中去。限幅平均滤波法相当于“限幅滤波法”+“递推平均滤波法”

A、方法:每次采样到的新数据先进行限幅处理,再送入队列进行递推平均滤波处理

B、优点:融合了两种滤波法的优点,对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差。缺点:比较浪费RAM

C、适用范围:缓变信号

1、限幅滤波法(又称程序判断滤波法)

/*
A、名称:限幅滤波法(又称程序判断滤波法)
B、方法:
    根据经验判断,确定两次采样允许的最大偏差值(设为A),
    每次检测到新值时判断:
    如果本次值与上次值之差<=A,则本次值有效,
    如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值。
C、优点:
    能有效克服因偶然因素引起的脉冲干扰。
D、缺点:
    无法抑制那种周期性的干扰。
    平滑度差。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;
int Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Value = Filter_Value;          // 最近一次有效采样的值,该变量为全局变量
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 限幅滤波法(又称程序判断滤波法)
#define FILTER_A 1
int Filter() {
  int NewValue;
  NewValue = Get_AD();
  if(((NewValue - Value) > FILTER_A) || ((Value - NewValue) > FILTER_A))
    return Value;
  else
    return NewValue;
}

/*
A、名称:限幅滤波法(又称程序判断滤波法)
B、方法:
    根据经验判断,确定两次采样允许的最大偏差值(设为A),
    每次检测到新值时判断:
    如果本次值与上次值之差<=A,则本次值有效,
    如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值。
C、优点:
    能有效克服因偶然因素引起的脉冲干扰。
D、缺点:
    无法抑制那种周期性的干扰。
    平滑度差。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;
int Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Value = Filter_Value;          // 最近一次有效采样的值,该变量为全局变量
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 限幅滤波法(又称程序判断滤波法)
#define FILTER_A 1
int Filter() {
  int NewValue;
  NewValue = Get_AD();
  if(((NewValue - Value) > FILTER_A) || ((Value - NewValue) > FILTER_A))
    return Value;
  else
    return NewValue;
}

2、中位值滤波法

/*
A、名称:中位值滤波法
B、方法:
    连续采样N次(N取奇数),把N次采样值按大小排列,
    取中间值为本次有效值。
C、优点:
    能有效克服因偶然因素引起的波动干扰;
    对温度、液位的变化缓慢的被测参数有良好的滤波效果。
D、缺点:
    对流量、速度等快速变化的参数不宜。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 中位值滤波法
#define FILTER_N 101
int Filter() {
  int filter_buf[FILTER_N];
  int i, j;
  int filter_temp;
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  // 采样值从小到大排列(冒泡法)
  for(j = 0; j < FILTER_N - 1; j++) {
    for(i = 0; i < FILTER_N - 1 - j; i++) {
      if(filter_buf[i] > filter_buf[i + 1]) {
        filter_temp = filter_buf[i];
        filter_buf[i] = filter_buf[i + 1];
        filter_buf[i + 1] = filter_temp;
      }
    }
  }
  return filter_buf[(FILTER_N - 1) / 2];
}

3、算术平均滤波法

/*
A、名称:算术平均滤波法
B、方法:
    连续取N个采样值进行算术平均运算:
    N值较大时:信号平滑度较高,但灵敏度较低;
    N值较小时:信号平滑度较低,但灵敏度较高;
    N值的选取:一般流量,N=12;压力:N=4。
C、优点:
    适用于对一般具有随机干扰的信号进行滤波;
    这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
D、缺点:
    对于测量速度较慢或要求数据计算速度较快的实时控制不适用;
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 算术平均滤波法
#define FILTER_N 12
int Filter() {
  int i;
  int filter_sum = 0;
  for(i = 0; i < FILTER_N; i++) {
    filter_sum += Get_AD();
    delay(1);
  }
  return (int)(filter_sum / FILTER_N);
}
/*
A、名称:算术平均滤波法
B、方法:
    连续取N个采样值进行算术平均运算:
    N值较大时:信号平滑度较高,但灵敏度较低;
    N值较小时:信号平滑度较低,但灵敏度较高;
    N值的选取:一般流量,N=12;压力:N=4。
C、优点:
    适用于对一般具有随机干扰的信号进行滤波;
    这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
D、缺点:
    对于测量速度较慢或要求数据计算速度较快的实时控制不适用;
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 算术平均滤波法
#define FILTER_N 12
int Filter() {
  int i;
  int filter_sum = 0;
  for(i = 0; i < FILTER_N; i++) {
    filter_sum += Get_AD();
    delay(1);
  }
  return (int)(filter_sum / FILTER_N);
}

4、递推平均滤波法(又称滑动平均滤波法)

/*
A、名称:递推平均滤波法(又称滑动平均滤波法)
B、方法:
    把连续取得的N个采样值看成一个队列,队列的长度固定为N,
    每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则),
    把队列中的N个数据进行算术平均运算,获得新的滤波结果。
    N值的选取:流量,N=12;压力,N=4;液面,N=4-12;温度,N=1-4。
C、优点:
    对周期性干扰有良好的抑制作用,平滑度高;
    适用于高频振荡的系统。
D、缺点:
    灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差;
    不易消除由于脉冲干扰所引起的采样值偏差;
    不适用于脉冲干扰比较严重的场合;
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 递推平均滤波法(又称滑动平均滤波法)
#define FILTER_N 12
int filter_buf[FILTER_N + 1];
int Filter() {
  int i;
  int filter_sum = 0;
  filter_buf[FILTER_N] = Get_AD();
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = filter_buf[i + 1]; // 所有数据左移,低位仍掉
    filter_sum += filter_buf[i];
  }
  return (int)(filter_sum / FILTER_N);
}
/*
A、名称:递推平均滤波法(又称滑动平均滤波法)
B、方法:
    把连续取得的N个采样值看成一个队列,队列的长度固定为N,
    每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则),
    把队列中的N个数据进行算术平均运算,获得新的滤波结果。
    N值的选取:流量,N=12;压力,N=4;液面,N=4-12;温度,N=1-4。
C、优点:
    对周期性干扰有良好的抑制作用,平滑度高;
    适用于高频振荡的系统。
D、缺点:
    灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差;
    不易消除由于脉冲干扰所引起的采样值偏差;
    不适用于脉冲干扰比较严重的场合;
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 递推平均滤波法(又称滑动平均滤波法)
#define FILTER_N 12
int filter_buf[FILTER_N + 1];
int Filter() {
  int i;
  int filter_sum = 0;
  filter_buf[FILTER_N] = Get_AD();
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = filter_buf[i + 1]; // 所有数据左移,低位仍掉
    filter_sum += filter_buf[i];
  }
  return (int)(filter_sum / FILTER_N);
}

5、中位值平均滤波法(又称防脉冲干扰平均滤波法)

/*
A、名称:中位值平均滤波法(又称防脉冲干扰平均滤波法)
B、方法:
    采一组队列去掉最大值和最小值后取平均值,
    相当于“中位值滤波法”+“算术平均滤波法”。
    连续采样N个数据,去掉一个最大值和一个最小值,
    然后计算N-2个数据的算术平均值。
    N值的选取:3-14。
C、优点:
    融合了“中位值滤波法”+“算术平均滤波法”两种滤波法的优点。
    对于偶然出现的脉冲性干扰,可消除由其所引起的采样值偏差。
    对周期干扰有良好的抑制作用。
    平滑度高,适于高频振荡的系统。
D、缺点:
    计算速度较慢,和算术平均滤波法一样。
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法1)
#define FILTER_N 100
int Filter() {
  int i, j;
  int filter_temp, filter_sum = 0;
  int filter_buf[FILTER_N];
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  // 采样值从小到大排列(冒泡法)
  for(j = 0; j < FILTER_N - 1; j++) {
    for(i = 0; i < FILTER_N - 1 - j; i++) {
      if(filter_buf[i] > filter_buf[i + 1]) {
        filter_temp = filter_buf[i];
        filter_buf[i] = filter_buf[i + 1];
        filter_buf[i + 1] = filter_temp;
      }
    }
  }
  // 去除最大最小极值后求平均
  for(i = 1; i < FILTER_N - 1; i++) filter_sum += filter_buf[i];
  return filter_sum / (FILTER_N - 2);
}


//  中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法2)
/*
#define FILTER_N 100
int Filter() {
  int i;
  int filter_sum = 0;
  int filter_max, filter_min;
  int filter_buf[FILTER_N];
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  filter_max = filter_buf[0];
  filter_min = filter_buf[0];
  filter_sum = filter_buf[0];
  for(i = FILTER_N - 1; i > 0; i--) {
    if(filter_buf[i] > filter_max)
      filter_max=filter_buf[i];
    else if(filter_buf[i] < filter_min)
      filter_min=filter_buf[i];
    filter_sum = filter_sum + filter_buf[i];
    filter_buf[i] = filter_buf[i - 1];
  }
  i = FILTER_N - 2;
  filter_sum = filter_sum - filter_max - filter_min + i / 2; // +i/2 的目的是为了四舍五入
  filter_sum = filter_sum / i;
  return filter_sum;
}*/
/*
A、名称:中位值平均滤波法(又称防脉冲干扰平均滤波法)
B、方法:
    采一组队列去掉最大值和最小值后取平均值,
    相当于“中位值滤波法”+“算术平均滤波法”。
    连续采样N个数据,去掉一个最大值和一个最小值,
    然后计算N-2个数据的算术平均值。
    N值的选取:3-14。
C、优点:
    融合了“中位值滤波法”+“算术平均滤波法”两种滤波法的优点。
    对于偶然出现的脉冲性干扰,可消除由其所引起的采样值偏差。
    对周期干扰有良好的抑制作用。
    平滑度高,适于高频振荡的系统。
D、缺点:
    计算速度较慢,和算术平均滤波法一样。
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法1)
#define FILTER_N 100
int Filter() {
  int i, j;
  int filter_temp, filter_sum = 0;
  int filter_buf[FILTER_N];
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  // 采样值从小到大排列(冒泡法)
  for(j = 0; j < FILTER_N - 1; j++) {
    for(i = 0; i < FILTER_N - 1 - j; i++) {
      if(filter_buf[i] > filter_buf[i + 1]) {
        filter_temp = filter_buf[i];
        filter_buf[i] = filter_buf[i + 1];
        filter_buf[i + 1] = filter_temp;
      }
    }
  }
  // 去除最大最小极值后求平均
  for(i = 1; i < FILTER_N - 1; i++) filter_sum += filter_buf[i];
  return filter_sum / (FILTER_N - 2);
}


//  中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法2)
/*
#define FILTER_N 100
int Filter() {
  int i;
  int filter_sum = 0;
  int filter_max, filter_min;
  int filter_buf[FILTER_N];
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  filter_max = filter_buf[0];
  filter_min = filter_buf[0];
  filter_sum = filter_buf[0];
  for(i = FILTER_N - 1; i > 0; i--) {
    if(filter_buf[i] > filter_max)
      filter_max=filter_buf[i];
    else if(filter_buf[i] < filter_min)
      filter_min=filter_buf[i];
    filter_sum = filter_sum + filter_buf[i];
    filter_buf[i] = filter_buf[i - 1];
  }
  i = FILTER_N - 2;
  filter_sum = filter_sum - filter_max - filter_min + i / 2; // +i/2 的目的是为了四舍五入
  filter_sum = filter_sum / i;
  return filter_sum;
}*/

6、限幅平均滤波法

/*
A、名称:限幅平均滤波法
B、方法:
    相当于“限幅滤波法”+“递推平均滤波法”;
    每次采样到的新数据先进行限幅处理,
    再送入队列进行递推平均滤波处理。
C、优点:
    融合了两种滤波法的优点;
    对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差。
D、缺点:
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/

#define FILTER_N 12
int Filter_Value;
int filter_buf[FILTER_N];

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  filter_buf[FILTER_N - 2] = 300;
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 限幅平均滤波法
#define FILTER_A 1
int Filter() {
  int i;
  int filter_sum = 0;
  filter_buf[FILTER_N - 1] = Get_AD();
  if(((filter_buf[FILTER_N - 1] - filter_buf[FILTER_N - 2]) > FILTER_A) || ((filter_buf[FILTER_N - 2] - filter_buf[FILTER_N - 1]) > FILTER_A))
    filter_buf[FILTER_N - 1] = filter_buf[FILTER_N - 2];
  for(i = 0; i < FILTER_N - 1; i++) {
    filter_buf[i] = filter_buf[i + 1];
    filter_sum += filter_buf[i];
  }
  return (int)filter_sum / (FILTER_N - 1);
}

7、一阶滞后滤波法

/*
A、名称:一阶滞后滤波法
B、方法:
    取a=0-1,本次滤波结果=(1-a)*本次采样值+a*上次滤波结果。
C、优点:
    对周期性干扰具有良好的抑制作用;
    适用于波动频率较高的场合。
D、缺点:
    相位滞后,灵敏度低;
    滞后程度取决于a值大小;
    不能消除滤波频率高于采样频率1/2的干扰信号。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;
int Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 一阶滞后滤波法
#define FILTER_A 0.01
int Filter() {
  int NewValue;
  NewValue = Get_AD();
  Value = (int)((float)NewValue * FILTER_A + (1.0 - FILTER_A) * (float)Value);
  return Value;
}

8、加权递推平均滤波法

/*
A、名称:加权递推平均滤波法
B、方法:
    是对递推平均滤波法的改进,即不同时刻的数据加以不同的权;
    通常是,越接近现时刻的数据,权取得越大。
    给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低。
C、优点:
    适用于有较大纯滞后时间常数的对象,和采样周期较短的系统。
D、缺点:
    对于纯滞后时间常数较小、采样周期较长、变化缓慢的信号;
    不能迅速反应系统当前所受干扰的严重程度,滤波效果差。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 加权递推平均滤波法
#define FILTER_N 12
int coe[FILTER_N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};    // 加权系数表
int sum_coe = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12; // 加权系数和
int filter_buf[FILTER_N + 1];
int Filter() {
  int i;
  int filter_sum = 0;
  filter_buf[FILTER_N] = Get_AD();
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = filter_buf[i + 1]; // 所有数据左移,低位仍掉
    filter_sum += filter_buf[i] * coe[i];
  }
  filter_sum /= sum_coe;
  return filter_sum;
}

9、消抖滤波法

/*
A、名称:消抖滤波法
B、方法:
    设置一个滤波计数器,将每次采样值与当前有效值比较:
    如果采样值=当前有效值,则计数器清零;
    如果采样值<>当前有效值,则计数器+1,并判断计数器是否>=上限N(溢出);
    如果计数器溢出,则将本次值替换当前有效值,并清计数器。
C、优点:
    对于变化缓慢的被测参数有较好的滤波效果;
    可避免在临界值附近控制器的反复开/关跳动或显示器上数值抖动。
D、缺点:
    对于快速变化的参数不宜;
    如果在计数器溢出的那一次采样到的值恰好是干扰值,则会将干扰值当作有效值导入系统。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;
int Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 消抖滤波法
#define FILTER_N 12
int i = 0;
int Filter() {
  int new_value;
  new_value = Get_AD();
  if(Value != new_value) {
    i++;
    if(i > FILTER_N) {
      i = 0;
      Value = new_value;
    }
  }
  else
    i = 0;
  return Value;
}

10、限幅消抖滤波法

/*
A、名称:限幅消抖滤波法
B、方法:
    相当于“限幅滤波法”+“消抖滤波法”;
    先限幅,后消抖。
C、优点:
    继承了“限幅”和“消抖”的优点;
    改进了“消抖滤波法”中的某些缺陷,避免将干扰值导入系统。
D、缺点:
    对于快速变化的参数不宜。
E、整理:shenhaiyu 2013-11-01
*/

int Filter_Value;
int Value;

void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}

void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}

// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}

// 限幅消抖滤波法
#define FILTER_A 1
#define FILTER_N 5
int i = 0;
int Filter() {
  int NewValue;
  int new_value;
  NewValue = Get_AD();
  if(((NewValue - Value) > FILTER_A) || ((Value - NewValue) > FILTER_A))
    new_value = Value;
  else
    new_value = NewValue;
  if(Value != new_value) {
    i++;
    if(i > FILTER_N) {
      i = 0;
      Value = new_value;
    }
  }
  else
    i = 0;
  return Value;
}

11、卡尔曼滤波(非扩展卡尔曼)

#include <Wire.h> // I2C library, gyroscope

// Accelerometer ADXL345
#define ACC (0x53)    //ADXL345 ACC address
#define A_TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)


// Gyroscope ITG3200 
#define GYRO 0x68 // gyro address, binary = 11101000 when AD0 is connected to Vcc (see schematics of your breakout board)
#define G_SMPLRT_DIV 0x15   
#define G_DLPF_FS 0x16   
#define G_INT_CFG 0x17
#define G_PWR_MGM 0x3E

#define G_TO_READ 8 // 2 bytes for each axis x, y, z


// offsets are chip specific. 
int a_offx = 0;
int a_offy = 0;
int a_offz = 0;

int g_offx = 0;
int g_offy = 0;
int g_offz = 0;



char str[512]; 

void initAcc() {
  //Turning on the ADXL345
  writeTo(ACC, 0x2D, 0);      
  writeTo(ACC, 0x2D, 16);
  writeTo(ACC, 0x2D, 8);
  //by default the device is in +-2g range reading
}

void getAccelerometerData(int* result) {
  int regAddress = 0x32;    //first axis-acceleration-data register on the ADXL345
  byte buff[A_TO_READ];
  
  readFrom(ACC, regAddress, A_TO_READ, buff); //read the acceleration data from the ADXL345
  
  //each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!
  //thus we are converting both bytes in to one int
  result[0] = (((int)buff[1]) << 8) | buff[0] + a_offx;   
  result[1] = (((int)buff[3]) << 8) | buff[2] + a_offy;
  result[2] = (((int)buff[5]) << 8) | buff[4] + a_offz;
}

//initializes the gyroscope
void initGyro()
{
  /*****************************************
  * ITG 3200
  * power management set to:
  * clock select = internal oscillator
  *     no reset, no sleep mode
  *   no standby mode
  * sample rate to = 125Hz
  * parameter to +/- 2000 degrees/sec
  * low pass filter = 5Hz
  * no interrupt
  ******************************************/
  writeTo(GYRO, G_PWR_MGM, 0x00);
  writeTo(GYRO, G_SMPLRT_DIV, 0x07); // EB, 50, 80, 7F, DE, 23, 20, FF
  writeTo(GYRO, G_DLPF_FS, 0x1E); // +/- 2000 dgrs/sec, 1KHz, 1E, 19
  writeTo(GYRO, G_INT_CFG, 0x00);
}


void getGyroscopeData(int * result)
{
  /**************************************
  Gyro ITG-3200 I2C
  registers:
  temp MSB = 1B, temp LSB = 1C
  x axis MSB = 1D, x axis LSB = 1E
  y axis MSB = 1F, y axis LSB = 20
  z axis MSB = 21, z axis LSB = 22
  *************************************/

  int regAddress = 0x1B;
  int temp, x, y, z;
  byte buff[G_TO_READ];
  
  readFrom(GYRO, regAddress, G_TO_READ, buff); //read the gyro data from the ITG3200
  
  result[0] = ((buff[2] << 8) | buff[3]) + g_offx;
  result[1] = ((buff[4] << 8) | buff[5]) + g_offy;
  result[2] = ((buff[6] << 8) | buff[7]) + g_offz;
  result[3] = (buff[0] << 8) | buff[1]; // temperature
  
}


float xz=0,yx=0,yz=0;
float p_xz=1,p_yx=1,p_yz=1;
float q_xz=0.0025,q_yx=0.0025,q_yz=0.0025;
float k_xz=0,k_yx=0,k_yz=0;
float r_xz=0.25,r_yx=0.25,r_yz=0.25;
  //int acc_temp[3];
  //float acc[3];
  int acc[3];
  int gyro[4];
  float Axz;
  float Ayx;
  float Ayz;
  float t=0.025;
void setup()
{
  Serial.begin(9600);
  Wire.begin();
  initAcc();
  initGyro();
  
}

//unsigned long timer = 0;
//float o;
void loop()
{
  
  getAccelerometerData(acc);
  getGyroscopeData(gyro);
  //timer = millis();
  sprintf(str, "%d,%d,%d,%d,%d,%d", acc[0],acc[1],acc[2],gyro[0],gyro[1],gyro[2]);
  
  //acc[0]=acc[0];
  //acc[2]=acc[2];
  //acc[1]=acc[1];
  //r=sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]);
  gyro[0]=gyro[0]/ 14.375;
  gyro[1]=gyro[1]/ (-14.375);
  gyro[2]=gyro[2]/ 14.375;
  
   
  Axz=(atan2(acc[0],acc[2]))*180/PI;
  Ayx=(atan2(acc[0],acc[1]))*180/PI;
  /*if((acc[0]!=0)&&(acc[1]!=0))
    {
      Ayx=(atan2(acc[0],acc[1]))*180/PI;
    }
    else
    {
      Ayx=t*gyro[2];
    }*/
  Ayz=(atan2(acc[1],acc[2]))*180/PI;
  
  
 //kalman filter
  calculate_xz();
  calculate_yx();
  calculate_yz();
  
  //sprintf(str, "%d,%d,%d", xz_1, xy_1, x_1);
  //Serial.print(xz);Serial.print(",");
  //Serial.print(yx);Serial.print(",");
  //Serial.print(yz);Serial.print(",");
  //sprintf(str, "%d,%d,%d,%d,%d,%d", acc[0],acc[1],acc[2],gyro[0],gyro[1],gyro[2]);
  //sprintf(str, "%d,%d,%d",gyro[0],gyro[1],gyro[2]);
    Serial.print(Axz);Serial.print(",");
    //Serial.print(Ayx);Serial.print(",");
    //Serial.print(Ayz);Serial.print(",");
  //Serial.print(str);
  //o=gyro[2];//w=acc[2];
  //Serial.print(o);Serial.print(",");
  //Serial.print(w);Serial.print(",");
  Serial.print("\n");

  
  //delay(50);
}
void calculate_xz()
{

 xz=xz+t*gyro[1];
 p_xz=p_xz+q_xz;
 k_xz=p_xz/(p_xz+r_xz);
 xz=xz+k_xz*(Axz-xz);
 p_xz=(1-k_xz)*p_xz;
}
void calculate_yx()
{
  
  yx=yx+t*gyro[2];
  p_yx=p_yx+q_yx;
  k_yx=p_yx/(p_yx+r_yx);
  yx=yx+k_yx*(Ayx-yx);
  p_yx=(1-k_yx)*p_yx;

}
void calculate_yz()
{
  yz=yz+t*gyro[0];
  p_yz=p_yz+q_yz;
  k_yz=p_yz/(p_yz+r_yz);
  yz=yz+k_yz*(Ayz-yz);
  p_yz=(1-k_yz)*p_yz;
 
}


//---------------- Functions
//Writes val to address register on ACC
void writeTo(int DEVICE, byte address, byte val) {
   Wire.beginTransmission(DEVICE); //start transmission to ACC 
   Wire.write(address);        // send register address
   Wire.write(val);        // send value to write
   Wire.endTransmission(); //end transmission
}


//reads num bytes starting from address register on ACC in to buff array
void readFrom(int DEVICE, byte address, int num, byte buff[]) {
  Wire.beginTransmission(DEVICE); //start transmission to ACC 
  Wire.write(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  
  Wire.beginTransmission(DEVICE); //start transmission to ACC
  Wire.requestFrom(DEVICE, num);    // request 6 bytes from ACC
  
  int i = 0;
  while(Wire.available())    //ACC may send less than requested (abnormal)
  { 
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission
}
  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
嵌入式开发是指将计算机硬件软件结合起来开发嵌入式系统的一项技术。在嵌入式开发硬件电路知识是非常重要的。 硬件电路知识是指对数字电路、模拟电路和信号处理等方面的理解和应用能力。在嵌入式开发,我们需要掌握各种电子元器件的功能和使用方法,了解各种电路的工作原理,以及掌握电路设计和调试的技巧。 在硬件电路知识,数字电路是非常重要的一部分。数字电路一般采用二进制数字来表示信息,通过逻辑门和触发器等组合电路来实现不同的逻辑功能。对于嵌入式开发来说,我们需要掌握数字信号的传输和处理方法,了解各种数字电路的设计和调试技术。 模拟电路也是嵌入式开发重要的一部分。模拟电路一般处理的是连续变化的信号,如声音、图像等。在嵌入式开发,我们需要了解模拟信号的采集和处理方法,掌握各种放大器、滤波器和混频器等模拟电路的设计和调试技术。 此外,信号处理也是嵌入式开发不可或缺的一部分。信号处理主要涉及到数字信号的处理和分析,如滤波、采样、编码等。在嵌入式开发,我们需要掌握各种信号处理的算法和方法,了解信号处理器的工作原理和使用方法。 总之,嵌入式开发硬件电路知识是非常重要的,它涉及到嵌入式系统的设计和开发的方方面面。只有掌握了硬件电路知识,才能更好地理解和应用嵌入式开发技术,并能够设计和调试出高质量的嵌入式系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小熊coder

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

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

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

打赏作者

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

抵扣说明:

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

余额充值