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

Problem with arm_rfft_fast_f32

Hi I tested  arm_rfft_fast_f32 function from CMSIS-DSP 1.4.4 with generated 50hz sine wave at 1000Hz sample rate using 1024 samples, but i get peek value at 102, not 51 which i should get 1000/1024 ~0,97 * 51 = 50Hz:

uint16_t i;

     float32_t khz10[1024];

     float32_t maxvalue;

     uint32_t maxindex;

     //float32_t output2[1024];

     arm_rfft_fast_instance_f32 S;

     arm_rfft_fast_init_f32(&S, 1024);

     printf("Input=[");

     for(i=0; i<1024; i++){

         khz10[i] = 1.2f*arm_sin_f32(2*3.1415926f*50*i/1000)+1;

         printf("%f,",khz10[i]);

     }

     printf("]\r\n");

     arm_rfft_fast_f32(&S, khz10,khz10,0);

     arm_abs_f32(khz10, khz10, 1024);

     arm_max_f32(khz10+1, 1023, &maxvalue, &maxindex);

     printf("Max:[%ld]:%f Output=[",maxindex,maxvalue);

     for(i=0; i<1024; i++){

         printf("%f,",khz10[i]);

     }

     printf("]\r\n");

I later tested this function  with real data from adc and I can only get 1/4 of frequency spectrum

not about 1/2 as I expected. Can anyone could me explain this ?

Parents
  • Hi, i find what was wrong. We can't just use the same buffer for input and output in function arm_rfft_fast_f32

    So the correct version looks like this:

            uint16_t i;

            float32_t khz10[1024];

            float32_t output[1024];

            float32_t maxvalue;

            uint32_t maxindex;

            arm_rfft_fast_instance_f32 S;

            arm_rfft_fast_init_f32(&S, 1024);

            printf("Input=[");

            for(i=0; i<1024; i++){

                khz10[i] = 1.2f*arm_sin_f32(2*3.1415926f*50*i/1000)+1;

                printf("%f,",khz10[i]);

            }

            printf("]\r\n");

            arm_rfft_fast_f32(&S, khz10,output,0);

            arm_cmplx_mag_f32(output,output, 512);

            arm_max_f32(&output[1], 511, &maxvalue, &maxindex);

           maxindex++;

                  printf("Max Value:[%ld]:%f Output=[",maxindex,maxvalue);

                       for(i=0; i<512; i++){                                                       /**/

                           printf("%f,",output[i]);

                       }

                  printf("]\r\n");

    I have aditional qestion about appling window functions

    In book Joseph Yiu The Definitive Guide to ARM® Cortex®-M3 and Cortex®-M4 Processors

    there example with using Hannning window

    defined like:

    // Create the Hanning window. This is usually done once at the

    // start of the program.

    for(i=0; i<L; i++) {

    hanning_window_q31[i] =

    (q31_t) (0.5f * 2147483647.0f * (1.0f - cosf(2.0f*PI*i / L)));

    }

    Why there is max integer value multiplied by 0.5. is this related with fixed point data type they use.

    Can I just use max integer value from ADC  which equals 4095 in stm32f4 ?

    If i understand correctly in other windows function like Hamming  we must also multiply equation by max value which can be obtained from ADC  to suppress signal at the edges of buffer ?

    Why he divide by L and not by L-1 ?

Reply
  • Hi, i find what was wrong. We can't just use the same buffer for input and output in function arm_rfft_fast_f32

    So the correct version looks like this:

            uint16_t i;

            float32_t khz10[1024];

            float32_t output[1024];

            float32_t maxvalue;

            uint32_t maxindex;

            arm_rfft_fast_instance_f32 S;

            arm_rfft_fast_init_f32(&S, 1024);

            printf("Input=[");

            for(i=0; i<1024; i++){

                khz10[i] = 1.2f*arm_sin_f32(2*3.1415926f*50*i/1000)+1;

                printf("%f,",khz10[i]);

            }

            printf("]\r\n");

            arm_rfft_fast_f32(&S, khz10,output,0);

            arm_cmplx_mag_f32(output,output, 512);

            arm_max_f32(&output[1], 511, &maxvalue, &maxindex);

           maxindex++;

                  printf("Max Value:[%ld]:%f Output=[",maxindex,maxvalue);

                       for(i=0; i<512; i++){                                                       /**/

                           printf("%f,",output[i]);

                       }

                  printf("]\r\n");

    I have aditional qestion about appling window functions

    In book Joseph Yiu The Definitive Guide to ARM® Cortex®-M3 and Cortex®-M4 Processors

    there example with using Hannning window

    defined like:

    // Create the Hanning window. This is usually done once at the

    // start of the program.

    for(i=0; i<L; i++) {

    hanning_window_q31[i] =

    (q31_t) (0.5f * 2147483647.0f * (1.0f - cosf(2.0f*PI*i / L)));

    }

    Why there is max integer value multiplied by 0.5. is this related with fixed point data type they use.

    Can I just use max integer value from ADC  which equals 4095 in stm32f4 ?

    If i understand correctly in other windows function like Hamming  we must also multiply equation by max value which can be obtained from ADC  to suppress signal at the edges of buffer ?

    Why he divide by L and not by L-1 ?

Children
  • My previous reply is for your previous post containing the plot for the real and imaginary parts. I wonder why I didn't see your follow-up post and prior to my posting of this reply, it was your post that was shown as latest in the welcome page.

    Hi, i find what was wrong. We can't just use the same buffer for input and output in function arm_rfft_fast_f32

    I pondered if it is possible to use the same buffer in arm_rfft_fast_f32. My attention was diverted from it because the signal and the spur has an interesting relationship. The frequency bin of the spur, 460, is equal to 511 - 51. Fortunately, you decided to restore the output buffer and found the trouble.

    There is still a minor problem with the output spectrum. Earlier I stated that the CMSIS-DSP real FFT functions pack the data for frequency bins 0 (DC) and N/2 (Nyquist frequency) at the beginning of the output array. So if the output array is passed to arm_cmplx_mag_f32 right after arm_rfft_fast_f32, the magnitude for DC will be erroneous and the Nyquist frequency will be missing in the spectrum. We can have it corrected in two ways.

    First, we use a temporary variable to save the Nyquist frequency data, later the saved data will be reinserted to the output array.

            uint16_t i;

            float32_t khz10[1024];

            float32_t output[1024];

            float32_t saveNyquist;                                        // Variable for saving the Nyquist frequency data

            float32_t maxvalue;

            uint32_t maxindex;

            arm_rfft_fast_instance_f32 S;

            arm_rfft_fast_init_f32(&S, 1024);

            printf("Input=[");

            for(i=0; i<1024; i++){

                khz10[i] = 1.2f*arm_sin_f32(2*3.1415926f*50*i/1000)+1;

                printf("%f,",khz10[i]);

            }

            printf("]\r\n");

            arm_rfft_fast_f32(&S, khz10,output,0);

            // Take the absolute value of the Nyquist frequency data and save it to saveNyquist

            arm_abs_f32(output+1, &saveNyquist, 1);

            // Convert real DC data to complex number with imaginary part = 0,

            // this 0 obliterates the Nyquist frequency data at index=1

            // so it was saved in the preceding function call

            output[1] = 0;

            arm_cmplx_mag_f32(output,output, 512);

            // Append the saved Nyquist frequency data

            output[512] = saveNyquist;

            // There are now 513 frequency bins because of the Nyquist frequency

            // and it should be included in the search for the bin with maximum magnitude

            arm_max_f32(output+1, 512, &maxvalue, &maxindex);

            maxindex++;

            printf("Max Value:[%ld]:%f Output=[",maxindex,maxvalue);

            for(i=0; i<513; i++){

                printf("%f,",output[i]);

            }

            printf("]\r\n");

    Second, instead of using a temporary variable, we extend the length of the output array to hold one more complex number. The Nyquist frequency data will be copied into the extended location.

            uint16_t i;

            float32_t khz10[1024];

            float32_t output[1026];

            float32_t maxvalue;

            uint32_t maxindex;

            arm_rfft_fast_instance_f32 S;

            arm_rfft_fast_init_f32(&S, 1024);

            printf("Input=[");

            for(i=0; i<1024; i++){

                khz10[i] = 1.2f*arm_sin_f32(2*3.1415926f*50*i/1000)+1;

                printf("%f,",khz10[i]);

            }

            printf("]\r\n");

            arm_rfft_fast_f32(&S, khz10,output,0);

            // Unpack the DC and Nyquist frequency data

            //

            // Copy the Nyquist frequency data to the end of the buffer

            output[1024] = output[1];

            // Convert the DC and Nyquist frequency data to complex numbers

            // with imaginary parts = 0

            output[1] = output[1025] = 0;

            // There are now 513 frequency bins because of the Nyquist frequency

            // and it should be included in the search for the bin with maximum magnitude

            arm_cmplx_mag_f32(output,output, 513);

            arm_max_f32(output+1, 512, &maxvalue, &maxindex);

            maxindex++;

            printf("Max Value:[%ld]:%f Output=[",maxindex,maxvalue);

            for(i=0; i<513; i++){

                printf("%f,",output[i]);

            }

            printf("]\r\n");

    Note: The corrections are with respect to the latest code that you posted, the one which you described as correct version.

  • Regarding the window functions, I'll just request that you post your questions in a new thread since the current discussion is already lengthy.