А также: - общий rms ток считается через сумму rms фаз, а не по векторам - в установку угла добавлен аргумент коррекции - пока только смщеение между фазными и линейными. Фильтр практически не смещает, но еще посмотрим - коэф пид приведены к диапзону 0-1 - ПИД надо еще донастраивать. не нравится пока как он работает И еще не были проверены тайминги. Мб это не будет успевать рассчитываться)))
199 lines
7.2 KiB
Matlab
199 lines
7.2 KiB
Matlab
%% МОДЕЛИРОВАНИЕ ПОЛОСОВОГО ФИЛЬТРА С ДИФФЕРЕНЦИАТОРОМ
|
||
clear all; close all; clc;
|
||
|
||
%% 1. ПАРАМЕТРЫ ФИЛЬТРА (подставь свои значения)
|
||
b0 = 0.000392540911;
|
||
b1 = 0.0;
|
||
b2 = -0.000392540911;
|
||
a1 = -1.99915338;
|
||
a2 = 0.999214947;
|
||
|
||
% Или рассчитай новые:
|
||
center_freq = 50; % Центральная частота (Гц)
|
||
sample_freq = 40000; % Частота дискретизации (Гц)
|
||
bandwidth = 5; % Ширина полосы (Гц)
|
||
|
||
% %% 2. РАСЧЕТ КОЭФФИЦИЕНТОВ (если нужно)
|
||
% if 1 % Поставь 0 если используешь готовые коэффициенты выше
|
||
% % Отношение частот
|
||
% fc_ratio = center_freq / sample_freq;
|
||
% bandwidth_ratio = bandwidth / center_freq;
|
||
%
|
||
% % Расчет коэффициентов полосового фильтра
|
||
% w0 = 2 * pi * fc_ratio;
|
||
% Q = 1 / bandwidth_ratio;
|
||
% alpha = sin(w0) / (2 * Q);
|
||
% cos_w0 = cos(w0);
|
||
%
|
||
% % Коэффициенты биквадратного полосового фильтра
|
||
% b0_bp = alpha;
|
||
% b1_bp = 0;
|
||
% b2_bp = -alpha;
|
||
% a0_bp = 1 + alpha;
|
||
% a1_bp = -2 * cos_w0;
|
||
% a2_bp = 1 - alpha;
|
||
%
|
||
% % Нормализация (a0 = 1)
|
||
% 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;
|
||
% end
|
||
|
||
fprintf('Коэффициенты фильтра:\n');
|
||
fprintf('b0 = %.6f\n', b0);
|
||
fprintf('b1 = %.6f\n', b1);
|
||
fprintf('b2 = %.6f\n', b2);
|
||
fprintf('a1 = %.6f\n', a1);
|
||
fprintf('a2 = %.6f\n', a2);
|
||
|
||
%% 3. ПРОВЕРКА УСТОЙЧИВОСТИ
|
||
poles = roots([1, a1, a2]);
|
||
fprintf('\nПолюса фильтра:\n');
|
||
for i = 1:length(poles)
|
||
fprintf(' pole%d = %.6f %+.6fj (|pole| = %.6f)\n', ...
|
||
i, real(poles(i)), imag(poles(i)), abs(poles(i)));
|
||
end
|
||
|
||
if any(abs(poles) >= 1)
|
||
fprintf('⚠️ ВНИМАНИЕ: Фильтр НЕУСТОЙЧИВ!\n');
|
||
else
|
||
fprintf('✅ Фильтр устойчив\n');
|
||
end
|
||
|
||
%% 5. ЧАСТОТНАЯ ХАРАКТЕРИСТИКА ПОЛНОГО ФИЛЬТРА (с дифференциатором)
|
||
% Дифференциатор: H_diff(z) = 1 - z^-1
|
||
b_diff = [1, -1];
|
||
a_diff = 1;
|
||
|
||
% % Каскадное соединение: дифференциатор + полосовой фильтр
|
||
% b_total = conv(b_diff, b_bp); % Перемножение полиномов
|
||
% a_total = conv(a_diff, a_bp);
|
||
% полосовой фильтр
|
||
b_total = [b0, b1, b2];
|
||
a_total = [1, a1, a2];
|
||
|
||
[h_total, f_total] = freqz(b_total, a_total, 2048, sample_freq);
|
||
|
||
figure();
|
||
subplot(1,2,1);
|
||
plot(f_total, 20*log10(abs(h_total)), 'r', 'LineWidth', 2);
|
||
grid on; hold on;
|
||
xline(center_freq, '--r', sprintf('%d Гц', center_freq), 'LineWidth', 1.5);
|
||
xlim([0, sample_freq/2]);
|
||
ylim([-60, 20]);
|
||
xlabel('Частота (Гц)');
|
||
ylabel('Усиление (дБ)');
|
||
title('АЧХ полного фильтра (дифференциатор + полосовой)');
|
||
|
||
subplot(1,2,2);
|
||
plot(f_total, angle(h_total)*180/pi, 'r', 'LineWidth', 2);
|
||
grid on; hold on;
|
||
xline(center_freq, '--r', sprintf('%d Гц', center_freq), 'LineWidth', 1.5);
|
||
xlim([0, sample_freq/2]);
|
||
xlabel('Частота (Гц)');
|
||
ylabel('Фаза (градусы)');
|
||
title('ФЧХ полного фильтра (дифференциатор + полосовой)');
|
||
|
||
%% 6. МОДЕЛИРОВАНИЕ ВО ВРЕМЕННОЙ ОБЛАСТИ
|
||
% Создаем тестовый сигнал
|
||
duration = 0.2; % 200 мс
|
||
t = 0:1/sample_freq:duration;
|
||
|
||
% Сигнал 50 Гц + шум
|
||
signal_freq = 50;
|
||
signal = sin(2*pi*signal_freq*t) + 0.1*randn(size(t));
|
||
|
||
% Имитация работы твоего кода на C
|
||
% Прямая форма II с дифференциатором
|
||
x1 = 0; x2 = 0; % Состояния входа фильтра
|
||
y1 = 0; y2 = 0; % Состояния выхода фильтра
|
||
prev_input = 0; % Для дифференциатора
|
||
|
||
filtered_signal = zeros(size(signal));
|
||
|
||
for i = 1:length(signal)
|
||
% 1. Дифференциатор
|
||
diff = signal(i);
|
||
prev_input = signal(i);
|
||
|
||
% 2. Полосовой фильтр (прямая форма II)
|
||
y = b0*diff + b1*x1 + b2*x2 - a1*y1 - a2*y2;
|
||
|
||
% 3. Обновление состояний
|
||
x2 = x1;
|
||
x1 = diff;
|
||
y2 = y1;
|
||
y1 = y;
|
||
|
||
filtered_signal(i) = y;
|
||
end
|
||
|
||
% Встроенная функция MATLAB для сравнения
|
||
filtered_matlab = filter(b_total, a_total, signal);
|
||
|
||
figure();
|
||
|
||
% Сигнал и выход
|
||
subplot(2,1,1);
|
||
plot(t, signal, 'b', 'LineWidth', 1);
|
||
hold on; grid on;
|
||
plot(t, filtered_signal, 'r', 'LineWidth', 2);
|
||
plot(t, filtered_matlab, 'g--', 'LineWidth', 1);
|
||
xlabel('Время (с)');
|
||
ylabel('Амплитуда');
|
||
legend('Исходный сигнал', 'Наш фильтр (имитация C)', 'MATLAB filter()', ...
|
||
'Location', 'best');
|
||
title(sprintf('Тестовый сигнал: %d Гц + помеха 150 Гц + шум', signal_freq));
|
||
|
||
% Ошибка между нашей реализацией и MATLAB
|
||
subplot(2,1,2);
|
||
error = filtered_signal - filtered_matlab;
|
||
plot(t, error, 'k', 'LineWidth', 1);
|
||
grid on;
|
||
xlabel('Время (с)');
|
||
ylabel('Ошибка');
|
||
title('Разница между нашей реализацией и MATLAB filter()');
|
||
fprintf('\nМаксимальная ошибка: %.2e\n', max(abs(error)));
|
||
|
||
%% 7. АНАЛИЗ НА ЧАСТОТЕ 50 Гц
|
||
freq_test = 50;
|
||
w_test = 2*pi*freq_test/sample_freq;
|
||
z = exp(1i*w_test);
|
||
|
||
% Передаточная функция полного фильтра
|
||
H_z = (b0 + b1*z^-1 + b2*z^-2) / (1 + a1*z^-1 + a2*z^-2) * (1 - z^-1);
|
||
|
||
fprintf('\n══════════════════════════════════════════════════\n');
|
||
fprintf('АНАЛИЗ НА %d Гц:\n', freq_test);
|
||
fprintf('Усиление: %.3f (%.2f дБ)\n', abs(H_z), 20*log10(abs(H_z)));
|
||
fprintf('Фазовый сдвиг: %.1f градусов\n', angle(H_z)*180/pi);
|
||
fprintf('Задержка: %.2f мс (фазовая)\n', -angle(H_z)*1000/(2*pi*freq_test));
|
||
fprintf('══════════════════════════════════════════════════\n');
|
||
|
||
%% 8. ГРАФИК ПОЛЮСОВ И НУЛЕЙ
|
||
figure();
|
||
|
||
% Единичная окружность
|
||
theta = linspace(0, 2*pi, 100);
|
||
plot(cos(theta), sin(theta), 'k--', 'LineWidth', 1);
|
||
hold on; grid on; axis equal;
|
||
|
||
% Полюса (красные кресты)
|
||
plot(real(poles), imag(poles), 'rx', 'MarkerSize', 15, 'LineWidth', 2);
|
||
|
||
% Нули полосового фильтра
|
||
zeros_bp = roots([b0, b1, b2]);
|
||
plot(real(zeros_bp), imag(zeros_bp), 'bo', 'MarkerSize', 10, 'LineWidth', 2);
|
||
|
||
% Нули дифференциатора (z=1)
|
||
plot(1, 0, 'go', 'MarkerSize', 10, 'LineWidth', 2);
|
||
|
||
xlim([-1.2, 1.2]);
|
||
ylim([-1.2, 1.2]);
|
||
xlabel('Re(z)');
|
||
ylabel('Im(z)');
|
||
title('Диаграмма полюсов и нулей фильтра');
|
||
legend('Единичная окружность', 'Полюса', 'Нули полосового фильтра', ...
|
||
'Нуль дифференциатора (z=1)', 'Location', 'best'); |