## ARM CMSIS FFT output scaling

Started by 6 years ago8 replieslatest reply 6 years ago1368 views

Background: To analyze mechanical vibration, I'm sampling a G-meter at 1kHz for 1.024 second, doing an FFT, and calculating the magnitude per bin. The scaling factors in the ARM CMSIS output are a bit bizarre and if they're documented its eluded me. It seems like frequencies are scaled by 512, except that DC is scaled by 1024. Is this really correct? Here's my test code:

// buckets to save FFT inputs#define FFT_INPUT_SAMPLES 1024static float32_t X_samples[FFT_INPUT_SAMPLES], Y_samples[FFT_INPUT_SAMPLES], Z_samples[FFT_INPUT_SAMPLES];static float32_t FFT_results[FFT_INPUT_SAMPLES*2]; // 2x because FFT returns real and imaginary parts, twice...static float32_t FFT_magnitudes[FFT_INPUT_SAMPLES];
static void AddTestFFTsinewave(float32_t (&samples)[FFT_INPUT_SAMPLES], double magnitude, double frequencyHz) {
for(int i=0; i<FFT_INPUT_SAMPLES; i++) {
}
}
static void AddTestFFTdc(float32_t (&samples)[FFT_INPUT_SAMPLES], double magnitude) {
for(int i=0; i<FFT_INPUT_SAMPLES; i++) { samples[i] += magnitude; }
}
static void PerformFFT(float32_t (&samples)[FFT_INPUT_SAMPLES]) {
arm_rfft_fast_instance_f32 armFFTcontrolStruct;
arm_rfft_fast_init_f32(&armFFTcontrolStruct, FFT_INPUT_SAMPLES);
arm_rfft_fast_f32(&armFFTcontrolStruct, samples, FFT_results, /* inverse FFT flag = */0);
// convert real-complex binned pairs into magnitudes
arm_cmplx_mag_f32(FFT_results, FFT_magnitudes, FFT_INPUT_SAMPLES);
}
static void test() {
AddTestFFTsinewave(X_samples,/* magnitude= */2.0, /* frequency= */1.0/*Hz*/);
AddTestFFTsinewave(X_samples,/* magnitude= */1.0, /* frequency= */5.0/*Hz*/);
PerformFFT(X_samples);
}

Printing the resulting magnitude/512.0 gives:
54.00, 2.00, 0.00, 0.00, 0.00, 1.00, 0.00, ...

So at least the sines are behaving as expected (given 512.0 scaling).
The complex portion of the bin 0 FFT result is 0.0
Is the DC result really just scaled by another factor of 2???

Or have I done something silly?
Best Regards, Dave

[ - ]

Check the magnitude of your FFT output  - bin #1 and #1023 must have the same magnitude, and similarly bin #5 and #1019 must have same magnitude. This is the conjugate-symmetry property of FFT on a "real-valued" signal.

The scaling is actually 1024, so you should have the right DC value, but the power of the sinusoid is distributed equally in the positive and negative frequencies.

Hope this helps,

Kiran

[ - ]

The normal FFT -- as in, done more than $$99 \frac{44}{100}$$ percent of the time -- expects complex inputs, and gives you frequency bins corresponding to a complex tone $$x_n = e^{j 2\pi\frac{n}{N}}$$.  DC corresponds to $$x_0 = 1$$.  A sine wave, $$\cos \omega t$$, corresponds to two tones, because $$\cos \omega t = \frac{e^{j \omega t} + e^{-j \omega t}}{2}$$.  So the FFT reflects both of those complex tones -- one at $$+\omega$$, and one at $$-\omega$$.

This gives rise to what kirantg said.

[ - ]

Got it; missed that arm magnitude function didn't sum positive and negative frequencies. Since they are by definition identical, I can either add them or just adjust the scaling factor for the lower bins, right?
Thanks for Kiran and Tim,
Best Regards, Dave

[ - ]

Well, not really.  The total energy in the FFT bins will be the same as the total energy in the time-domain signal.  Consider that a unit-magnitude sine wave has a power of $$\frac{1}{\sqrt{2}}$$, not 1.

[ - ]

Apologies Tim, I don't understand.
Client wants to see acceleration in XYZ, in Gs, from DC to 500Hz.
Isn't the magnitude of the sine-wave the G-load (ie no power scaling)?
Thanks,
Best Regards, Dave

[ - ]
Isn't the magnitude of the sine-wave the G-load (ie no power scaling)?

Oi.  That seems like a simple question, doesn't it?

Possibly not in any sensible way, unless you're talking about discrete tones.

The g-loading requirements that I've seen are a composite of the magnitudes of tones at specific frequencies, plus an RMS level for the underlying "random" vibration, plus a requirement for a peak level (usually applied as a shock).

If you're talking about taking a spectrum, then you're usually talking RMS, because the amount of G-loading "power" that an assembly is absorbing matters in that case.  When I've seen this it is was specified as an operational parameter.

If you're talking about g-loads that might damage a unit then you're usually talking about the amplitude of a tone, or the peak amplitude of a shock.  The former can be easily derived from spectral data, but the latter is pretty much a time-domain thing.

If your customer is working off of some commercial or military standard it would probably be a very good idea to get your hands on the text of the standard and read it.  Specifying g loads is one of those things that sounds easy on the surface but can get very byzantine (and for good reason).  Moreover, I'm not an expert -- what I've just told you I'm sure about, but I've mostly learned it by peeking at tests over the shoulders of the real experts.

[ - ]

Got it. Here we're looking at vibration to detect mechanical wear (if assembly vibrates when moving, there's wear in the drive mechanism and/or support bearings and maintenance is required). Previous versions of this measurement system reported raw acceleration; this incarnation customer wants FFT included. Spec calls for acceleration (in G) over frequency bins, not power...

Thanks again for the help,
Best Regards, Dave

[ - ]