# How can I find a specific frequency after doing FFT?

I have some samples from an SDR that I run through FFT and I want to detect the presence of a specific signal, exactly 148.369MHz.

The maximum sample rate of the device is 2Mhz, this is just something else that I don't understand, how can I detect 100Mhz+ signal if the maximum sample rate is 2Mhz ?

Anyway, if I understand correctly, the maximum frequency in FFT is 1Mhz, via nyquist, my question is, how can I find the bin that corresponds to the 148Mhz signal ? I can see a spike that corresponds to the signal but I want to be able to index into the bins and find it.

Thanks

Edit: This is a plot of the signal using GNU Radio's FFT block, I'm trying to achieve the same results with my code

• How are you calculating the FFT? I'm not understanding that part. – dext0rb Jun 25 '12 at 1:23
• Well, I'm using Python numpy.fft and GNU Radio. – mux Jun 25 '12 at 1:41
• Your "SDR" is not actually a software defined radio. See my answer. – Connor Wolf Jun 25 '12 at 10:10

The maximum sample rate of the device is 2Mhz, this is just something else that I don't understand, how can I detect 100Mhz+ signal if the maximum sample rate is 2Mhz ?

You can't, at least not unambiguously if there are other signals that are of a lower frequency in the input.

Anyway, if I understand correctly, the maximum frequency in FFT is 1Mhz, via nyquist, my question is, how can I find the bin that corresponds to the 148Mhz signal ? I can see a spike that corresponds to the signal but I want to be able to index into the bins and find it.

Probably reason why you see a spike that corresponds to the signal is because you're experiencing aliasing. There's no way to unambiguously detect the $148.369\text{ MHz}$ signal without a sufficiently high sample rate. It could actually be a much lower frequency signal.

For example, if I try to sample a $2\text{ kHz}$ sine wave signal with a sampling rate of $1.5\text{ kHz}$, the ADC reconstruction of the signal might end up actually being $0.5\text{ kHz}$, so there's no way to tell the difference between a $2\text{ kHz}$ or a $0.5\text{ kHz}$ signal using only the data acquired by an ADC. That's why ADCs are often used with an analog low-pass antialiasing filter to avoid the problem.

If you want to detect this $148.369\text{ MHz}$ signal, you need to either sample the signal at more than twice that frequency (the more, the better), or use an alternative strategy that does not involve directly looking for the $148.369\text{ MHz}$ signal.

For example, you can mix the signal with another (sine wave) signal generated by a local oscillator and look for the beat frequencies instead of the $148.369\text{ MHz}$ signals. You can then use an ADC and antialiasing filter filter to look for them. A proper choice of the local oscillator frequency would create beat frequencies much less than the sampling rate of the system.

This is actually the technique used in some (all?) radios to tune to a specific frequency, called heterodyning.

• But how can GNU Radio show the 148Mhz frequency in the FFT plot ? is it handled by the hardware maybe ? I would post an image but it seems that I can't yet. – mux Jun 25 '12 at 1:52
• @mux: As I've mentioned in my answer, your ADC is probably experiencing aliasing issues, where a signal frequency higher than half the sampling rate will "show" up as a lower frequency when you reconstruct the signal. That's probably the case here. You can't have peaks corresponding to 148 MHz with a sampling rate at only 2 MHz. – In silico Jun 25 '12 at 1:56
• What if the radio is tuned to the 148Mhz frequency ? will the sample contain that frequency ? this is an image of the plot from GNU Radio, as you can see it detects the signal perfectly, I really appreciate your help so far. oi49.tinypic.com/f084n4.jpg – mux Jun 25 '12 at 2:03
• @mux: How are you receiving the signal? Either the hardware is doing more than just feeding the signal to an ADC, or you're somehow mistaken about the 2 MHz sampling rate. Either way, can't you write a Python program to find the maximum peak in the FFT data points? Without more information we really can't do much to help you. – In silico Jun 25 '12 at 2:06
• Also see: en.wikipedia.org/wiki/Undersampling – datageist Jun 25 '12 at 12:29

You are using an RTL tuner based front end to your SDR application. This combination gives you an SDR. The RTL chipset is quite capable of sampling at 2.4MSPS at 8 bit resolution, giving you I&Q samples 1.2MHz to either side of your center tuning frequency.

So, if the RTL SDR is tuned to 148MHz, then in the FFT result you can look for the desired 148.369MHz in whichever bin corresponds to -369kHz from the sampling frequency. If you run an FFT of 1024 points on the sampled 2.4MSPS signal, I guess you get about 23437Hz per bin (2.4MSPS / 1024). So, at a guess, you would look in the bin about 16 to the left of centre (15.744 bins).