This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

DSP Sampling Rate, FFT Size, and Buffer Size

Hi,

Hope someone can provide some assistance on this issue.

1 - Using an STM32F407 processor, clock at 168Mhz

2 - Using ADC to sample low frequency signals (< 50Hz) from sensors

3 - Have timer interrupt set such that setting timer period to frequency will interrupt at that rate and add a sample from ADC to buffer. Using timestamps, I have confirmed that the interrupt is operating correctly

4 - I have used ScopeFIR to create 3 sets of filter coefficients to test: one at Fs = 512Hz, one at 1024Hz, and one at 2048Hz. The reason I'm using power of 2 values for sampling is so that when I divide the sampling rate into the FFT size, I should get 0.5Hz resolution. (according to resolution = Fs / Fn)

In the header, I have three #defines that control the interrupt operation:

#define SAMPLE_FREQ

#define BUFFER_SIZE

#define FFT_SIZE

In the interrupt handler:

    if(sampleCount == BUFFER_SIZE)

    {

inputBufPtr = &ADC_Values[0];
outputBufPtr = &outputBuffer[0];
arm_fir_instance_f32 S;
arm_fir_init_f32(&S, FILTER_TAP_NUM, (float32_t  *)&filter_taps[0], &firStateF32[0], BLOCK_SIZE);

for(uint16_t i = 0; i < NUM_BLOCKS; i++)
{
arm_fir_f32(&S, inputBufPtr + (i * BLOCK_SIZE), outputBufPtr + (i * BLOCK_SIZE), BLOCK_SIZE);
}
if( FFT_SIZE == 512 )
arm_cfft_f32(&arm_cfft_sR_f32_len512, outputBuffer, ifftFlag, doBitReverse);
if( FFT_SIZE == 1024 )
arm_cfft_f32(&arm_cfft_sR_f32_len1024, outputBuffer, ifftFlag, doBitReverse);
else if( FFT_SIZE == 2048 )
arm_cfft_f32(&arm_cfft_sR_f32_len2048, outputBuffer, ifftFlag, doBitReverse);
/* Calculate the magnitude at each bin */
arm_cmplx_mag_f32(outputBuffer, cfftBuffer, FFT_SIZE);
//zero the DC component

cfftBuffer[0] = 0;

//do stuff here...look for bins of interest....

} //end: if (samplecount...

So this is where my questions are:

With the defines set to these values:

#define SAMPLE_FREQ  512

#define BUFFER_SIZE 2048

#define FFT_SIZE 1024

And using the Dolph-Cheby filter coefficients for Fs = 512, with a 22Hz sensor signal into the ADC, here are the bin values from 1 to 25:

Power at 1 = 201.5

Power at 2 = 203.8

Power at 3 = 183.8

Power at 4 = 215.4

Power at 5 = 137.4

Power at 6 = 107.9

Power at 7 = 112.4

Power at 8 = 125.5

Power at 9 = 81.0

Power at 10 = 128.6

Power at 11 = 190.1

Power at 12 = 60.5

Power at 13 = 53.6

Power at 14 = 103.9

Power at 15 = 76.4

Power at 16 = 84.4

Power at 17 = 29.6

Power at 18 = 61.4

Power at 19 = 48.9

Power at 20 = 18.0

Power at 21 = 40.9

Power at 22 = 47.6

Power at 23 = 524.6

Power at 24 = 123.5

Power at 25 = 55.9

Power at 58 = 43.9

Power at 59 = 96.4

The sensor is signalling at precisely 22Hz, clearly the highest bin level is at 23, one higher than it should be.

Now, if I set the defines to these values:

#define SAMPLE_FREQ  1024

#define BUFFER_SIZE 2048

#define FFT_SIZE 1024

And use the Dolph-Cheby filter coefficients for Fs = 1024, here are the new bin values (shown from 20 to 50):

Power at 21 = 197.2

Power at 22 = 64.0

Power at 23 = 81.5

Power at 24 = 70.8

Power at 25 = 72.8

Power at 26 = 49.3

Power at 27 = 31.5

Power at 28 = 37.9

Power at 29 = 7.5

Power at 30 = 18.7

Power at 31 = 20.3

Power at 32 = 30.4

Power at 33 = 17.6

Power at 34 = 27.1

Power at 35 = 67.4

Power at 36 = 28.9

Power at 37 = 12.6

Power at 38 = 29.6

Power at 39 = 14.5

Power at 40 = 52.4

Power at 41 = 46.9

Power at 42 = 44.1

Power at 43 = 21.2

Power at 44 = 28.1

Power at 45 = 89.8

Power at 46 = 311.5

Power at 47 = 236.7

Power at 48 = 83.2

Power at 49 = 54.1

Power at 50 = 35.7

The high bin has now moved to 46. Dividing by 2 and subtracting 1 it is 22, which again is correct.

Can someone explain what is happening with this? I'll soon need a hair transplant if I don't figure it out. Any comments or suggestions would be appreciated.

Thanks,

Gary

  • Clearly, no support from ARM or anyone writing CMSIS can be expected here. Not a difficult question, but perhaps I need to offer my credit card number first??   8---) ??

    Think I'll move over to Siglib and perhaps even go with the XMOS multi-core processors where I know I can get support.

  • Hi Grog,

    I replied to this a minute ago before I noticed you had actually responded to me on the other thread, so please disregard that message which I have now deleted.

    I'll make a quick program to attempt to test something like this, but it would really be a lot easier to find the source of this problem if you would send me a complete, compilable, working program that showcases the reported issue.  The best I can think of on my end is to run a 22Hz sine wave through cfft + cfft mag and make sure it pops up at the right spot with the fft sizes you mentioned.

    As I mentioned before, you can email me at dwhite@dspconcepts.com .

    Cheers,

    Dan

  • Below is a sample program I created without all the FIR and interrupt stuff.  It just generates a real 22Hz sine wave and puts it in cfft then cfft mag.  I ran it through the simulator for FFT_SIZE 512 and FFT_SIZE 1024.

    FFT_SIZE 512 - bin 22 (indexing starts at 0 not 1 just to be clear)

    FFT_SIZE 1024 - bin 44

    These are the expected values.  So I may need more information about these FIRs and your actual input data to offer a more informative response. 

    #include <arm_math.h>

    #include <arm_const_structs.h>

    #include <math.h>

    #define FFT_SIZE 512

    #define SIGNAL_FREQ (22.0f)

    #define SAMPLE_FREQ  (512.0f)

    float32_t outputBuffer[FFT_SIZE*2];

    float32_t magBuffer[FFT_SIZE];

    int main ()

    {

        int i;

       

        for(i=0;i<FFT_SIZE;i++)

        {

            outputBuffer[2*i] = sinf(SIGNAL_FREQ*2.0f*3.14159265358979f*(float)i/SAMPLE_FREQ);

            outputBuffer[2*i+1] = 0;

        }

       

       

    #if FFT_SIZE == 512

        arm_cfft_f32(&arm_cfft_sR_f32_len512, outputBuffer, 0, 1);    

    #elif FFT_SIZE == 1024

        arm_cfft_f32(&arm_cfft_sR_f32_len1024, outputBuffer, 0, 1);

    #endif

       

        /* Calculate the magnitude at each bin */

        arm_cmplx_mag_f32(outputBuffer, magBuffer, FFT_SIZE);

       

       

        return 0;

    }