在该基础上,我们再演变出一种带死区和限幅控制的队列平均值实用算法。 采样值 C、累加器 S,平均值 A,采样次数 N
传统的平均值滤波算法: S = C(1) + C(2) + ... + C(N) A = S / N 需要用循环来计算累加和,比较耗时,C(1~N)是缓存,随采样数N增大,所需内存量也增大
向队列平均值算法推进: S = C(1) + C(2) + ... + C(N) (第一次) C(x) = C(x + 1) (队列前移) C(N) = C S = S - C(1) + C(N) A = S / N 运算量有所改进(用指针维护循环队列,不实际移动数据),占用内存问题不变
鬼斧神工算法: 初始化:A=初始值,S=A*N S = S - A + C A = S / N 就这么简单,三个变量(N可以是常数),只要 S 的量程足够,N可以任意调整。 可以看出,此算法是从队列平均值算法演变而来,因没有了队列,每次计算时不知道该丢弃的最老的一个采样值是多少,这里用了个替代的办法,丢弃上次计算出的平均值。 去掉了缓存维护,节省内存空间,同时也将运算量压缩到了最小,执行效率非常高。调试时容易修改采样数。
优化算法: 此算法的核心思想还是平均值滤波,虽然改进了运算量和内存占用,但同样继承了平均值滤波法 N 值较大时平滑度好,反应迟钝的特点。 为此,对算法引入 S7-200 系统滤波程序中死区的概念:采样值偏差在死区范围内时,进行滤波计算,采样值偏差在死区范围以外时直接使用采样值,达到快速反应的效果。 再溶合限幅滤波法去掉偶然的干扰脉冲:采样值偏差在限幅范围内时,进行滤波计算,采样值偏差在限幅范围以外时直接丢弃,使用上次滤波输出值。显然,限幅值应该大于死区值。
本文只是提出一种算法而已,仅供参考 二楼的方法当然也是一种好方法,但那只是代码上的技巧(只是优化了内存占用,运算量跟先采集再用循环计算是相当的),而不是算法本身的优劣。即使按二楼的方法进行代码优化,大概也不会比下面的再简洁多少: +* C, S LD*>= n, 10 mov* S, A /* n, A mov* 0, n mov* 0, S not inc* n
而本文的算法: +* C, S -* A, S mov* S, A /* 10, A 只需要3个变量,4条语句,不需做采样计数与比较,效率不言自明 而且更重要的区别是算法本身,本文的方法是基于队列平均值,它用相对简洁的代码利用了队列平均值算法的精髓。假如采样时间为100mS,二楼的方法要每隔1S才得到一个有效的平均值,而本算法每100mS就可以得到一个有效的平均值。 本文主要是比较算法本身的优劣,而不是代码,首先要算法好,代码才可能更简洁。
举一个简单的例子来检测一下你的算法 采集N=2次,每次采集假设为A=10,数值总和为S=20, 假设下次采集数据为11,根据你的公式: S = S - A + C A = S / N S=20-10+11=21 A=21/2=11.5 再一次采集为9,再次计算: S=21-10.5+9=19.5 A=19.5/2=9.75 但是实际上两次采集平均值为(9+11)/2=10,好象与你公式差了好多? 还是不明白你的算法!