Help using ArduinoFFT

I download this library: ArduinoFFT - Open Music Labs Wiki
and tried this example code (which I don't understand at all...): Example - Open Music Labs Wiki
But it only outputs weird characters in serial monitor.

Is there any simple way I could somehow get some value of a sound level at 20 specific frequencies? (some values in range from 40Hz to 15kHz)

As I said before I don't really understand any code of that example (while I can code C, this seems to be different)

Try this:
http://coolarduino.wordpress.com/2012/03/24/radix-4-fft-integer-math/

There is a Pure Data patch for visualising the data.

The serial output of the example code is intended to be used as input to Pure Data (http://puredata.info/). It doesn't say where/what the patch is. I have never used Pure Data so I can't help with it other than to say that it runs on your PC and provides visualization of the data from the FFT.

At the end of the example code:

  Serial.write(255); // send a start byte
  Serial.write(fft_log_out, 128); // send out the data

this sends the data out the serial port. You could replace it with your own code. The magnitudes (amplitudes) of the result of the FFT are the 128 values in the fft_log_out array.

Pete

there are both puredata and processing sketches for reading out the data up on the wiki
http://wiki.openmusiclabs.com/wiki/ArduinoFFT

the processing sketch is up on the FHT wiki
http://wiki.openmusiclabs.com/wiki/ArduinoFHT

the FHT is really the way to go, only 3ms for a 256 sample input.

if you want to build your own, replace the

Serial.write(fht_log_out, FHT_N/2);

with

for (int i = 0; i< FFT_N/2; i++) {
  Serial.println(fft_log_out(i));
}

basically, Serial.write does binary, and Serial.println does ascii with a carriage return, so its human readable

Thanks guys, it seems to be a bit more clear right now, I will let you know when I have tried it!

g_u_e_s_t:
So I tried FHT's example code and replaced that line with:

    for (int i = 0; i< FHT_N/2; i++)
    {
      Serial.println(fht_log_out[i]);
    }

Now it outputs 103 numbers in serial port monitor ONCE and after that it starts outputting weird characters again...
Here's full code:

/*
fht_adc.pde
guest openmusiclabs.com 9.5.12
example sketch for testing the fht library.
it takes in data on ADC0 (Analog0) and processes them
with the fht. the data is sent out over the serial
port at 115.2kb.  there is a pure data patch for
visualizing the data.
*/

#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht

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

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 < FHT_N ; i++) { // 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; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put real data into bins
    }
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
    sei();
    //Serial.write(255); // send a start byte
    //Serial.write(fht_log_out, FHT_N/2); // send out the data
    for (int i = 0; i< FHT_N/2; i++)
    {
      Serial.println(fht_log_out[i]);
    }
  }
}

You need to flush the serial buffer before collecting the next batch of samples.

    for (int i = 0; i< FHT_N/2; i++)
    {
      Serial.println(fht_log_out[i]);
    }
    Serial.flush();

Pete

Doesn't seem to make any difference. :confused:

i just tested your code and it worked fine on my duemilanove. did you set the serial monitor baud rate to 115200?

Serial.begin(115200); // use the serial port

As the code says...

So you're saying it constantly outputs numbers for you? Because it doesn't for me on UNO, it keeps repeating weird characters and displays numbers only in the beginning

you also have to set the serial monitor to 115200 in the bottom right hand corner of the serial monitor window after you open it.

Thanks, now it seems to output the values! :slight_smile:

Just 2 more questions:

  1. So these values are already the needed amplitudes at each frequency, right?
  2. if 1. is correct, then how do I get the frequency of each amplitude?

each number you output is associate with a frequency (indexed by the integer i in this case). so for i = 0 you get the 0th frequency, and for i = 128 you get the 128th frequency. these are linearly spaced and depend upon your sampling frequency. the sample rate is set by ADCSRA and the CPU clock frequency. in this case its 16MHz/32/13 = ~38kHz. 16MHz is the arduino clock frequency, the last 3 bits in ADCSRA are set to 5, which means /32, and its in free running mode, so it takes 13 clock cycles to get a sample.

for FHT_N = 256, you have 256 bins to cover the full frequency range, so each bin is 38kHz/256 = 150Hz. but, half of the bins repeat, so you really only have FHT_N/2 bins covering half the frequency range. in this case 128 bins, from 0Hz to 19kHz, with a step size of 150Hz.

Thank you so much for everyone contributing to this thread I basically had the exact same issue as OP, and this thread finally helped me yield numeric outputs.

I only have one question remaining; as I understand it, 128 frequencies will be displayed in the serial monitor, in which the 0th frequency is the most dominant, and the 128th frequency is the least dominant. Since the values scroll so quickly, does anyone have a simple approach to see which values are first in this list, i.e. the ranking such that I may view the most dominant frequencies? seems like something easy but I am honestly confused how to approach this.

Thank you very much to anyone willing to drop some knowledge

g_u_e_s_t: thanks a lot!

austincb90: just print something before printing the list of amplitudes, like:

    Serial.println("here starts the list");
    for (int i = 0; i< FHT_N/2; i++)
    {
      Serial.println(fht_log_out[i]);
    }
    Serial.flush();

the 0th frequency is the most dominant, and the 128th frequency is the least dominant

No, that's not it at all. As g_u_e_s_t has explained, each bin represents a range of frequencies. The 0th bin has the amplitude of the zero frequency (DC) component of the signal. The next bin will have the amplitude of frequencies around 150Hz, then 300Hz etc. up to the 127th bin with the amplitude of frequencies around 19050Hz.
If you want to know the frequency with the highest amplitude you would have to search the array to find the highest amplitude and then the index of that entry multiplied by 150 gives its frequency.

Pete

to find the highest amplitude, you can go through and check each value, saving the largest you have found. for example:

int j = 0;
int k;
for (int i = 0; i < FHT_N/2; i++) {
  if (fht_log_out[i] > j) {
    j = fht_log_out[i];
    k = i;
  }
}
Serial.println(k);

again, this just gives you the bin number. you will need to multiply by 150 to get the frequency.

Arvis . Perfect thank you. Rock on

el_supremo:
Thanksyou this clarified a fundamental misunderstanding i had with the code i.e. bins vs actual frequency.

g_u_e_s_t: thanks very much for taking the time to post the code.

very much appreciated.