177 lines
7.9 KiB
Matlab
177 lines
7.9 KiB
Matlab
%% КЛАСС ДЛЯ РАСЧЕТА КОЭФФИЦИЕНТОВ БИКВАДРАТНЫХ ФИЛЬТРОВ
|
||
classdef BiquadFilterDesigner
|
||
%BIQUADFILTERDESIGNER Класс для расчета коэффициентов биквадратных фильтров
|
||
% Поддерживает: ФНЧ, ФВЧ, полосовые, режекторные фильтры
|
||
|
||
methods (Static)
|
||
|
||
%% 1. ФНЧ (Low-Pass Filter)
|
||
function [b, a, coeffs_cmsis] = lpf(fc, Fs, Q)
|
||
% lpf - Расчет коэффициентов ФНЧ через MATLAB функции
|
||
% fc - частота среза [Гц]
|
||
% Fs - частота дискретизации [Гц]
|
||
|
||
if fc >= Fs/2
|
||
error('Частота среза должна быть меньше Fs/2');
|
||
end
|
||
|
||
% Используем встроенные функции MATLAB
|
||
if nargin < 3
|
||
% По умолчанию - Баттерворт
|
||
[b, a] = butter(2, fc/(Fs/2), 'low');
|
||
else
|
||
% С указанной добротностью
|
||
[b, a] = butter(2, fc/(Fs/2), 'low');
|
||
end
|
||
|
||
% Стабилизация коэффициентов
|
||
[b, a] = BiquadFilterDesigner.stabilize_filter(b, a);
|
||
|
||
% Формат для CMSIS-DSP [b0, b1, b2, a1, a2]
|
||
coeffs_cmsis = [b(1), b(2), b(3), a(2), a(3)];
|
||
end
|
||
|
||
%% 2. ФВЧ (High-Pass Filter)
|
||
function [b, a, coeffs_cmsis] = hpf(fc, Fs, Q)
|
||
% hpf - Расчет коэффициентов ФВЧ через MATLAB функции
|
||
% fc - частота среза [Гц]
|
||
% Fs - частота дискретизации [Гц]
|
||
|
||
if fc >= Fs/2
|
||
error('Частота среза должна быть меньше Fs/2');
|
||
end
|
||
|
||
% Используем встроенные функции MATLAB
|
||
[b, a] = butter(2, fc/(Fs/2), 'high');
|
||
|
||
% Стабилизация коэффициентов
|
||
[b, a] = BiquadFilterDesigner.stabilize_filter(b, a);
|
||
|
||
coeffs_cmsis = [b(1), b(2), b(3), a(2), a(3)];
|
||
end
|
||
|
||
%% 3. Полосовой фильтр (Band-Pass Filter) - ИСПРАВЛЕННЫЙ
|
||
function [b, a, coeffs_cmsis] = bpf(fc, bw, Fs)
|
||
% bpf - Расчет коэффициентов полосового фильтра через MATLAB функции
|
||
% fc - центральная частота [Гц]
|
||
% bw - ширина полосы [Гц]
|
||
% Fs - частота дискретизации [Гц]
|
||
|
||
f_low = fc - bw/2;
|
||
f_high = fc + bw/2;
|
||
|
||
if f_high >= Fs/2
|
||
error('Верхняя граница полосы должна быть меньше Fs/2');
|
||
end
|
||
|
||
% Используем встроенные функции MATLAB
|
||
[b, a] = butter(2, [f_low, f_high]/(Fs/2), 'bandpass');
|
||
|
||
% Стабилизация коэффициентов
|
||
[b, a] = BiquadFilterDesigner.stabilize_filter(b, a);
|
||
|
||
coeffs_cmsis = [b(1), b(2), b(3), a(2), a(3)];
|
||
end
|
||
|
||
%% 4. Режекторный фильтр (Band-Stop/Notch Filter)
|
||
function [b, a, coeffs_cmsis] = bsf(fc, bw, Fs)
|
||
% bsf - Расчет коэффициентов режекторного фильтра через MATLAB функции
|
||
% fc - центральная частота [Гц]
|
||
% bw - ширина полосы подавления [Гц]
|
||
% Fs - частота дискретизации [Гц]
|
||
|
||
f_low = fc - bw/2;
|
||
f_high = fc + bw/2;
|
||
|
||
if f_high >= Fs/2
|
||
error('Верхняя граница полосы должна быть меньше Fs/2');
|
||
end
|
||
|
||
% Используем встроенные функции MATLAB
|
||
[b, a] = butter(2, [f_low, f_high]/(Fs/2), 'stop');
|
||
|
||
% Стабилизация коэффициентов
|
||
a_stable = a;
|
||
if abs(a(3)) > 0.99
|
||
a_stable(3) = 0.99 * sign(a(3));
|
||
end
|
||
if abs(a(2)) > 1.98
|
||
a_stable(2) = 1.98 * sign(a(2));
|
||
end
|
||
|
||
b = b;
|
||
a = a_stable;
|
||
|
||
coeffs_cmsis = [b(1), b(2), b(3), a(2), a(3)];
|
||
end
|
||
|
||
%% 5. Показать характеристики фильтра
|
||
function show_response(b, a, Fs, filter_name)
|
||
% show_response - Визуализация характеристик фильтра
|
||
% b, a - коэффициенты фильтра
|
||
% Fs - частота дискретизации [Гц]
|
||
% filter_name - название фильтра для заголовка
|
||
|
||
figure('Position', [100, 100, 1000, 700]);
|
||
|
||
% АЧХ
|
||
subplot(2,2,1);
|
||
[h, f] = freqz(b, a, 1024, Fs);
|
||
plot(f, 20*log10(abs(h)), 'LineWidth', 2);
|
||
title([filter_name ' - АЧХ']);
|
||
xlabel('Частота [Гц]'); ylabel('Усиление [дБ]');
|
||
grid on;
|
||
|
||
% ФЧХ
|
||
subplot(2,2,2);
|
||
plot(f, angle(h)*180/pi, 'LineWidth', 2);
|
||
title([filter_name ' - ФЧХ']);
|
||
xlabel('Частота [Гц]'); ylabel('Фаза [градусы]');
|
||
grid on;
|
||
|
||
% Групповая задержка
|
||
subplot(2,2,3);
|
||
[gd, f_gd] = grpdelay(b, a, 1024, Fs);
|
||
plot(f_gd, gd/Fs*1000, 'LineWidth', 2);
|
||
title([filter_name ' - Групповая задержка']);
|
||
xlabel('Частота [Гц]'); ylabel('Задержка [мс]');
|
||
grid on;
|
||
|
||
% Импульсная характеристика
|
||
subplot(2,2,4);
|
||
imp_resp = filter(b, a, [1 zeros(1, 99)]);
|
||
stem(0:99, imp_resp, 'filled', 'MarkerSize', 4);
|
||
title([filter_name ' - Импульсная характеристика']);
|
||
xlabel('Отсчеты'); ylabel('Амплитуда');
|
||
grid on;
|
||
end
|
||
|
||
%% 6. Генерация C-кода для коэффициентов
|
||
function generate_c_code(coeffs, filter_name)
|
||
% generate_c_code - Генерация C-кода для коэффициентов
|
||
% coeffs - коэффициенты в формате CMSIS [b0, b1, b2, a1, a2]
|
||
% filter_name - имя фильтра для переменной
|
||
|
||
fprintf('// Коэффициенты фильтра: %s\n', filter_name);
|
||
fprintf('const float32_t %s_coeffs[5] = {\n', filter_name);
|
||
fprintf(' %.6ff, // b0\n', coeffs(1));
|
||
fprintf(' %.6ff, // b1\n', coeffs(2));
|
||
fprintf(' %.6ff, // b2\n', coeffs(3));
|
||
fprintf(' %.6ff, // a1\n', coeffs(4));
|
||
fprintf(' %.6ff // a2\n', coeffs(5));
|
||
fprintf('};\n\n');
|
||
end
|
||
|
||
function [b_stable, a_stable] = stabilize_filter(b, a)
|
||
a_stable = a;
|
||
% Ограничиваем коэффициенты a для устойчивости
|
||
if abs(a_stable(3)) > 0.95
|
||
a_stable(3) = 0.95 * sign(a_stable(3));
|
||
end
|
||
if abs(a_stable(2)) > 1.9
|
||
a_stable(2) = 1.9 * sign(a_stable(2));
|
||
end
|
||
b_stable = b;
|
||
end
|
||
end
|
||
end |