Чи існує алгоритм для обчислення фази для однієї фрекету?


17

Якщо у вас є функція f(t)=Asin(ωt+ϕ) та опорна син хвиля sin(ωx) який би був швидкий алгоритм для обчислення ϕ ?

Я дивився алгоритм Ґерцеля , але він, схоже, не має відношення до фази?

Відповіді:


5

Використовуйте DFT на певній частоті. Потім обчисліть амплітуду та фазу з реальних / зображень частин. Це дає вам фазу, на яку посилається початок часу вибірки.

У нормальній FFT (або DFT, обчисленій для всіх N гармонік), ти зазвичай обчислюєш частоту з f = k * (sample_rate) / N, де k - ціле число. Хоча це може здатися божевільним (особливо для членів Церкви цілого цілого цілого), ви можете насправді використовувати не цілі значення k при виконанні однієї DFT.

Наприклад, припустимо, що ви створили (або отримали) N = 256 точок синусоїди в 27 Гц. (скажімо, sample_rate = 200). Ваші "звичайні" частоти для 256-кратної FFT (або N точки DFT) відповідали б: f = k * (sample_rate) / N = k * (200) / 256, де k - ціле число. Але не ціле число 'k' 34,56 відповідало б частоті 27 Гц, використовуючи перелічені вище параметри. Це як створити DFT "смітник", який точно орієнтований на частоту, що цікавить (27 Гц.). Деякий код C ++ (компілятор DevC ++) може виглядати наступним чином:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;

// arguments in main needed for Dev-C++ I/O
int main (int nNumberofArgs, char* pszArgs[ ] ) {
const long N = 256 ;
double sample_rate = 200., amp, phase, t, C, S, twopi = 6.2831853071795865; 
double  r[N] = {0.}, i[N] = {0.}, R = 0., I = 0. ;
long n ;

// k need not be integer
double k = 34.56;

// generate real points
for (n = 0; n < N; n++) {
    t =  n/sample_rate;
    r[n] = 10.*cos(twopi*27.*t - twopi/4.);
}  // end for

// compute one DFT
for (n = 0; n < N; n++) {
    C = cos(twopi*n*k/N); S = sin(twopi*n*k/N);
    R = R + r[n]*C + i[n]*S;
    I = I + i[n]*C - r[n]*S;
} // end for

cout<<"\n\ndft results for N = " << N << "\n";
cout<<"\nindex k     real          imaginary       amplitude         phase\n";

amp = 2*sqrt( (R/N)*(R/N) + (I/N)*(I/N) ) ;
phase = atan2( I, R ) ;
// printed R and I are scaled
printf("%4.2f\t%11.8f\t%11.8f\t%11.8f\t%11.8f\n",k,R/N,I/N,amp,phase);

cout << "\n\n";
system ("PAUSE");
return 0;
} // end main

//**** end program

(PS: Я сподіваюся, що вищесказане добре перекладається на stackoverflow - частина цього може обернутися)

Результатом вищесказаного є фаза -twopi / 4, як показано в генерованих реальних точках (а підсилювач подвоюється, щоб відображати частоту pos / neg).

Кілька речей, які слід зазначити - я використовую косинус для генерування форми тестової хвилі та інтерпретації результатів - ви повинні бути обережними з цього приводу - фаза посилається на час = 0, тобто коли ви почали вибірку (тобто: коли ви збирали r [0] ), а косинус - це правильне тлумачення).

Вищевказаний код не є ні елегантним, ні ефективним (наприклад: використовуйте оглядові таблиці для значень sin / cos тощо).

Ваші результати стануть більш точними, коли ви використовуєте більший N, і є невелика помилка через те, що частота вибірки та N вище не кратні один одному.

Звичайно, якщо ви хочете змінити швидкість вибірки, N або f, вам доведеться змінити код і значення k. Ви можете збивати бункер DFT в будь-якій точці лінії безперервної частоти - просто переконайтеся, що ви використовуєте значення k, яке відповідає частоті, що цікавить.


Цей підхід можна вдосконалити, налаштувавши N, щоб k наблизився до цілого. Я опублікував окрему відповідь, яка зменшує точність цього алгоритму.
mojuba

10

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

F(ϕ)=12i=1n[Asin(ωi+ϕ)fi(ω)]2

F(ϕ)ϕ

Похідна дуже проста:

F(ϕ)=i=1nAcos(ωi+ϕ)[Asin(ωi+ϕ)fi(ω)]

F(ϕ)

Очевидно, що вищевказана цільова функція має декілька мінімумів через періодичність, отже, може бути доданий певний стягнення для розмежування інших мінімумів (наприклад, додавання до рівняння моделі). Але я думаю , що оптимізація буде просто сходитися до найближчого мінімуму , і ви можете оновити результат віднімання . 2 π k , k Nϕ22πk,kN


Я не думаю, що потрібно штрафувати через періодичність ні? Ви можете просто взяти будь-які мінімуми у фазовому просторі, до якого він сходиться, і зробити модуль , ні? 2π
Спейсі

@Mohammad Так, але деякі методи оптимізації можуть використовувати декілька вихідних точок, які повинні сходитися до одного значення або приймати опуклу функцію з єдиним глобальним мінімізатором, який може бути добре наближений до квадратичного. Інша перевага полягає в тому, що ми закінчуємо однаковим результатом для будь-якої початкової точки . ϕ0
Лібор

Цікаво. Чи можу я запропонувати вам також розірвати це питання ? :-)
Spacey

@Mohammad Добре, я там трохи долучився :)
Libor

Куди йде функція fi (w)? fi (w) не є константою, тому коли ви берете похідну від постійної, як вона стає нульовою?
SamFisher83

5

Існує кілька різних формулювань алгоритму Ґерцеля. Ті, що забезпечують 2 змінних стану (ортогональні або близькі до), або складну змінну стану, як можливі виходи, часто можуть бути використані для обчислення або оцінки фази з посиланням на деяку точку вікна Ґерцеля, наприклад середину. Ті, які забезпечують одиночний скалярний вихід, як правило, не можуть.

Вам також потрібно знати, де знаходиться ваше вікно Ґерцеля стосовно вашої часової осі.

Якщо ваш сигнал не є точно цілим періодичним періодом у вашому вікні Ґерцеля, фазова оцінка навколо опорної точки посередині вікна може бути точнішою, ніж посилання фази на початок чи кінець.

Повний FFT є надмірним, якщо ви знаєте частоту сигналу. Крім того, Ґерцель може бути налаштований на частоту, не періодичну по довжині FFT, тоді як для FFT знадобиться додаткова інтерполяція або нульове набивання для неперіодичних віконних частот.

Складний Ґерцель еквівалентний 1 бункеру DFT, який використовує повтор для косинусних і синусоїдних векторів або коефіцієнтів зміщення FFT.


Чи не фазова оцінка де-небудь у вікні абсолютно однакової точності, тому що ви просто додасте до фазової оцінки на початку вікна, щоб обчислити оцінку фази в зразку всередині вікна ( є початком вікна)? k k = 0ωkkk=0
Оллі Ніемітало

Ні, тому що додавання wk призводить до іншої фази в кінці вікна, ніж на початку для синусоїди без цілого числа, періодичної діафрагми. Але 1-бін DFT обчислює одну кругову фазу в тій же точці. Таким чином, всі 3 значення будуть різними. Але центральна фаза завжди пов'язана зі співвідношенням непарної / парної функції, незалежно від того, яка f0.
hotpaw2

Намагаюся, але я цього не розумію.
Оллі Ніемітало

Використовуйте косинус (фаза нуля при k = 0), трохи змініть частоту (на крихітне ірраціональне число, але без зміни фази на k = 0). DFT повідомляє, що фаза змінилася! Спробуйте те ж саме з косинусом, точно в центрі k = N / 2. Немає змін при k = N / 2 для жодного df. Те саме для гріха чи будь-якої суміші. Центрирування опорної точки фази показує менші зміни вимірюваної фази зі змінами f0. наприклад, помилка частоти не сприяє збільшенню помилок вимірювання фаз.
hotpaw2

1
Так, помилка оцінки фази, яка менша в центрі вікна, має сенс, якщо синусоїда та фільтр Ґерцеля знаходяться на різних частотах. У цьому випадку фазова оцінка в кінці вікна зміщується на постійну, яка є добутком відстані між центром та кінцем вікна та різниці між частотами фільтра синусоїди та Ґерцеля. Віднімання цього зміщення дає таку ж похибку розміру, що і для центральної оцінки, але для цього потрібно знати частоту синусоїди.
Оллі Ніемітало

4

Якщо ваші сигнали безшумні, ви можете ідентифікувати нульові переходи в обох і визначити частоту та відносну фазу.


3

Це залежить від того, яке ваше визначення "швидкий" - це, наскільки точна ви хочете оцінити, чи хочете ви або фазу відносно ваших вибірок, і скільки шуму є у вашої функції та опорної синусоїди.ϕ

Один із способів зробити це - просто взяти FFT і просто подивитися на бункер, найближчий до . ωf(t)ω Однак це залежатиме від наближення до частоти центрального біна.ω

Так:

  • Що ви маєте на увазі під швидким?
  • Наскільки точна вам потрібна оцінка?
  • Ви хочете (відносна фаза) або фаза відносно початку вибірки? Це важливо?ϕ
  • Який рівень шуму кожного сигналу?

PS: Я припускаю, що ви мали на увазі , а не .f(t)=Asin(ωt+ϕ)f(t)=Asin(ωx+ϕ)


2

Початкова точка:
1) помножте свій сигнал і опорну грішну хвилю: = A⋅sin (ωt + ϕ) ⋅sin (ωt) = 0,5⋅A⋅ (cos (ϕ) - cos (2⋅ωt + ϕ) ) 2) знайти інтеграл на період : 3) можна обчислити :
T = π / ω I ( ϕ ) = T 0 F ( t ) d t = 0,5 A c o s ( ϕ ) T ϕ c o s ( ϕ ) = I ( t ) / ( 0,5 A T )F(t)
T=π/ω
I(ϕ)=0TF(t)dt =0.5Acos(ϕ)T
ϕ
cos(ϕ)=I(t)/(0.5AT)

Подумайте:
як виміряти А?
як визначити через інтервал ? (подумайте про "еталонну хвилю cos ")0 .. ( 2 π )ϕ0..(2π)

Для дискретного сигналу змініть інтеграл на суму і обережно виберіть T!


1

Ви також можете це зробити (у нумерованому позначенні):

np.arctan( (signal*cos).sum() / (signal*sin).sum() ))

де сигнал - ваш фазовий зміщений сигнал, cos і sin є опорними сигналами, і ви генеруєте наближення інтеграла протягом певного часу шляхом підсумовування двох продуктів.


0

Це вдосконалення щодо пропозиції @Kevin McGee використовувати одночастотний DFT з індексом дробової бінки. Алгоритм Кевіна не дає великих результатів: в той час як на половині і цілих бункерах він дуже точний, також близький до цілих і половинок, це також досить добре, але в іншому випадку помилка може бути в межах 5%, що, мабуть, не прийнятно для більшості завдань .

Я пропоную вдосконалити алгоритм Кевіна, регулюючи , тобто довжину вікна DFT, щоб наблизився до цілого, наскільки це можливо. Це працює, оскільки на відміну від FFT, DFT не вимагає, щоб був потужністю 2.NkN

Нижче наведений код у Swift, але він повинен бути зрозумілим:

let f = 27.0 // frequency of the sinusoid we are going to generate
let S = 200.0 // sampling rate
let Nmax = 512 // max DFT window length
let twopi = 2 * Double.pi

// First, calculate k for Nmax, and then round it
var k = round(f * Double(Nmax) / S)

// The magic part: recalculate N to make k as close to whole as possible
// We also need to recalculate k once again due to rounding of N. This is important.
let N = Int(k * S / f)
k = f * Double(N) / S

// Generate the sinusoid
var r: [Double] = []
for i in 0..<N {
    let t = Double(i) / S
    r.append(sin(twopi * f * t))
}

// Compute single-frequency DFT
var R = 0.0, I = 0.0
let twopikn = twopi * k / Double(N)
for i in 0..<N {
    let x = Double(i) * twopikn
    R += r[i] * cos(x)
    I += r[i] * sin(x)
}
R /= Double(N)
I /= Double(N)

let amp = 2 * sqrt(R * R + I * I)
let phase = atan2(I, R) / twopi

print(String(format: "k = %.2f    R = %.8f    I = %.8f    A = %.8f    φ/2π = %.8f", k, R, I, amp, phase))

FFT - це просто спосіб обчислити DFT ефективно. У сучасних бібліотеках потужність двох обмежень вже не існує. Якщо вам потрібно лише одне або два значення біна, то краще обчислити їх безпосередньо так, як ви робили. Для одного чистого тону (реального або складного) потрібні лише два значення біна, щоб точно обчислити частоту, фазу та амплітуду. Див. Dsprelated.com/showarticle/1284.php . Математика досить складна, але є посилання на статті, де пояснюються виводи. Лінійна алгебра є необхідною умовою справжнього розуміння.
Кедрон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.