0
$\begingroup$

I'm struggling for few hours now with FFT normalization. I'm working in Matlab to prove my concept before moving to embedded application.

I have 4 sine wave signals with:

DC offset | frequency | amplitude
5V        | 1Hz       | 10V
-2V       | 3Hz       | 3V
0V        | 6Hz       | 2V
0V        | 8Hz       | 2V

Sampling frequency = 64Hz Number of samples = 64

In theory, I have frequency resolution of 1 Hz and I can detect samples < 32Hz (Nyquist-Shannon) before spectrum gets mirrored. So far so good.

At the output of FFT I have following spikes (after normalization)

Normalization

fft_out_norm = fft_out / fft_size = fft_out / 64 (sample by sample divide)

index
0 = DC value = 3 (ok as one signal has 5V DC, second -2V = 3V together)
1 = 1Hz sine = 5 (but sine has 10V amplitude)
3 = 2Hz sine = 1.5 (but sine has 3V amplitude)
6 = 6Hz sine = 1 (bit sine has 2V amplitude)
8 = 8Hz ... -----------||----------

I understand that spectrum is mirrored and that part of it is on other side:

Index 0 (DC) is not mirrored
Index 1 and 63 are mirrored
Index 2 and 62 are mirrored
Index 3 and 61 are mirrored

Now important part. Since we have mirrored spectrum on all frequencies except DC value and according to the fact that only half of spectrum is enough for useful information, can we simply normalize the signal this way:

fft_out_norm[0] = fft_out[0] / samples_len
fft_out_norm[1] = (fft_out[1] + fft_out[samples_len - 1]) / samples_len
fft_out_norm[i] = (fft_out[i] + fft_out[samples_len - i]) / samples_len
Equation would apply if i > 0 and i < samples_len

And further optimization, if we know we have mirrored spectrum, we can do this:

fft_out_norm[0] = fft_out[0] / samples_len
fft_out_norm[1] = 2 * fft_out[1] / samples_len
fft_out_norm[i] = 2 * fft_out[i] / samples_len
Equation would apply if i > 0 and i < (samples_len / 2)

Can we use this approach? If I do this, I have on output

index
0 = DC value = 3
1 = 1Hz sine = 10 
3 = 2Hz sine = 3
6 = 6Hz sine = 2
8 = 8Hz sine = 2

Which seems perfectly ok. Is there a problem with this approach and if it is, how to eliminate it or how to proceed?

For example, Real-FFT in ARM-DSP gives you only first half of spectrum on output. If you normalize only first half, you get wrong values (as explained on top). So solution would be to multiply all values by 2 first before normalizing, except DC value (because DC is always only 1 value, it is never mirrored).

Thanks for answers.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.