Playing with FFT

I've been playing around with the FFT code that was posted here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1286718155
I wrote a sketch which generates various signals and then prints out their FFT and I've written some info about the output of the sketch and posted it to a web page. Have a peek if you're interested.
2017/04/16 MY ISP shut down the free webspace they provided so I've transferred the zip file to my dropbox.
Unzip the file into your Arduino folder and then open ffttest/ffttest.htm in a browser for the info about the output.

Pete

el_supremo:
I've been playing around with the FFT code that was posted here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1286718155
I wrote a sketch which generates various signals and then prints out their FFT and I've written some info about the output of the sketch and posted it to a web page. Have a peek if you're interested. http://members.shaw.ca/el.supremo/Arduino/fft/ffttest.htm

Pete

thanks pete, it's very usefull

Thank you.

Pete

Looks great, thanks :slight_smile:

You're welcome.

Pete

If you are interested in using FFT for a real world application, have a look at the ATmega328Accuracy project, at lxardoscope - Browse /accuracyInvestigation at SourceForge.net . In this project, FFT was used with sinewaves for characterization of the ATmega328 ADC. Results include Signal-to-Noise Ratio and Effective Number of Bits.

Is this for making an FM transmitter? What is FFT used for?

The Fast Fourier Transform is a mathematical technique to analyze the frequency components of a signal.

Pete

Hi, peter, thank you for linking me to your post. (http://forum.arduino.cc/index.php?topic=175679.15)

I still don't understand why the way I generate sine wave data is not correct.
Can you explain how you generate useful data to test fft please?

I was using "k = 127sin(23.14 * 100 * t )" to generate the data, 100 = wave frequency, but someone asked me what my simulated sampling frequency is, I have no idea what it is, or how to set it.
I wanted to simulate it as if I'm take the data out of A0 from an oscilloscope at a sampling rate of 38.5 khz . I don't have access to an socilloscope right now, but even if I do, I think it's better to simulate it with pure data first.

Thank you

k = 127*sin(2*3.14 * 100 * t )

The problem is with the values of t that you use. The basic formula is, as you have it there, Asin(23.14 * f * t)
where A is amplitude, f is the frequency in Hertz, and t is in seconds.
But in your loop the values of t are 0, 1, 2, 3 etc. So your code is "sampling" the 100Hz sine wave once every second - i.e. at t=0 seconds, then t=1 second, etc.
To sample the sine wave at, say, 1000Hz you would need to generate samples for t = 0, .001, .002, .003 etc. which would require that t be a floating point value and increment it by .001 each time through the loop.
For a simulated sampling rate of 38.5kHz you would need to increment t by .000025974.
With 256 samples you will be generating the equivalent of 6.65ms.

BTW, I don't know how sensitive the FFT will be to numerical errors but I would suggest that you use a more precise value for pi. use 127sin(2PI100t)

Pete

el_supremo:

k = 127*sin(2*3.14 * 100 * t )

The problem is with the values of t that you use. The basic formula is, as you have it there, Asin(23.14 * f * t)
where A is amplitude, f is the frequency in Hertz, and t is in seconds.
But in your loop the values of t are 0, 1, 2, 3 etc. So your code is "sampling" the 100Hz sine wave once every second - i.e. at t=0 seconds, then t=1 second, etc.
To sample the sine wave at, say, 1000Hz you would need to generate samples for t = 0, .001, .002, .003 etc. which would require that t be a floating point value and increment it by .001 each time through the loop.
For a simulated sampling rate of 38.5kHz you would need to increment t by .000025974.
With 256 samples you will be generating the equivalent of 6.65ms.

BTW, I don't know how sensitive the FFT will be to numerical errors but I would suggest that you use a more precise value for pi. use 127sin(2PI100t)

Pete

Hey, Pete:
Great explanation! Thank you so much.

Hi, pete,

It worked! Thank you.

When I tried to to have A =1 from "k = Asin(23.14159 * 100 * t / 400 )", every bin is zero. When I used large A,I was able to see much larger numbers in the bins where the frequency closest to. I still have a lot of other numbers in other bins. Is that normal to FFT?
I can set a limit and filter out these numbers, but I wanna make sure I'm using FFT correctly.

The sine function has values between plus one and minus one so if you set A=1, all your samples will be small values. With a clean signal you should still be able to pick out the tone but it is a lot easier when the amplitude is larger.

I still have a lot of other numbers in other bins. Is that normal to FFT?

You have exhausted what I know about the FFT :slight_smile: You can get noise in the resulting signal but it should be significantly lower than the tone you're looking for. I also get strange results with some signals and I haven't been able to figure out why it happens.

Pete

if you set A=1, all your samples will be small values

More to the point, if you are using the same library as I am, the samples are all 8-bit integers so if A=1 the only values you would be giving the FFT would be -1, 0 and +1 which would result in a very noisy signal!

Pete

When you use integer values, for example 0..1023 with 512 points fft you may use:

f=20; //frequency 
for (i=0; i<512; i++) {
  k[i] = 1023*sin(2*pi*f*i/511);
}

As the result you shall see a frequency in the bin n. 20 with an amplitude of aprox 511 (where in bin n. 0 is DC).
You will see of course some data in other bins as well. That is normal. When sampling real data you have to be aware of aliasing, and you need to apply a "windowing" function before doing the fft (Hamming, Hann(ing), Blackman, and 20 others - in order to eliminate the effect of the sampling window).
By using the windowing function the "shape" of the spectral lines (ie your n.20) changes - you will see less noise around the particular spectral line.

PS: Corrected

for (i=0; i<511; i++) {
k = 1023sin(2pi*f/i);
}[/quote]
Divide by zero. And the time difference between samples, since it is 1/i, will not be constant.
Pete

Corrected. Thanks.