Arduino FFT

Hi, I am trying to create an algorithm that takes in data in from real life and tells me the frequency. I am using an Arduino UNO, an Electret Microphone Amplifier - MAX4466 with Adjustable Gain. [. right now I am just getting tons of zeros. could you please help me. I am using the FFT Library. ArduinoFFT - Open Music Labs Wiki. here is my current Code.

/*
  fft_adc_serial.pde
  guest openmusiclabs.com 7.7.14
  example sketch for testing the fft library.
  it takes in data on ADC0 (Analog0) and processes them
  with the fft. the data is sent out over the serial
  port at 115.2kb.
*/

#define LIN_OUT8 1 // use the lin8 output function
#define FFT_N 256 // set to 256 point fft

#include <FFT.h> // include the library

int total;
int artificial_delay;
void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while (1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
      while (!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = ((j << 8) | m) - 512; // form into an int and subtract DC Offset
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
      fft_input[i + 1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_lin8(); // take the output of the fft
    sei();
    Serial.println();
    for (byte x = 0 ; x < (FFT_N / 2) ; x++) {
      Serial.println(fft_lin_out8[x]); // send out the data
    }
    for (int i = 0; i < 128; i++) {
      total = total + fft_lin_out8[i]; // adding all items in the fft output list for use in the following "if" filter
    }

    
  }


  /*if (total>0){ //IGNORE EVERYTHING IN THIS COMMENTED OUT SECTION.
    if (fft_lin_out8[127] == 0){
      digitalWrite(bassLED, HIGH);
      Serial.println(total);
    }
    }*/
}

Tomigee2.ino (1.89 KB)](Electret Microphone Amplifier - MAX4466 with Adjustable Gain : ID 1063 : $6.95 : Adafruit Industries, Unique & fun DIY electronics and kits)

if you haven't already,

  1. verify by plotting the data captured from the ADC (microphone) and
  2. using synthetic data (i.e. sine wave), verify that the fft operations give you the expected results.

also, how do you periodically sample the data? seems like you're capturing data as quick as the ADC can. Voice is often sample at 8 kHz (125 usec).

Ok but what is there to verify? And how do I know how frequently I am sampling?

you're trying to figure out why it doesn't work. So you need to find the problem -- are you collecting samples properly? are you calling the fft functions correctly? this is what I mean by verify. verify that you're doing things correctly

do you understand that for the fft to work, samples need to be periodic and the sampling period determines what the frequency in each bin of the fft output is.

typical systems have some mechanism (clock) to trigger samples periodically. an Arduino is limited in what it can do. Using an ISR triggered by a timer is one approach. collecting timestamps using micros() allows you to measure the time between cycles in your loop. But samples need to be collected periodically for the FFT to provide meaningful results. (samples also need to be frequency limited -- see Nyquist)

figuring out how to verify the performance of your system (your code) is important to debug.

Post a circuit diagram.

To test the input, use the ADC to collect some data from the microphone, and print out the values. If those are all small, therein is the problem.

Note that this line sets the ADC sample frequency to 38462 Hz.

  ADCSRA = 0xe5; // set the adc to free running mode