Pages: [1] 2 3   Go Down
Author Topic: Help using ArduinoFFT  (Read 3841 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 2
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I download this library: http://wiki.openmusiclabs.com/wiki/ArduinoFFT
and tried this example code (which I don't understand at all...): http://wiki.openmusiclabs.com/wiki/Example
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)
Logged

Montreal
Offline Offline
Faraday Member
**
Karma: 27
Posts: 2568
Per aspera ad astra.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 43
Posts: 1556
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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:
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
Logged

Where are the Nick Gammons of yesteryear?

Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Code:
Serial.write(fht_log_out, FHT_N/2);

with
Code:
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
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 2
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

g_u_e_s_t:
So I tried FHT's example code and replaced that line with:
Code:
    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:
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]);
    }
  }
}
Logged

Offline Offline
Edison Member
*
Karma: 43
Posts: 1556
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Pete
Logged

Where are the Nick Gammons of yesteryear?

Offline Offline
Newbie
*
Karma: 2
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Doesn't seem to make any difference. :/
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 2
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, now it seems to output the values! smiley

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?
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

g_u_e_s_t: thanks a lot!

austincb90: just print something before printing the list of amplitudes, like:
Code:
    Serial.println("here starts the list");
    for (int i = 0; i< FHT_N/2; i++)
    {
      Serial.println(fht_log_out[i]);
    }
    Serial.flush();
Logged

Pages: [1] 2 3   Go Up
Jump to: