首页 > 编程语言 >网上看到的一个IIR算法,记录一下

网上看到的一个IIR算法,记录一下

时间:2024-03-27 14:33:22浏览次数:36  
标签:IIR iir 记录 NSEC else filter 算法 include

本帖最后由 monkeynav 于 2013-8-21 18:09 编辑

原帖刊载于ourdev:http://www.amobbs.com/thread-4165021-1-1.html
原帖代码搞错,也无法编辑,很多人又找不到后面的更正,为了不误导更多人,就在这里重新发一遍。

这里提供用于AVR和STM32的IIR滤波器代码下载,保证可用,不需要额外修改:

------------------------------------------------------------------------------------------------------------------------------------------------------

放假实在无聊,即将到来的高三非常恐怖,先偷闲一把。

matlab的fdatool是好东西,不过很多人不知道该怎么使用它生成的C头文件。

该程序已经用于心电采集实验

 


不多说,切入正题

这里有个fdatool设计的IIR高通滤波器,采样率400Hz时截止频率1Hz。
设计定型之后,要做些调整。

以下说明中的英文名词有些可能对不上fdatool界面上的原文,请大家意会吧

第一步:
点击菜单中的Edit->Convert Structure 选择Direct Form I ,SOS,(必须是Direct Form I,  II不行)
一般情况下,按照默认设置,fdatool设计都是由二阶部分串联组成的。
这种结构的滤波器稳定性比一个section的要好很多,其他方面的性能也好些。
如果不是的话,点击Convert to second order sections。
这时,滤波器的结构(structure)应该显示为 Direct Form I,second order sections

第二步:
选择quantize filter,精度选择single precision floating point (单精度浮点)
之所以不用定点是因为噪声太大,也不容易稳定。
点击菜单中的Targets -> generate c header ,选择export as:single precision floating point (单精度浮点)
填写变量名称时,把NUM改成IIR_B,DEN改成IIR_A,其他不用动,保存为iir_coefs.h

保存好的文件如下:
//一大堆注释
//然后:
/* General type conversion for MATLAB generated C-code  */
#include "tmwtypes.h"
/*
* Expected path to tmwtypes.h
* C:\Program Files\MATLAB\R2010a\extern\include\tmwtypes.h
*/
/*
* Warning - Filter coefficients were truncated to fit specified data type.  
*   The resulting response may not match generated theoretical response.
*   Use the Filter Design & Analysis Tool to design accurate
*   single-precision filter coefficients.
*/
#define MWSPT_NSEC 9
const int NL[MWSPT_NSEC] = { 1,3,1,3,1,3,1,3,1 };
const real32_T IIR_B[MWSPT_NSEC][3] = {
{
     0.8641357422,              0,              0
  },
  {
                1,             -2,              1
  },
  {
     0.9949035645,              0,              0
  },
  {
                1,   -1.999938965,              1
  },
  {
     0.9985351563,              0,              0
  },
  {
                1,    -1.99987793,              1
  },
{
     0.9996337891,              0,              0
  },
  {
               1,    -1.99987793,              1
  },
  {
                1,              0,              0
  }
};
const int DL[MWSPT_NSEC] = { 1,3,1,3,1,3,1,3,1 };
const real32_T IIR_A[MWSPT_NSEC][3] = {
  {
                1,              0,              0
  },
  {
                1,   -1.938049316,   0.9401855469
  },
  {
                1,              0,              0
  },
  {
                1,   -1.989501953,   0.9900512695
  },
{
                1,              0,              0
  },
  {
                1,   -1.996887207,   0.9971923828
  },
  {
                1,              0,              0
  },
  {
                1,   -1.999084473,   0.9993286133
  },
  {
                1,              0,              0
  }
};


第三步:
打开iir_coefs.h把MWSPT_NSEC替换成IIR_NSEC,
NL、DL数组删除掉,real32_T改成float ,
其中有一个#include "twmtypes.h",不要它了,删掉
改完的文件如下:

#define IIR_NSEC 9
  //原来叫做MWSPT_NSEC


const float IIR_B[IIR_NSEC][3] = {
  //为什么改为float很明显了吧
  {
    0.8641357422,              0,              0
  },
  {
                1,            -2,              1
  },
  {
    0.9949035645,              0,              0
  },
  {
                1,  -1.999938965,              1
  },
{
    0.9985351563,              0,              0
  },
  {
                1,    -1.99987793,              1
  },
  {
   0.9996337891,              0,              0
  },
  {
                1,    -1.99987793,              1
  },
  {
                1,              0,              0
  }
};
const float IIR_A[IIR_NSEC][3] = {
  {
                1,              0,              0
  },
  {
                1,  -1.938049316,  0.9401855469
  },
  {
                1,              0,              0
  },
  {
                1,  -1.989501953,  0.9900512695
  },
  {
                1,              0,              0
  },
  {
                1,  -1.996887207,  0.9971923828
  },
  {
                1,              0,              0
  },
  {
                1,  -1.999084473,  0.9993286133
  },
  {
                1,              0,              0
  }
};


保存文件,然后使用以下代码进行滤波
这段代码是根据Direct Form I 2阶IIR滤波的差分方程编写的
a0*y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] -a2*y[n-2];


#include "../platform.h"
//#include "iir_coefs.float.flat.h"
//#include "iir_coefs.float.sharp.h"
#include "iir_coefs_pass@[email protected]"
#include "iir_filter.h"
static float y[IIR_NSEC][3];
static float x[IIR_NSEC+1][3];
//IIR_NSEC阶直接型II IIR滤波器
//IIR_NSEC个二阶biquad串联
int16 iir_filter(int16 in)
{
      uint16 i;
      
      x[0][0] = in;
      
      for(i=0;i<IIR_NSEC;i++)
      {
        
        //  y[0] = x[0]*IIR_B[0] +x[1]*IIR_B[1] +x[2]*IIR_B[2]-y[1]*IIR_A[1]-y[2]*IIR_A[2];
          y[0] = 0;
         
          if(IIR_B[0] == 1) y[0]+=x[0];
          else if(IIR_B[0] == -1) y[0]-=x[0];
          else if(IIR_B[0] == -2) y[0]=y[0]-x[0]-x[0];
          else if(IIR_B[0] == 0);   
          else y[0] += x[0]*IIR_B[0];
         
          if(IIR_B[1] == 1) y[0]+=x[1];
          else if(IIR_B[1] == -1) y[0]-=x[1];
          else if(IIR_B[1] == -2) y[0]=y[0]-x[1]-x[1];
          else if(IIR_B[1] == 0);  
          else y[0] += x[1]*IIR_B[1];
         
          if(IIR_B[2] == 1) y[0]+=x[2];
          else if(IIR_B[2] == -1) y[0]-=x[2];
          else if(IIR_B[2] == -2) y[0]=y[0]-x[2]-x[2];
          else if(IIR_B[2] == 0);
          else y[0] += x[2]*IIR_B[2];
         
          if(IIR_A[1] == 1) y[0]-=y[1];
          else if(IIR_A[1] == -1) y[0]+=y[1];
          else if(IIR_A[1] == -2) y[0]=y[0]+y[1]+y[1];
          else if(IIR_A[1] == 0);
          else y[0] -= y[1]*IIR_A[1];
         
          if(IIR_A[2] == 1) y[0]-=y[2];
          else if(IIR_A[2] == -1) y[0]+=y[2];
          else if(IIR_A[2] == -2) y[0]=y[0]+y[2]+y[2];
          else if(IIR_A[2] == 0);
          else y[0] -= y[2]*IIR_A[2];
         
          if(IIR_A[0] != 1) y[0] /= IIR_A[0];
         
          y[2]=y[1];y[1]=y[0];
          x[2]=x[1];x[1]=x[0];
         
          x[i+1][0] = y[0];
      }
      
      if( x[IIR_NSEC][0]>32767)  x[IIR_NSEC][0]=32767;
      if( x[IIR_NSEC][0]<-32768) x[IIR_NSEC][0]=-32768;
      return  ((int16)x[IIR_NSEC][0]);   
      
}
//复位滤波器
void iir_reset(void)
{
    uint16 i,j;
   
    for(i=0;i<IIR_NSEC+1;i++)
    {
       for(j=0;j<3;j++)
       {
          x[j]=0;
       }
    }
   
    for(i=0;i<IIR_NSEC;i++)
    {
       for(j=0;j<3;j++)
       {
          y[j]=0;
       }
    }
}


//iir_filter.h
#ifndef _IIR_FILTER_H__
#define _IIR_FILTER_H__
int16 iir_filter(int16 x);
void iir_reset(void);
#endif


使用方法:
首先写好iir_coefs.h,然后调用iir_filter.c对数据流进行滤波
一个伪代码例子:
while(运行中)
{
保存到SD卡(iir_filter(读取ADC采样值()));
}

这个函数比STM32 DSP库中的函数要好很多,DSP库中的2个IIR滤波函数都不能连续处理数据流。
记得在开始滤波之前重置滤波器
iir_reset();

标签:IIR,iir,记录,NSEC,else,filter,算法,include
From: https://www.cnblogs.com/saulgoodman611/p/18099102

相关文章

  • 学算法要读《算法导论》吗?
    这篇文章是我学习算法的心得,希望它能够给一些将要学习算法且准备要读大部头算法书籍的朋友一些参考,节省一些时间,也为了给经典的“黑皮书”祛魅,我觉得这些书籍在大部分互联网从业者心中已经不再是进步的阶梯,而是恐惧的阴影了,因为当一些学习路线中列出这些书目时,评论区多是调侃少是......
  • 支持向量机算法
    文章目录谷歌笔记本(可选)SMO高效优化算法谷歌笔记本(可选)fromgoogle.colabimportdrivedrive.mount("/content/drive")Mountedat/content/driveSMO高效优化算法importrandomdefloadDataSet(fileName):dataMat=[]labelMat=[]fr=open(fileN......
  • 极高创新性!基于斑马算法优化并行卷积神经网络注意力机制结合支持向量机ZOA-PCNN-AT-SV
     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。......
  • 【深度学习】最强算法模型之:潜在狄利克雷分配(LDA)
    潜在狄利克雷分配1、引言2、潜在狄利克雷分配2.1定义2.2原理2.3算法公式2.4代码示例3、总结1、引言小屌丝:鱼哥,给我讲一讲LDA小鱼:LDA?你指的是?小屌丝:就是算法模型的LDA啊,你想啥?小鱼:哦,哦,那就好,小屌丝:你告诉我,你想啥了?小鱼:不滴,我就不小屌丝:…你就说吧,我......
  • 数据结构-排序算法(Java实现)
    1.插入排序1.1基本思想把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。1.2图解 1.3原理解析第一趟:一组数据可以分为有序序列和无序序列, i表示无序序列的第一个元素,j表示有序序列的......
  • 前缀和算法讲解(二)
    首先,大家看一下一维的前缀和:https://blog.csdn.net/hjyowl/article/details/136580832?spm=1001.2014.3001.5502今天,我们讲解一下二维的前缀和.先看题:输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下......
  • mmpretrain安装教程(踩雷记录)
    目录ModuleNotFoundError:Nomodulenamed‘mmcv‘包命令pkgutil报错OSError:CUDA_HOMEenvironmentvariableisnotset.PleasesetittoyourCUDAinstallroot.error:MicrosoftVisualC++14.0orgreaterisrequired.Getitwith"MicrosoftC++BuildTools......
  • git 常用操作记录(tag、remote、rebase等)
             关于git的常用命令(add、commit、pull、push、merge、stash等)在之前的博文已经介绍过了,下面根据工作中遇到的问题,总结一些更为常用的命令使用方式。1、版本标签tag    tag是基于一次commit的,可以指定在某个分支的提交进行打标签。1.1、本地tag常......
  • NPP-VIIRS 数据注意事项
    1.年度合成数据通过“vcm”合成,去除了stray-light。V1和V2版本年度数据移除了太阳光、月光和云,但仍包含火、极光和噪声。V1版本数据由全年的日DNB数据合成;V2版本使用月度增量数据合成,这两种方法都采用离群值去除法去除生物质燃烧像素并隔离背景。2.年度全球数据中含median、lit......
  • 2024年人工智能、算法与自动化工程国际学术会议(ICAIAAE 2024)
    【会议简介】   2024年人工智能、算法与自动化工程国际学术会议将汇聚来自世界各地的顶尖学者,共同探讨人工智能、算法与自动化工程领域的尖端技术和发展趋势。会议将围绕深度学习、机器学习算法和自动化系统设计等多个主题展开,展示最新的研究成果,推动技术创新和产业应......