Why is my fft peak frequency slightly lower than my known input signal?

2 views (last 30 days)
I do an fft of an input signal which I know is exactly one 1kHz, since it comes from a frequency generator.
The peak is at 996, with a measurment time of 10 sec and a sampling frequency of 51000.
measurement1=importdata('765_180.txt');
t=measurement1(:,1);
MIC2=measurement1(:,2);
MIC2_FFT=fft(MIC2);
N = length(measurement1);
figure
grid on
grid minor
subplot(2,1,1)
bin_vals = [0 : N-1]; %adapt to frquency instead of bins
time_new = bin_vals*fs/N; %adapt to frquency instead of bins
N_2 = ceil(N/2); %ceil rounds to next integer-->eliminates the artifacts at the end
plot(time_new(1:N_2), MIC2_FFT_ABS(1:N_2))
%plot(time_new, MIC2_FFT) %this would be with artifacts at freq end
xlabel('Frequency [Hz]')
ylabel('Magnitude');
title('Magnitude spectrum Mic 2 FFT');
Thanks for your help :)

Accepted Answer

Wayne King
Wayne King on 18 Apr 2016
Hi David, we don't see what fs is in your code above, but in general your code looks like it would generate the expected answer. Once you obtain your t variable above from the first column of the imported data, if you execute
mean(diff(t))
Does that return 1.9608e-05?
You would expect a sampling interval of 1.9608e-05 seconds given the sampling frequency of 51 kHz. I would check to see if that is what you get, otherwise everything else will be off. Again, if fs is specified corrected and the spacing in the t vector is correct, then once you generate your time_new vector if you execute
mean(diff(time_new))
Do you get 0.1? That should be your frequency resolution. Here is an example that produces the expected result, it is essentially your code with a few variables renamed.
fs = 51e3;
dt = 1/fs;
t = 0:dt:10-dt;
% test signal
x = cos(2*pi*1e3*t);
xdft = fft(x);
powerx = abs(xdft(1:Nyq));
N = length(t);
bins = 0:N-1;
freq = bins*fs/N;
Nyq = N/2;
plot(freq(1:Nyq),powerx);
You see in the above, the maximum occurs at bin 1001
[~,idx] = max(powerx);
idx
freq(idx)
Which corresponds to 1000 Hz.
  1 Comment
David Streinger
David Streinger on 18 Apr 2016
Edited: David Streinger on 18 Apr 2016
Hello Wayne King, fs is my sampling frequency and 51khz. I included your suggestions of the mean values in my code and get the following:
mean(diff(t)) = 1.9531e-05
mean(diff(time_new)) = 0.1
So it is pretty much what you expected.
The weird part is that with a test signal like you put in, I actually get the correct 1kHz, but not With my measurment data. That's weird because I use a TGA1244 Frequency generator, which should provide a correct signal. Also with a test tone 1kHz from youtube I had 996 Hz as a result.
here is a link to my test file if that helps:
https://www.dropbox.com/s/si1q6rnb3qwg2st/1kHz_10s_3mics.txt?dl=0
thanks for your help :)

Sign in to comment.

More Answers (1)

Wayne King
Wayne King on 18 Apr 2016
Hi David, You are using the wrong sampling frequency. The actually sampling frequency is 51200. You can see this by entering
1/mean(diff(t))
Once you have the correct sampling frequency, the tone is exactly where you would expect it.
data = importdata('1kHz_10s_3mics.txt');
fs = 1/mean(diff(data(:,1))); % corrected
N = length(data(:,2));
freq = (0:N-1)*fs/N;
Nyq = N/2;
datadft = fft(data(:,2));
% Power but not scaled properly
powerdata = abs(datadft(1:Nyq));
plot(freq(1:Nyq),powerdata);
[~,idx] = max(powerdata);
freq(idx)
  1 Comment
David Streinger
David Streinger on 18 Apr 2016
Thanks a lot, looks like I have a problem with my labview code. :)
I know have 1000,0063 which is completely enough for my purpurse :)
Regards David

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!