Domanda

Questa domanda si basa su una precedente domanda simile.

Ho la seguente equazione e aggiustato (alcuni dati casuali): 0,44 * sin (N * 2 * PI / 30)

Sto cercando di utilizzare la FFT per ottenere la frequenza dai dati generati. Tuttavia la frequenza finisce per essere vicino ma non uguale alla frequenza (che rende l'onda un po 'più grande destinato)

Le frequenze che sono al massimo per la FFT è 7 Hz, tuttavia la frequenza attesa è (30 / 2PI) 4.77hz.

Ho incluso un grafico della FFT e valori tracciati.

alt text

Il codice che sto usando è:

[sampleFFTValues sFreq] = positiveFFT(sampledata, 1);
sampleFFTValues = abs(sampleFFTValues);
[v sFFTV]= max(sampleFFTValues)

FFT positivo può essere trovato qui . Fondamentalmente si centra il grafico FFT e taglia i segnali negativi.

La mia domanda è come posso ottenere la FFT per essere più precisi, senza dover ricorrere a minimi quadrati solo per la frequenza?

È stato utile?

Soluzione

Non credo FFT è buono per una misura di frequenza fine-risoluzione per la (quasi) segnali periodici - Vedere di seguito.

Ogni discreta FFT ha diffondendo su frequenze bin non interi (cioè su qualsiasi frequenza che non corrisponde esattamente a uno dei passi di frequenza del particolare FFT); queste frequenze "intermedi" saranno macchiate / sparsi in tutto il bidone intero più vicino. La forma di questo ( "funzione diffusione") diffusione dipende dalla funzione finestre usato per la FFT. Questa funzione diffusione - semplificare e generalizzare cose - o è molto stretta, ma molto-molto frastagliato (molto elevati picchi / valli molto bassi), o più ampia ma meno irregolare. In teoria, si potrebbe fare una scansione di frequenza molto fine di onde sinusoidali e calcolare FFT per ciascuno di essi, e quindi si potrebbe "tarare" la forma e il comportamento della funzione salvando le uscite di tutti FFT insieme con la frequenza che ha condotto a tale uscita, e poi confrontando l'uscita FFT del segnale da misurare i risultati salvati in precedenza e trovare il "più vicino" uno trovare una frequenza più precisa.

Un sacco di sforzo.

Ma non fare questo se avete bisogno solo di misurare la frequenza di un singolo segnale.

cercare Invece di misurare la lunghezza d'onda. Questo può essere semplice come la misurazione della distanza tra lo zero incroci (forse per più cicli per ottenere più precisione - diamine, misura 1000 cicli se si dispone che molti) nei campioni, e dividere la frequenza di campionamento da quello di arrivare alla frequenza. Molto più semplice, più veloce e molto più precisa.

Esempio: frequenza di campionamento 48000 Hz, 4,77 Hz risultati segnale in ~ risoluzione 0,0005 Hz semplicemente misurando la lunghezza di una ciclo con l'approccio più cruda. (Se si prende n cicli, le moltiplica risoluzione di frequenza per n pure.)

Altri suggerimenti

Come detto da altri, si sta interpretando male la frequenza del segnale. Faccio un esempio per chiarire un paio di cose:

Fs = 200;                        %# sampling rate
t = 0:1/Fs:1-1/Fs;               %# time vector of 1 second 
f = 6;                           %# frequency of signal
x = 0.44*sin(2*pi*f*t);          %# sine wave

N = length(x);                   %# length of signal
nfft = N;                        %# n-point DFT, by default nfft=length(x)
                                 %# (Note: it is faster if nfft is a power of 2)
X = abs(fft(x,nfft)).^2 / nfft;  %# square of the magnitude of FFT

cutOff = ceil((nfft+1)/2);       %# nyquist frequency
X = X(1:cutOff);                 %# FFT is symmetric, take first half
X(2:end -1) = 2 * X(2:end -1);   %# compensate for the energy of the other half
fr = (0:cutOff-1)*Fs/nfft;       %# frequency vector

subplot(211), plot(t, x)
title('Signal (Time Domain)')
xlabel('Time (sec)'), ylabel('Amplitude')

subplot(212), stem(fr, X)
title('Power Spectrum (Frequency Domain)')
xlabel('Frequency (Hz)'), ylabel('Power')

time_frequency_domain

Ora si può vedere che il picco nella FFT corrisponde alla frequenza originale del segnale a 6 Hz

[v idx] = max(X);
fr(idx)
ans = 
      6

Si può anche verificare che di Parseval teorema detiene:

( sum(x.^2) - sum(X) )/nfft < 1e-6

Opzione 2

In alternativa, si possono usare le funzioni di elaborazione del segnale Toolbox:

%# estimate the power spectral density (PSD) using the periodogram
h = spectrum.periodogram;
hopts = psdopts(h);
set(hopts, 'Fs',Fs, 'NFFT',nfft, 'SpectrumType','onesided')

hpsd = psd(h, x, hopts);
figure, plot(hpsd)

Pxx = hpsd.Data;
fr = hpsd.Frequencies;
[v idx]= max(Pxx)
fr(idx)

avgpower(hpsd)

periodogramma

Si noti che questa funzione utilizza una scala logaritmica: plot(fr,10*log10(Pxx)) anziché plot(fr,Pxx)

Supponendo N è il tempo in secondi, la frequenza è di 1 / 30Hz (y=A * sin( 2* PI * f * t))

Risoluzione Frequenza = frequenza di campionamento / FFT Punti

La frequenza di campionamento è determinato dal criterio di Nyquist, la frequenza di campionamento (campioni / secondo) deve essere almeno due volte la massima frequenza da analizzare, ad esempio 48kHz per analizzare fino a 24kHz. (Per i dati "vita reale", è bene avere un po 'di un buffer).

Quindi, potrebbe essere necessario aumentare la dimensione della vostra FFT.

Quello che state cercando è un metodo di stima di frequenza, e ci sono molti. Un FFT è un componente di diversi metodi di stima. Usando solo la grandezza bin picco, come nel tuo esempio, si dà la risoluzione peggiore (ma la più grande immunità al rumore a qualsiasi altro sinusoidi esattamente periodici). In situazioni di basso rumore, è possibile interpolare. interpolazione parabolica dell'entità log è uno stimatore comune, ma Sync interpolazione dei risultati FFT può essere meglio per una finestra rettangolare. Zero padding e facendo una FFT più equivale sostanzialmente a interpolazione.

Per una sinusoide è a zero rumore, dimentica la FFT, e solo risolvere l'equazione in 3 incognite, che può comportare appena 3 o 4 punti campione non-aliasing, algoritmi per fare questo qui e qui .

Ne elenco alcuni altri metodi di stima di frequenza sul mio pagina web DSP .

Se si sta generando da una funzione, rispetto a lavorare con i campioni, è possibile generare un sacco di punti ed eseguire una FFT BIG così i bidoni di frequenza sono molto piccole per alta precisione. Ma non risolverà il problema di fondo.

In primo luogo, una correzione alla tua domanda: (30 / 2PI) non è la frequenza. La frequenza del segnale è 1/30 * qualunque frequenza di campionamento è stata utilizzata. In secondo luogo, mi puoi dire qual è stata la lunghezza del vettore SampleData? Quando FFT restituisce un vettore di valori, i-esimo valore sarà conforme a f_i = i / N, dove N è la lunghezza del vettore e i \ in [0, N-1] Volete i / N per esattamente uguale 1/30 per qualche intero i. In altre parole, dovrebbe N uguale 30 * i, vale a dire, N deve essere un multiplo di 30. Ora, era la lunghezza del vettore è stato utilizzato, un multiplo di 30? se non provare a fare, e che dovrebbe risolvere il problema.

Provare una a finestre funzione ?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top