【Launchpad 心得】launchpad课后练习十六之软件滤波

常见泽1   2012-6-11 15:49 楼主

launchpad课后练习十六之软件滤波

 

本文参考的《匠人笔记》里的十种软件滤波方法,这里只是滤波的简单介绍,不一定合理,高手绕道。版权属于《匠人笔记》

 

这里选用了其中的5种做了编程与测试,测试结果还算比较稳定与准确。当然滤波方法还有很多很多,下面只是其中的一部分而已。

 

本人也是初学者,里面难免有不合理之处,还望多多指教。

 

 

原理图

原理图数码管.JPG

1.JPG

 

课后练习十六之ADC软件滤波.pdf (215.99 KB)
(下载次数: 284, 2012-6-11 15:49 上传)

 

[ 本帖最后由 常见泽1 于 2012-6-11 15:56 编辑 ]

回复评论 (7)

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

   A、方法:

      根据经验判断,确定两次采样允许的最大偏差值(设为A

    每次检测到新值时判断:

    如果本次值与上次值之差<=A,则本次值有效

    如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值

  B、优点:

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

  C、缺点

    无法抑制周期性的干扰

    平滑度差

 

  1. #include <msp430g2452.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define A 2
    unsigned char i,j;
    long result[31],resultsum,resultend;
    uchar ge,shi,bai,qian;

    #define SER ( 1 << 1 ) //也是所谓的DS
    #define SRCLK ( 1 << 0 ) //也是所谓的SHCP
    #define RCLK ( 1 << 2 ) //也是所谓的STCP

    void delay_1ms(void)
    {
    unsigned int i;
    for (i=0;i<1000;i++);
    }
    void delay_nms(unsigned int n)
    {
    unsigned int i=0;
    for (i=0;i<n;i++)
    delay_1ms();
    }

    uchar table[]={ 0xC0,0xF9,0xA4,0xB0,
    0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,
    0xC6,0xA1,0x86,0x8E };
    void Write595(uchar data)
    {

    P2OUT &= ~RCLK;
    for( i=0;i<8;i++ )
    {
    if(data&0x80)
    {
    P2OUT |= SER;
    }
    else
    {
    P2OUT &= ~SER;
    }
    P2OUT &= ~SRCLK;
    P2OUT |= SRCLK;
    data <<= 1;
    }
    P2OUT |= RCLK;
    }

    void ADC_init(void)
    {
    P1SEL |= 0x01;
    ADC10CTL0 = SREF_1 + REFON + ADC10ON;
    ADC10AE0 |= 0x01; // P1.0 ADC option select
    ADC10CTL1 = INCH_0+ADC10SSEL_2;
    }

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1DIR |= (BIT2|BIT3|BIT4|BIT5);
    P2DIR |= 0xff;
    ADC_init();
    for(j=0;j<31;j++)
    {
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    while (ADC10CTL1 & ADC10BUSY); // ADC10BUSY?
    result[j] = ADC10MEM;
    if(j>=2)
    {
    if((result[j] - result[j-1]>A)||(result[j-1] - result[j]>A))
    resultsum = result[j-1];
    else
    resultsum = result[j];
    }
    }

    while(1)
    {
    //result = resultsum/30;
    resultend = resultsum*1500/1024;
    qian = resultend/1000;
    bai = resultend/100%10;
    shi = resultend/10%10;
    ge = resultend%10;
    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[ge]);
    P1OUT |= ( 1 << 2 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[shi]);
    P1OUT |= ( 1 << 3 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[bai]);
    P1OUT |= ( 1 << 4 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[qian]);
    P1OUT |= ( 1 << 5 );
    delay_nms(1);
    }
    }

点赞  2012-6-11 15:51

第2种:中位值滤波法

  A、方法:

    连续采样N次(N取奇数)

    把N次采样值按大小排列

    取中间值为本次有效值

  B、优点:

    能有效克服因偶然因素引起的波动干扰

    对温度、液位的变化缓慢的被测参数有良好的滤波效果

  C、缺点:

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

 

  1. #include <msp430g2452.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define X 31
    unsigned char i,j,k;
    long resultsum,temp;
    uint result[31];
    uchar ge,shi,bai,qian;

    #define SER ( 1 << 1 ) //也是所谓的DS
    #define SRCLK ( 1 << 0 ) //也是所谓的SHCP
    #define RCLK ( 1 << 2 ) //也是所谓的STCP

    void delay_1ms(void)
    {
    unsigned int i;
    for (i=0;i<1000;i++);
    }
    void delay_nms(unsigned int n)
    {
    unsigned int i=0;
    for (i=0;i<n;i++)
    delay_1ms();
    }

    uchar table[]={ 0xC0,0xF9,0xA4,0xB0,
    0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,
    0xC6,0xA1,0x86,0x8E };
    void Write595(uchar data)
    {

    P2OUT &= ~RCLK;
    for( i=0;i<8;i++ )
    {
    if(data&0x80)
    {
    P2OUT |= SER;
    }
    else
    {
    P2OUT &= ~SER;
    }
    P2OUT &= ~SRCLK;
    P2OUT |= SRCLK;
    data <<= 1;
    }
    P2OUT |= RCLK;
    }

    void ADC_init(void)
    {
    P1SEL |= 0x01;
    ADC10CTL0 = SREF_1 + REFON + ADC10ON;
    ADC10AE0 |= 0x01; // P1.0 ADC option select
    ADC10CTL1 = INCH_0+ADC10SSEL_2;
    }

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1DIR |= (BIT2|BIT3|BIT4|BIT5);
    P2DIR |= 0xff;
    ADC_init();
    for(j=0;j<X;j++)
    {
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    while (ADC10CTL1 & ADC10BUSY); // ADC10BUSY?
    result[j]= ADC10MEM;
    }

    for(j=0;j<X-1;j++)
    {
    for(k=0;k<X-j;k++)
    {
    if(result[k]>result[k+1])
    {
    temp = result[k];
    result[k] = result[k+1];
    result[k+1] = temp;
    }
    }
    }

    while(1)
    {
    //result = resultsum/30;
    //result = result*1500/1024;
    resultsum = result[(X-1)/2];
    resultsum = resultsum*1500/1024;
    qian = resultsum/1000;
    bai = resultsum/100%10;
    shi = resultsum/10%10;
    ge = resultsum%10;
    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[ge]);
    P1OUT |= ( 1 << 2 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[shi]);
    P1OUT |= ( 1 << 3 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[bai]);
    P1OUT |= ( 1 << 4 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[qian]);
    P1OUT |= ( 1 << 5 );
    delay_nms(1);
    }
    }

点赞  2012-6-11 15:52

算术平均滤波法

  A、方法:

    连续取N个采样值进行算术平均运算

    N值较大时:信号平滑度较高,但灵敏度较低

    N值较小时:信号平滑度较低,但灵敏度较高

    N值的选取:一般流量,N=12;压力:N=4

  B、优点:

    适用于对一般具有随机干扰的信号进行滤波

    这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动

  C、缺点:

    对于测量速度较慢或要求数据计算速度较快的实时控制不适用

    比较浪费RAM

 

  1. #include <msp430g2452.h>
    #define uchar unsigned char
    #define uint unsigned int

    unsigned char i,j;
    long result,resultsum;
    uchar ge,shi,bai,qian;

    #define SER ( 1 << 1 ) //也是所谓的DS
    #define SRCLK ( 1 << 0 ) //也是所谓的SHCP
    #define RCLK ( 1 << 2 ) //也是所谓的STCP

    void delay_1ms(void)
    {
    unsigned int i;
    for (i=0;i<1000;i++);
    }
    void delay_nms(unsigned int n)
    {
    unsigned int i=0;
    for (i=0;i<n;i++)
    delay_1ms();
    }

    uchar table[]={ 0xC0,0xF9,0xA4,0xB0,
    0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,
    0xC6,0xA1,0x86,0x8E };
    void Write595(uchar data)
    {

    P2OUT &= ~RCLK;
    for( i=0;i<8;i++ )
    {
    if(data&0x80)
    {
    P2OUT |= SER;
    }
    else
    {
    P2OUT &= ~SER;
    }
    P2OUT &= ~SRCLK;
    P2OUT |= SRCLK;
    data <<= 1;
    }
    P2OUT |= RCLK;
    }

    void ADC_init(void)
    {
    P1SEL |= 0x01;
    ADC10CTL0 = SREF_1 + REFON + ADC10ON;
    ADC10AE0 |= 0x01; // P1.0 ADC option select
    ADC10CTL1 = INCH_0+ADC10SSEL_2;
    }

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1DIR |= (BIT2|BIT3|BIT4|BIT5);
    P2DIR |= 0xff;
    ADC_init();
    for(j=0;j<31;j++)
    {
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    while (ADC10CTL1 & ADC10BUSY); // ADC10BUSY?
    if(j!=0)
    {
    resultsum += ADC10MEM;
    }
    }

    while(1)
    {
    result = resultsum/30;
    result = result*1500/1024;
    qian = result/1000;
    bai = result/100%10;
    shi = result/10%10;
    ge = result%10;
    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[ge]);
    P1OUT |= ( 1 << 2 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[shi]);
    P1OUT |= ( 1 << 3 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[bai]);
    P1OUT |= ( 1 << 4 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[qian]);
    P1OUT |= ( 1 << 5 );
    delay_nms(1);
    }
    }

点赞  2012-6-11 15:53

 

第四种:中位值平均滤波法(又称防脉冲干扰平均滤波法)

  A、方法:

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

    连续采样N个数据,去掉一个最大值和一个最小值

    然后计算N-2个数据的算术平均值

    N值的选取:3~14

  B、优点:

    融合了两种滤波法的优点

    对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差

  C、缺点:

    测量速度较慢,和算术平均滤波法一样

    比较浪费RAM

  1. #include <msp430g2452.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define X 31
    unsigned char i,j,k;
    long resultsum,temp,resultend;
    uint result[31];
    uchar ge,shi,bai,qian;

    #define SER ( 1 << 1 ) //也是所谓的DS
    #define SRCLK ( 1 << 0 ) //也是所谓的SHCP
    #define RCLK ( 1 << 2 ) //也是所谓的STCP

    void delay_1ms(void)
    {
    unsigned int i;
    for (i=0;i<1000;i++);
    }
    void delay_nms(unsigned int n)
    {
    unsigned int i=0;
    for (i=0;i<n;i++)
    delay_1ms();
    }

    uchar table[]={ 0xC0,0xF9,0xA4,0xB0,
    0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,
    0xC6,0xA1,0x86,0x8E };
    void Write595(uchar data)
    {

    P2OUT &= ~RCLK;
    for( i=0;i<8;i++ )
    {
    if(data&0x80)
    {
    P2OUT |= SER;
    }
    else
    {
    P2OUT &= ~SER;
    }
    P2OUT &= ~SRCLK;
    P2OUT |= SRCLK;
    data <<= 1;
    }
    P2OUT |= RCLK;
    }

    void ADC_init(void)
    {
    P1SEL |= 0x01;
    ADC10CTL0 = SREF_1 + REFON + ADC10ON;
    ADC10AE0 |= 0x01; // P1.0 ADC option select
    ADC10CTL1 = INCH_0+ADC10SSEL_2;
    }

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1DIR |= (BIT2|BIT3|BIT4|BIT5);
    P2DIR |= 0xff;
    ADC_init();
    for(j=0;j<X;j++)
    {
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    while (ADC10CTL1 & ADC10BUSY); // ADC10BUSY?
    result[j]= ADC10MEM;
    }

    for(j=0;j<X-1;j++)
    {
    for(k=0;k<X-j;k++)
    {
    if(result[k]>result[k+1])
    {
    temp = result[k];
    result[k] = result[k+1];
    result[k+1] = temp;
    }
    }
    }
    for(j=1;j<30;j++)
    {
    resultsum += result[j];
    }

    while(1)
    {
    resultend = resultsum/29;
    resultend = resultend*1500/1024;
    //resultsum = result[(X-1)/2];
    //resultsum = resultsum*1500/1024;
    qian = resultend/1000;
    bai = resultend/100%10;
    shi = resultend/10%10;
    ge = resultend%10;
    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[ge]);
    P1OUT |= ( 1 << 2 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[shi]);
    P1OUT |= ( 1 << 3 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[bai]);
    P1OUT |= ( 1 << 4 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[qian]);
    P1OUT |= ( 1 << 5 );
    delay_nms(1);
    }
    }

点赞  2012-6-11 15:53

 

第五种:加权递推平均滤波法

  A、方法:

    是对递推平均滤波法的改进,即不同时刻的数据加以不同的权

    通常是,越接近现时刻的数据,权取得越大。

    给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低

  B、优点:

    适用于有较大纯滞后时间常数的对象

    和采样周期较短的系统

  C、缺点:

    对于纯滞后时间常数较小,采样周期较长,变化缓慢的信号

    不能迅速反应系统当前所受干扰的严重程度,滤波效果差

  1. #include <msp430g2452.h>
    #define uchar unsigned char
    #define uint unsigned int
    const int coefficient[10]= {1,2,3,4,5,6,7,8,9,10};
    const int coesum = 55;

    unsigned char i,j;
    long resultsum,resultend,resultsum1;
    unsigned int result[11];
    uchar ge,shi,bai,qian;

    #define SER ( 1 << 1 ) //也是所谓的DS
    #define SRCLK ( 1 << 0 ) //也是所谓的SHCP
    #define RCLK ( 1 << 2 ) //也是所谓的STCP

    void delay_1ms(void)
    {
    unsigned int i;
    for (i=0;i<1000;i++);
    }
    void delay_nms(unsigned int n)
    {
    unsigned int i=0;
    for (i=0;i<n;i++)
    delay_1ms();
    }

    uchar table[]={ 0xC0,0xF9,0xA4,0xB0,
    0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,
    0xC6,0xA1,0x86,0x8E };
    void Write595(uchar data)
    {

    P2OUT &= ~RCLK;
    for( i=0;i<8;i++ )
    {
    if(data&0x80)
    {
    P2OUT |= SER;
    }
    else
    {
    P2OUT &= ~SER;
    }
    P2OUT &= ~SRCLK;
    P2OUT |= SRCLK;
    data <<= 1;
    }
    P2OUT |= RCLK;
    }

    void ADC_init(void)
    {
    P1SEL |= 0x01;
    ADC10CTL0 = SREF_1 + REFON + ADC10ON;
    ADC10AE0 |= 0x01; // P1.0 ADC option select
    ADC10CTL1 = INCH_0+ADC10SSEL_2;
    }

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1DIR |= (BIT2|BIT3|BIT4|BIT5);
    P2DIR |= 0xff;
    ADC_init();
    for(j=0;j<11;j++)
    {
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
    while (ADC10CTL1 & ADC10BUSY); // ADC10BUSY?
    result[j] = ADC10MEM;
    }
    for(j=0;j<10;j++)
    {
    result[j] = result[j+1];
    resultsum += result[j]*coefficient[j];
    }
    resultsum /= coesum;

    while(1)
    {
    //resultend = resultsum/30;
    resultend = resultsum*1500/1024;
    qian = resultend/1000;
    bai = resultend/100%10;
    shi = resultend/10%10;
    ge = resultend%10;
    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[ge]);
    P1OUT |= ( 1 << 2 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[shi]);
    P1OUT |= ( 1 << 3 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[bai]);
    P1OUT |= ( 1 << 4 );
    delay_nms(1);

    P1OUT &= ~(( 1 << 2 )|(1<<3)|(1<<4)|(1<<5));
    Write595(table[qian]);
    P1OUT |= ( 1 << 5 );
    delay_nms(1);
    }
    }

点赞  2012-6-11 15:54
学习学习
我常用的还用一种新旧值对比的方法
新值 = 新值*a + 上一次值*(1-a)
效果看起来也不错
点赞  2012-8-8 20:47

回复 7楼 shasidaran 的帖子

这个办法值得一试  a的取值应该是个讲究 0.5还是根据不同的改变
点赞  2012-8-11 17:31
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复