pythonspectrogramusrpuhd

How Can I generate detect signals (2.4GHz) and generate spectrograms from them like this one?


I'm new to the world of RF and signal processing. I have a USRP B210 and I'm trying to detect and generate spectrograms that will be later used to train an AI model that identifies if the signal is a wifi, bluetooth, drone... which means we're focusing on 2.4GHz I guess.

this is the code provided by ettus research on

import uhd
import numpy as np

usrp = uhd.usrp.MultiUSRP()

num_samps = 10000 # number of samples received
center_freq = 100e6 # Hz
sample_rate = 1e6 # Hz
gain = 50 # dB

usrp.set_rx_rate(sample_rate, 0)
usrp.set_rx_freq(uhd.libpyuhd.types.tune_request(center_freq), 0)
usrp.set_rx_gain(gain, 0)

# Set up the stream and receive buffer
st_args = uhd.usrp.StreamArgs("fc32", "sc16")
st_args.channels = [0]
metadata = uhd.types.RXMetadata()
streamer = usrp.get_rx_stream(st_args)
recv_buffer = np.zeros((1, 1000), dtype=np.complex64)

# Start Stream
stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.start_cont)
stream_cmd.stream_now = True
streamer.issue_stream_cmd(stream_cmd)

# Receive Samples
samples = np.zeros(num_samps, dtype=np.complex64)
for i in range(num_samps//1000):
    streamer.recv(recv_buffer, metadata)
    samples[i*1000:(i+1)*1000] = recv_buffer[0]

# Stop Stream
stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.stop_cont)
streamer.issue_stream_cmd(stream_cmd)

print(len(samples))
print(samples[0:10])

I tried the basic code provided by Ettus Research on their website and experimented with different values and parameters, sometimes adding a filter... But It seems I'm still very far from my objective

This is the last code I used

import uhd
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter

def butter_lowpass_filter(data, cutoff_freq, sample_rate, order=5):
    nyquist = 0.5 * sample_rate
    normal_cutoff = cutoff_freq / nyquist
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    y = lfilter(b, a, data)
    return y

usrp = uhd.usrp.MultiUSRP()

num_samps = 1000000
center_freq = 2.4e9
sample_rate = 1e7
gain = 2
duration = 0.25
order = 10
cutoff_frequency = 2.5e6
denoised_samples = butter_lowpass_filter(samples, cutoff_frequency, sample_rate, order)


usrp.set_rx_rate(sample_rate, 0)
usrp.set_rx_freq(uhd.libpyuhd.types.tune_request(center_freq), 0)
usrp.set_rx_gain(gain, 0)

st_args = uhd.usrp.StreamArgs("fc32", "sc16")
st_args.channels = [0]
metadata = uhd.types.RXMetadata()
streamer = usrp.get_rx_stream(st_args)
recv_buffer = np.zeros((1, 1000), dtype=np.complex64)

stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.start_cont)
stream_cmd.stream_now = True
streamer.issue_stream_cmd(stream_cmd)

samples = np.zeros(num_samps, dtype=np.complex64)
for i in range(num_samps // 1000):
    streamer.recv(recv_buffer, metadata)
    samples[i * 1000:(i + 1) * 1000] = recv_buffer[0]

stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.stop_cont)
streamer.issue_stream_cmd(stream_cmd)

denoised_samples = butter_lowpass_filter(samples, cutoff_frequency, sample_rate)

print(len(denoised_samples))
print(denoised_samples[0:10])

plt.specgram(denoised_samples, NFFT=int(duration * sample_rate), Fs=sample_rate, noverlap=int(duration * sample_rate * 0.9), cmap='viridis')
plt.xlabel('Time (s)')
plt.ylabel('Frequency (Hz)')
plt.title('Spectrogram aver filter pass-bas 2')
cbar = plt.colorbar()
cbar.set_label('Intensity (dB)')


plt.show()

This is What I get: this is What I get

This is my objective: This is my objective


Solution

  • Here's an example of my code that I used to get a signal similar to the one you're trying to get

    import uhd
    import numpy as np
    import matplotlib.pyplot as plt
    import scipy
    
    usrp = uhd.usrp.MultiUSRP()
    
    num_samps = 1000 * 1000 # number of samples received
    num_samps_h = 2000 # number of samples received
    num_samps_w = 2000 # number of samples received
    center_freq = 2422e6 # Hz
    sample_rate = 15e6 # Hz
    gain = 50 # dB
    
    usrp.set_rx_rate(sample_rate, 0)
    usrp.set_rx_bandwidth(20e6)
    usrp.set_rx_freq(uhd.libpyuhd.types.tune_request(center_freq), 0)
    usrp.set_rx_gain(gain, 0)
    
    print("bandwidth", usrp.get_rx_bandwidth())
    
    # Set up the stream and receive buffer
    st_args = uhd.usrp.StreamArgs("fc32", "sc16")
    st_args.channels = [0]
    metadata = uhd.types.RXMetadata()
    streamer = usrp.get_rx_stream(st_args)
    recv_buffer = np.zeros((1, num_samps_w), dtype=np.complex64)
    
    # Start Stream
    stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.start_cont)
    stream_cmd.stream_now = True
    streamer.issue_stream_cmd(stream_cmd)
    
    # Receive Samples
    samples = np.zeros((num_samps_h, num_samps_w), dtype=np.complex64)
    for i in range(num_samps_h):
        streamer.recv(recv_buffer, metadata)
        samples[i] = scipy.fft.fft(recv_buffer[0])
    
    # Stop Stream
    stream_cmd = uhd.types.StreamCMD(uhd.types.StreamMode.stop_cont)
    streamer.issue_stream_cmd(stream_cmd)
    
    print(len(samples))
    print(samples[0:10])
    abs_samples = np.absolute(samples)
    print(abs_samples.max(), abs_samples.mean(), abs_samples.std())
    max_display_value =  abs_samples.mean() + 2 * abs_samples.std()
    abs_samples[np.where(abs_samples > max_display_value)] = max_display_value
    plt.imshow(abs_samples)
    plt.show()
    
    

    As a result, I managed to get waterfall images of the spectra, as in the attached pictures. Horizontal frequency, vertical time enter image description here