Post Go back to editing

Spectrum Analyzer using Adalm Pluto

Category: Software
Product Number: AD9361

I'm trying to make a spectral analyzer with adalm pluto Rev B, but the values are no equals. The conections are made how the image show:

For processing de data I used this code:

import numpy as np
import adi
import matplotlib.pyplot as plt
import time

# Setting Parameter

sample_rate = 10e6 # Hz
center_freq = 3e9 # Hz

#Configuration of Pluto

sdr = adi.Pluto("ip:192.168.2.1")
sdr.sample_rate = int(sample_rate)
sdr.rx_rf_bandwidth = int(sample_rate) # filter cutoff, just set it to the same as sample rate
sdr.rx_lo = int(center_freq)
sdr.rx_buffer_size = 1024 # this is the buffer the Pluto uses to buffer samples
sdr.gain_control_mode_chan0 = 'manual'
sdr.rx_hardwaregain_chan0 = -40.0 # dB


# FFT setup
fft_size = 1024
nSweep = 100
spectrogram = np.zeros((nSweep, fft_size))

# Take samples
start_time = time.time()

for i in range(nSweep):
    sample = sdr.rx() # receive samples off Pluto
    window = np.hamming(1024)
    filter_sample = sample*window
    fft_sample = np.fft.fftshift(np.fft.fft(filter_sample))
    s_mag = np.abs(fft_sample) / (np.sum(window)/2) # Scale FFT by window and /2 since we are using half the FFT spectrum
    spectrogram[i,:] = 20*np.log10(s_mag/(2**12)) + 6.6943 # Pluto is a 12 bit ADC, so use that to convert to dBFS

end_time = time.time()
print('seconds elapsed:', end_time - start_time)

peak = np.max(np.max(spectrogram, axis=0))
plt.figure(figsize=(5, 6.5))
plt.plot(np.linspace(sample_rate/-2/1e6, sample_rate/2/1e6, spectrogram.shape[1]),np.max(spectrogram, axis=0))
plt.text(0, peak,str(round(peak,2))+' dBm', fontsize = 12)
plt.xlabel("Frequency [MHz]")
#plt.ylabel("PSD dBm")
plt.title('Centre: 3000MHz'.ljust(40)+ "Span: 10Mhz\nRBW: 10MHz".ljust(55)+"VBW: 10MHz\nAtt:20dB".ljust(78))
plt.grid(color = "grey", linestyle = "--",linewidth = "1.4", alpha=0.4)
plt.xticks([-5,-4,-3,-2,-1,0,1,2,3,4,5])
plt.show()

Expain the code:

  1. For data processing, the FFT size is set to 1024 (following the recommendation that it be a multiple of 2^x ), which means each sample is spaced approximately 10kHz apart.
  2. N sweeps are taken while the AGC stabilizes; if it is configured in manual mode, this would not be necessary.
  3. A windowing function is applied to each sample to minimize the effect of disparity in the values at the edges of our signal. In our case, the Hamming window was applied.
  4. The Fourier transform is applied to the sample, and a shift is applied to center the DC component.Se obtiene la magnitud de la muestra y se lo escala para el tamaño de la ventana.
  5. The obtained value is converted to dBFS using the equation, considering that the ADC/DAC of the Pluto is 12 bits with this formula we could transform raw data to dBFS 20*log10(|P|/2^12)
  6. The value in dBFS can be converted to dBm by using the reference of the maximum peak-to-peak voltage that the AD9364 chip supports (Vpp), to convert it into RMS voltage ( Vrms). Additionally, knowing that the impedance is Z=100 ohm, with Vrms = Vpp/2sqrt(2), the conversion value can be obtained through the following formula: 10*log(Vrms^2/Z(1mW)))

But in processing data I not sure about scale by window length /2. That is a code copy from Pluto Rev. C

Results

The values obtain are close to spectrum analyzer, but I don't how justify why are divide by 2. On the left side, the result obtained by the TTi PSA6005 spectrum analyzer is shown, and on the right side, the sample obtained by the ADALM PLUTO is observed.

   

Thread Notes