文章目录
- 前言
- 一、数字信号处理
- 二、基于频域的滤波器设计
-
- 1.一阶低通滤波器
-
- [1.1 如何理解低通滤波器](#1.1 如何理解低通滤波器)
- [1.2 经典自控理论下的一阶低通滤波器](#1.2 经典自控理论下的一阶低通滤波器)
- [1.3 一阶低通滤波器的离散形式](#1.3 一阶低通滤波器的离散形式)
- [1.4 一阶低通滤波器的应用](#1.4 一阶低通滤波器的应用)
以下为个人理解,仅供参考。
前言
在拿到传感器之前,首先要进行的是信号处理。然后根据接收到的数据进行控制,设计系统等操作。例如,PID,LQR,MPC和卡尔曼滤波等经典控制算法。
一、数字信号处理
对于数字信号处理,就是将时域中的信号转换成频域中的信号进行分析。
为什么要进行这样的转换呢? 时域主要是看信号的变化过程,频域看信号的组成结构,所以,频域可简化对信号的分析与特征的提取,方便分析系统的特性,提取分类特征等。主要是解决难以处理的问题。
信号处理主要有两种方式:分析和设计系统(传递函数,稳定性)时用拉普拉斯变换;分析信号(噪声,振动,频率成分)时用傅里叶变换。
二、基于频域的滤波器设计
什么是滤波器? 只让指定的信号通过,阻挡或滤掉其他频率的电路或算法。
为什么要使用滤波器?使用滤波器能解决什么问题? 滤波器可过滤传感器传来的高频毛刺,抖动,电磁干扰,只保留有用的信号。对于底盘电机速度环反馈值进行滤波,由于编码器测速原始值波动极大,如果不加滤波,PID输出会剧烈波动。
简单理解就是:放行低频信号选择低通滤波器,放行高频信号选择高通滤波器,
1.一阶低通滤波器
1.1 如何理解低通滤波器
低通滤波器可以理解为只让慢悠悠的低频信号通过,把疯狂快速乱蹦的高频抖动全部挡下来。(具体体现就是将电机某个快慢程度之下的动作保留下来,但是将这个快慢程度之上的动作,也就是剧烈的抖动滤掉。我们将这个快慢程度称作截止频率。)
- 高于截止频率的乱动,全部干掉
- 低于截止频率的动作,全部保留
需要注意的是:低通滤波器本身就是一个独立的,完整的信号处理系统。虽然低通滤波器具体体现为几行代码或一种算法,但是是当做系统来进行设计的。强调这点,是因为接下来我们要使用自控原理对滤波器进行分析。
所以不是只有特定的系统才能使用低通滤波器,而是任何信号,任何控制系统,任何传感器数据都可以外挂叠加这个低通系统。
1.2 经典自控理论下的一阶低通滤波器
首先我们要明确低通滤波器要实现什么功能,根据功能进行设计。
低通滤波器的功能:允许低频慢变化信号顺利通过,高频快速抖动信号被衰减压制。
根据需求进而我们发现低通滤波器与一阶惯性系统相对应。
为什么低通滤波器与一阶惯性环节相对应呢? 这里首先引入一阶惯性系统的微分方程,至于为什么一阶惯性系统的微分方程是这个形式,这里不做证明。
一阶惯性系统的微分方程:

对上述微分方程进行拉普拉斯变换,从时域转换到复数域得到:

需要注意的是:上述变换对应零初始条件下的线性时不变系统
根据傅里叶分解原理,任何连续时域的信号,都可以分解为一系列不同频率,不同幅值的正弦信号叠加。对于线性时不变系统,满足叠加定理。即系统对混合信号的作用效果可以等价于对每一个正弦分量分别作用后再叠加。所以这里仅对正弦信号进行分析,得到的结论可以等效到对任意输入信号的滤波效果
根据经典控制理论,我们可知令传递函数的s=jw可以得到频率特性(此性质的推导是基于输入信号为正弦信号的基础上的):

如果想了解该性质的原理,可参考卢京潮老师的自动控制原理
进而我们可以发现:

由此可以发现一阶惯性系统具备典型低通滤波特性。进而可以得到一阶惯性系统的性质均适配于低通滤波器。
1.3 一阶低通滤波器的离散形式
1.2节说明低通滤波器和一阶惯性系统相对应,是为了更好的理解低通滤波器的传递函数的由来。
因为在单片机里是离散采样,所以这里对微分方程进行离散化。 采样周期为Ts。
首先用差分近似导数:
将上述差分代入到微分方程进行替换可以得到:
这里的Wc对应一阶系统微分方程的1/T,Xn就是当前采样到的原始输入信号。Yn-1上一次采样周期算出来的旧滤波值。
将上述公式化简可得:

进而得到最终的离散迭代公式:

其中:

1.4 一阶低通滤波器的应用
低通滤波器输出相对于输入有延迟,系统越激进,即截止频率越低,引入的滞后越大。在快速响应回路中,这种滞后可能会导致系统失稳。
下面展示一下低通滤波器在robomaster机器人嵌入式系统中的应用,主要就是对陀螺仪传回来的数据进行处理,加入低通滤波器。简单理解就是在传入PID的反馈数据中加入一定比例的旧数据,这样能防止云台的剧烈抖动。
下面展示一下代码:

这里需要注意的是:针对不同的机械架构,需要调节参数。
不过由于一年前比赛的时候能力有限,时间有限,所以写出来的代码比较杂乱。多模块间交叉融合,不是很好。下面提供一般优化后的代码:
c
//一阶低通滤波器结构体
typedef struct{
float alpha;//滤波系数
float last_out;//上一次输出
}LPF;
//初始化低通
void lpf_init(LPF *f, float alpha){
f->alpha=alpha;
f->last_out=0;
}
//每一次采样周期调用一次,输入原始值,输出滤波后的值
float lpf_update(LPF *f,float x){
f->last_out=f->alpha*x+(1-f->alpha)*f->last_out;
return f->last_out;
}