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.
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:
/* 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.
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.
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.
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:
Thanks guys got a Goetzel working great with my tone generator at the frequency I want. Thanks for the help!
Could you post how you did it?