идентификация сдвига фаз между сигналами
Я сгенерировал три идентичные волны с фазовым сдвигом в каждой. Например:
t = 1:10800; % generate time vector
fs = 1; % sampling frequency (seconds)
A = 2; % amplitude
P = 1000; % period (seconds), the time it takes for the signal to repeat itself
f1 = 1/P; % number of cycles per second (i.e. how often the signal repeats itself every second).
y1 = A*sin(2*pi*f1*t); % signal 1
phi = 10; % phase shift
y2 = A*sin(2*pi*f1*t + phi); % signal 2
phi = 15; % phase shift
y3 = A*sin(2*pi*f1*t + phi); % signal 3
YY = [y1',y2',y3'];
plot(t,YY)

Теперь я хотел бы использовать метод для обнаружения этого сдвига фаз между волнами. Смысл этого в том, чтобы в конечном итоге применить метод к реальным данным и определить фазовые сдвиги между сигналами.
До сих пор я думал о вычислении поперечных спектров между каждой волной и первой волной (т. е. без фазового сдвига):
for i = 1:3;
[Pxy,Freq] = cpsd(YY(:,1),YY(:,i));
coP = real(Pxy);
quadP = imag(Pxy);
phase(:,i) = atan2(coP,quadP);
end
Но я ... не уверен, что это имеет какой-то смысл.
Кто-нибудь еще делал нечто подобное? Желаемый результат должен показать сдвиг фазы на 10 и 15 для волн 2 и 3 соответственно.
Любой совет был бы признателен.
5 ответов:
Существует несколько способов измерения сдвига фаз между сигналами. Между вашим ответом, комментариями под вашим ответом и другими ответами вы получили большинство вариантов. Конкретный выбор техники обычно основывается на таких вопросах, как:
- шумно или Чисто : есть ли шум в вашем сигнале?
- многокомпонентный или однокомпонентный : существует ли более одного типа сигнала в вашей записи (несколько тонов на несколько частот, движущихся в разных направлениях)? Или есть только один сигнал, как в вашем примере с синусоидальной волной?
- мгновенный или усредненный: вы ищете среднюю фазовую задержку по всей записи, или вы хотите отслеживать, как изменяется фаза на протяжении всей записи?
В зависимости от вашего ответа на эти вопросы, вы можете рассмотреть следующие методы:
Кросс-корреляция : используйте команда типа
[c,lag]=xcorr(y1,y2);для получения перекрестной корреляции между двумя сигналами. Это работает на исходных сигналах временной области. Вы ищете индекс, гдеcявляется максимальным ([maxC,I]=max(c);), а затем получаете значение лага в единицах выборокlag = lag(I);. Этот подход дает вам среднюю фазовую задержку для всей записи. Это требует, чтобы ваш сигнал интереса к записи был сильнее, чем что-либо еще в вашем теле. recording...in другими словами, он чувствителен к шуму и другим вмешательство.частотная область : здесь вы преобразуете свои сигналы в частотную область (используя
fftилиcpsdили что угодно). Затем вы найдете ячейку, которая соответствует частоте, о которой вы заботитесь, и получите угол между двумя сигналами. Так, например, если bin #18 соответствует частоте вашего сигнала, вы получите фазовую задержку в радианах черезphase_rad = angle(fft_y1(18)/fft_y2(18));. Если ваши сигналы имеют постоянную частоту, это отличный подход, потому что это естественно отклоняет все шумы и помехи на других частотах. Вы можете иметь действительно сильные помехи на одной частоте, но вы все еще можете чисто получить свой сигнал на другой частоте. Этот метод не является лучшим для сигналов, которые изменяют частоту во время окна анализа БПФ.преобразование Гильберта : третий метод, часто упускаемый из виду, заключается в преобразовании сигнала временной области в аналитический сигнал с помощью преобразования Гильберта:
y1_h = hilbert(y1);. Как только вы это сделаете, ваш сигнал является вектором комплексных чисел. Вектор, содержащий простую синусоидальную волну во временной области, теперь будет вектором комплексных чисел, величина которых постоянна и фаза которых изменяется синхронно с исходной синусоидальной волной. Эта методика позволяет получить мгновенную фазовую задержку между двумя signals...it мощно:phase_rad = angle(y1_h ./ y2_h);илиphase_rad = wrap(angle(y1_h) - angle(y2_h));. Основное ограничение этого подхода заключается в том, что ваш сигнал должен быть монокомпонентным, то есть ваш сигнал интереса должен доминировать в вашей записи. Поэтому вам, возможно, придется отфильтровать любые существенные помехи, которые могут существовать.
Для двух синусоидальных сигналов фаза комплексного коэффициента корреляции дает вам то, что вы хотите. Я могу только привести пример python (используя scipy), поскольку у меня нет matlab для его тестирования.
x1 = sin( 0.1*arange(1024) ) x2 = sin( 0.1*arange(1024) + 0.456) x1h = hilbert(x1) x2h = hilbert(x2) c = inner( x1h, conj(x2h) ) / sqrt( inner(x1h,conj(x1h)) * inner(x2h,conj(x2h)) ) phase_diff = angle(c)В matlab есть функция corrcoeff, которая тоже должна работать (python One отбрасывает мнимую часть). То есть c = corrcoeff(x1h,x2h) должен работать в matlab.
С правильными сигналами:
t = 1:10800; % generate time vector fs = 1; % sampling frequency (seconds) A = 2; % amplitude P = 1000; % period (seconds), the time it takes for the signal to repeat itself f1 = 1/P; % number of cycles per second (i.e. how often the signal repeats itself every second). y1 = A*sin(2*pi*f1*t); % signal 1 phi = 10*pi/180; % phase shift in radians y2 = A*sin(2*pi*f1*t + phi); % signal 2 phi = 15*pi/180; % phase shift in radians y3 = A*sin(2*pi*f1*t + phi); % signal 3Должно работать следующее:
Достаточно ли этого для ваших "реальных" сигналов, можете сказать только вы.>> acos(dot(y1,y2)/(norm(y1)*norm(y2))) >> ans*180/pi ans = 9.9332 >> acos(dot(y1,y3)/(norm(y1)*norm(y3))) ans = 0.25980 >> ans*180/pi ans = 14.885
Вот небольшая модификация вашего кода:
phi = 10на самом деле в степени, затем в функции синуса, информация о фазе в основном выражается в радиане,поэтому вам нужно изменитьdeg2rad(phi)следующим образом:t = 1:10800; % generate time vector fs = 1; % sampling frequency (seconds) A = 2; % amplitude P = 1000; % period (seconds), the time it takes for the signal to repeat itself f1 = 1/P; % number of cycles per second (i.e. how often the signal repeats itself every second). y1 = A*sin(2*pi*f1*t); % signal 1 phi = deg2rad(10); % phase shift y2 = A*sin(2*pi*f1*t + phi); % signal 2 phi = deg2rad(15); % phase shift y3 = A*sin(2*pi*f1*t + phi); % signal 3 YY = [y1',y2',y3']; plot(t,YY)Затем, используя метод частотной области, как упоминалось chipaudette
Теперь это даст вам оценку сдвига фазы с помощьюfft_y1 = fft(y1); fft_y2 = fft(y2); phase_rad = angle(fft_y1(1:end/2)/fft_y2(1:end/2)); phase_deg = rad2deg(angle(fft_y1(1:end/2)/fft_y2(1:end/2)));error = +-0.2145
Код Matlab для нахождения относительной фазы с использованием перекрестной корреляции:
fr = 20; % input signal freq timeStep = 1e-4; t = 0:timeStep:50; % time vector y1 = sin(2*pi*t); % reference signal ph = 0.5; % phase difference to be detected in radians y2 = 0.9 * sin(2*pi*t + ph); % signal, the phase of which, is to be measured relative to the reference signal [c,lag]=xcorr(y1,y2); % calc. cross-corel-n [maxC,I]=max(c); % find max PH = (lag(I) * timeStep) * 2 * pi; % calculated phase in radians >> PH PH = 0.4995
Comments