Нахождение фазы каждой гармоники с помощью БПФ



Я использую Matlab.



У меня есть синусоидальный сигнал:



X (amp: 220 / Freq:50)



К которому я добавляю 3 гармоники:



X1 = > (h2) amp: 30 / Freq: 100 / фаза:30°



X2 = > (h4) amp: 10 / Freq: 200 / фаза:50°



X3 = > (h6) amp: 05 / Freq: 300 / фаза:90°



Я суммирую все сигналы вместе (например, X, содержащий 3 гармоники), результирующий сигнал называется: Xt



Вот код :



%% Original signal
X = 220.*sin(2 .* pi .* 50 .* t);

%% Harmonics
x1 = 30.*sin(2 .* pi .* 100 .* t + 30);
x2 = 10.*sin(2 .* pi .* 200 .* t + 50);
x3 = 05.*sin(2 .* pi .* 300 .* t + 90);

%% adding the harmonics
Xt = X + x1 + x2 + x3;


Вот что я хочу сделать : найти Сигнал 3 гармоник (их амплитуду, частоту и фазу), начиная с суммированного сигнала Xt и зная основной сигнал X (амплитуда и частота) !



До сих пор мне удавалось с помощью fft получать частоты и амплитуды гармоник, теперь проблема заключается в нахождении фаз гармоник (в нашем случае : 30°, 50° и 90°).

765   2  

2 ответов:

FFT возвращает вам массив, состоящий из комплексных чисел. Для определения фаз частотных составляющих необходимо использовать функцию angle() для комплексных чисел. Не забывайте: фаза ваших гармоник должна быть дана в радианах.

Вот код:

Fs = 1000; % Sampling frequency                     

t=0 : 1/Fs : 1-1/Fs; %time

X = 220*sin(2 * pi * 50 * t);

x1 = 30*sin(2*pi*100*t + 30*(pi/180));
x2 = 10*sin(2*pi*200*t + 50*(pi/180));
x3 = 05*sin(2*pi*300*t + 90*(pi/180));

%% adding the harmonics
Xt = X + x1 + x2 + x3;

%Transformation
Y=fft(Xt); %FFT

df=Fs/length(Y); %frequency resolution

f=(0:1:length(Y)/2)*df; %frequency axis


subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum
stem(f, M(1:length(f)), 'LineWidth', 0.5);
xlim([0 350]);
grid on;  

xlabel('Frequency (Hz)')
ylabel('Magnitude');

subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f, P(1:length(f)), 'LineWidth', 0.5);
xlim([0 350]);
grid on;

xlabel('Frequency (Hz)');
ylabel('Phase (degree)');

Это приведет к такому беспорядку (но вы можете очень хорошо видеть свои амплитуды):

Введите описание изображения здесь

На втором графике можно увидеть множество фазовых составляющих. Но если вы устраните все частоты, соответствующие нулевым амплитудам, вы увидите своими фазами.

Вот мы и здесь:

Y=fft(Xt); %FFT

df=Fs/length(Y); %frequency resolution

f=(0:1:length(Y)/2)*df; %frequency axis

subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum

M_rounded = int16(M(1:size(f, 2))); %Limit the frequency range
ind = find(M_rounded ~= 0);

stem(f(ind), M(ind), 'LineWidth', 0.5);
xlim([0 350]);
grid on;  

xlabel('Frequency (Hz)')
ylabel('Magnitude');

subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f(ind), P(ind), 'LineWidth', 0.5);
xlim([0 350]);
ylim([-100 100]);
grid on;

xlabel('Frequency (Hz)');
ylabel('Phase (degree)');

Введите описание изображения здесь

Теперь вы можете видеть фазы, но все они сдвинуты на 90 градусов. Почему? Поскольку FFT работает с cos () вместо sin (), то:
X = 220*sin(2*pi*50*t + 0*(pi/180)) = 220*cos(2*pi*50*t - 90*(pi/180));

Обновить

Что делать, если параметры некоторых компонентов сигнала не являются целыми числами?

Добавим новый компонент x4:

x4 = 62.75*cos(2*pi*77.77*t + 57.62*(pi/180));

Использование предоставленного код вы получите следующий сюжет:

БПФ сигнала с вещественными числовыми параметрами

Это не совсем то, что мы ожидали получить, не так ли? Проблема заключается в разрешении частотных выборок. Код аппроксимирует сигнал гармониками, частоты которых дискретизируются с частотой 1 Гц. Очевидно, что недостаточно работать с такими частотами, как 77,77 Гц. Разрешение по частоте равно обратному значению времени сигнала. В нашем предыдущем примере длина сигнала была равна 1 во-вторых, именно поэтому частотная выборка была 1/1s=1Hz. Поэтому для того, чтобы увеличить разрешение, необходимо расширить временное окно обрабатываемого сигнала. Для этого просто исправьте определение vaiable t:
frq_res = 0.01; %desired frequency resolution

t=0 : 1/Fs : 1/frq_res-1/Fs; %time

Это приведет к следующим спектрам:

спектры для сигналов с нецелыми параметрами

Обновление 2

Не имеет значения, какой диапазон частот должен быть проанализирован. Компоненты сигнала могут быть из очень высокого диапазона, что показано на следующем рисунке. образец. Предположим, что сигнал выглядит следующим образом:
f=20e4; % 200 KHz
Xt = sin(2*pi*(f-55)*t + pi/7) + sin(2*pi*(f-200)*t-pi/7);

Вот результирующий сюжет:

Введите описание изображения здесь

Фазы смещены на -90 градусов, что было объяснено ранее.

Вот код:

Fs = 300e4; % Sampling frequency                     

frq_res = 0.1; %desired frequency resolution

t=0 : 1/Fs : 1/frq_res-1/Fs; %time

f=20e4;
Xt = sin(2*pi*(f-55)*t + pi/7) + sin(2*pi*(f-200)*t-pi/7);

Y=fft(Xt); %FFT

df=Fs/length(Y); %frequency resolution

f=(0:1:length(Y)/2)*df; %frequency axis

subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum

M_rounded = int16(M(1:size(f, 2))); %Limit the frequency range
ind = find(M_rounded ~= 0);

stem(f(ind), M(ind), 'LineWidth', 0.5);
xlim([20e4-300 20e4]);
grid on;  

xlabel('Frequency (Hz)')
ylabel('Magnitude');

subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f(ind), P(ind), 'LineWidth', 0.5);
xlim([20e4-300 20e4]);
ylim([-180 180]);
grid on;

xlabel('Frequency (Hz)');
ylabel('Phase (degree)');

Для начала отметим (как вы правильно выяснили в комментариях), что Matlab использует радианы для углов, поэтому гармоники должны быть:

%% Harmonics
x1 = 30.*sin(2 .* pi .* 100 .* t + 30*pi/180);
x2 = 10.*sin(2 .* pi .* 200 .* t + 50*pi/180);
x3 = 05.*sin(2 .* pi .* 300 .* t + 90*pi/180);

простой случай

Процесс оценки амплитуды, частоты и фазы частотных составляющих обычно начинается с быстрого преобразования Фурье (FFT) и выбора наиболее сильных частотных составляющих:
% Compute the frequency spectrum
N  = length(Xt);
Xf = fft(Xt);
Nmax = N/2 + 1;
Xf = Xf(1:Nmax);

% Locate the peaks
largest_peak = max(20*log10(abs(Xf)));
peak_floor   = largest_peak - 100;     % to reject peaks from spectral leakage and noise
[pks,idx] = findpeaks((max(peak_floor, 20*log10(abs(Xf))) - peak_floor)')

Теперь, если основная частота и частота гармоники оказываются точными кратными fs/N, где fs - частота дискретизации, а N - число выборок (в данном случае length(Xt)), тогда тоны будут падать точно на Бин, а частоты, амплитуды и фазы каждого компонента можно довольно легко оценить с помощью:

Amp   = 2*abs(Xf(idx))/N;
freq  = (idx-1)*fs/N;
phase = angle(Xf(idx));
phase = phase - phase(1); % set phase reference to that of the fundamental

Обычная и более сложная реальность

Если, с другой стороны, частотные компоненты не являются точными кратными fs/N, (или, по крайней мере, не известны как точные кратные из fs/N, вы все-таки пытаетесь оценить частоту этих компонентов), то все становится сложнее. Обратите внимание, что это может иметь особенно значительное влияние на оценку фазы.

Начнем с того, что чистый комплексный тон (exp(2*pi*j*n*f/fs)) конечной длины N имеет дискретное преобразование Фурье (DFT), заданное:

Введите описание изображения здесь

Один из подходов к оценке может заключаться в том, чтобы начать с оценки частоты. Амплитуда и фаза могут быть учтены выходим, глядя на соотношение величин двух последовательных бункеров Xf вокруг пика, главным образом на индексы idx(i) и idx(i)+1. В предположении, что эти два бункера испытывают мало помех, тогда отношение может быть выражено следующим образом:
ratio = abs(Xf(idx(i)+1)/Xf(idx)) 
      = abs(sin(pi*frac/N)/sin(pi*(frac-1)/N))
Где частота, подлежащая оценке, равна f = (idx(i)-1 + frac)*fs/N. Затем параметр frac может быть получен с помощью метода Ньютона-Рафсона:
% Solve for "f" for which ratio = sin(pi*frac/N)/sin(pi*(frac-1)/N)
function f = fractional_frequency(ratio, N)

  niter = 20;
  K = (pi/N) * sin(pi/N);
  f = 0;
  for i=1:niter
    a  = sin(pi*f/N);
    b  = sin(pi*(f-1)/N);

    y  = ratio - a/b;
    yp = K / (b^2);
    f = max(-0.5, min(f - y/yp, 0.5));
  end
end

Который мы используем для оценки частоты с помощью:

freq  = zeros(1,length(idx));
for i=1:length(idx)
  ratio = abs(Xf(idx(i)+1))/abs(Xf(idx(i)));
  if (abs(Xf(idx(i)+1)) > abs(Xf(idx(i)-1)))
    ratio = -ratio;
  end

  frac = fractional_frequency(ratio, N)
  freq(i)  = (idx(i)-1+frac)*fs/N;
end

Теперь, когда у нас есть тон частота, мы можем получить амплитуду и фазу, установив уравнение DFT, приведенное выше (где мы также добавляем коэффициент 2 для амплитуды, так как мы имеем дело с реальным тоном):

  Amp(i)   = 2 * abs(Xf(idx(i))) * abs(sin(pi*frac/N)/sin(pi*frac));
  phase(i) = angle( Xf(idx(i)) .* (1-exp(2*pi*frac*j/N)) ./ (1-exp(2*pi*frac*j)) );

И сложить все это вместе:

Amp   = zeros(1,length(idx));
freq  = zeros(1,length(idx));
phase = zeros(1,length(idx));
for i=1:length(idx)
  ratio = abs(Xf(idx(i)+1))/abs(Xf(idx(i)));
  if (abs(Xf(idx(i)+1)) > abs(Xf(idx(i)-1)))
    ratio = -ratio;
  end

  frac = fractional_frequency(ratio, N)
  freq(i)  = (idx(i)-1+frac)*fs/N;
  Amp(i)   = 2 * abs(Xf(idx(i))) * abs(sin(pi*frac/N)/sin(pi*frac));
  phase(i) = angle( Xf(idx(i)) .* (1-exp(2*pi*frac*j/N)) ./ (1-exp(2*pi*frac*j)) );
end
phase = phase - phase(1); % set phase reference to that of the fundamental

Comments

    Ничего не найдено.