Go Down

Topic: FFT Library (Read 41050 times) previous topic - next topic

Ps991

The input imaginary array should be 0, while the output is important. To calculate the real bin value you must take sqrt(re*re + im*im). The imaginary represents the phase shift of the signal.
If you can't write your program in plain english where anyone could understand it then you have no hope of writing code for it.  -Delta_G

Shadorc

Okay, thank you all for your responses.
We found a guitar has its lowest note to 82.4Hz and most acute in 1318.52Hz.

Is it possible to adjust the Fourier analysis for more accurate values between 0Hz and 2000Hz ?
I understood what is the imaginary array. But, what is the third argument, "7"? I know this is 2**7=128 but I do not know what it is.

Thank you !

Ps991

#17
Mar 14, 2015, 10:18 pm Last Edit: Mar 14, 2015, 10:30 pm by Ps991
The 7 is to limit your results to that of a "char" which is only 8 bits, otherwise you would have an overflow and your results would be useless.

To accurately sample between 0-2000, your best bet is to sample at 4000 times a second and set your FFT_N to 256 (or the max), this would mean your accuracy would be (4000 / 2) / (256 / 2) = 15 hz per bin

To really accurately sample between 0-2000hz you will need a new chip altogether or get creative. As a new chip, you would be better off using an Arduino Due or if you want something cheaper an ATmega1284P because they have much more memory to work with. If this is not an option, then maybe try using some of the flash memory as your memory to get larger FFT_N sizes

The only library I used that actually worked was OpenMusicLabs FFT
If you can't write your program in plain english where anyone could understand it then you have no hope of writing code for it.  -Delta_G

Shadorc

#18
Mar 31, 2015, 03:13 pm Last Edit: Apr 04, 2015, 09:04 pm by Shadorc
PS991 thank you very much, it's perfect!

We changed our Arduino Uno to an Arduino MEGA2560 and adjusted the FFT_N to 256 bits.
This is much more accurate!

A new question:
for lines
Code: [Select]

val = analogRead(A0);
data[i] = val / 4 - 128;


What is the point of dividing val by 4 and subtract it 128 ?

Thank you all for your help

Ps991

#19
Apr 03, 2015, 09:21 pm Last Edit: Apr 03, 2015, 09:22 pm by Ps991
Please be sure to use code tags when posting code, because this
Code: [Select]
array[i] = 0; //this text is not italic
now becomes
array = 0; //this text IS italic, also notice the [ i ] is now missing

back on track

Code: [Select]

if (millis() > tt){
     if (i < 128){
       val = analogRead(pin_adc);
       data[i] = val / 4 - 128;
       im[i] = 0;
       i++;   
       
     }

the reason it is divided by 4 and subtracted by 128 is because the "data" is of type "char" which is an 8 bit variable (-128 to 127). So because analogRead returns 0-1023, dividing it by 4 gives you 0-255, subtracting it by 128 gives you -128-127.

You will notice that a (sine wave)/(audio wave) has positive and negative values, so this is why you see it centered around 0.
If you can't write your program in plain english where anyone could understand it then you have no hope of writing code for it.  -Delta_G

Shadorc

Thank you! I added code tags.

All right, our project seems to work as intended, thanks to you !
Thank you for all, you have been of great help!

tmd3

All right, our project seems to work as intended ...
That's good news.  Can you post your code, and a description or schematic of the circuit?  Some sample output would be interesting, as well.

Shadorc

We wanted to post a video of the project with the code, cabling, once finished.
But we're working on it once a week, there is still a lot to do but we will post it once finished !

tmd3

Before you go, let me ask:  does this -
... our project seems to work as intended ...
- mean that you accomplished your original goal, which was to accurately and reliably get the frequency of a guitar string using the FFT?  If you did, I hope you'll tell us which of the several suggested techniques you used, and give us an idea of how well it works.

Shadorc

For now we just tried with a simulation on ISIS.
We still have to connect the microphone to the Arduino by amplifying the sound and adding a DC component.

Finaly, we used the library fix_fft : http://forum.arduino.cc/index.php?topic=38153.0 and set FFT_N to 256 by using an Arduino Mega 2560.

I prefer wait Tuesday before to explain, I would have the code available to me and it will be simpler to explain

Shadorc

Hello !

I'm here because I have some others questions...

To set FFT_N to 256, we need to change it in the library or in my program ? (like change all the 128 to 256 : im[256], data[256], if(i < 256), etc...)

And, there's something I don't understand, if we use
Code: [Select]
for (i=0; i<64;i++){
, i will be set to 65 when for loop finished so, in the next loop(),
Code: [Select]
if (i < 128){
 will only fill data with 63 values ! (128-65) Why ?

And my last question,
is
Code: [Select]
if (millis() > tt){
 necessary ? I know why there is this line but, it is really necessary ?

Thanks you !

Ps991

#26
Apr 16, 2015, 05:23 am Last Edit: Apr 16, 2015, 05:39 am by Ps991
Code: [Select]

char im[256];
char data[256];

void loop(){
 int static i = 0;
 static long tt;
 int val;
 
  if (millis() >= tt){
     if (i < 256){
       val = analogRead(pin_adc);
       data[i] = val / 4 - 128;
       im[i] = 0;
       i++;   
       
     }
     else{
       //this could be done with the fix_fftr function without the im array.
       fix_fft(data,im,8,0);
       // I am only interessted in the absolute value of the transformation
       for (i=0; i< 128;i++){
          data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
       }
       
       //do something with the data values 1..128 and ignore im
       show_big_bars(data,0);
     }
   
   tt = millis();
  }
}


As far as
Code: [Select]
if (millis() > tt) part, this is your sample rate. This is very poor programming. Ideally you would use interrupts for precise timing. Ideally you would also eliminate analogRead() and replace it with much faster code.
But if you want a better, just slightly improved version, do something like this...
Code: [Select]

long frequency = 500; //hz
...
if(micros() >= tt){
  tt = micros() + (int)(1000000L / frequency);
  ...
}
If you can't write your program in plain english where anyone could understand it then you have no hope of writing code for it.  -Delta_G

Shadorc

#27
May 12, 2015, 04:52 pm Last Edit: May 12, 2015, 05:15 pm by Shadorc
Hello !

First of all, thank to PS991 for the explications !

I'm here again for new questions ! :D (Sorry but you are the only ones who can help me, my professor doesn't understand this library...)

So, the data[] returns by the fix_fft() function,
If I understand correctly, this array contains amplitudes in ascending order of frequency ? Is that exact ?

And if it's true, why the maximum value contained in the data[] array will increase with the frequency and, arrived at 127, decrease to 0, and increase to 127, and decrease to 0... ?

Thank you !

KeithRB

What is the data being passed to fix_fft()?

The data can look like anything depending on the spectrum of the time domain signal you are inputting. You might also have aliasing problems.

Ps991

Sorry for the huge delay...I have not been on much...

Quote
If I understand correctly, this array contains amplitudes in ascending order of frequency ? Is that exact ?
I'm no expert, but this seems exactly correct.

Quote
And if it's true, why the maximum value contained in the data[] array will increase with the frequency and, arrived at 127, decrease to 0, and increase to 127, and decrease to 0... ?
You will be need to be more specific, I do not understand the question. What is oscillating between 127 and 0, under what conditions? Maybe post some data?
If you can't write your program in plain english where anyone could understand it then you have no hope of writing code for it.  -Delta_G

Go Up