CMSIS DSP FFT library harmonics level measurement
I tried to use CMSIS DSP library for FFT implementation on STM32F407. I based my project on Tilen MaJerle library.
I sample data with on board ADC and fill the input buffer with function TM_FFT_AddToBuffer(TM_FFT_F32_t* FFT, float32_t sampleValue). Hereafter I process data with function TM_FFT_Process_F32(TM_FFT_F32_t* FFT).
uint8_t TM_FFT_AddToBuffer(TM_FFT_F32_t* FFT, float32_t sampleValue) {
/* Check if memory available */
if (FFT->Count < FFT->FFT_Size) {
/* Add to buffer, real part */
FFT->Input[2 * FFT->Count] = sampleValue;
/* Imaginary part set to 0 */
FFT->Input[2 * FFT->Count + 1] = 0;
/* Increase count */
FFT->Count++;
}
/* Check if buffer full */
if (FFT->Count >= FFT->FFT_Size) {
/* Buffer full, samples ready to be calculated */
return 1;
}
/* Buffer not full yet */
return 0;
}
void TM_FFT_Process_F32(TM_FFT_F32_t* FFT) {
uint16_t iCntr = 0;
float coeff = 2.0*0.7071067812/(float)(FFT->FFT_Size);
/* Process FFT input data */
arm_cfft_f32(FFT->S, FFT->Input, 0, 1);
/* Process the data through the Complex Magniture Module for calculating the magnitude at each bin */
arm_cmplx_mag_f32(FFT->Input, FFT->Output, FFT->FFT_Size);
for (iCntr = 1; iCntr < (FFT->FFT_Size); iCntr++)
FFT->Output[iCntr] *= coeff; //high-order harmonics values - magnitude
FFT->Output[0] /= (float)FFT->FFT_Size; //dc component value
/* Reset count */
FFT->Count = 0;
}I added some simple transformations in TM_FFT_Process_F32 aimed to harmonics level adjustment. Of course, when I exclude them and use original Tilen code I get the same result.
As you see, I tried arm_cfft_f32(…) and arm_cmplx_mag_f32(…) functions. I also tried arm_rfft_fast_f32(…) function for my purposes and got the same result.
My problem is magnitude calculation accuracy. My task expects to get accurate level calculations of predetermined harmonics. I measure clear sinusoidal AC signal with DC offset on the ADC input with voltmeter. Then I measure the signal frequency with FFT lib and get the signal level degradation with the frequency increase. I take into account restrictions regarding the maximum measured frequency for the given sampling rate and that fact, I can't use more than 4096 samples with CMSIS DSP FFT.
I also need small frequency step, e.g., 1 Hz for the range between 100 and 1000 Hz.
There I show you the results. Blue line is measured with AC voltmeter. Red line is my measurements with FFT library. Sampling rate 4096 Hz, number of samples – 4096. By the way, the frequency is measured with some error. 100 Hz is defined as 101Hz, 800 Hz – as 808Hz. But this doesn't confuse me much.

The same picture is attained for other frequency ranges and sampling rates.
Now I see the only head-on decision is to mathematically adjust my results to real measured values. But this is not an elegant solution. It's highly likely that I neglect some important features of DSP FFT analysis and lack understanding of the math algorithm.
Other FFT realizations are not so clear to me. And does it really make sense to use other libs, for example, kissFFT and so on? Who has proven experience with other libs and would be kind to share his view with me? Any piece of advice is highly appreciated.

