web-dev-qa-db-fra.com

Déterminer la fréquence à partir des données de signal dans MATLAB

J'ai des données d'un capteur et j'ai besoin d'en trouver la fréquence. Il semble que fft() semble être la voie à suivre, mais la documentation MATLAB montre uniquement comment obtenir un graphique des fréquences, je ne sais pas quoi faire à partir de là.

Voici à quoi ressemblent mes données:

enter image description here

13
edc1591

Une solution consiste en effet à utiliser un fichier fft. Comme le fft vous donne la représentation en fréquence du signal, vous voulez rechercher le maximum, et comme le fft est un signal complexe, vous voudrez d’abord prendre la valeur absolue. L'indice correspondra à la fréquence normalisée à énergie maximale. Enfin, si votre signal a un décalage, comme c'est le cas avec celui que vous montrez, vous voulez vous en débarrasser avant de prendre le fft afin de ne pas obtenir un maximum à l'origine représentant le composant DC. .

Tout ce que je décris mis dans une ligne serait:

[maxValue,indexMax] = max(abs(fft(signal-mean(signal))));

où indexMax est l'index où la valeur fft maximale peut être trouvée.

Remarque: pour passer d'indexMax à la fréquence réelle d'intérêt, vous devez connaître la longueur L du fft (identique à la longueur de votre signal) et la fréquence d'échantillonnage Fs. La fréquence du signal sera alors:

frequency = indexMax * Fs / L;

Alternativement, plus rapide et fonctionnant assez bien en fonction du signal que vous avez, prenez l'autocorrélation de votre signal:

autocorrelation = xcorr(signal);

et trouver le premier maximum se produisant après le point central de l'autocorrélation. (L'autocorrélation sera symétrique avec son maximum au milieu.) En trouvant ce maximum, vous trouvez le premier endroit où le signal décalé ressemble plus ou moins à lui-même. C'est à dire. vous trouvez la période de votre signal. Étant donné que le signal décalé d’un multiple de sa période se ressemblera toujours, vous devez vous assurer que le maximum que vous trouvez correspond effectivement à la période du signal et non à un de ses multiples.

En raison du bruit dans votre signal, le maximum absolu pourrait très bien se produire à un multiple de votre période au lieu de la période elle-même. Donc, pour prendre en compte ce bruit, prenez le maximum absolu de l’autocorrélation (autocorrélation (longueur (autocorrelation)/2 + 1)), puis recherchez où l’autocorrélation est supérieure à 95% de cette valeur maximale pour la première 95%, 99% ou un autre nombre dépend de la quantité de bruit qui corrompt votre signal.

UPDATE: Je me rends compte que je pensais que vous entendiez par "fréquence" de votre signal la hauteur ou l'harmonique de base ou la fréquence avec le plus d'énergie, quelle que soit la façon dont vous voulez l'examiner. Si, par fréquence, vous entendiez la représentation en fréquence de votre signal, une première approximation consiste simplement à tracer les abs de la FFT pour avoir une idée de la position de l'énergie:

plot(abs(fft));

Si vous voulez comprendre pourquoi il y a un abs, ou quelle information pertinente vous perdez en ne représentant pas la phase de la fft, vous voudrez peut-être en savoir un peu plus sur la transformation DFT pour comprendre exactement ce que vous obtenez.

18
Lolo

Je pense que ça devrait être 

 (indexMax-1) * Fs / L 

Le premier élément de abs (fft (x)) est le courant continu (DC), ou polarisation, ou moyenne du signal, ou X0. Nous comptons à partir du deuxième élément (X1) . S'il vous plaît laissez-moi savoir si je me trompe. Merci.  enter image description here

clear all
clc
close all
Fs = 1;
T = 11 % Note this T is deliberately chosen , so that we have about 1.7 cycle of cosine singal
t = 0:Fs:T; % T seconds
L = length(t); % L is the length of sample sequence
bias = 4
signal = sin(t) + bias;

[maxValue,indexMax] = max(abs(fft(signal-mean(signal))));

frequency_method1 = (indexMax-1) * Fs / (L-1);
frequency_method2 = (indexMax-1) * Fs / L;


number_of_cycles_method1 = frequency_method1*T

number_of_cycles_method2 = frequency_method2*T


subplot(2,1,1)
plot(t,signal,'-or') ; grid on;
legend('about 1.7 cycles of cosine signal')
subplot(2,1,2)
plot(abs(fft(signal-mean(signal))),'-xb'); grid on
legend('abs of fft')

number_of_cycles_method1 =

     2


number_of_cycles_method2 =

    1.8333