• 正文
  • 相关推荐
申请入驻 产业图谱

从matlab到FPGA:一阶卡尔曼滤波的matlab工程实现

04/23 08:59
Image2695
加入交流群
Image 扫码加入
获取工程师必备礼包
参与热点资讯讨论

数字信号处理领域,传感器噪声是每个工程师都无法回避的问题。无论是工业现场的电压采集,还是通信系统基带信号,真实世界中的信号总是夹杂着各种噪声干扰。如何从这些"脏数据"中提取出干净的有效信号,是信号处理的核心课题之一。

从充满噪声的观测数据中还原出原始的真实信号

在MATLAB中生成带噪方波信号,通过卡尔曼滤波进行最优估计,导出FPGA可用的COE初始化文件,最后运用经典的卡尔曼滤波算法,实现高效实时的信号降噪。

一、方波、噪声与最优估计

包含三个核心模块:

    信号生成模块 —— 构造"理想信号+高斯白噪声"的测试环境数据导出模块 —— 生成Xilinx BRAM可用的COE格式文件滤波处理模块 —— 实现一维卡尔曼滤波的最优估计
SAMPLE_NUM = 1024;         % 总采样点数
SQUARE_PERIOD = 314;       % 方波周期
NOISE_STD = 10;            % 噪声标准差
DC_OFFSET = 1.4;           % 直流偏置
AMPLITUDE_SCALE = 80;      % 幅度缩放系数

信号生成

我们使用MATLAB的square()函数生成标准方波,并通过三个步骤进行信号调理

    • 周期控制:将方波周期设为314个采样点(对应50Hz工频信号的数字化)直流偏置:添加1.4V偏置电压,使信号整体抬升至正电压区间幅度缩放:乘以80倍系数,将幅值范围从[-1,1]映射到[32,192]噪声部分采用randn()生成高斯白噪声,标准差设为10。

Image

% 生成时间序列
timeIndex = 1:SAMPLE_NUM;
% 生成标准方波(范围[-1, 1])
% square(T, DUTY)生成周期为2*pi的方波,通过T缩放调整周期
squareWave = square(timeIndex/(SQUARE_PERIOD/(2*pi)), DUTY_CYCLE);
% 信号调理:添加偏置并缩放幅度
% 原始范围[-1, 1] → 偏置后[0.4, 2.4] → 缩放后[32, 192]
signalClean = (squareWave + DC_OFFSET) * AMPLITUDE_SCALE;
% 生成高斯白噪声
noiseGaussian = randn(1, SAMPLE_NUM) * NOISE_STD + NOISE_MEAN;
% 合成含噪观测信号
signalNoisy = signalClean + noiseGaussian;

COE文件导出

FPGA开发中,Block RAM的初始化通常需要COE(Coefficient)格式文件。我们在MATLAB中创建了一个Q16.16定点数量化器:

    总位宽32位:1位符号位 + 15位整数位 + 16位小数位舍入模式:四舍五入(Round)溢出处理:饱和截断(Saturate)

这种定点格式兼顾了动态范围和精度:15位整数部分可表示±32767的范围,足以覆盖我们的信号幅度;16位小数部分提供了约15μV的电压分辨率。通过num2bin()函数将浮点数量化为二进制字符串,按Xilinx标准格式写入文件,即可直接用于Vivado的BRAM初始化。

% 创建定点数量化器对象(Q16.16格式:1符号位+15整数位+16小数位)
quantizerObj = quantizer('fixed', [FIXED_WORD_LEN, FIXED_FRAC_LEN], ...
'RoundMode', 'round', 'OverflowMode', 'saturate');
% 打开文件写入
fileId = fopen(COE_FILE_NAME, 'w');
if fileId == -1
error('无法创建文件: %s', COE_FILE_NAME);
end
% 写入COE文件头
fprintf(fileId, '; Xilinx COE File Formatn');
fprintf(fileId, '; Memory Initialization File for BRAMn');
fprintf(fileId, '; Data: %d samples, %d-bit fixed point (Q%d.%d)n', ...
SAMPLE_NUM, FIXED_WORD_LEN, FIXED_WORD_LEN-FIXED_FRAC_LEN-1, FIXED_FRAC_LEN);
fprintf(fileId, '; Generated by MATLAB on %snn', datestr(now));
fprintf(fileId, 'memory_initialization_radix=%d;n', RADIX_TYPE);
fprintf(fileId, 'memory_initialization_vector=n');
% 转换并写入数据(除最后一个外,均带逗号)
for idx = 1:SAMPLE_NUM-1
binaryStr = num2bin(quantizerObj, signalNoisy(idx));
fprintf(fileId, '%s,n', binaryStr);
end
% 最后一个数据用分号结束
binaryStrLast = num2bin(quantizerObj, signalNoisy(SAMPLE_NUM));
fprintf(fileId, '%s;n', binaryStrLast);
% 关闭文件
fclose(fileId);
fprintf('COE文件已成功生成: %sn', COE_FILE_NAME);

卡尔曼滤波

卡尔曼滤波的精妙之处在于它融合了系统模型预测和实际观测,通过动态调整两者权重,得到最优估计。它基于一个简单但强大的假设:当前状态只与前一时刻状态有关(马尔可夫性)。

滤波过程分为两步循环:

    预测阶段:状态保持不变,但不确定性(协方差)会累积过程噪声Q更新阶段:根据观测残差(新息)和卡尔曼增益K,修正状态估计

关键参数的选择:

    过程噪声Q=0.1:表示我们对"信号恒定"这个模型有一定信任,但不完全确信观测噪声R=3:反映传感器噪声的统计特性,R越大说明观测越不可靠初始协方差P₀=1:给滤波器一个中等程度的初始不确定度
% 预分配输出数组
stateEstimate = zeros(1, SAMPLE_NUM); % 状态估计值(滤波后信号)
kalmanGainLog = zeros(1, SAMPLE_NUM); % 卡尔曼增益记录(用于分析)
% 初始化滤波器状态
statePredPrev = INIT_STATE_X0; % k-1时刻状态估计(X_{k-1|k-1})
covariancePrev = INIT_COV_P0; % k-1时刻误差协方差(P_{k-1|k-1})
% 卡尔曼滤波迭代
for idx = 1:SAMPLE_NUM
% ===== 步骤1: 预测(时间更新)=====
% 状态预测:采用零阶随机游走模型(假设信号恒定)
% X_{k|k-1} = X_{k-1|k-1}
statePredicted = statePredPrev;
% 协方差预测:不确定性增加过程噪声Q
% P_{k|k-1} = P_{k-1|k-1} + Q
covariancePredicted = covariancePrev + PROC_NOISE_Q;
% ===== 步骤2: 更新(测量更新)=====
% 计算卡尔曼增益:平衡预测与观测的信任度
% K_k = P_{k|k-1} / (P_{k|k-1} + R)
kalmanGain = covariancePredicted / (covariancePredicted + MEAS_NOISE_R);
% 状态修正:利用观测残差进行最优估计
% X_{k|k} = X_{k|k-1} + K_k * (Z_k - X_{k|k-1})
measurementResidual = signalNoisy(idx) - statePredicted; % 新息(Innovation)
stateUpdated = statePredicted + kalmanGain * measurementResidual;
% 协方差修正:更新估计不确定性
% P_{k|k} = (1 - K_k) * P_{k|k-1}
covarianceUpdated = (1 - kalmanGain) * covariancePredicted;
% ===== 步骤3: 状态保存(为下一次迭代)=====
statePredPrev = stateUpdated; % 更新状态估计
covariancePrev = covarianceUpdated; % 更新误差协方差
% 记录结果
stateEstimate(idx) = stateUpdated; % 保存滤波结果
kalmanGainLog(idx) = kalmanGain; % 保存增益(用于收敛分析)
% 显示卡尔曼增益(观察收敛过程)
fprintf('Step %04d: Kalman Gain = %.6fn', idx, kalmanGain);
end

卡尔曼增益的收敛

收敛过程分析,从仿真数据中可以清晰地看到卡尔曼增益的收敛轨迹:

初始阶段(Step 0001-0010):

    初始增益:0.268293快速下降:在10步内从0.268降到0.170特性:系统“探索”阶段,对观测值赋予较高权重

稳定阶段(Step 0033-0041):

    稳态增益:0.166667(正好是1/6)收敛值:精确稳定在0.166667数学意义:达到理论稳态解

稳态增益的物理解读

稳态增益K=1/6≈0.166667具有深刻的物理意义: 根据卡尔曼滤波理论,稳态增益公式:K∞ = P∞/(P∞ + R),已知:K∞ = 1/6 = 0.166667,求解:P∞/(P∞ + 3) = 1/6,得:P∞ = 0.6。

    • 过程噪声协方差Q = 0.1观测噪声协方差R = 3.0最终状态估计方差P∞ = 0.6

Image

滤波效果分析

Image

信号跟踪能力:
    蓝色曲线(卡尔曼估计)紧密跟踪绿色曲线(理想信号)即使在方波跳变处,响应迅速,延迟极小滤波后信号平滑,保留了理想信号的完整特征
噪声抑制效果:
    有效抑制了橙色曲线(含噪信号)的高频抖动方波平台期保持平稳,无明显波动信噪比显著提升

响应特性分析

瞬态响应:
    上升时间:方波上升沿响应快速过冲:无明显过冲,稳定平滑建立时间:快速达到稳态值
稳态误差:
    方波平台期跟踪精度高幅值误差极小无累积误差

相关推荐