Transmitter-side: Wireless Spectrum Analysis based on Fast Fourier Transform techniques

Fast Fourier Transform (FFT) based spectrum analysis is a fundamental technique used across various disciplines for analyzing signals in the frequency domain. Here’s a more detailed breakdown of how FFT-based spectrum analysis works and its applications:

  1. Signal Acquisition: In any system where FFT-based spectrum analysis is applied, the first step involves acquiring a time-domain signal. This signal could originate from sensors, antennas, communication receivers, audio devices, or any other source that produces a continuous-time waveform.

  2. **Sampling: The continuous-time signal is then sampled at discrete intervals, converting it into a sequence of digital samples. The sampling process involves measuring the amplitude of the signal at regular time intervals, typically governed by the Nyquist-Shannon sampling theorem to ensure faithful representation of the original signal.

  3. Windowing (Optional): Prior to applying the FFT, a windowing function may be applied to the sampled signal. Windowing functions serve to reduce spectral leakage, which occurs when the frequency components of a signal extend beyond the boundaries of the sampled data. Common windowing functions include the Hamming, Hanning, and Blackman-Harris windows.

  4. FFT Computation: The heart of FFT-based spectrum analysis lies in the computation of the Fast Fourier Transform. The FFT algorithm efficiently computes the discrete Fourier transform (DFT) of the sampled signal. By decomposing the time-domain signal into its frequency components, the FFT provides a representation of the signal’s spectral content.

  5. Frequency Bin Selection: The output of the FFT is a frequency-domain representation of the signal, typically organized into frequency bins. Each frequency bin corresponds to a specific range of frequencies. The magnitude or power of each frequency bin indicates the strength of the signal component at that frequency.

  6. Spectrum Analysis: The resulting spectrum provides valuable insights into the frequency characteristics of the signal. By analyzing the spectrum, engineers and researchers can:

    • Identify dominant frequency components and harmonic content.

    • Detect and analyze signals of interest, such as communication signals or biomedical signals.

    • Characterize noise and interference in the signal.

    • Perform modulation recognition and demodulation.

    • Estimate channel frequency responses in communication systems.

    • Monitor spectral occupancy in spectrum sensing applications.

FFT-based spectrum analysis is used across a wide range of fields, including telecommunications, audio engineering, radar systems, medical imaging, and scientific research. Its efficiency, speed, and versatility make it an indispensable tool for understanding and analyzing signals in the frequency domain.

2.1 Import libraries

[1]:
# %matplotlib widget

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

%matplotlib widget
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.animation as animation

import numpy as np
import adi

2.1 System Parameters

[2]:

fftSize = 2**12 # fft-size subcarrierSpacing = 10**3 # subcarrier spacing sampleRate = fftSize*subcarrierSpacing carrierFrequency = 10**9 # Hz numSamples = fftSize*2 # number of samples per call to rx()

2.1 Setup SDRs

[3]:

sdr = adi.Pluto("ip:192.168.3.1") sdr.sample_rate = int(sampleRate) # Config Tx sdr.tx_rf_bandwidth = int(sampleRate) # filter cutoff, just set it to the same as sample rate sdr.tx_lo = int(carrierFrequency) sdr.tx_hardwaregain_chan0 = 0 # Increase to increase tx power, valid range is -90 to 0 dB # Config Rx sdr.rx_lo = int(carrierFrequency) sdr.rx_rf_bandwidth = int(sampleRate) sdr.rx_buffer_size = 16*numSamples sdr.gain_control_mode_chan0 = 'slow_attack' # sdr.rx_hardwaregain_chan0 = 30.0 # dB, increase to increase the receive gain, but be careful not to saturate the ADC

2.1 Transmitter Side

2.1 Generate Samples for transmission

[4]:
fm1 = 5000
fm2 = 20000

t   = (1/sampleRate)*np.arange(4*sampleRate/fm1)
x   = np.cos(2*np.pi*fm1*t) + 1j*np.sin(2*np.pi*fm2*t)/2

# Plot time domain
fig, ax = plt.subplots()
ax.plot(t, np.real(x))
ax.plot(t, np.imag(x))
ax.grid()
ax.set_xlabel("Time")

plt.show()

2.1 Transmit the samples

[5]:
# Create transmit waveform (QPSK, 16 samples per symbol)

# Stop transmitting
sdr.tx_destroy_buffer()

numRepetition = 1
scale         = 2**12
# Start the transmitter
sdr.tx_cyclic_buffer = True # Enable cyclic buffers
sdr.tx(scale*x.repeat(numRepetition)) # start transmitting

[ ]: