UPP/Информация для программиста (УПП СП СЭД)/MATLAB_CALC/calc_biquad.m

295 lines
14 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.

%% Моделирование биквадратных фильтров для АЦП с автоматическим расчетом коэффициентов
clear all; close all; clc;
%% Параметры моделирования
Fs = 100000; % Частота дискретизации [Гц]
T = 0.5; % Время моделирования [с]
t = 0:1/Fs:T-1/Fs; % Временной вектор
N = length(t); % Количество отсчетов
%% Уровни шума для разных каналов
noise_levels.voltage = 0.2; % 2% шума для напряжений
noise_levels.current = 0.2; % 5% шума для токов
noise_levels.temperature = 0.2; % 1% шума для температур
%% АВТОМАТИЧЕСКИЙ РАСЧЕТ КОЭФФИЦИЕНТОВ ЧЕРЕЗ КЛАСС
fprintf('=== АВТОМАТИЧЕСКИЙ РАСЧЕТ КОЭФФИЦИЕНТОВ ФИЛЬТРОВ ===\n\n');
% 1. Полосовой фильтр 45-55 Гц для напряжений
% [b_bpf, a_bpf, coeffs_bpf] = BiquadFilterDesigner.bpf(20, 10, Fs);
[b_bpf, a_bpf, coeffs_bpf] = BiquadFilterDesigner.lpf(100, Fs);
fprintf('1. Полосовой фильтр 45-55 Гц:\n');
BiquadFilterDesigner.generate_c_code(coeffs_bpf, 'voltage_bpf');
% 2. ФНЧ 100 Гц для токов
[b_lpf_current, a_lpf_current, coeffs_lpf_current] = BiquadFilterDesigner.lpf(100, Fs);
fprintf('2. ФНЧ 100 Гц (токи):\n');
BiquadFilterDesigner.generate_c_code(coeffs_lpf_current, 'current_lpf');
% 3. ФНЧ 10 Гц для температур
[b_lpf_temp, a_lpf_temp, coeffs_lpf_temp] = BiquadFilterDesigner.lpf(10, Fs);
fprintf('3. ФНЧ 10 Гц (температуры):\n');
BiquadFilterDesigner.generate_c_code(coeffs_lpf_temp, 'temperature_lpf');
% Вывод коэффициентов в консоль
fprintf('\n=== РАСЧЕТНЫЕ КОЭФФИЦИЕНТЫ ===\n');
fprintf('Напряжение (BPF 45-55 Гц): b = [%.6f, %.6f, %.6f], a = [1, %.6f, %.6f]\n', ...
b_bpf, a_bpf(2), a_bpf(3));
fprintf('Ток (LPF 100 Гц): b = [%.6f, %.6f, %.6f], a = [1, %.6f, %.6f]\n', ...
b_lpf_current, a_lpf_current(2), a_lpf_current(3));
fprintf('Температура (LPF 10 Гц): b = [%.6f, %.6f, %.6f], a = [1, %.6f, %.6f]\n\n', ...
b_lpf_temp, a_lpf_temp(2), a_lpf_temp(3));
%% Генерация тестовых сигналов
% 1. Сетевое напряжение 50 Гц + гармоники
f_net = 50;
voltage_clean = 1.0 * sin(2*pi*f_net*t) + ... % основная 50 Гц
0.1 * sin(2*pi*3*f_net*t) + ... % 3-я гармоника 150 Гц
0.05 * sin(2*pi*5*f_net*t); % 5-я гармоника 250 Гц
% 2. Ток с модуляцией
f_current = 50;
current_clean = 1 * sin(2*pi*f_current*t); %.* ...
%(1 + 0.2 * sin(2*pi*2*t)); % амплитудная модуляция 2 Гц
% 3. Температура (медленно меняющийся сигнал)
temperature_clean = 25 + 2 * sin(2*pi*0.1*t) + ... % медленные колебания 0.1 Гц
0.5 * sin(2*pi*1*t); % быстрые колебания 1 Гц
%% Добавление шума
voltage_noisy = voltage_clean + noise_levels.voltage * randn(size(t));
current_noisy = current_clean + noise_levels.current * randn(size(t));
temperature_noisy = temperature_clean + noise_levels.temperature * randn(size(t));
%% Фильтрация сигналов
voltage_filtered = filter(b_bpf, a_bpf, voltage_noisy);
current_filtered = filter(b_lpf_current, a_lpf_current, current_noisy);
temperature_filtered = filter(b_lpf_temp, a_lpf_temp, temperature_noisy);
%% НОРМАЛИЗАЦИЯ УСИЛЕНИЯ (важно для правильного SNR)
% Получаем АЧХ для нормализации
[h_bpf, f_bpf] = freqz(b_bpf, a_bpf, 1024, Fs);
[h_lpf_curr, f_lpf_curr] = freqz(b_lpf_current, a_lpf_current, 1024, Fs);
[h_lpf_temp, f_lpf_temp] = freqz(b_lpf_temp, a_lpf_temp, 1024, Fs);
% Нормализация полосового фильтра на центральной частоте
[~, idx_50hz] = min(abs(f_bpf - 50));
gain_bpf = abs(h_bpf(idx_50hz));
if gain_bpf > 0
voltage_filtered = voltage_filtered / gain_bpf;
end
% Нормализация ФНЧ на постоянной составляющей
gain_lpf_current = sum(b_lpf_current) / (1 + sum(a_lpf_current(2:end)));
if gain_lpf_current > 0
current_filtered = current_filtered / gain_lpf_current;
end
gain_lpf_temp = sum(b_lpf_temp) / (1 + sum(a_lpf_temp(2:end)));
if gain_lpf_temp > 0
temperature_filtered = temperature_filtered / gain_lpf_temp;
end
%% ОКНО 1: НАПРЯЖЕНИЕ
figure('Name', 'Анализ напряжения');
% Временные характеристики
subplot(2,3,1);
plot(t, voltage_noisy, 'b', 'LineWidth', 1); hold on;
plot(t, voltage_filtered, 'r', 'LineWidth', 2);
plot(t, voltage_clean, 'g--', 'LineWidth', 1);
title('Напряжение: временная область');
legend('С шумом', 'Фильтрованный', 'Идеальный', 'Location', 'best');
xlabel('Время [с]'); ylabel('Амплитуда');
grid on;
% АЧХ фильтра
subplot(2,3,2);
plot(f_bpf, 20*log10(abs(h_bpf)), 'LineWidth', 2);
title('АЧХ: Полосовой фильтр 45-55 Гц');
xlabel('Частота [Гц]'); ylabel('Усиление [дБ]');
grid on; xlim([0, 200]);
% Спектр фильтрованного сигнала
subplot(2,3,3);
[P_voltage, f_voltage] = pwelch(voltage_filtered, [], [], 1024, Fs);
plot(f_voltage, 10*log10(P_voltage), 'LineWidth', 2);
title('Спектр фильтрованного напряжения');
xlabel('Частота [Гц]'); ylabel('Мощность [дБ]');
grid on; xlim([0, 200]);
% Групповая задержка
subplot(2,3,4);
[gd_bpf, f_gd] = grpdelay(b_bpf, a_bpf, 1024, Fs);
plot(f_gd, gd_bpf/Fs*1000, 'LineWidth', 2);
title('Групповая задержка фильтра');
xlabel('Частота [Гц]'); ylabel('Задержка [мс]');
grid on; xlim([0, 100]);
% Детальный вид (последние 0.1 секунды)
idx_end_voltage = max(1, length(t) - 0.1*Fs + 1):length(t); % последние 100 мс
subplot(2,3,5);
plot(t(idx_end_voltage), voltage_noisy(idx_end_voltage), 'b', 'LineWidth', 2); hold on;
plot(t(idx_end_voltage), voltage_filtered(idx_end_voltage), 'r', 'LineWidth', 2);
plot(t(idx_end_voltage), voltage_clean(idx_end_voltage), 'g--', 'LineWidth', 2);
title('Напряжение: УВЕЛИЧЕННЫЙ ВИД (900-1000 мс)');
legend('С шумом', 'Фильтрованный', 'Идеальный', 'Location', 'best');
xlabel('Время [с]'); ylabel('Амплитуда');
grid on;
xlim([t(idx_end_voltage(1)) t(idx_end_voltage(end))]);
% Статистика
subplot(2,3,6);
snr_voltage_in = snr(voltage_clean, voltage_noisy - voltage_clean);
snr_voltage_out = snr(voltage_clean, voltage_filtered - voltage_clean);
improvement_voltage = snr_voltage_out - snr_voltage_in;
text(0.1, 0.8, sprintf('SNR вход: %.1f дБ', snr_voltage_in), 'FontSize', 12);
text(0.1, 0.6, sprintf('SNR выход: %.1f дБ', snr_voltage_out), 'FontSize', 12);
text(0.1, 0.4, sprintf('Улучшение: %.1f дБ', improvement_voltage), 'FontSize', 12);
text(0.1, 0.2, sprintf('Задержка 50 Гц: %.1f мс', gd_bpf(idx_50hz)/Fs*1000), 'FontSize', 12);
title('Статистика фильтрации напряжения');
axis off;
%% ОКНО 2: ТОК
figure('Name', 'Анализ тока');
% Временные характеристики
subplot(2,3,1);
plot(t, current_noisy, 'b', 'LineWidth', 1); hold on;
plot(t, current_filtered, 'r', 'LineWidth', 2);
plot(t, current_clean, 'g--', 'LineWidth', 1);
title('Ток: временная область');
legend('С шумом', 'Фильтрованный', 'Идеальный', 'Location', 'best');
xlabel('Время [с]'); ylabel('Амплитуда');
grid on;
% АЧХ фильтра
subplot(2,3,2);
plot(f_lpf_curr, 20*log10(abs(h_lpf_curr)), 'LineWidth', 2);
title('АЧХ: ФНЧ 100 Гц');
xlabel('Частота [Гц]'); ylabel('Усиление [дБ]');
grid on; xlim([0, 200]);
% Спектр фильтрованного сигнала
subplot(2,3,3);
[P_current, f_current] = pwelch(current_filtered, [], [], 1024, Fs);
plot(f_current, 10*log10(P_current), 'LineWidth', 2);
title('Спектр фильтрованного тока');
xlabel('Частота [Гц]'); ylabel('Мощность [дБ]');
grid on; xlim([0, 200]);
% Групповая задержка
subplot(2,3,4);
[gd_lpf_curr, f_gd] = grpdelay(b_lpf_current, a_lpf_current, 1024, Fs);
plot(f_gd, gd_lpf_curr/Fs*1000, 'LineWidth', 2);
title('Групповая задержка фильтра');
xlabel('Частота [Гц]'); ylabel('Задержка [мс]');
grid on; xlim([0, 100]);
% Детальный вид (последние 0.1 секунды)
idx_end_current = max(1, length(t) - 0.1*Fs + 1):length(t); % последние 100 мс
subplot(2,3,5);
plot(t(idx_end_current), current_noisy(idx_end_current), 'b', 'LineWidth', 2); hold on;
plot(t(idx_end_current), current_filtered(idx_end_current), 'r', 'LineWidth', 2);
plot(t(idx_end_current), current_clean(idx_end_current), 'g--', 'LineWidth', 2);
title('Ток: УВЕЛИЧЕННЫЙ ВИД (900-1000 мс)');
legend('С шумом', 'Фильтрованный', 'Идеальный', 'Location', 'best');
xlabel('Время [с]'); ylabel('Амплитуда');
grid on;
xlim([t(idx_end_current(1)) t(idx_end_current(end))]);
% Статистика
subplot(2,3,6);
snr_current_in = snr(current_clean, current_noisy - current_clean);
snr_current_out = snr(current_clean, current_filtered - current_clean);
improvement_current = snr_current_out - snr_current_in;
[~, idx_50hz_curr] = min(abs(f_gd - 50));
text(0.1, 0.8, sprintf('SNR вход: %.1f дБ', snr_current_in), 'FontSize', 12);
text(0.1, 0.6, sprintf('SNR выход: %.1f дБ', snr_current_out), 'FontSize', 12);
text(0.1, 0.4, sprintf('Улучшение: %.1f дБ', improvement_current), 'FontSize', 12);
text(0.1, 0.2, sprintf('Задержка 50 Гц: %.1f мс', gd_lpf_curr(idx_50hz_curr)/Fs*1000), 'FontSize', 12);
title('Статистика фильтрации тока');
axis off;
%% ОКНО 3: ТЕМПЕРАТУРА
figure('Name', 'Анализ температуры');
% Временные характеристики
subplot(2,3,1);
plot(t, temperature_noisy, 'b', 'LineWidth', 1); hold on;
plot(t, temperature_filtered, 'r', 'LineWidth', 2);
plot(t, temperature_clean, 'g--', 'LineWidth', 1);
title('Температура: временная область');
legend('С шумом', 'Фильтрованный', 'Идеальный', 'Location', 'best');
xlabel('Время [с]'); ylabel('Температура [°C]');
grid on;
% АЧХ фильтра
subplot(2,3,2);
plot(f_lpf_temp, 20*log10(abs(h_lpf_temp)), 'LineWidth', 2);
title('АЧХ: ФНЧ 10 Гц');
xlabel('Частота [Гц]'); ylabel('Усиление [дБ]');
grid on; xlim([0, 20]);
% Спектр фильтрованного сигнала
subplot(2,3,3);
[P_temp, f_temp] = pwelch(temperature_filtered, [], [], 1024, Fs);
plot(f_temp, 10*log10(P_temp), 'LineWidth', 2);
title('Спектр фильтрованной температуры');
xlabel('Частота [Гц]'); ylabel('Мощность [дБ]');
grid on; xlim([0, 10]);
% Групповая задержка
subplot(2,3,4);
[gd_lpf_temp, f_gd_temp] = grpdelay(b_lpf_temp, a_lpf_temp, 1024, Fs);
plot(f_gd_temp, gd_lpf_temp/Fs*1000, 'LineWidth', 2);
title('Групповая задержка фильтра');
xlabel('Частота [Гц]'); ylabel('Задержка [мс]');
grid on; xlim([0, 20]);
% Детальный вид (последне 0.1 секунды)
idx_end_temp = max(1, length(t) - 0.1*Fs + 1):length(t); % последние 100 мс
subplot(2,3,5);
plot(t(idx_end_temp), temperature_noisy(idx_end_temp), 'b', 'LineWidth', 2); hold on;
plot(t(idx_end_temp), temperature_filtered(idx_end_temp), 'r', 'LineWidth', 2);
plot(t(idx_end_temp), temperature_clean(idx_end_temp), 'g--', 'LineWidth', 2);
title('Температура: УВЕЛИЧЕННЫЙ ВИД (900-1000 мс)');
legend('С шумом', 'Фильтрованный', 'Идеальный', 'Location', 'best');
xlabel('Время [с]'); ylabel('Температура [°C]');
grid on;
xlim([t(idx_end_temp(1)) t(idx_end_temp(end))]);
% Статистика
subplot(2,3,6);
snr_temp_in = snr(temperature_clean, temperature_noisy - temperature_clean);
snr_temp_out = snr(temperature_clean, temperature_filtered - temperature_clean);
improvement_temp = snr_temp_out - snr_temp_in;
[~, idx_1hz] = min(abs(f_gd_temp - 1));
text(0.1, 0.8, sprintf('SNR вход: %.1f дБ', snr_temp_in), 'FontSize', 12);
text(0.1, 0.6, sprintf('SNR выход: %.1f дБ', snr_temp_out), 'FontSize', 12);
text(0.1, 0.4, sprintf('Улучшение: %.1f дБ', improvement_temp), 'FontSize', 12);
text(0.1, 0.2, sprintf('Задержка 1 Гц: %.1f мс', gd_lpf_temp(idx_1hz)/Fs*1000), 'FontSize', 12);
title('Статистика фильтрации температуры');
axis off;
%% Вывод результатов в командное окно
fprintf('\n=== ИТОГИ ФИЛЬТРАЦИИ С АВТОРАСЧЕТОМ КОЭФФИЦИЕНТОВ ===\n\n');
fprintf('НАПРЯЖЕНИЕ (полосовой 45-55 Гц):\n');
fprintf(' SNR вход: %.1f дБ, выход: %.1f дБ, улучшение: %.1f дБ\n', ...
snr_voltage_in, snr_voltage_out, improvement_voltage);
fprintf(' Задержка на 50 Гц: %.1f мс\n\n', gd_bpf(idx_50hz)/Fs*1000);
fprintf('ТОК (ФНЧ 100 Гц):\n');
fprintf(' SNR вход: %.1f дБ, выход: %.1f дБ, улучшение: %.1f дБ\n', ...
snr_current_in, snr_current_out, improvement_current);
fprintf(' Задержка на 50 Гц: %.1f мс\n\n', gd_lpf_curr(idx_50hz_curr)/Fs*1000);
fprintf('ТЕМПЕРАТУРА (ФНЧ 10 Гц):\n');
fprintf(' SNR вход: %.1f дБ, выход: %.1f дБ, улучшение: %.1f дБ\n', ...
snr_temp_in, snr_temp_out, improvement_temp);
fprintf(' Задержка на 1 Гц: %.1f мс\n\n', gd_lpf_temp(idx_1hz)/Fs*1000);