Go Down

Topic: Improving FHT resolution (Read 3030 times) previous topic - next topic


Aug 12, 2013, 05:36 pm Last Edit: Aug 13, 2013, 01:35 am by FantasticMrSimpson Reason: 1
I currently have code for an FHT but I need it to be able to identify changes as small as 4Hz.
Following another forum post I have changed my ADSCRA to 0xe7 but this gives the frequency to the nearest 37Hz and having read up on the ADSCRA function I realised that this is the best it can do. I need it to be as accurate as possible between 70-400Hz.

I don't mind if it takes longer to process, I just need a higher resolution.

Code: [Select]
void setup(){
 ADCSRA = 0xe7; // set the adc to free running mode
 ADMUX = 0x41; // use adc1
 DIDR1 = 0x01;

Code: [Select]
void loop(){
 for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
   while(!(ADCSRA & 0x10)); // wait for adc to be ready
   ADCSRA = 0xf7; // restart adc
   byte m = ADCL; // fetch adc data
   byte j = ADCH;
   int q = (j << 8) | m; // form into an int
   q -= 0x0200; // form into a signed int
   q <<= 6; // form into a 16b signed int
   fht_input[i] = q; // 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



I have tried to use the code posted by g_u_e_s_t in this forum: http://forum.arduino.cc/index.php?topic=179095.15

But that hasn't worked for me. Please help.


As I undersand this, you need to caputre data at 800 Hz sample rate. That will give you the bins from 0Hz to 400Hz with a resolution of 3.15 Hz


Aug 12, 2013, 08:40 pm Last Edit: Aug 12, 2013, 08:48 pm by FantasticMrSimpson Reason: 1
Yep, sample rate has to be at least twice the highest frequency. Poisson distribution or Nquist distribution or something, certainly one of the distributions (it's been a while).


Please do not cross-post. This wastes time and resources as people attempt to answer your question on multiple threads.

Your other post deleted.

- Moderator
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


Its the nyquist-shannon sampling frequency you need to be paying attention to.


that should give you an idea of sampling rates.

Need any help give me a shout

And stop posting twice. Bad FantasticMrFox. Stop it...


also this may be of use to you



My FHT does work, It's just changing the sampling rate which I'm having trouble with because the ADCSRA function has a resolution of 37Hz at it's best.


to sample slower, you can either setup the ADC to sample on a slower interrupt, or just use analogRead().  the latter is probably easier to get started with.  you can call analogRead(), and then put a delay in for the right amount of time.  be sure to comment out all the ADC setup code before using analogRead().


Aug 13, 2013, 04:53 pm Last Edit: Aug 13, 2013, 04:56 pm by tmd3 Reason: 1
You can try parabolic interpolation.  The theory is that the continuous Fourier transform of the input signal looks like a parabola near a peak; the practice is to locate a peak among three adjacent frequency bins, fit a parabola to the magnitudes at those bins, and estimate the location of the vertex.  Here's a link that describes how to do it: https://ccrma.stanford.edu/~jos/parshl/Peak_Detection_Steps_3.html.

Alternatively, you could give up on the digital Fourier transform, and use autocorrelation instead.  Here's a scholarly paper that describes autocorrelation and the YIN algorithm for frequency estimation: http://www.ircam.fr/pcm/cheveign/pss/2002_JASA_YIN.pdf.  

Here's a link to an Arduino-based guitar tuner project, using the YIN algorithm, that looks to be very much like the one you're attempting: http://deambulatorymatrix.blogspot.com/2010/11/digital-chromatic-guitar-tuner-2008.html

Edit: fixed link

Go Up