Go Down

Topic: FFT for picking out amplitude of a frequency band. (Read 2587 times) previous topic - next topic

Harlan

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.

johnwasser

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: [Select]

/* 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.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Magician

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.

Harlan

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.

Magician

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

Harlan

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


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy