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

# A、方法:

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

# B、优点:

  1. 能有效克服因偶然因素引起的脉冲干扰

# C、缺点:

  1. 无法抑制那种周期性的干扰
  2. 平滑度差

# D、代码:

#if LIMITING
Data_Typedef Limiting_Filter( Data_Typedef Value, int Range )
{
    Data_Typedef new_value;
    new_value = Get_AD();
    DUBUG_PRINTF("A%f\r\n", new_value);
    if((new_value - Value > Range)
            || (Value - new_value > Range))
    {
        return Value;
    }
    return new_value;
}
#endif /* LIMITING */

# 中位值滤波法

# A、方法:

  1. 连续采样 N 次(N 取奇数)
  2. 把 N 次采样值按大小排列
  3. 取中间值为本次有效值

# B、优点:

  1. 能有效克服因偶然因素引起的波动干扰
  2. 对温度、液位的变化缓慢的被测参数有良好的滤波效果

# C、缺点:

  1. 对流量、速度等快速变化的参数不宜

# D、代码:

#if MEDIAN
Data_Typedef Median_Filter( int Count )
{
    int i,j;
    Data_Typedef temp;
    Data_Typedef *str;
    if(0 == Count % 2)
        Count++;
    str = (Data_Typedef*)malloc(Count * sizeof(Data_Typedef));
    if(str != NULL) {
        for(i = 0; i < Count; i++) {
            temp = Get_AD();
            *(str + i) = temp;
            DUBUG_PRINTF("A%f\r\n", temp);
            Delay(0x10F);
        }
        /* 冒泡排序 */
        for(j = 0; j < Count - 1; j++) {
            for(i = 0; i < Count - j - 1; i++) {
                if(*(str + i) > *(str + i + 1)) {
                    temp = *(str + i);
                    *(str + i) = *(str + i + 1);
                    *(str + i + 1) = temp;
                }
            }
        }
    } else {
        return -1;
    }
    temp = *(str + (Count-1)/2);
    free(str);
    return temp;
}
#endif /* MEDIAN */

# 算术平均滤波法

# A、方法:

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

# B、优点:

  1. 适用于对一般具有随机干扰的信号进行滤波
  2. 这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动

# C、缺点:

  1. 对于测量速度较慢或要求数据计算速度较快的实时控制不适用
  2. 比较浪费 RAM

# D、代码:

#if MEAN
Data_Typedef Mean_Filter( int Count )
{
    int i;
    Data_Typedef temp;
    Data_Typedef sum = 0;
    for(i = 0; i < Count; i++) {
        temp = Get_AD();
        sum += temp;
        DUBUG_PRINTF("A%f\r\n", temp);
        Delay(0x10F);
    }
    return (Data_Typedef)(sum / Count);
}
#endif /* MEAN */

# 递推平均滤波法

# A、方法:

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

# B、优点:

  1. 对周期性干扰有良好的抑制作用,平滑度高
  2. 适用于高频振荡的系统

# C、缺点:

  1. 灵敏度低
  2. 对偶然出现的脉冲性干扰的抑制作用较差
  3. 不易消除由于脉冲干扰所引起的采样值偏差
  4. 不适用于脉冲干扰比较严重的场合
  5. 比较浪费 RAM

# D、代码:

#if RECURSIVE_MEAN
Data_Typedef Recursive_Mean_Filter( int Count )
{
    static int Start = 0;
    static int Num = 0;
    int i;
    Data_Typedef temp;
    Data_Typedef sum = 0;
    Data_Typedef *str;
    if(0 == Start) {
        Start = Count;
        str = (Data_Typedef*)calloc(Count, sizeof(Data_Typedef));
    } else if(Start != Count) {
        Start = Count;
        str = (Data_Typedef*)realloc(str, Count);		// 重新分配
    }
    if(str != NULL) {
        temp = Get_AD();
        *(str + Num++) = temp;
        DUBUG_PRINTF("A%f\r\n", temp);
        // 覆盖最早采样的数据,相当于递推数据 FIFO
        if(Num >= Count)
            Num = 0;
        for(i = 0; i < Count; i++) {
            sum += *(str + i);
        }
    } else {
        return -1;
    }
    return (Data_Typedef)(sum / Count);
}
#endif /* RECURSIVE_MEAN */

# 中位值平均滤波法

# A、方法:

  1. 相当于 “中位值滤波法” + “算术平均滤波法”
  2. 连续采样 N 个数据,去掉一个最大值和一个最小值
  3. 然后计算 N-2 个数据的算术平均值
  4. N 值的选取:3~14

# B、优点:

  1. 融合了两种滤波法的优点
  2. 对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差

# C、缺点:

  1. 测量速度较慢,和算术平均滤波法一样
  2. 比较浪费 RAM

# D、代码:

#if MEDIAN_MEAN
Data_Typedef Median_Mean_Filter( int Count )
{
    int i,j;
    Data_Typedef temp;
    Data_Typedef sum = 0;
    Data_Typedef *str;
    if(0 == Count % 2)
        Count++;
    str = (Data_Typedef*)malloc(Count * sizeof(Data_Typedef));
    if(str != NULL) {
        for(i = 0; i < Count; i++) {
            temp = Get_AD();
            *(str + i) = temp;
            DUBUG_PRINTF("A%f\r\n", temp);
            Delay(0x10F);
        }
        for(j = 0; j < Count - 1; j++) {
            for(i = 0; i < Count - j - 1; i++) {
                if(*(str + i) > *(str + i + 1)) {
                    temp = *(str + i);
                    *(str + i) = *(str + i + 1);
                    *(str + i + 1) = temp;
                }
            }
        }
    } else {
        return -1;
    }
    /* 去除最大最小极值后求平均 */
    for(i = 1; i < Count - 1; i++)
        sum += *(str + i);
    free(str);
    return (Data_Typedef)(sum / (Count - 2));
}
#endif /* MEDIAN_MEAN */

# 限幅平均滤波法

# A、方法:

  1. 相当于 “限幅滤波法” + “递推平均滤波法”
  2. 每次采样到的新数据先进行限幅处理
  3. 再送入队列进行递推平均滤波处理

# B、优点:

  1. 融合了两种滤波法的优点
  2. 对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差

# C、缺点:

  1. 比较浪费 RAM

# D、代码:

#if LIMITING_MEAN
Data_Typedef Limiting_Mean_Filter( int Range, int Count )
{
    static int Start = 0;
    static int Num = 0;
    static Data_Typedef Value = 0;
    int i;
    Data_Typedef new_value;
    Data_Typedef sum = 0;
    Data_Typedef *str;
    if(0 == Start) {
        Start = Count;
        Value = Get_AD();
        str = (Data_Typedef*)calloc(Count, sizeof(Data_Typedef));
    } else if(Start != Count) {
        Start = Count;
        Value = Get_AD();
        str = (Data_Typedef*)realloc(str, Count);		// 重新分配
    }
    if(str != NULL) {
        new_value = Get_AD();
        if((new_value - Value > Range)
                || (Value - new_value > Range))
        {
            *(str + Num++) = Value;
        } else {
            *(str + Num++) = new_value;
            Value = new_value;
        }
        DUBUG_PRINTF("A%f\r\n", Value);
        if(Num >= Count)
            Num = 0;
        for(i = 0; i < Count; i++) {
            sum += *(str + i);
        }
    } else {
        return -1;
    }
    return (Data_Typedef)(sum / Count);
}
#endif /* LIMITING_MEAN */

# 一阶滞后滤波法

# A、方法:

  1. 取滤波系数 a=0~1
  2. 本次滤波结果 =(1-a)× 上次滤波结果 + a× 本次采样值

# B、优点:

  1. 对周期性干扰具有良好的抑制作用
  2. 适用于波动频率较高的场合

# C、缺点:

  1. 相位滞后,灵敏度低
  2. 滞后程度取决于 a 值大小
  3. 不能消除滤波频率高于采样频率的 1/2 的干扰信号

# D、代码:

#if LOW_PASS
Data_Typedef Low_Pass_Filter( Data_Typedef Value, float Factor )
{
    Data_Typedef new_value;
    new_value = Get_AD();
    DUBUG_PRINTF("A%f\r\n", new_value);
    new_value = (Data_Typedef)(new_value * Factor + (1.0f - Factor) * Value);
    return new_value;
}
#endif /* LOW_PASS */

# 加权递推平均滤波法

# A、方法:

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

# B、优点:

  1. 适用于有较大纯滞后时间常数的对象
  2. 和采样周期较短的系统

# C、缺点:

  1. 对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号
  2. 不能迅速反应系统当前所受干扰的严重程度,滤波效果差

# D、代码:

#if WEIGHTED_RECURSIVE_MEAN
Data_Typedef Weighted_Recursive_Mean_Filter( char *Weight_factor, int Count )
{
    static int Sum_coe;
    static int Start = 0;
    static int Num = 0;
    int i;
    Data_Typedef temp;
    Data_Typedef sum = 0;
    Data_Typedef *str;
    if(0 == Start) {
        Start = Count;
        str = (Data_Typedef*)calloc(Count, sizeof(Data_Typedef));
        for(i = 0; i < Count; i++) {
            Sum_coe += *(Weight_factor + i);
        }
    } else if(Start != Count) {
        Start = Count;
        str = (Data_Typedef*)realloc(str, Count);		// 重新分配
        for(i = 0; i < Count; i++) {
            Sum_coe += *(Weight_factor + i);
        }
    }
    if(str != NULL) {
        temp = Get_AD();
        *(str + Num++) = temp;
        DUBUG_PRINTF("A%f\r\n", temp);
        // 覆盖最早采样的数据,相当于递推数据 FIFO
        if(Num >= Count)
            Num = 0;
        for(i = 0; i < Count; i++) {
            sum += *(str + i) * *(Weight_factor + i);
        }
    } else {
        return -1;
    }
    return (Data_Typedef)(sum / Sum_coe);
}
#endif /* WEIGHTED_RECURSIVE_MEAN */

# 消抖滤波法

# A、方法:

  1. 设置一个滤波计数器
  2. 将每次采样值与当前有效值比较:
    如果采样值=当前有效值,则计数器清零
    如果采样值 <> 当前有效值,则计数器 + 1,并判断计数器是否>= 上限 N (溢出)
    如果计数器溢出,则将本次值替换当前有效值,并清计数器

# B、优点:

  1. 对于变化缓慢的被测参数有较好的滤波效果
  2. 可避免在临界值附近控制器的反复开 / 关跳动或显示器上数值抖动

# C、缺点:

  1. 对于快速变化的参数不宜
  2. 如果在计数器溢出的那一次采样到的值恰好是干扰值,则会将干扰值当作有效值导入系统

# D、代码:

#if DEBOUNCE
Data_Typedef Debounce_Filter( Data_Typedef Value, int Count )
{
    static int Num = 0;
    Data_Typedef new_value;
    new_value = Get_AD();
	DUBUG_PRINTF("A%f\r\n", new_value);
    if(Value != new_value) {
        Num++;
        if(Num > Count) {
            Num = 0;
            Value = new_value;
        }
    }
    else
        Num = 0;
    return Value;
}
#endif /* DEBOUNCE */

# 限幅消抖滤波法

# A、方法:

  1. 相当于 “限幅滤波法” + “消抖滤波法”
  2. 先限幅,后消抖

# B、优点:

  1. 继承了 “限幅” 和 “消抖” 的优点
  2. 改进了 “消抖滤波法” 中的某些缺陷,避免将干扰值导入系统

# C、缺点:

  1. 对于快速变化的参数不宜

# D、代码:

#if LIMITING_DEBOUNCE
Data_Typedef Limiter_Debounce_Filter( Data_Typedef Value, int Range, int Count )
{
    static int Num = 0;
    Data_Typedef new_value;
    new_value = Get_AD();
    DUBUG_PRINTF("A%f\r\n", new_value);
    if((new_value - Value > Range)
            || (Value - new_value > Range))
    {
        new_value = Value;
    }
	if(Value != new_value) {
        Num++;
        if(Num > Count) {
            Num = 0;
            Value = new_value;
        }
    }
    else
        Num = 0;
    return Value;
}
#endif /* LIMITING_DEBOUNCE */
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

夏沫の浅雨 微信支付

微信支付

夏沫の浅雨 支付宝

支付宝