文章目录
前言
题外话 :
本文是博主对几个滤波算法整理的笔记之一,原本一篇,但由于CSDN篇幅限制分为了几个部分,包括:
卡尔曼滤波器:标准卡尔曼滤波器公式推导及算法实现
陷波滤波器:陷波滤波器的数学模型推导及算法实现
以及本文的RC滤波器。
包括:
- 一阶低通滤波器的数学模型推导及算法实现
- 一阶高通滤波器的数学模型推导及算法实现
- 二阶低通滤波器的数学模型推导
- 二阶高通滤波器的数学模型推导
原文PDF下载链接:https://mp.csdn.net/mp_download/manage/download/UpDetailed
- 在工程使用中,难免要使用到滤波算法,比如均值滤波,低通滤波等等,本文主要分析常用得低通和高通滤波算法(软件)
- 文中公式基本都是从物理模型推导而来,由浅入深得逐步推算,过程相对详细,并使用C++给出了验证代码验证了滤波算法。
- 由于up主水平有限,难免有错误,欢迎大家指正和交流。
1、一阶低通滤波
低通滤波器(英语:Low-pass filter)容许低频信号通过,但减弱(或减少)频率高于截止频率的信号的通过。对于不同滤波器而言,每个频率的信号的减弱程度不同。
1.1 一阶RC低通滤波器的连续域数学模型
1.2 一阶RC低通滤波器的算法推导
1.3 代码实现
#define PI 3.1415926
#define Get_LPF_Cof(fc, ts) (2 * PI * fc * ts / (float)(1 + 2 * PI * fc * ts))
#define LPF1(Yn, Xn, cof) Yn = (1 - cof) * Yn + cof * Xn
1.4 算法验证
验证代码:
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib> // For random number generation
#include <ctime> // For seeding the random number generator
using namespace std;
#define PI 3.1415926
#define Get_LPF_Cof(fc, ts) (2 * PI * fc * ts / (float)(1 + 2 * PI * fc * ts))
#define LPF1(Yn, Xn, cof) Yn = (1 - cof) * Yn + cof * Xn
void saveToCSV(const vector<double>& data, const string& filename) {
ofstream file(filename);
if (file.is_open()) {
for (const double& value : data) {
file << value << endl;
}
file.close();
cout << "Data saved to " << filename << endl;
}
else {
cerr << "Unable to open the file: " << filename << endl;
}
}
int main() {
float fc = 1.0; // Cutoff frequency
float ts = 0.1; // Sampling time
int numSamples = 100; // Number of samples
vector<double> inputSignal(numSamples);
vector<double> noisySignal(numSamples);
vector<double> filteredSignal(numSamples);
// Seed the random number generator
srand(time(nullptr));
// Generate input signal with noise
for (int i = 0; i < numSamples; ++i) {
inputSignal[i] = sin(2 * PI * 0.05 * i) + 0.2 * (rand() / (double)RAND_MAX - 0.5);
}
// Apply the low-pass filter
double Yn = 0.0;
for (int i = 0; i < numSamples; ++i) {
double Xn = inputSignal[i];
LPF1(Yn, Xn, Get_LPF_Cof(fc, ts));
filteredSignal[i] = Yn;
}
// Save data to CSV files
std::string filename1 = "LPF_before_Data.csv";
saveToCSV(inputSignal, "input_signal.csv");
std::string filename2 = "LPF_after_Data.csv";
saveToCSV(filteredSignal, "filtered_signal.csv");
return 0;
}
2、一阶高通滤波
高通滤波器(英语:High-pass filter)是容许高频信号通过、但减弱(或减少)频率低于截止频率信号通过的滤波器。对于不同滤波器而言,每个频率的信号的减弱程度不同。
2.1 一阶RC高通滤波器的连续域数学模型
2.2 一阶RC低通滤波器的算法推导
2.3 代码实现
#define PI 3.1415926
#define Get_HPF_Cof(fc,ts) (1/(float)(1+2*PI*fc*ts)) /* get coefficient */
#define HPF1(Yn,Xn,cof) Yn = (1-cof)*Yn + cof*Xn /* Yn:out;Xn:in;a:coefficient */
2.4
验证代码:
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdlib> // For random number generation
#include <ctime> // For seeding the random number generator
using namespace std;
#define PI 3.1415926
#define Get_HPF_Cof(fc,ts) (1/(float)(1+2*PI*fc*ts)) /* get coefficient */
#define HPF1(Yn,Xn,cof) Yn = (1-cof)*Yn + cof*Xn /* Yn:out;Xn:in;a:coefficient */
void saveToCSV(const vector<double>& data, const string& filename) {
ofstream file(filename);
if (file.is_open()) {
for (const double& value : data) {
file << value << endl;
}
file.close();
cout << "Data saved to " << filename << endl;
}
else {
cerr << "Unable to open the file: " << filename << endl;
}
}
int main() {
float fc = 1.0; // Cutoff frequency
float ts = 0.1; // Sampling time
int numSamples = 100; // Number of samples
vector<double> inputSignal(numSamples);
vector<double> noisySignal(numSamples);
vector<double> filteredSignal(numSamples);
// Seed the random number generator
srand(time(nullptr));
// Generate input signal with noise
for (int i = 0; i < numSamples; ++i) {
inputSignal[i] = sin(2 * PI * 0.05 * i) + 0.2 * (rand() / (double)RAND_MAX - 0.5);
}
// Apply the low-pass filter
double Yn = 0.0;
for (int i = 0; i < numSamples; ++i) {
double Xn = inputSignal[i];
HPF1(Yn, Xn, Get_HPF_Cof(fc, ts));
filteredSignal[i] = Yn;
}
// Save data to CSV files
std::string filename1 = "HPF_before_Data.csv";
saveToCSV(inputSignal, "input_signal1.csv");
std::string filename2 = "HPF_after_Data.csv";
saveToCSV(filteredSignal, "filtered_signal1.csv");
return 0;
}
3、二阶低通滤波器
3.1 二阶RC低通滤波器的连续域数学模型
3.2 二阶RC低通滤波器的算法推导
4、二阶高通滤波器
3.1 二阶RC高通滤波器的连续域数学模型
3.2 二阶RC高通滤波器的算法推导
式(35)的求解过程相对复杂,这里使用python工具进行求解:
# coding: utf-8
from sympy import symbols, Eq, solve
# 定义符号变量
Vo_k, Vo_k_minus_1, Vo_k_minus_2 = symbols('Vo_k Vo_k_minus_1 Vo_k_minus_2')
Vx_k, Vx_k_minus_1, Vx_k_minus_2 = symbols('Vx_k Vx_k_minus_1 Vx_k_minus_2')
Vi_k, Vi_k_minus_1, Vi_k_minus_2 = symbols('Vi_k Vi_k_minus_1 Vi_k_minus_2')
RC, Ts = symbols('RC Ts')
# 定义方程组
equations = [
Eq(RC * ( (Vx_k - Vo_k) - (Vx_k_minus_1 - Vo_k_minus_1) ) / Ts, Vo_k),
Eq(RC * ( (Vx_k_minus_1 - Vo_k_minus_1) - (Vx_k_minus_2 - Vo_k_minus_2) ) / Ts, Vo_k_minus_1),
Eq(RC * ( (Vi_k - Vx_k) - (Vi_k_minus_1 - Vx_k_minus_1) ) / Ts, Vx_k),
Eq(RC * ( (Vi_k_minus_1 - Vx_k_minus_1) - (Vi_k_minus_2 - Vx_k_minus_2) ) / Ts, Vx_k_minus_1)
]
# 解方程组,得到Vx_k_minus_1、Vx_k_minus_2和Vx_k(前三个公式)
solutions_ab = solve(equations[:3], (Vx_k_minus_1, Vx_k_minus_2,Vx_k))
# 将Vx_k_minus_1和Vx_k_minus_2 的解代入第四个方程
equation_c = equations[3].subs(solutions_ab)
# 解方程,得到 Vo_k 关于 Vo_k_minus_1、Vo_k_minus_2、Vi_k、Vii_k_minus_1、Vi_k_minus_2的表达式
solution_c = solve(equation_c, Vo_k)
# 打印结果
print("Vo_k表达式:")
print(solution_c)