RoboMaster

标题: 【分享帖】RM入门教学系列数字滤波器设计与实现(含代码) [打印本页]

作者: Extreme    时间: 2018-1-24 20:57
标题: 【分享帖】RM入门教学系列数字滤波器设计与实现(含代码)
随着RoboMaster比赛的推广,不断有新的学校参与进来,有些同学因为刚接触比赛,缺乏实践经验,可能会遇到一些基础的技术问题。我们可能会陆续更新一些基础教程。今天给大家介绍一个实用技巧:利用MATLAB设计滤波器并在STM32平台上跑起来。

滤波器的重要作用不必多说,在传感器数据处理、电机控制、视觉算法中都会用到。这里举一个最简单的例子,对陀螺仪采集的数据进行低通滤波,从而达到去除噪声的作用。


1. 分析原数据
首先我们将MPU6500的陀螺仪数据带宽设置为250Hz,然后使用J-Scope采集静置时候的陀螺仪x轴的数据。可以看出角速度有幅度约为0.3°/s的跳动。(为了让J-Scope读到值,这里将原始数据乘以1000转化成整型了)
[attach]15753[/attach]
对数据进行FFT变换之后得到频谱图:
[attach]15758[/attach]
可以看出信号在250Hz之后有衰减,证明MPU6500确实有对原始adc采样数据做过滤波,但是效果不明显。


2. FDATool工具介绍
现在我们来自己设计一个低通滤波器。
首先打开MATLAB,在命令行窗口键入 fdatool,打开滤波器设计和分析工具(Filter Design & Analysis Tool),初始界面如下图所示:
[attach]15757[/attach]
这是经典的MATLAB工具箱界面,第一行菜单栏,第二行工具栏,中间展示结果,最下方的功能区可以切换,默认的功能就是设置滤波器参数。这点英文肯定难不倒大家,随便点点看就能学会。

3. 设计滤波器
在设计滤波器界面,可以根据自己的需求选择滤波器类型、阶数、频率特性、幅度特性等参数。
例如我选择了切比雪夫Ⅱ型低通滤波器,采用Minimum order模式(根据频率、幅度指标自动选择最小阶数),设置采样频率(Fs)1000Hz,通带频率(Fpass)50Hz,阻带频率(Fstop)60Hz,衰减幅度保持默认。点击Design Filter按钮,一个滤波器就出来了。
[attach]15755[/attach]
该滤波器是17阶的,点击工具栏的按钮可以看到该滤波器的详细特性,例如幅频、相频、群延时、零极点等等。蓝色线表示的幅频响应曲线,橙色线是相频响应曲线。可以看出切比雪夫Ⅱ型滤波器在通带内平滑,阻带内有等幅度纹波。

4. 转化和导出
FDATool默认生成的滤波器是二阶级联组成,这样的稳定性更高(尤其是滤波器阶数较高时),但是结构比较复杂,程序实现也不方便,一般将其转化成一阶级联型再使用,点击菜单栏的Edit->Convert to Single Section进行转换。至此,一个50Hz的切比雪夫Ⅱ型低通滤波器就完成了。
点击 Targets-> Generate C Header,将滤波器的系数存到.h文件中。然后我们可以进入C语言的部分了。
[attach]15756[/attach]

[attach]15754[/attach]

5. C语言实现
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
[attach]15760[/attach]
(注意:分子系数是成对出现的,可以先合并来提高运算效率)

6. 结果对比
静止测试时,噪声得到了有效的抑制。
[attach]15761[/attach]
再看频谱,滤波效果非常明显,50Hz以上的分量几乎被完全消除了。
[attach]15759[/attach]
动态测试图:
[attach]15762[/attach]
曲线平滑很多,毛刺都被消除了,但是可以明显看出,滤波之后的信号相比原信号有滞后,这是滤波造成的相位延迟。这里只是为了给大家展示滤波器的效果,实际上该滤波器并不一定适合用于对陀螺仪数据进行处理,要综合考虑各种因素来确定滤波器。

7. 计算原理
详细内容可以去翻信号与系统的课本:
FDATool生成的滤波器其实传递函数形式 ,两组系数分别是传递函数的分子分母,结构如下:
[attach]15773[/attach]
上下同除以z^n :
[attach]15749[/attach]
将上式展开,并利用z变换的时移性质[attach]15776[/attach]可以得到:
[attach]15750[/attach]

最后整理为:
[attach]15751[/attach]
此即代码里循环累加的过程。
这个算法是用差分方程表示线性时不变系统的通用方法,也适用于将自己设计的传递函数形式的控制器转化成代码。需要注意的是,如果传递函数是连续形式的,需要先经过离散化,可以利用MATLAB的c2d函数。

最后附上频谱分析的m文件和滤波器实现的C代码,有优化空间,仅供参考。

作者: 20164160    时间: 2018-1-24 21:16
。。。。。。。。。。。。。。。。。。。。
作者: 物非人非    时间: 2018-1-25 10:04
大佬,表示之前没有用过
作者: 小仙男    时间: 2018-1-27 09:30
好厉害
作者: 风中的少年    时间: 2018-1-27 20:51
学习了
作者: Jizefeng0810    时间: 2018-1-29 22:27
厉害!学习了
作者: Daqo_Lee    时间: 2018-1-30 09:12
666,学习了
作者: 老神棍    时间: 2018-1-30 18:08
66666666666
作者: 游离子    时间: 2018-1-30 20:44
thanks....
作者: H.F.    时间: 2018-2-4 19:51
幸苦了,收藏!
作者: 深林未晚    时间: 2018-2-5 14:42
学习了学习了
作者: 韩光闪闪    时间: 2018-2-9 09:42
好牛掰.......
作者: 一只小小鸟    时间: 2018-3-20 18:57
很棒啊,学习了
作者: 一只小小鸟    时间: 2018-3-20 18:57
很棒啊,学习了
作者: 就这样吧    时间: 2018-4-3 14:00
谢谢大神,解决大问题了
作者: YSU木糖醇    时间: 2018-4-3 15:34
学习啦 很棒很棒
作者: 桐桐    时间: 2018-5-20 15:31
66666666666666666666
作者: sjqsjq520    时间: 2018-5-22 17:19
双路全H桥PWM控MOS管电机驱动
作者: Hansen    时间: 2018-5-22 20:26
学习学习,大神辛苦了
作者: Copyright    时间: 2018-5-31 16:57
666666666666666666
作者: geek_1    时间: 2018-11-24 12:22
谢谢楼主, 学习了
作者: 快拆小分队    时间: 2019-3-21 18:17
顶上去
作者: lcpdeb    时间: 2019-3-31 06:47
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)


请问如何按照固定频率运行这个滤波器呢,是只需要放在中断里就行了吗
作者: Extreme    时间: 2019-4-8 20:13
lcpdeb 发表于 2019-3-31 06:47
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行 ...

用定时器中断或者rtos的任务里,只要保证执行周期稳定即可
作者: 进击者    时间: 2019-4-9 23:46
收藏,收藏

作者: Kimji    时间: 2019-4-23 16:02
学习一下。。。
作者: 小梁的机器人    时间: 2019-5-6 10:51
理论结合实际 唉
作者: 薅电机狂魔    时间: 2019-5-22 15:21
谢谢老师
作者: innholderdu    时间: 2019-6-6 01:04
腻害了
腻害了
腻害了

作者: michaelzhong009    时间: 2019-6-8 04:45
在学习中收集金币
作者: xfj    时间: 2019-6-10 09:54
学习了
作者: yandongyu1998    时间: 2019-10-12 19:15
讲的干货满满,超棒!就是最后这里应该是bk*y(n-k)吧
作者: RMBO    时间: 2019-11-16 18:13
那个FFT变换不知道如何实现。。。
作者: 周新杰00    时间: 2019-11-16 20:15
太赞了!!
作者: Benp    时间: 2019-11-16 22:07
this is so good!
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:00
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
v把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:01
v把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:02
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:02
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:03
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 14:05
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:12
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:12
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:13
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:14
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:14
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: liufengle    时间: 2019-11-17 16:14
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行,即可输出滤波后的陀螺仪数据了。(具体原理再文章最后有介绍)
作者: 飞翔的机械人    时间: 2019-11-26 09:25
liufengle 发表于 2019-11-17 16:14
把系数提取出来,然后把下面这个滤波器函数放到定时器中断或者数据接收中断处理函数里面,按照固定频率运行 ...

???????????????????
作者: RMwcm    时间: 2020-3-27 18:06
学习了。

作者: xulei1999    时间: 2020-4-11 01:01
好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西好东西
作者: Lxctdjy    时间: 2020-4-20 17:54
真的受益匪浅,谢谢大佬
作者: jafiol    时间: 2020-4-21 09:13
f = Fs_n*(0L_n/2))/L_n;
作者: jafiol    时间: 2020-4-21 09:14
f = Fs_n*(0L_n/2))/L_n;
错误使用  /
矩阵维度必须一致。
报这个错是什么意思?
作者: Lxctdjy    时间: 2020-4-23 08:16
一定好好学一学,谢谢大佬
作者: Jobcreat    时间: 2020-4-28 14:36
学习了!!!
作者: dao草人    时间: 2020-4-28 21:24
很厉害的一篇帖子,希望论坛这种帖子越来越多
作者: 拉普拉斯兽    时间: 2020-8-25 10:58
大牛大牛
作者: sleeping    时间: 2022-2-21 16:12
在学习中收集金币

作者: 红红火火恍恍惚惚    时间: 2022-2-25 20:13
谢了
作者: marty    时间: 2023-1-4 17:17
让我康康
作者: 与月同醉    时间: 2024-1-12 12:00
明白了

作者: Apro1066    时间: 2024-4-27 11:34

日常逛论坛,看看有没有干货,随便评论一波拿点金钱




欢迎光临 RoboMaster (https://bbs.robomaster.com/) Powered by Discuz! X3.2