cancel
Showing results for 
Search instead for 
Did you mean: 

Question regarding FFTs in arm_math.h

JayDev
Senior II

Hello!

I am trying to simulate an octave model on a microcontroller and ran into a snag I thought I'd get some help with.

So I have an FFT I am running on a sample of data (we'll say 4096 bytes). In octave, I'm using an FFT of the sample (where the sample is a 1 x 8192 array):

fft_data = fft(sample);

Pretty straight forward function. I have the data extracted to a csv file for comparison to ensure the data matches up.

I am now trying to replicate the fft on a microcontroller. I thought I had set it up correctly from a few forum posts but I can't tell if I'm using the wrong type of fft, the wrong data size, etc. Below is essentially what I have on the microcontroller:

float32_t sample_flt[4096] = {0};
float32_t fft_out_buf[4096] = {0};
 
arm_rfft_fast_instance_f32 fft_handler;
arm_rfft_fast_init_f32(&fft_handler, 4096);
 
arm_rfft_fast_f32(&fft_handler, (float32_t *)sample_flt,(float32_t *)fft_out_buf,0);

When I'm looking at the contents of the sample, I'm getting sample[0] and sample[1] filled with information (that doesn't match my octave data) and the rest are nan.

Is it safe to assume the nan is because it's a complex number and can't be displayed?

Am I using the fft correctly or am I setting something up wrong?

I think I am close but I think I'm missing something really simple.

Any information you can give me would be greatly appreciated. Thanks!

NOTE: Edited original code posted to reflect fft init command that I forgot to add to post (but is in code).

Additional info given in post below as well.

1 ACCEPTED SOLUTION

Accepted Solutions

My link from above lists limitations, so 8192 seems to be out of bounds.

View solution in original post

8 REPLIES 8
KnarfB
Principal III

Bah, I did have it in my code but forgot to add it to the above snippet (sorry, lots of other code to sort through and looked right by it). The code looks like this:

    float32_t sample_flt[4096] = {0};
    float32_t fft_out_buf[4096] = {0};
     
    arm_rfft_fast_instance_f32 fft_handler;
    arm_rfft_fast_init_f32(&fft_handler, 4096);
     
    arm_rfft_fast_f32(&fft_handler, (float32_t *)sample_flt,(float32_t *)fft_out_buf,0);

Sorry about that! I knew I was going to forget to add that.

JayDev
Senior II

Some additional context about what is weird, I expected to get the real portions stored in sample_flt and the imaginary portions stored in fft_out_buf, which I believe how this code works (or at least how it appeared to work in other code).

What was odd about this is that I received 16 "normal sized" real samples in sample_flt (without exponents), 16 additional real samples (with exponents in the xxxxe+034 range), and then the rest seemed to vary between the inf, -inf, and nan.

For the imaginary portion, I received two "normal sized" imaginary samples and the rest were all nan.

I expected I might have some differences between octave and this that I might need to resolve/understand, but it seems odd to have such massive differences, which makes me think I am doing something wrong. What's odd is this doesn't seem to be a particularly complicated function so I'm not entirely sure what the core of the issue is.

For reference, here's what Octave provided:0693W00000DmTd0QAF.jpg 

Here's the real portion (sample_flt):

0693W00000DmTd5QAF.jpg 

Here's the imaginary portion (fft_out_buf):

0693W00000DmTdAQAV.jpg

KnarfB
Principal III

No, nan stands not for a complex number. There is no complex hardware data type on STM32. Complex numbers are stored as two consecutive real number (re+im part). Are the arrays global (static) variables? Otherwise it could be a stack overflow.

Try a smaller example first. Like so:

#define N 32
 
    static float32_t X[N] = {0};
    static float32_t Y[N] = {0};
    arm_rfft_fast_instance_f32 fft_handler;
 
    arm_status status = arm_rfft_fast_init_f32(&fft_handler, N);
    if( status != ARM_MATH_SUCCESS ) {
        Error_Handler();
    }
 
    // DC coeff
    // Y[0] = 1000.0f;
    // Y[1] = 0.0f;
 
    // fundamental frequency
    Y[2] = 1000.0f; // real part
    Y[3] = 0.0f;    // imag. part
 
    // inverse first, make a cos function
    arm_rfft_fast_f32(&fft_handler, Y, X, 1);
 
    // inspect X here, because the input will be overwritten by the next function call
 
    // back to the freq. domain
    arm_rfft_fast_f32(&fft_handler, X, Y, 0);
 
    // Y is almost equal to the original Y input, except for rounding

hth

KnarfB

Thanks for the help with this!

I actually was working with an example from this site:

http://stm32f4-discovery.net/2014/10/stm32f4-fft-example/

I ported it over to a different microcontroller and made a few changes (mainly hardware related, bin size, sample rates, etc) and the FFT portion of the code looks like this:

float32_t fft_in_buf[2048];
float32_t fft_out_buf[2048];
 
arm_rfft_fast_instance_f32 fft_handler;
arm_rfft_fast_init_f32(&fft_handler, 2048);
 
        //Do FFT
	arm_rfft_fast_f32(&fft_handler, &fft_in_buf,&fft_out_buf,0);
 
	int freqs[1024];
	int freqpoint = 0;
	int offset = 0; //variable noisefloor offset
 
	//calculate abs values and linear-to-dB
	for (int i=0; i<2048; i=i+2)
	{
		freqs[freqpoint] = (int)(20*log10f(complexABS(fft_out_buf[i], fft_out_buf[i+1])))-offset;
		if (freqs[freqpoint]<0) freqs[freqpoint]=0;
		freqpoint++;
	}
 
 
 
 
float complexABS(float real, float compl) {
	return sqrtf(real*real+compl*compl);
}

I then put in a 2.2khz tone into the mic (which I can only assume is the same frequency modems used back in the day by my ears) and ran through the code. It appears to be working as expected, even with my changes (it had an external GUI for doing a spectrum analysis and it analyzed the core frequency spike correctly, which is good).

This is the data before running the FFT:0693W00000DmZMZQA3.jpg 

Here is the data post FFT:0693W00000DmZJlQAN.jpg0693W00000DmZQ2QAN.jpgSo my understanding (based on the above example) is the out of the FFT function (fft_out_buf) was the imaginary portion without the i argument, would I be wrong about this? If that is the case, I'm a bit confused as to why I'm getting the results I'm getting. If my understanding is wrong though, that could be an explanation. I tried converting the values in my project using that same complexABS function but the output of my project just gave a bunch more nans.

I guess what I'm still confused about why I'm getting the results I am on mine. I don't fully understand what the problem is. I can simulate the results in octave and it doesn't match there and the data doesn't even really make sense.

Is there a chance I have an issue like I'm out of RAM (even though my resource manager shows I have plenty) or something more along those lines than with the data itself? My resource manager shows I'm sitting at about 31% of each (so, unless that's wrong, I should be ok. Not sure if I'm getting a spike of RAM usage that might not be tracked there though).

Ok, I might have found the issue. I went back to the tone example above, had it working with an FFT size of 2048. Tried it at 4096 and it worked fine. Tried it at 8192 and got similar issues. I assume it's a RAM limitation and I'll likely need to move to a chip with more RAM than this one.

Is there a way to find out how much RAM is needed for an FFT of a given size?

This is what I'm seeing:

FFT Size RAM Used on Compilation Status

2048 14.39% Working

4096 22.73% Working

8192 39.39% Not Working

If I follow this, I'll need somewhere around 60%+ to be able to run an FFT of size 8192 (about 115.2 kB of RAM, min since the default RAM setup for the WB55 is 192 kB).

I might be able to get a boost if I can configure the full 256 kB of RAM (since it's configured as 192 kB). Regardless, it would be helpful to know how much RAM an FFT takes. Any idea where one might be able to find this information?

Also, any chances there could be another potential limitation (ie the library will only do a max FFT size of 4096)?

My link from above lists limitations, so 8192 seems to be out of bounds.

Gotcha, well, that makes sense then! Thanks!