Please help with arduino fft library

Hello, people,

I've been trying to figure out how to use arduino fft library provided by musical lab for the past two weeks.
I couldn't find any decent documentations on how to use this library. Maybe I should say I really couldn't understand the things in the fft_read_me.txt. I have no where to find working sample code to read. Please help me out.

Here is my problem:
After I upload the first fft sample code provided in arduino 1.0.5 example, it outputs some weird character in the serial monitor. I was expecting some numbers even if they're in dB scale. Do you guys have any ideas what is going here? For all the projects that I looked over, it seemed the output was hooked up to processing to be visualized in graphs. What if I just want the frequency itself as a number? let's say I use a oscilloscope with 2.5DC offset and generate a sine wave with 100 Hz at a sampling frequency of 38.5kHz. How do I go about extracting this 100Hz from the output of the fft?
Here is what I found from the readings:

of bins = # of samples;

use the first half bins because the second part is the mirror image of the first part;
frequency = (sampling frequency / # samples) * bin #
Output available from fft library: fft_lin_out8; fft_mag_lin; fft_mag_log. but they seemed to look like the magnitude of the waveform, not the frequency component which I'm interested in. For the testing purpose, all I wanted to do is to input a sine wave ranges from 10hz to 20khz, and I want to have those frequency outputed to serial port, or store it in a variable or array where I have access to it, I will use it to make a auto tuner.
Here is the code:

/*
/*
fft_adc.pde
guest openmusiclabs.com 8.18.12
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.  there is a pure data patch for
visualizing the data.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft

#include <FFT.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 < 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; // form into an int
      k -= 0x0200; // form into a signed int
      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_log(); // take the output of the fft
    sei();
    Serial.write(255); // send a start byte
    Serial.write(fft_log_out, 128); // send out the data
  }
}

Thank you guys for the help in advance. If I can get this project to work, I will produce a full document and post it to here.

UPDATE 1:
To print out the number from fft_log_out, use a for loop and Serial.print() to print out each element in the array. Thank you all for the help. But I still have more questions on the second page!

it outputs some weird character in the serial monitor. I was expecting some numbers

I don't see where you set the baud rate, and anyway you're printing raw data with "write", not "print"

The code is using Serial.write() to send binary bytes. To make numbers human readable, use Serial.print().

AWOL:
I don't see where you set the baud rate, and anyway you're printing raw data with "write", not "print"

I didn't copy the complete code. sorry about that. I copied and pasted it again.
The baud rate is 115200. I also tried 9600.

The code is from the example. I've tried to use serial.print.
but I always get this error:

fft_adc.pde: In function 'void loop()':
fft_adc:44: error: call of overloaded 'print(uint8_t [128], int)' is ambiguous
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:59: note: candidates are: size_t Print::print(unsigned char, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:60: note: size_t Print::print(int, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:61: note: size_t Print::print(unsigned int, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:62: note: size_t Print::print(long int, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:63: note: size_t Print::print(long unsigned int, int)

It's unlikely that you'd want to print binary data as a C string, so print it a sample at a time, in a for loop.

johnwasser:
The code is using Serial.write() to send binary bytes. To make numbers human readable, use Serial.print().

Is it possible to process these binary bytes to get a useful frequency component out? Please point me to the right direction. I don't mind to read more code or concepts.

I tried to use serial.print.
but I always get the error:

fft_adc.pde: In function 'void loop()':
fft_adc:44: error: call of overloaded 'print(uint8_t [128], int)' is ambiguous
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:59: note: candidates are: size_t Print::print(unsigned char, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:60: note: size_t Print::print(int, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:61: note: size_t Print::print(unsigned int, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:62: note: size_t Print::print(long int, int)
E:\programming\arduino-1.0.2\hardware\arduino\cores\arduino/Print.h:63: note: size_t Print::print(long unsigned int, int)

There is no "print" overload that prints a byte buffer as numeric.
Use a for loop to print each sample.

AWOL:
It's unlikely that you'd want to print binary data as a C string, so print it a sample at a time, in a for loop.

Can you elaborate a little more please? I'm brand new to arduino, and not that much programming experience.
If I were to print one sample at time, will I be able to print out the frequency or just magnitude of the sample?

Thanks.

AWOL:
There is no "print" overload that prints a byte buffer as numeric.
Use a for loop to print each sample.

Thank you all so much! I got some numbers out. Let me test it!

The results of the FFT will be a list of amplitudes at a set of frequencies. The frequency of each sample depends on the sample frequency.

For each 'bin' N the frequency is N * Sample_Rate / FFT_Size

Your sample rate is whatever the free-runing rate of the ADC is. I don't remember offhand. It should be in the datasheet. Let's call it 70 KHz.

Your FFT_Size is 256.

Bin 0 frequency = 0 * 70,000/256 = 0 (DC offset)
Bin 1 frequency = 1 * 70,000/256 = 273.43 Hz (this will also be the step size in your frequency)
Bin 2 frequency = 2 * 70,000/256 = 546.875
Bin 3 frequency = 3 * 70,000/256 = 820.3125
...
Bin 127 frequency = 127 * 70,000/256 = 34,726.56

The top frequency is half the sample rate.
The sample step size is the sample rate divided by the the sample size.

So I think I can print out the magnitude in dB. Not sure if it is correct or not, but it feels really good to have some numbers coming out.

How do I go about extracting the frequency?
Just to learn FFT, I tried out kissFFT in C++ a couple days ago. I filled up an array with single sine function, and I passed the array to kissfft, then I output all the numbers from the first half of the bin. The array was set to have size the same as number of samples, so that the bin number = frequency for testing purpose. The output I had was all zero except the bin where the frequency of sine function is.

Can I do the same to fft library in arduino? I tried it. but a lot of the outputs aren't zero. Not sure if it's correct. Please point out any possible error.
Here is the code I used to test fft library:

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft
#include <FFT.h> // include the library

void setup() {
  Serial.begin(9600); // use the serial port
}

void loop() {
  // put your main code here, to run repeatedly: 
   int k = 0;
   int t = 0;
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
      k = 127*sin(2*3.14 * 100 * t );
      t++;
      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_log(); // take the output of the fft
    for(int i = 0; i < 128; i++){
          Serial.println(fft_log_out[i]);
    }
    delay(1000); 
}

johnwasser:
The results of the FFT will be a list of amplitudes at a set of frequencies. The frequency of each sample depends on the sample frequency.

For each 'bin' N the frequency is N * Sample_Rate / FFT_Size

Your sample rate is whatever the free-runing rate of the ADC is. I don't remember offhand. It should be in the datasheet. Let's call it 70 KHz.

Your FFT_Size is 256.

Bin 0 frequency = 0 * 70,000/256 = 0 (DC offset)
Bin 1 frequency = 1 * 70,000/256 = 273.43 Hz (this will also be the step size in your frequency)
Bin 2 frequency = 2 * 70,000/256 = 546.875
Bin 3 frequency = 3 * 70,000/256 = 820.3125
...
Bin 127 frequency = 127 * 70,000/256 = 34,726.56

The top frequency is half the sample rate.
The sample step size is the sample rate divided by the the sample size.

Great explanation! Thank you so much! that clears out a lot of confusion!
So I want to test out fft library by filling up the bins with numbers from one single sine function, but I get many bins with nonzero output. Am I supposed to get only one bin with non-zero number? Because that bin has to be the frequency of the sine function scaled in the way you explained here.
Here is the code I used to test:

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft
#include <FFT.h> // include the library

void setup() {
  Serial.begin(9600); // use the serial port
}

void loop() {
  // put your main code here, to run repeatedly: 
   int k = 0;
   int t = 0;
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
      k = 127*sin(2*3.14 * 100 * t );
      t++;
      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_log(); // take the output of the fft
    for(int i = 0; i < 128; i++){
          Serial.println(fft_log_out[i]);
    }
    delay(1000); 
}

If the frequency of the sine wave matches one of the bins then you should get a strong signal in that bin and little or no signal in the other bins. If the frequency is between bins you should get signals in the two bins on either side.

If the frequency of the sine wave matches one of the bins then you should get a strong signal in that bin and little or no signal in the other bins. If the frequency is between bins you should get signals in the two bins on either side.

True, if "float" math involved, better 64-bits. For 8/16-bits integer microprocessor w/o floating coprocessor truncation error would get into scene, don't expect clean output.
To OP: What kind of arduino board do you have?
What you are trying to achieve, resolution, freq. range, nature of the input signal?

Magician:

If the frequency of the sine wave matches one of the bins then you should get a strong signal in that bin and little or no signal in the other bins. If the frequency is between bins you should get signals in the two bins on either side.

True, if "float" math involved, better 64-bits. For 8/16-bits integer microprocessor w/o floating coprocessor truncation error would get into scene, don't expect clean output.
To OP: What kind of arduino board do you have?
What you are trying to achieve, resolution, freq. range, nature of the input signal?

I'm using arduino UNO. Frequency range = human detectable range; input signal = instrument sound, but for testing purpose, it is oscilloscope with 2.5DC offset, 4Vpp, frequency ranges from 10hz to the limit when output frequency is not accurate anymore, hopefully close to 20khz;
I'm going to make a frequency auto-tuner. I've seen people make the guitar frequency tuner, mine is different, but the concept is the same.

Do you guys know what the free running sampling frequency is? I'm really new to arduino, did a few search. Didn't find the one correspond to UNO.
Also, if you have a link to a tutorial that explains what those parameters are, it would be great!

johnwasser:
If the frequency of the sine wave matches one of the bins then you should get a strong signal in that bin and little or no signal in the other bins. If the frequency is between bins you should get signals in the two bins on either side.

It makes sense.
Can you look at my test code to see if I coded it correctly? I think the sine wave I used has 256 samples = #bins. And the frequency is set at 100hz.
I should get some numbers in bin#100, but I got zero in it, and a lot of other numbers in most of the bins.

Here is the output:
bin #: 0 log mag: 32
bin #: 1 log mag: 43
bin #: 2 log mag: 39
bin #: 3 log mag: 43
bin #: 4 log mag: 35
bin #: 5 log mag: 39
bin #: 6 log mag: 39
bin #: 7 log mag: 39
bin #: 8 log mag: 30
......

bin #: 84 log mag: 27
bin #: 85 log mag: 8
bin #: 86 log mag: 19
bin #: 87 log mag: 19
bin #: 88 log mag: 0
bin #: 89 log mag: 19
bin #: 90 log mag: 0
bin #: 91 log mag: 8
bin #: 92 log mag: 19
bin #: 93 log mag: 0
bin #: 94 log mag: 8
bin #: 95 log mag: 8
bin #: 96 log mag: 8
bin #: 97 log mag: 8
bin #: 98 log mag: 8
bin #: 99 log mag: 8
bin #: 100 log mag: 0
bin #: 101 log mag: 8
bin #: 102 log mag: 8
bin #: 103 log mag: 0
bin #: 104 log mag: 0
bin #: 105 log mag: 0
bin #: 106 log mag: 0
bin #: 107 log mag: 8

I don't think your test code is generating a useful sine wave. Have a look at the code I reference in this thread:
http://forum.arduino.cc/index.php?topic=96562.0

Pete

hongp:
Can you look at my test code to see if I coded it correctly? I think the sine wave I used has 256 samples = #bins. And the frequency is set at 100hz.
I should get some numbers in bin#100, but I got zero in it, and a lot of other numbers in most of the bins.

What is the (simulated) sample rate in Hz? In order to get 100 Hz to be in Bin 100 you have to have sampleRate == sampleCount.

100 * sampleRate (Hz) / sampleCount = 100 (Hz)

I'm using arduino UNO.
You hardly can get FFT-256 on UNO, check on memory specification. 512 only with 8-bits word size.

Frequency range = human detectable range; input signal = instrument sound, but for testing purpose, it is oscilloscope with 2.5DC offset, 4Vpp, frequency ranges from 10hz to the limit when output frequency is not accurate anymore, hopefully close to 20khz;
Free running arduno samples ~9 kHz, upper limit 4.5 kHz, you have to use your own sampling subroutine with tweaking ADC registers.

I'm going to make a frequency auto-tuner. I've seen people make the guitar frequency tuner, mine is different, but the concept is the same.
You can't get better than 4 Hz resolution, too pure for instrument tunning.

You 'd be better with http://interface.khm.de/index.php/lab/experiments/frequency-measurement-library/

Magician:

I'm using arduino UNO.
You hardly can get FFT-256 on UNO, check on memory specification. 512 only with 8-bits word size.

Frequency range = human detectable range; input signal = instrument sound, but for testing purpose, it is oscilloscope with 2.5DC offset, 4Vpp, frequency ranges from 10hz to the limit when output frequency is not accurate anymore, hopefully close to 20khz;
Free running arduno samples ~9 kHz, upper limit 4.5 kHz, you have to use your own sampling subroutine with tweaking ADC registers.

I'm going to make a frequency auto-tuner. I've seen people make the guitar frequency tuner, mine is different, but the concept is the same.
You can't get better than 4 Hz resolution, too pure for instrument tunning.

You 'd be better with http://interface.khm.de/index.php/lab/experiments/frequency-measurement-library/

I have access to other arduinos. Most of them. Can you suggest one that has the juice to get the job done?
I saw a tutorial before, that a girl was able to set the sampling rate to 38.5kHz. I was hoping that's the rate I will use.
When you say the resolution is too pure for instrument tunning, is that good or bad? 4Hz difference sounds very reasonable.
How did you find out free running sampling frequency is 9 kHz for UNO? Can you post a link here, please? I want to know where or how to find those infos. Also, I looked at arduino reference page, UNO has 16 MHz ceramic resonator. Why does it only sample at a max rate of 9kHz? Can you teach me how to figure it out?
Thanks