Токи были странными из-за неправильного определения перехода через ноль и преждевременного открытия тиристоров. Добавлен полосовой фильтр на напряжения, чтобы коммутации тиристоров не смещали переход через ноль

А также:
- общий rms ток считается через сумму rms фаз, а не по векторам
- в установку угла добавлен аргумент коррекции - пока только смщеение между фазными и линейными. Фильтр практически не смещает, но еще посмотрим
- коэф пид приведены к диапзону 0-1
- ПИД надо еще донастраивать. не нравится пока как он работает

И еще не были проверены тайминги. Мб это не будет успевать рассчитываться)))
This commit is contained in:
2025-12-06 18:14:56 +03:00
parent 1690cdcb93
commit 9234b4508b
16 changed files with 792 additions and 330 deletions

View File

@@ -0,0 +1,199 @@
%% МОДЕЛИРОВАНИЕ ПОЛОСОВОГО ФИЛЬТРА С ДИФФЕРЕНЦИАТОРОМ
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');