Files
UPP/MATLAB/calc_filt.m
Razvalyaev deac6d5b06 Тесты в матлабе
А также:
- Коррекция фазового сдвига фильтра
- Определение порядка фаз
2026-01-30 15:56:09 +03:00

182 lines
6.4 KiB
Matlab
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
clc, clear all
%% Конфигурация фильтра
fs = 1000000/25; % Частота дискретизации = 40000 Гц
fc = 50; % Центральная частота фильтра = 50 Гц
fc_ratio = fc/fs; % 50/40000 = 0.00125
bandwidth_ratio = 0.3; % Полоса 30%
% Создаем фильтр
[b, a] = create_bandpass_filter(fc_ratio, bandwidth_ratio);
%% 1. Расчет ФЧХ для графика (в Гц)
% Частоты для подробного графика
freqslow = 40:0.1:49; % [40 41 ... 49] Гц
freqshigh = 51:0.1:60; % [51 52 ... 60] Гц
freqscenter = 49:0.1:51; % [49.0 49.1 ... 51.0] Гц
freqs_hz = [freqslow, freqscenter, freqshigh]; % Все в Гц
% Преобразуем в нормированные частоты (f/fs)
freqs_ratio = freqs_hz / fs; % Разделить на fs
% Рассчитываем фазы для этих частот
phases = zeros(size(freqs_ratio));
for i = 1:length(freqs_ratio)
phases(i) = calc_phase_at_freq(b, a, freqs_ratio(i));
end
% График ФЧХ (по частоте в Гц)
figure;
plot(freqs_hz, phases, 'b-', 'LineWidth', 2);
xlabel('Частота, Гц');
ylabel('Фаза, градусы');
title(sprintf('ФЧХ фильтра: fc=%d Гц, fs=%d Гц', fc, fs));
grid on;
xlim([40 60]);
%% 2. Табличный расчет (используем ТЕ ЖЕ данные!)
% Используем ТЕ ЖЕ частоты для таблицы
table_freqs_ratio = freqs_ratio; % нормированные частоты
table_phases = phases; % соответствующие фазы
table_freqs_hz = freqs_hz; % частоты в Гц
% Вывод таблицы
fprintf('=== Таблица фазовых сдвигов ===\n');
fprintf('f/fs\t\tФаза, °\t\tЧастота, Гц\n');
fprintf('-------------------------------\n');
for i = 1:length(table_freqs_hz)
fprintf('%.6f\t%6.1f\t\t%6.1f\n', ...
table_freqs_ratio(i), table_phases(i), table_freqs_hz(i));
end
%% 3. Проверка поиска по таблице (ближайшее значение)
% Теперь target_freq ДОЛЖНА быть в нормированных частотах!
% Например, хотим найти фазу для 53 Гц:
target_freq_hz = 53; % 53 Гц
target_freq_ratio = target_freq_hz / fs; % 53/40000 = 0.001325
% Ищем в таблице по нормированным частотам
phase_from_table = get_phase_from_table(table_phases, table_freqs_ratio, target_freq_ratio);
phase_exact = calc_phase_at_freq(b, a, target_freq_ratio);
fprintf('\n=== Проверка поиска по таблице ===\n');
fprintf('Целевая частота: %.3f Гц (%.6f f/fs)\n', target_freq_hz, target_freq_ratio);
fprintf('Из таблицы: %.1f°\n', phase_from_table);
fprintf('Точное значение: %.1f°\n', phase_exact);
fprintf('Погрешность: %.1f°\n', abs(phase_exact - phase_from_table));
%% 4. Дополнительная проверка на разных частотах
test_freqs_hz = [45, 49.5, 50, 50.5, 55]; % Частоты в Гц для проверки
fprintf('\n=== Проверка на разных частотах ===\n');
fprintf('Частота, Гц\tИз таблицы\tТочное\t\tПогрешность\n');
fprintf('-----------------------------------------------\n');
for i = 1:length(test_freqs_hz)
test_freq_hz = test_freqs_hz(i);
test_freq_ratio = test_freq_hz / fs;
% Из таблицы
phase_table = get_phase_from_table(table_phases, table_freqs_ratio, test_freq_ratio);
% Точное значение
phase_exact = calc_phase_at_freq(b, a, test_freq_ratio);
fprintf('%6.1f\t\t%6.1f\t\t%6.1f\t\t%6.1f\n', ...
test_freq_hz, phase_table, phase_exact, abs(phase_exact - phase_table));
end
%% 5. Сравнение идеальной ФЧХ и табличной (ступенчатой)
figure;
% Идеальная ФЧХ (гладкая)
plot(table_freqs_hz, table_phases, 'b-', 'LineWidth', 2);
hold on;
% Табличная ФЧХ (ступенчатая)
stairs(table_freqs_hz, table_phases, 'r-', 'LineWidth', 1.5);
% Точки таблицы
plot(table_freqs_hz, table_phases, 'ko', 'MarkerSize', 5, 'MarkerFaceColor', 'k');
xlabel('Частота, Гц');
ylabel('Фаза, градусы');
title('Сравнение идеальной и табличной ФЧХ');
legend('Идеальная ФЧХ', 'Табличная ФЧХ (ступеньки)', 'Точки таблицы', 'Location', 'best');
grid on;
xlim([40 60]);
%% ФУНКЦИИ
function [b, a] = create_bandpass_filter(fc_ratio, bandwidth_ratio)
w0 = 2 * pi * fc_ratio;
Q = 1 / bandwidth_ratio;
alpha = sin(w0) / (2 * Q);
cos_w0 = cos(w0);
b0_bp = alpha;
b1_bp = 0.0;
b2_bp = -alpha;
a0_bp = 1.0 + alpha;
a1_bp = -2.0 * cos_w0;
a2_bp = 1.0 - alpha;
b0 = b0_bp / a0_bp;
b1 = b1_bp / a0_bp;
b2 = b2_bp / a0_bp;
a1 = a1_bp / a0_bp;
a2 = a2_bp / a0_bp;
b = [b0, b1, b2];
a = [1, a1, a2];
end
function phase_deg = calc_phase_at_freq(b, a, freq_ratio)
omega = 2 * pi * freq_ratio;
cos_w = cos(omega);
sin_w = sin(omega);
cos_2w = cos(2 * omega);
sin_2w = sin(2 * omega);
num_real = b(1) + b(2) * cos_w + b(3) * cos_2w;
num_imag = -b(2) * sin_w - b(3) * sin_2w;
den_real = 1 + a(2) * cos_w + a(3) * cos_2w;
den_imag = -a(2) * sin_w - a(3) * sin_2w;
den_sqr = den_real^2 + den_imag^2;
if den_sqr < 1e-12
phase_deg = 0;
return;
end
H_real = (num_real * den_real + num_imag * den_imag) / den_sqr;
H_imag = (num_imag * den_real - num_real * den_imag) / den_sqr;
phase_rad = atan2(H_imag, H_real);
phase_deg = phase_rad * 180 / pi;
while phase_deg > 180
phase_deg = phase_deg - 360;
end
while phase_deg < -180
phase_deg = phase_deg + 360;
end
end
function phase_table = calc_phase_table(b, a, freq_points)
num_points = length(freq_points);
phase_table = zeros(1, num_points);
for i = 1:num_points
phase_table(i) = calc_phase_at_freq(b, a, freq_points(i));
end
end
function phase = get_phase_from_table(phase_table, freq_table, target_freq)
[~, idx] = min(abs(freq_table - target_freq));
phase = phase_table(idx);
end