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

cFFT using CMSIS in the TI Tiva/Stellaris

Hi,

I'm starting to test/study the CMSIS lib in the Stellaris/Tiva. Using the paper "Using the CMSIS DSP Library in Code Composer Studio™ for TM4C MCUs", I got build the library and it works fine. The examples return the expected state.

Now I'm trying to use the cFFT in a signal. To the test I created a pure sine wave with amplitude of 1000 and 10 cycles in an array of 1024 samples, as in the image.

array float.png

After the processing the indexer return the correct harmonic (10th), but I don't understand the result of the magnitude. The magnitude of the 10th hamonic is 727.98. How it relates to the amplitude of the harmonic? The RMS value, if yes, why the error?

This is the principal part of code:


#define     N_points    1024

...


uint32_t ifftFlag = 1;
uint32_t doBitReverse = 1;

/* Process the data through the CFFT/CIFFT module */
arm_cfft_f32(&arm_cfft_sR_f32_len512, wave_float, ifftFlag, doBitReverse);

/* Process the data through the Complex Magnitude Module for calculating the magnitude at each bin */
arm_cmplx_mag_f32(wave_float, wave_out, N_points/2);

/* Calculates maxValue and returns corresponding BIN value */
arm_max_f32(wave_out, N_points/2, &maxValue, &testIndex);

I tried to scale the sine wave between 1 and -1, but the result was the same. Instead of 727 the magnitude of the harmonic was 0.727.

It's strange because for different numbers of cycles the result of respective "bin" change.

Maintaining the same buffer size (1024) I changed to just one cycle and the result was around 708, very close to the RMS value. See this little list:

1024 samples

01 cycle -> 708.8323

02 cycles -> 710.9644

04 cycles -> 715.2491

08 cycles -> 723.74

16 cycles -> 740.4352

I tried to change the buffer size to 64 samples to test. In this case the result of one cycle was around 740.

I'm reading about how to obtain the amplitude, but in this moment I'm lost!

  • What is the frequency of your sine wave?  Does it fit perfectly within the bounds of 1 fft "bucket"?

    One way to check, what are the magnitudes in wave_out on either side of the peak?  Are they nonzero?  Some of the lost magnitude may be in an adjacent bucket.

  • Hi agaelema,

    dwhite85's reply is about the leaking of the amplitude of your signal to the adjacent bins of the FFT output. From the information you supplied, the affliction is throughout the spectrum not just the bins adjacent to the frequency of the input signal. This happens when the frequency of the signal cannot be exactly represented in the discrete spectrum. Methods for minimizing the detriments of this kind of problem exist. Before we plunge into that idea however, there could be other source(s) of error that complicates the situation and it's preferable to sift through it first.

    I presume that the tool you used to generate the waveform didn't need an absolute frequency for what you were doing. You can give an absolute frequency for your signal (if you want or if you have used any in your "test") as additional detail but we can use relative or normalized quantities.

    You have computed the amplitude, not the power, spectrum since you forwarded the FFT output to the Complex Magnitude function only. For power spectrum estimation the magnitude should be squared (or you could have used the Complex Magnitude Squared instead of just the Complex Magnitude function) and scale it with an appropriate factor.

    The "bin change" every time you adjust the number of cycles and samples should be normal if the change is proportionate. Somewhat puzzling however, is the "little list" that you provided. When you changed to just one cycle you should have obtained a clean spectrum both at 1024 and 64 samples. There should be a large magnitude at 1 cycle (index=1) and practically zero for all others (ignoring the large magnitude at index=N-1). From your list, the magnitude increases with frequency and 01 cycle has the smallest. This spectrum is quite anomalous for a rather simple input signal.

    A likely cause of the anomaly is the way you set the arguments for the function arm_cfft_f32. You used &arm_cfft_sR_f32_len512 when the FFT length is 1024 (N_points in your code, array of 1024 samples in your description of the input signal), ifftFlag = 1 when you are supposed to perform a forward, not inverse, FFT. Moreover, check the data types of the relevant structures, fields, variables, and arguments such as ifftFlag, doBitReverse, etc. Verify that they match the data types of the corresponding parameters. You should have also modified the argument to the parameter arm_cfft_instance_f32 when you altered the number of samples. If you fix these irregularities, you may eradicate the bulk, if not all, of the problem.

    I recommend you repeat your "test" at the different settings you have stated and post the ff:

    numerical data, not just the waveform, for the input

    numerical data and the FFT plot for the output

    I also suggest that you use an amplitude between 1 and 100 (perhaps 10 could be convenient to you). To reiterate, you will have to repeat the test and provide data for the following:

    10 cycles at 1024 samples

    1 cycle  at 1024 samples

    1 cycle  at   64 samples

    For the plot you can simply insert the images in your message but for the numerical data you may send it as attachment (maybe text files) since those are too large to display.

    Regards,

    Goodwin

  • Hi dwhite85 and goodwin, sorry for the delay.

    I managed to solve my doubt.

    I posted the same question in the e2e forum and the Matin's answer guided me to solve the problem. cFFT using CMSIS in the Tiva/Stellaris - TM4C Microcontrollers Forum - TM4C Microcontrollers - TI E2E Community.

    In the function "arm_cfft_f32( )" the argument "&arm_cfft_sR_f32_len512" was correct, but the input of the function not. The size of array is 1024 because is complex (real, imag). In this case the true lenght is 512 points.

    In the end I changed the cfft by the rfft because the input data are real.

    To solve the problem was necessary to scale each bin based in the RMS value of the input wave. After understand this the code worked well. I have tested some waves with different length, THD, amplitude and number of cycles. Now works fine.

  • Hi agaelema,

    I commend you if everything work smoothly now, I'll just give additional thoughts since this topic may still be useful for us in the future.

    I asked for the numerical data of the input signal because of the following:

    • There could be some settings in your signal generation tool, such as delay or phase etc., that you overlooked and the effects were not accounted in your input data.
    • You used the Complex FFT function but the input data may not be in the proper arrangement, the real and the imaginary components must be interleaved.
    • You can use a real input signal for the Complex FFT function by supplying 0s to the imaginary components but you forgot to do so.

    To avoid swamping your list of things to mind, I deferred to state any of these until you provide a detailed information about your input and output data, meanwhile I just assumed you know that you are using a Complex version of FFT. This is water under the bridge now.

    Although you switched to Real FFT it may worth stating some concerns about the Complex FFT function since you may stumble upon it again.

    • The ifftFlag is just to get things in the proper perspective since you intend to do a forward FFT. If it is set to 1, as you did, your output will still show just two impulses (at index=1 and it's conjugate at index=N-1) when you used just one cycle at 1024 and 64 samples. Note, however, that the numerical values will be scaled differently had you used ifftFlag = 0.
    • There are issues that you should be aware of regarding the parameter arm_cfft_instance_f32 and DFT/FFT in general. The data buffer size is twice the FFT length, you've got it now. However, from your description and graph of the input signal it's clear that you generated 1024 samples. You're supposed to do a 1024-point FFT and you should have used arm_cfft_sR_f32_len1024, the data buffer size would be 2048. In your original setting the argument arm_cfft_sR_f32_len512 worked without harmful effects, the Complex FFT function just operated through half of your samples.

    If you have used 10 cycles in 1024 samples in your recent experiment, arm_cfft_sR_f32_len512 will work. The reason is that you are just actually giving only half of your samples (512) to FFT and the first half of your input data is the same as the second half, just as in your previous test.

    You can try to prove what I am pointing out by trying just one cycle at 1024 samples and use arm_cfft_sR_f32_len512. The defect will become obvious when you work with it.

    If you used 10 cycles in 1024 samples in your recent experiment, you will not get a faithful spectrum from your FFT until you do something about the spectral leakage that Daniel white mentioned in his reply to your original post.

    Regards,

    Goodwin

  • I opened the TI E2E Community link you provided, and these are my views about your discussion:

    • Whether you can expect to recover the time domain amplitude of 1000 in the frequency domain depends on the particular definition used for the DFT. You have to be aware that there are slight variations in the definition of DFT, different implementations may use different scaling. For most references (textbooks, journals, articles, appnotes, and other publications) that I've previously read about DFT, the magnitude can grow by a factor of DFT length (1024 in your test) that's why I recommended that you use a smaller peak value.
    • Although the DFT/FFT is for discrete data, we don't have to worry about the discontinuity of the data all the time. In these settings that you used:

    1 cycle at 1024 samples, 1 cycle at 64 samples

    if we properly use the FFT Function we can get a faithful spectrum, that is, a spectrum that is free from harmonics, other form of aliasing, or forms of distortion (of course the amplitude is subjected to round-off errors but we don't have to get bothered by this for the moment).

    • Martin Valencia's "baby step" outlines the operations you have to do when building a spectrum analyzer. In my reply to you I focused only on FFT. There are also other ways of computing and formatting the spectrum and other information such as SNR, THD, SINAD, etc.

    Enjoy working with your Tiva/Stellaris.