Trying to get specific info from FHT library

I think the FHT and FFT libraries are nothing short of incredible but despite that, I simply can't use them in any constructive way without being able to tell what frequency is in a given bucket.

The FHT library for example, so far as I have understood the documentation (so correct me if I'm wrong), is able to sample a waveform and break down the frequencies therein into discrete, equally spaced buckets, spanning from the lowest to highest frequencies in the sample. As such, the boundaries and bucket sizes can float around arbitrarily depending on the sample. I need something I can depend on programmatically so that when I check bucket number 93, I know that corresponds to 5.1 kHz for example.

Am I just understanding things wrong? How can I start with an arbitrary data set and target just the frequency I want once the FHT has been performed on it and have that repeatable with different waveforms? Thanks.

As such, the boundaries and bucket sizes can float around arbitrarily depending on the sample

No, they are fixed and depend on the size of the transform buffer and the sample rate. Also, for the FHT or FFT to perform properly, the sample rate must be fixed.

What do you mean by "an arbitrary data set"?

Thanks for the quick reply.

This is what I'm having trouble understanding. Ok, practical example:

I connect my nano to my car's knock sensor. It is nothing more than a piezoelectric microphone so it produces an audio waveform from 0 Hz up to... I dunno, let's say 10 kHz. Now, the waveform will consist of engine vibrations, car vibrations, road noise and anything else it can pick up so the waveform will change every second. Its constituent frequencies will change in amplitude and in scope. Maybe at 1 moment, 10khz only carries 1% of the audio energy of the whole waveform. The next second it carries 5% of the energy and now 11 kHz is at 1%. In other words, in the frequency domain, the width of frequencies may fluctuate so that breaking it down into 128 pieces results in columns of different widths. This seems to present a problem to me.

Now, I want to detect ONLY 5.1 kHz, +/- 100Hz. How can I declare that bucket so that every minute of every day, as the nano sifts through reams and reams of knock sensor signals, I can always check the amplitude of the same bucket and say for certain that that amplitude is the knock I'm listening for at 5.1 kHz?

If you are interested in just a single frequency, you either can do a single frequency discrete Fourier transform, an autocorrelation analysis, or a Goertzel transform.

For a single frequency Fourier transform, you take a small sample of the data, multiply the samples with sine and cosine terms corresponding to the frequency of interest, and sum up the results. An inefficient program to do so is described here.

To calculate the autocorrelation (easier), you multiply some number of points taken from the sampled data with sample points that are delayed by the time for one cycle of the frequency of interest and sum up the result. However, the result is contaminated by any frequencies in the sample that are an integer multiple of the fundamental.

The Goertzel transform is fast and efficient, but usually must be carefully tuned to work correctly.

Thank you for the pertinent answers. Can I deduce from this, that the FHT/FFT algorithms in their current implementation on the Arduino, are incapable of focusing in on a specific frequency of interest with reliability? Is it meant more to show the shape of the complete spectrum?

Can I deduce from this

No, you can always look at the amplitude of a single FFT/FHT frequency bin. However, you have to calculate all of the bin amplitudes and that wastes time.

In light of your last post, as well as reading a whole bunch last night about the 3 alternatives you posted, I came back to the FHT function and something occurred to me...

The ADC can only do 125 kHz sample rate with 10 bit resolution right? So if I did FHT at that sample rate, and I perform the FHT at 256 bins (the maximum it supports), then does it follow that the range of the Fourier Transform is from 0Hz to 125 kHz broken up into 256 equally sized bins? If that is true, does it mean that the bin containing 5.1 kHz would be bin number 5.1/125*(256/2) = Bin #5 ? Sure I'd be wasting 99% of the CPU to get it but would it at least be reliable?

This whole time I've been trying to ascertain how the lower and upper limits of the frequency spectrum are determined. I think I didn't understand that it's the sample frequency itself that dictates that range. Therefore, I suspect if one were interested in audio frequencies, one would want to reduce the sample frequency down to something like 15 kHz somehow (I don't know if this is possible on the ADC) right?

By default, on ATMega chips, the Arduino ADC samples at 9.6 kHz [u]maximum[/u], which means that signals containing frequencies up to 4.8 kHz can be analyzed. Frequencies higher than 4.8 kHz [u]must not[/u] be present in the sample, or they will contaminate the calculation (called aliasing).

If you collect 256 samples, the result ends up in 128 frequency bins, with each bin width = 4800 Hz/128 = 37.5 Hz.

Using some tricks it is possible to sample signals at higher rates, but the accuracy goes down.

Oh... where was I getting my information then? I read something about a prescaler that set free running adc speed from 125 khz and up. I don't suppose there are any tricks that could be used to get the maximum up above that 5.1 khz number I'm interested in?

For that matter, will any of the aforementioned solutions you proposed work on this target frequency? It just so happens that knock on most engines, particularly this one happen at 5khz and up.

As a last resort the only thing I can think of is using an analog hardware band-pass filter constructed from resistors and caps, rectifying that and filtering again into DC and then feed that into the ADC and just read it as a constant DC voltage. This would give a proportional value representing knock intensity, but I would rather not build discrete circuitry if I could use the arduino instead.

Finally, I have read about this aliasing phenomenon elsewhere but am only starting to understand what it means now. It suggests to me that a hardware low-pass filter would be necessary in most cases to prevent the aliasing you're talking about since most waveforms originating in nature don't have discrete cut-off points.

Resurrecting an old thread to ask a directly applicable question:

What is the best visualization technique to show the frequency buckets that come out of the fht function?

Specifically, I'm using the fix_fft method on an ATTiny85, which yields 64 buckets and I'm trying to figure out a convenient way to see the results visually. What is the fastest/easiest means of doing this? Thanks.