Pages: [1]   Go Down
 Author Topic: FFT for picking out amplitude of a frequency band.  (Read 626 times) 0 Members and 1 Guest are viewing this topic.
Offline
Newbie
Karma: 0
Posts: 3
 « on: December 01, 2012, 07:17:29 pm » Bigger Smaller Reset

I'm trying to use my arduino for a engine knock sensor, but I can't wrap my head around using FFTs. All I want is a single output representing the volume of a 3.5khz +-.3 signal, but everything I read is about creating graphical equalizers.  Could someone please point me in the right direction.
 Logged

Massachusetts, USA
Offline
Tesla Member
Karma: 108
Posts: 6607
 « Reply #1 on: December 01, 2012, 08:03:36 pm » Bigger Smaller Reset

Rather than using an FFT you might want to research a Digital Bandpass Filter.

In either case you will probably be setting the ADC in free-running mode (take readings as frequently as possible).  The filter will depend on the sampling interval so you might need to work that out first.

Here is an example of a calculator that will write the code for you:
http://www-users.cs.york.ac.uk/~fisher/mkfilter

The generated code looks like this:
Code:
/* Digital filter designed by mkfilter/mkshape/gencode   A.J. Fisher
Command line: /www/usr/fisher/helpers/mkfilter -Bu -Bp -o 3 -a 1.0000000000e-01 1.1875000000e-01 -l */

#define NZEROS 6
#define NPOLES 6
#define GAIN   5.485702260e+03

static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
{ for (;;)
{ xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6];
xv[6] = next input value / GAIN;
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6];
yv[6] =   (xv[6] - xv[0]) + 3 * (xv[2] - xv[4])
+ ( -0.7899732587 * yv[0]) + (  3.8143619741 * yv[1])
+ ( -8.6998844482 * yv[2]) + ( 11.5413569160 * yv[3])
+ ( -9.4113261268 * yv[4]) + (  4.4637724618 * yv[5]);
next output value = yv[6];
}
}

As an experiment I just shoved in a 32 kHz sample rate.  I don't know if the Arduino can sample that fast or not.  I think you will want to RMS average the "next output value" values (square them, add them up, and divide by the number of samples).

An alternative would be to make a hardware audio bandpass filter and integrator BEFORE the analog input.
 Logged

Montreal
Offline
Edison Member
Karma: 18
Posts: 2227
 « Reply #2 on: December 01, 2012, 08:09:26 pm » Bigger Smaller Reset

Probably, you mean graphical spectrum analyzers, equalizers usually based in FIR/IIR digital filters. +- 0.3 is about 0.6 kHz wide band, you also could use just filters, or may be Goetzel, instead of FFT. Are there any other "pattern" or temporal characteristics? because it's unlikely filtering a such wide band you can reliably detect anything in the noise.
 Logged

Offline
Newbie
Karma: 0
Posts: 3
 « Reply #3 on: December 01, 2012, 08:34:54 pm » Bigger Smaller Reset

Wow, Goetzel looks much closer to what I need. I'm just trying to convert the volume of a band into a usable output. There shouldn't be too much extra noise in the band, I just want to eliminate other components and come up with a numeric value. Thanks guys, I'm searching more now.
 Logged

Montreal
Offline
Edison Member
Karma: 18
Posts: 2227
 « Reply #4 on: December 01, 2012, 08:50:08 pm » Bigger Smaller Reset

Volume itself can't be an indicator, as it would vary with RPM, at least. More informative a ratio : band of interest to overall, in this case you would need two values, representing in-band level and everything else, or overall. But look on filtering first, other value much easier to obtain:
http://www.embedded.com/design/configurable-systems/4024443/The-Goertzel-Algorithm
 Logged

Offline
Newbie
Karma: 0
Posts: 3
 « Reply #5 on: December 01, 2012, 11:53:23 pm » Bigger Smaller Reset

Thanks guys got a Goetzel working great with my tone generator at the frequency I want. Thanks for the help!
 Logged

Offline
Newbie
Karma: 0
Posts: 22
 « Reply #6 on: June 14, 2013, 08:04:22 pm » Bigger Smaller Reset

Could you post how you did it?
 Logged

 Pages: [1]   Go Up