I don't think this concern is related to the specific library I'm using but for the record, I'm using a lib called Fix_FFT, which is supposed to be a butchered version of FFT that will function on a Tiny. It "appears" to work, spitting out values that do change (albeit the output only seems to be 0, 1, 2 or 3 at the most).
The problem is, I have come to understand that the FFT buckets you get on the output array are evenly spaced across the sampled frequency. What is the sampled frequency? For the longest time I tried to figure out how to set that and I believe now it is actually the ADC capture frequency that determines it. Set the ADC capture frequency to 1MHz for example, it takes 13 clocks to grab a value, so that's 77 KHz and then by Nyquist, you can get an accurate sampling at half that rate so that means 38KHz. This would then be split into 64 buckets, each 601 Hz in size.
In my case, I want to do a knock sensor for a car. I've estimated the knock to be at 6500 Hz. Now if I set ADPS2 and ADPS1 bits per the datasheet, that yields a prescaler of 64. 16500000 / 64 is 257812Hz and with 13 clocks per sampling, you get 19831 Hz. Then by Nyquist, halving that you get, 9916 Hz. If this is split into 64 buckets, each bucket is 155 Hz and 6500 Hz would be bucket #42.
Putting that aside for the moment, normally if you do an FFT in open air, you'll get a lot of noise on the first bucket where all the 60 Hz noise would be and then a bunch of nothing after that. This is precisely what I get if I don't touch the prescaler bits at all (30 something on bucket 0 and 0,1,2 on bucket 1). However if I set the prescaler bits to 1 1 1, which is 128 (and this is supposed to be the default, so no change at all), Then I get all 1s on bucket 0. It makes no sense. It's like setting the bits somehow breaks the FFT. But I need to set the bits to get the resolution I want.
Can anyone shed some light on this? If you have a Digispark Tiny85 this code should compile and work with no additional effort. You merely have to place your cursor in a notepad window because the program will spew numbers into whatever your cursor is on due to the keyboard library.
#include <fix_fft.h>
//#include <TinyWireM.h>
#include "DigiKeyboard.h"
byte i = 0;
int8_t data[128];
int8_t im[128];
byte sent = 0;
void setup() {
ADCSRA = (1 << ADPS2) | (1 << ADPS1); // approx 10kHz sample rate
// ADCSRA = (1 << ADPS0);
// ADMUX = 00000001; // use adc1
// DIDR0 = 00000100; // turn off the digital input for adc1
// TinyWireM.begin();
}
void loop() {
for (i=0; i < 128; i++){
data[i] = analogRead(PB3)*0.25-128;
im[i] = 0;
}
fix_fft(data,im,7,0);
for (i=0; i< 64;i++) //real val is for the amplitude
data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
sent = data[16];
DigiKeyboard.println(data[1]);
// TinyWireM.beginTransmission(1); // Begin transmission mode to slave 1
//TinyWireM.send(sent); // Send 1 byte to the mega
//TinyWireM.endTransmission(); // End transmission
}