Go Down

Topic: Find fundamental frequency using FFT (Read 332 times) previous topic - next topic

Grumpy_Mike

Can you tell me what you think this bit is doing?
Code: [Select]
if (millis() > tt){
Because you only seem to be doing:-
Code: [Select]
tt = millis();
And so for all but 1mS that if will pass.

louisch

The original program can be found here : https://code.google.com/archive/p/arduino-integer-fft/downloads  (sketch.txt file). Since I'm not very at ease with programming, I didn't want to delete a instruction without knowing exactly what it does. So maybe it's useless if you say it but it was in the original code so I didn't want to make a mistake and delete it

Grumpy_Mike

#17
May 19, 2017, 04:56 am Last Edit: May 19, 2017, 05:20 am by Grumpy_Mike
Quote
I didn't want to delete a instruction without knowing exactly what it does.
But you were quite happy to change
Code: [Select]
"data[i]" into "data"
 
because you know what the difference is.

EDIT:- I see what happened, you did not use code tags like it says in How to use this forum and as a result of not using code tags the forum software took the i in square brackets as an instruction to put the text into italics. So you never saw these were missing or you just couldn't be bothered telling us even when we pointed out the missing index. Why did you not say "but I already have those"? You have wasted the time of the people trying to help you. This makes me cross.  >:(
End of EDIT

Basically the original code puts in all the things we told you about. To save anyone else the trouble of looking it up here it is:-
Code: [Select]

char im[128];
char data[128];

void loop(){
  int static i = 0;
  static long tt;
  int val;
  
   if (millis() > tt){
 if (i < 128){
  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,7,0);
  // I am only interessted in the absolute value of the transformation
  for (i=0; i< 64;i++){
     data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
  }
  
  //do something with the data values 1..64 and ignore im
  show_big_bars(data,0);
 }
    
    tt = millis();
   }
}


Now how have you installed this libiary? I can see no evidence that you have included it in your sketch. In fact the original sketch will not compile, so how have you got it to compile? Their is no #include statement in either your code or the original code, so how does it know where to find the fix_fft function?

Their is a whole lot of stuff you are not telling us.

How is your microphone module wired up?
Can you provide a link to it?
What have you done to test that it is actually giving you a waveform and not an envelope?

To answer this question:-
Quote
Just an other question : how could I know which frequency are sampled and can I adjust this ( for example if I only want 0-400 Hz wich parameter should I change)?
The sample rate and the length of the buffer determine what frequency each bin represents. You have a sample rate of 10KHz and it takes two samples to recognise a frequency so the top frequency is 5KHz. Each bin therefore represents :-
top frequency / number of bins
Which for a buffer of 128 is 39Hz - so you can only ever measure to the nearest 39Hz to be more accurate then use a bigger buffer.

louisch

Ok there's a lot of confusion and I'm at fault, so excuse me, I will start again:
 There's some missing line int the demo code but I noticed it so I've changed to this :
Code: [Select]
#include "fix_fft.h"
char im[128];
char data[128];
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
int static i = 0;
  static long tt;
  int val;
 
   if (millis() > tt){
  if (i < 128){
    val = analogRead(A0);
    data[i] = val / 4 - 128;
    im[i] = 0;
    i++; 
   
  }
  else{
    i=0;
    //this could be done with the fix_fftr function without the im array.
    fix_fft(data,im,7,0);
    // I am only interessted in the absolute value of the transformation
    for (i=0; i< 64;i++){
       data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
       
       Serial.print((data[i]);
       Serial.print("  ");
       
    }
    Serial.print("\n\n");
    //do something with the data values 1..64 and ignore im
   
  }
   
    tt = millis();
   }
}


Because I had no results, with your help I changed it to the program published in my last post and I have results published in this one too. When I said there was no change in my results, It was when Pete told me to change the i in the for loop to a j and to initialize i to 0 in the else part.

My microphone is an adafruit one for arduino, I know my wiring is ok because first I have values when I do the analog read serial test and also because I use an other program that can find fundamental frequency and it works ( my project consists in comparing ways to find guitar frequency). Scopes give me the expected signal so I'm pretty sure there's no problem with my microphone.


Ok I hope there's no misunderstanding now, I'm sorry to have wasted your time again even if you have already help me a lot.


to be more accurate then use a bigger buffer.
Ok so in my case, if I want to be more accurate I have to change the lenght of im and data arrays ? And is there a way to change the top frequency because the one I'd like to have is around 500 Hz

Excuse me again

Grumpy_Mike

Quote
f I want to be more accurate I have to change the lenght of im and data arrays ?
Yes.

Quote
And is there a way to change the top frequency because the one I'd like to have is around 500 Hz
Reduce your sample rate to 1000 times a second. However, you need an anti-aliasing filter and a very good one at that. I would leave the sample rate alone.

Quote
I use an other program that can find fundamental frequency and it works
Can you supply a link to that.

louisch

#20
May 19, 2017, 11:50 am Last Edit: May 19, 2017, 11:56 am by louisch
Yes of cours here it is :

look at the Step 6

I've changed the void loop a bit as  there seemed to be a lot of noise so for a D string I have this :
Code: [Select]
void loop(){
 
  checkClipping();
 
  frequency = 38462/float(period);//calculate frequency timer rate/period
  if(100<frequency and frequency<180 and c-15<frequency and frequency<c+15){

  Serial.print(frequency);
  Serial.println(" hz");
  c=frequency;
  }
  delay(80);//feel free to remove this if you want
 
  //do other stuff here
}

I know it's really minimalist and a bit do-it-yourself but results satisfy me so that's why I try to use FFT and PLL now to compare them

MarkT

#21
May 23, 2017, 11:31 pm Last Edit: May 23, 2017, 11:39 pm by MarkT
The fundamental frequency is best found using autocorrelation surely?

[ or the FFT of the autocorrelation ]
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up