MATLAB: Normalisation of FFT not consistent.

fftsignal processing

Hi, I am having a few issues normalising my frequency and amplitude for a test FFT I am trying to code. I think it boils down to my understanding of the relationship between signal length, sampling frequency etc.
Below is an example of my code for one set of configuration parameters. We are looking to convert the frequency space results into the physical space. Hence I want to recover a 20Hz frequency and an amplitude of 3 from a FFT.
clc; clear all; close all;
%%Creating test data to ensure FFT is working correctly
Ls = 10; % Length of signal
ds = 10000 % discrete data points
var = linspace(0,Ls,ds);
% Signal Frequencies and amplitudes
kx = 20; ax = 3;
% Signal creation
D = ax*cos(2*pi*kx*var);
%%FFT Stage
Fs = 1000; % Sampling Frequency
n = 2^nextpow2(Fs);
Y = fft(D,n);
% Normalising Y amplitude by number of sampling points
Y = abs(Y/n);
%%Plotting
% Creating vector f that transforms FFT frequency bins to frequency space
% defined by var.
f = linspace(0,1,length(Y))*Fs;
plot(f,Y)
xlabel('Frequency')
ylabel('Amplitude')
This produces the plot:
Which is giving me the correct frequency but not the right amplitude (I am not concerned with the one sided spectrum at the moment).
If I increase my sampling rate by an order of magnitude to Fs = 10000, my frequency changes and my amplitude is still not correct.
I have tried a few permutations of scaling behaviour, but cannot isolate the exact problem. What is the relationship between my signal length (Ls), the resolution of the data over that length (ds), and the sampling frequency used for FFT of that data (Fs)?
Also, how do I best go about increasing the accuracy of FFT so that my frequency is as close and sharp at 20Hz with magnitude exactly 3?
Please help me signal processing gurus! I am eager to learn!

Best Answer

Three problems:
n = 2^nextpow2(ds); % ← Use ‘ds’ Not ‘Fs’
Y = fft(D,n)/ds; % ← Divide by ‘ds’ Here
Y = abs(Y); % ← Do Not Divide By ‘n’ Here
You have to divide by the length of the original signal, because that is where all the energy is. There is no additional energy in the zero-padded signal.
That should solve the amplitude problem. Note that the signal energy is divided into two equal peaks in the two-sided Fourier transform, so the amplitudes will be half the original signal amplitude. In the one-sided Fourier transform, you need to multiply the amplitude by 2.