Add files via upload

This commit is contained in:
Jon Kraft
2024-06-10 16:53:29 -06:00
committed by GitHub
parent 162615e184
commit 1415e78db1
2 changed files with 327 additions and 158 deletions

View File

@@ -1,5 +1,5 @@
# %%
# Copyright (C) 2019 Analog Devices, Inc.
# Copyright (C) 2024 Analog Devices, Inc.
#
# All rights reserved.
#
@@ -33,30 +33,41 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''FMCW Range Doppler Demo with Phaser (CN0566)
Jon Kraft, Jan 20 2024'''
Jon Kraft, June 9 2024'''
# %%
# Imports
import sys
import time
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import time
plt.close('all')
'''This script uses the new Pluto TDD engine
As of Jan 2024, this is in the "dev_phaser_merge" branch of https://github.com/analogdevicesinc/pyadi-iio
As of March 2024, this is in the main branch of https://github.com/analogdevicesinc/pyadi-iio
Also, make sure your Pluto firmware is updated to rev 0.38 (or later)
'''
#sys.path.insert(0,'/home/analog/cn0566_merge/pyadi-iio/')
import adi
print(adi.__version__)
# Parameters
'''Key Parameters'''
sample_rate = 5e6
center_freq = 2.1e9
signal_freq = int(sample_rate/10)
ramp_time = 200 # us
signal_freq = 100e3
rx_gain = 40 # must be between -3 and 70
tx_gain = -0 # must be between 0 and -88
output_freq = 9.9e9
chirp_BW = 500e6
ramp_time = 500 # us
num_chirps = 128
plot_data = True
save_data = False # saves data for later processing (use "Range_Doppler_Processing.py")
f = "phaserRadarData.npy"
# %%
""" Program the basic hardware settings
"""
# Instantiate all the Devices
rpi_ip = "ip:phaser.local" # IP address of the Raspberry Pi
sdr_ip = "ip:192.168.2.1" # "192.168.2.1, or pluto.local" # IP address of the Transceiver Block
@@ -65,73 +76,60 @@ my_phaser = adi.CN0566(uri=rpi_ip, sdr=my_sdr)
# Initialize both ADAR1000s, set gains to max, and all phases to 0
my_phaser.configure(device_mode="rx")
my_phaser.element_spacing = 0.014
my_phaser.load_gain_cal()
my_phaser.load_phase_cal()
for i in range(0, 8):
my_phaser.set_chan_phase(i, 0)
gain_list = [8, 34, 84, 127, 127, 84, 34, 8] # Blackman taper
gain_list = [127] * 8
#gain_list = [8, 34, 84, 127, 127, 84, 34, 8] # Blackman taper
for i in range(0, len(gain_list)):
my_phaser.set_chan_gain(i, gain_list[i], apply_cal=True)
# Setup Raspberry Pi GPIO states
try:
my_phaser._gpios.gpio_tx_sw = 0 # 0 = TX_OUT_2, 1 = TX_OUT_1
my_phaser._gpios.gpio_vctrl_1 = 1 # 1=Use onboard PLL/LO source (0=disable PLL and VCO, and set switch to use external LO input)
my_phaser._gpios.gpio_vctrl_2 = 1 # 1=Send LO to transmit circuitry (0=disable Tx path, and send LO to LO_OUT)
except:
my_phaser.gpios.gpio_tx_sw = 0 # 0 = TX_OUT_2, 1 = TX_OUT_1
my_phaser.gpios.gpio_vctrl_1 = 1 # 1=Use onboard PLL/LO source (0=disable PLL and VCO, and set switch to use external LO input)
my_phaser.gpios.gpio_vctrl_2 = 1 # 1=Send LO to transmit circuitry (0=disable Tx path, and send LO to LO_OUT)
my_phaser._gpios.gpio_tx_sw = 0 # 0 = TX_OUT_2, 1 = TX_OUT_1
my_phaser._gpios.gpio_vctrl_1 = 1 # 1=Use onboard PLL/LO source (0=disable PLL and VCO, and set switch to use external LO input)
my_phaser._gpios.gpio_vctrl_2 = 1 # 1=Send LO to transmit circuitry (0=disable Tx path, and send LO to LO_OUT)
# Configure SDR Rx
my_sdr.sample_rate = int(sample_rate)
my_sdr.rx_lo = int(center_freq) # set this to output_freq - (the freq of the HB100)
my_sdr.rx_enabled_channels = [0, 1] # enable Rx1 (voltage0) and Rx2 (voltage1)
my_sdr.rx_lo = int(center_freq)
my_sdr.rx_enabled_channels = [0, 1] # enable Rx1 and Rx2
my_sdr.gain_control_mode_chan0 = 'manual' # manual or slow_attack
my_sdr.gain_control_mode_chan1 = 'manual' # manual or slow_attack
my_sdr.rx_hardwaregain_chan0 = int(30) # must be between -3 and 70
my_sdr.rx_hardwaregain_chan1 = int(30) # must be between -3 and 70
my_sdr.rx_hardwaregain_chan0 = int(rx_gain) # must be between -3 and 70
my_sdr.rx_hardwaregain_chan1 = int(rx_gain) # must be between -3 and 70
# Configure SDR Tx
my_sdr.tx_lo = int(center_freq)
my_sdr.tx_enabled_channels = [0, 1]
my_sdr.tx_cyclic_buffer = True # must set cyclic buffer to true for the tdd burst mode. Otherwise Tx will turn on and off randomly
my_sdr.tx_cyclic_buffer = True # must set cyclic buffer to true for the tdd burst mode
my_sdr.tx_hardwaregain_chan0 = -88 # must be between 0 and -88
my_sdr.tx_hardwaregain_chan1 = -0 # must be between 0 and -88
my_sdr.tx_hardwaregain_chan1 = int(tx_gain) # must be between 0 and -88
# Read properties
print("RX LO %s" % (my_sdr.rx_lo))
# Configure the ADF4159 Rampling PLL
output_freq = 12.145e9
BW = 500e6
num_steps = ramp_time # in general it works best if there is 1 step per us
my_phaser.frequency = int(output_freq / 4) # Output frequency divided by 4
my_phaser.freq_dev_range = int(
BW / 4
) # frequency deviation range in Hz. This is the total freq deviation of the complete freq ramp
my_phaser.freq_dev_step = int(
(BW/4) / num_steps
) # frequency deviation step in Hz. This is fDEV, in Hz. Can be positive or negative
my_phaser.freq_dev_time = int(
ramp_time
) # total time (in us) of the complete frequency ramp
# Configure the ADF4159 Ramping PLL
vco_freq = int(output_freq + signal_freq + center_freq)
BW = chirp_BW
num_steps = int(ramp_time) # in general it works best if there is 1 step per us
my_phaser.frequency = int(vco_freq / 4)
my_phaser.freq_dev_range = int(BW / 4) # total freq deviation of the complete freq ramp in Hz
my_phaser.freq_dev_step = int((BW / 4) / num_steps) # This is fDEV, in Hz. Can be positive or negative
my_phaser.freq_dev_time = int(ramp_time) # total time (in us) of the complete frequency ramp
print("requested freq dev time (us) = ", ramp_time)
ramp_time = my_phaser.freq_dev_time
print("actual freq dev time (us) = ", ramp_time)
my_phaser.delay_word = 4095 # 12 bit delay word. 4095*PFD = 40.95 us. For sawtooth ramps, this is also the length of the Ramp_complete signal
my_phaser.delay_clk = "PFD" # can be 'PFD' or 'PFD*CLK1'
my_phaser.delay_start_en = 0 # delay start
my_phaser.ramp_delay_en = 0 # delay between ramps.
my_phaser.trig_delay_en = 0 # triangle delay
my_phaser.ramp_mode = "single_sawtooth_burst" # ramp_mode can be: "disabled", "continuous_sawtooth", "continuous_triangular", "single_sawtooth_burst", "single_ramp_burst"
my_phaser.sing_ful_tri = (
0 # full triangle enable/disable -- this is used with the single_ramp_burst mode
)
my_phaser.sing_ful_tri = 0 # full triangle enable/disable -- this is used with the single_ramp_burst mode
my_phaser.tx_trig_en = 1 # start a ramp with TXdata
my_phaser.enable = 0 # 0 = PLL enable. Write this last to update all the registers
# %%
""" Synchronize chirps to the start of each Pluto receive buffer
"""
# Configure TDD controller
sdr_pins = adi.one_bit_adc_dac(sdr_ip)
sdr_pins.gpio_tdd_ext_sync = True # If set to True, this enables external capture triggering using the L24N GPIO on the Pluto. When set to false, an internal trigger pulse will be generated every second
@@ -140,67 +138,71 @@ sdr_pins.gpio_phaser_enable = True
tdd.enable = False # disable TDD to configure the registers
tdd.sync_external = True
tdd.startup_delay_ms = 1
tdd.frame_length_ms = ramp_time/1e3 + 0.2 # each GPIO toggle is spaced this far apart
tdd.frame_length_ms = ramp_time/1e3 + 0.2 # each chirp is spaced this far apart
tdd.burst_count = num_chirps # number of chirps in one continuous receive buffer
tdd.out_channel0_enable = True
tdd.out_channel0_polarity = False
tdd.out_channel0_on_ms = 0.01 # each GPIO pulse will be 100us (0.6ms - 0.5ms). And the first trigger will happen 0.5ms into the buffer
tdd.out_channel0_off_ms = 0.2
tdd.out_channel1_enable = True
tdd.out_channel1_polarity = False
tdd.out_channel1_on_ms = 0
tdd.out_channel1_off_ms = 0.1
tdd.out_channel2_enable = False
tdd.channel[0].enable = True
tdd.channel[0].polarity = False
tdd.channel[0].on_ms = 0.01
tdd.channel[0].off_ms = 0.1
tdd.channel[1].enable = True
tdd.channel[1].polarity = False
tdd.channel[1].on_ms = 0
tdd.channel[1].off_ms = 0.1
tdd.channel[2].enable = False
tdd.enable = True
# buffer size needs to be greater than the frame_time
frame_time = tdd.frame_length_ms*tdd.burst_count # time in ms
print("frame_time: ", frame_time, "ms")
# From start of each ramp, how many "good" points do we want?
# For best freq linearity, stay away from the start of the ramps
ramp_time = int(my_phaser.freq_dev_time) # - begin_offset_time)
ramp_time_s = ramp_time / 1e6
begin_offset_time = 0.1 * ramp_time_s # time in seconds
print("actual freq dev time = ", ramp_time)
good_ramp_samples = int((ramp_time_s - begin_offset_time) * sample_rate)
start_offset_time = tdd.channel[0].on_ms/1e3 + begin_offset_time
start_offset_samples = int(start_offset_time * sample_rate)
# size the fft for the number of ramp data points
power=8
fft_size = int(2**power)
num_samples_frame = int(tdd.frame_length_ms/1000*sample_rate)
while num_samples_frame > fft_size:
power=power+1
fft_size = int(2**power)
if power==18:
break
print("fft_size =", fft_size)
# Pluto receive buffer size needs to be greater than total time for all chirps
total_time = tdd.frame_length_ms * num_chirps # time in ms
print("Total Time for all Chirps: ", total_time, "ms")
buffer_time = 0
power=12
while frame_time > buffer_time:
while total_time > buffer_time:
power=power+1
buffer_size = int(2**power)
buffer_time = buffer_size/my_sdr.sample_rate*1000 # buffer time in ms
buffer_time = buffer_size/sample_rate*1000 # buffer time in ms
if power==23:
break # max pluto buffer size is 2**23, but for tdd burst mode, set to 2**22
print("buffer_size:", buffer_size)
my_sdr.rx_buffer_size = buffer_size
print("buffer_time:", buffer_time, " ms")
# Create a sinewave waveform
#fs = int(my_sdr.sample_rate)
fs = sample_rate
print("sample_rate:", fs)
N = buffer_size
fc = int(signal_freq / (fs / N)) * (fs / N)
ts = 1 / float(fs)
t = np.arange(0, N * ts, ts)
i = np.cos(2 * np.pi * t * fc) * 2 ** 14
q = np.sin(2 * np.pi * t * fc) * 2 ** 14
iq = 0.9* (i + 1j * q)
my_sdr._ctx.set_timeout(30000)
my_sdr._rx_init_channels()
# Send data
my_sdr.tx([iq, iq])
print("buffer_time:", buffer_time, " ms")
# %%
""" Calculate ramp parameters
"""
PRI = tdd.frame_length_ms / 1e3
PRF = 1 / PRI
num_bursts = tdd.burst_count
# Split into frames
N_frame = int(PRI / ts)
N_frame = int(PRI * float(sample_rate))
# Obtain range-FFT x-axis
c = 3e8
wavelength = c / (output_freq - center_freq)
ramp_time_s = ramp_time / 1e6
wavelength = c / output_freq
slope = BW / ramp_time_s
freq = np.linspace(-fs / 2, fs / 2, N_frame)
freq = np.linspace(-sample_rate / 2, sample_rate / 2, N_frame)
dist = (freq - signal_freq) * c / (2 * slope)
# Resolutions
@@ -211,52 +213,35 @@ v_res = wavelength / (2 * num_bursts * PRI)
max_doppler_freq = PRF / 2
max_doppler_vel = max_doppler_freq * wavelength / 2
# First ramp starts with some offset (as defined in the TDD section above)
start_offset_time = tdd.out_channel0_on_ms/1e3
# From start of each ramp, how many "good" points do we want?
# For best freq linearity, stay away from the start of the ramps
begin_offset_time = 0.02e-3
good_ramp_time = ramp_time_s - begin_offset_time
good_ramp_samples = int(good_ramp_time * fs)
start_offset_samples = int((start_offset_time+begin_offset_time)*fs)
# %%
""" Create a sinewave waveform for Pluto's transmitter
"""
# Create a sinewave waveform
N = int(2**18)
fc = int(signal_freq)
ts = 1 / float(sample_rate)
t = np.arange(0, N * ts, ts)
i = np.cos(2 * np.pi * t * fc) * 2 ** 14
q = np.sin(2 * np.pi * t * fc) * 2 ** 14
iq = 0.9* (i + 1j * q)
# transmit data from Pluto
my_sdr._ctx.set_timeout(30000)
my_sdr._rx_init_channels()
my_sdr.tx([iq, iq])
# %%
range_doppler_fig, ax = plt.subplots(figsize=(14, 7))
extent = [-max_doppler_vel, max_doppler_vel, dist.min(), dist.max()]
# %%
# Collect data
my_phaser.gpios.gpio_burst = 0
my_phaser.gpios.gpio_burst = 1
my_phaser.gpios.gpio_burst = 0
data = my_sdr.rx()
chan1 = data[0]
chan2 = data[1]
sum_data = chan1+chan2
# Process data
# Make a 2D array of the chirps for each burst
rx_bursts = np.zeros((num_bursts, good_ramp_samples), dtype=complex)
for burst in range(num_bursts):
start_index = start_offset_samples + (burst) * N_frame
stop_index = start_index + good_ramp_samples
rx_bursts[burst] = sum_data[start_index:stop_index]
rx_bursts_fft = np.fft.fftshift(abs(np.fft.fft2(rx_bursts)))
# %%
# Function to collect data
i = 0
cmn = ''
def get_radar_data():
global range_doppler
# Collect data
my_phaser.gpios.gpio_burst = 0
my_phaser.gpios.gpio_burst = 1
my_phaser.gpios.gpio_burst = 0
my_phaser._gpios.gpio_burst = 0
my_phaser._gpios.gpio_burst = 1
my_phaser._gpios.gpio_burst = 0
data = my_sdr.rx()
chan1 = data[0]
chan2 = data[1]
@@ -272,57 +257,69 @@ def get_radar_data():
rx_bursts_fft = np.fft.fftshift(abs(np.fft.fft2(rx_bursts)))
range_doppler_data = np.log10(rx_bursts_fft).T
plot_data = range_doppler_data
#plot_data = np.clip(plot_data, 0, 6) # clip the data to control the max spectrogram scale
return plot_data
radar_data = range_doppler_data
#radar_data = np.clip(radar_data, 0, 6) # clip the data to control the max spectrogram scale
return rx_bursts, radar_data
# %%
plot_data = np.log10(rx_bursts_fft).T
#plot_data = np.clip(plot_data, 0, 6) # clip the data to control the max spectrogram scale
rx_bursts, radar_data = get_radar_data()
all_data = []
if plot_data == True:
range_doppler_fig, ax = plt.subplots(figsize=(14, 7))
extent = [-max_doppler_vel, max_doppler_vel, dist.min(), dist.max()]
print(extent)
cmaps = ['inferno', 'plasma']
cmn = cmaps[0]
try:
range_doppler = ax.imshow(radar_data, aspect='auto',
extent=extent, origin='lower', cmap=matplotlib.colormaps.get_cmap(cmn),
)
except:
print("Using an older version of MatPlotLIB")
from matplotlib.cm import get_cmap
range_doppler = ax.imshow(radar_data, aspect='auto', vmin=0, vmax=8,
extent=extent, origin='lower', cmap=get_cmap(cmn),
)
ax.set_title('Range Doppler Spectrum', fontsize=24)
ax.set_xlabel('Velocity [m/s]', fontsize=22)
ax.set_ylabel('Range [m]', fontsize=22)
cmaps = ['inferno', 'plasma']
cmn = cmaps[0]
try:
range_doppler = ax.imshow(plot_data, aspect='auto',
extent=extent, origin='lower', cmap=matplotlib.colormaps.get_cmap(cmn),
)
except:
print("Using an older version of MatPlotLIB")
from matplotlib.cm import get_cmap
range_doppler = ax.imshow(plot_data, aspect='auto', vmin=0, vmax=8,
extent=extent, origin='lower', cmap=get_cmap(cmn),
)
ax.set_title('Range Doppler Spectrum', fontsize=24)
ax.set_xlabel('Velocity [m/s]', fontsize=22)
ax.set_ylabel('Range [m]', fontsize=22)
max_range = 10
ax.set_xlim([-6, 6])
ax.set_ylim([0, max_range])
ax.set_yticks(np.arange(2, max_range, 2))
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
print("sample_rate = ", sample_rate/1e6, "MHz, ramp_time = ", ramp_time, "us, num_chirps = ", num_chirps)
print("CTRL + c to stop the loop")
max_range = 20
ax.set_xlim([-10, 10])
ax.set_ylim([0, max_range])
ax.set_yticks(np.arange(2, max_range, 2))
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
print("sample_rate = ", sample_rate/1e6, "MHz, ramp_time = ", ramp_time, "us, num_chirps = ", num_chirps)
print("CTRL + c to stop the loop")
try:
while True:
plot_data = get_radar_data()
range_doppler.set_data(plot_data)
plt.show(block=False)
plt.pause(.1)
rx_bursts, radar_data = get_radar_data()
if save_data == True:
all_data.append(rx_bursts)
print("save")
if plot_data == True:
range_doppler.set_data(radar_data)
plt.show(block=False)
plt.pause(.1)
except KeyboardInterrupt: # press ctrl-c to stop the loop
pass
# %%
# Pluto transmit shutdown
my_sdr.tx_destroy_buffer()
print("Buffer Destroyed!")
print("Pluto Buffer Cleared!")
if save_data == True:
np.save(f, all_data)
np.save("radar_config.npy", [sample_rate, signal_freq, output_freq, num_chirps, chirp_BW, ramp_time_s, tdd.frame_length_ms])
# # To disable TDD and revert to non-TDD (standard) mode
# disable TDD and revert to non-TDD (standard) mode
tdd.enable = False
sdr_pins.gpio_phaser_enable = False
tdd.out_channel1_polarity = not(sdr_pins.gpio_phaser_enable)
tdd.out_channel2_polarity = sdr_pins.gpio_phaser_enable
tdd.channel[1].polarity = not(sdr_pins.gpio_phaser_enable)
tdd.channel[2].polarity = sdr_pins.gpio_phaser_enable
tdd.enable = True
tdd.enable = False

172
Range_Doppler_Processing.py Normal file
View File

@@ -0,0 +1,172 @@
# %%
# Copyright (C) 2024 Analog Devices, Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# - Neither the name of Analog Devices, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
# - The use of this software may or may not infringe the patent rights
# of one or more patent holders. This license does not release you
# from the requirement that you obtain separate licenses from these
# patent holders to use this software.
# - Use of the software either in source or binary form, must be run
# on or directly connected to an Analog Devices Inc. component.
#
# THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED.
#
# IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
# RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''FMCW Range Processing Data from the Phaser (CN0566)
Jon Kraft, April 22 2024'''
# Imports
import sys
import time
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
plt.close('all')
from target_detection_dbfs import cfar
config = np.load("radar_config.npy") # these files are generated by the "Range_Doppler_Plot.py" program
all_data = np.load("phaserRadarData.npy")
# %%
""" Calculate and print summary of ramp parameters
"""
sample_rate = config[0]
signal_freq = config[1]
output_freq = config[2]
num_chirps = int(config[3])
chirp_BW = config[4]
ramp_time_s = config[5]
frame_length_ms = config[6]
PRI = frame_length_ms / 1e3
PRF = 1 / PRI
# Split into frames
N_frame = int(PRI * float(sample_rate))
# Obtain range-FFT x-axis
c = 3e8
wavelength = c / output_freq
slope = chirp_BW / ramp_time_s
freq = np.linspace(-sample_rate / 2, sample_rate / 2, N_frame)
dist = (freq - signal_freq) * c / (2 * slope)
# Resolutions
R_res = c / (2 * chirp_BW)
v_res = wavelength / (2 * num_chirps * PRI)
# Doppler spectrum limits
max_doppler_freq = PRF / 2
max_doppler_vel = max_doppler_freq * wavelength / 2
print("sample_rate = ", sample_rate/1e6, "MHz, ramp_time = ", int(ramp_time_s*(1e6)), "us, num_chirps = ", num_chirps)
# %%
# Function to process data
i = 0
cmn = ''
def get_radar_data():
global i
print(i)
rx_bursts = []
rx_bursts = all_data[i]
i=int((i+1) % len(all_data))
#rx_bursts_fft = np.fft.fft2(rx_bursts)
rx_bursts_fft = np.fft.fft(rx_bursts)
bias = 10
num_guard_cells = 16
num_ref_cells = 16
cfar_method = 'average'
use_CFAR = False
if use_CFAR == True:
for burst in range(num_chirps):
threshold, targets = cfar(rx_bursts_fft[burst], num_guard_cells, num_ref_cells, bias, cfar_method)
targets = targets.reshape(1,-1) # make a row vector
rx_bursts_fft[burst] = targets.filled(min(abs(rx_bursts_fft[burst]))) # fill the values below the threshold with -200 dBFS
rx_bursts_fft = np.fft.fft(rx_bursts_fft.T).T
rx_bursts_fft = np.fft.fftshift(abs(rx_bursts_fft))
range_doppler_data = np.log10(rx_bursts_fft).T
radar_data = range_doppler_data
num_good = len(radar_data[:,0])
center_delete = 6 # delete ground clutter velocity bins around 0 m/s
if center_delete != 0:
for g in range(center_delete):
end_bin = int(num_chirps/2+center_delete/2)
radar_data[:,(end_bin-center_delete+g)] = np.ones(num_good)*4.2
range_delete = 50 # delete the zero range bins (these are Tx to Rx leakage)
if range_delete != 0:
for r in range(range_delete):
start_bin = int(len(radar_data)/2)
radar_data[start_bin+r, :] = np.ones(num_chirps)*4.2
radar_data = np.clip(radar_data, 4, 5.5) # clip the data to control the max spectrogram scale
return radar_data
# %%
radar_data = get_radar_data()
range_doppler_fig, ax = plt.subplots(figsize=(14, 7))
extent = [-max_doppler_vel, max_doppler_vel, dist.min(), dist.max()]
cmaps = ['inferno', 'plasma']
cmn = cmaps[0]
try:
range_doppler = ax.imshow(radar_data, aspect='auto',
extent=extent, origin='lower', cmap=matplotlib.colormaps.get_cmap(cmn),
)
except:
print("Using an older version of MatPlotLIB")
from matplotlib.cm import get_cmap
range_doppler = ax.imshow(radar_data, aspect='auto', vmin=0, vmax=8,
extent=extent, origin='lower', cmap=get_cmap(cmn),
)
ax.set_title('Range Doppler Spectrum', fontsize=24)
ax.set_xlabel('Velocity [m/s]', fontsize=22)
ax.set_ylabel('Range [m]', fontsize=22)
max_range = 16
ax.set_xlim([-8, 8])
ax.set_ylim([0, max_range])
ax.set_yticks(np.arange(0, max_range, 2))
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
#print("sample_rate = ", sample_rate/1e6, "MHz, ramp_time = ", ramp_time, "us, num_chirps = ", num_chirps)
print("CTRL + c to stop the loop")
try:
while True:
radar_data = get_radar_data()
range_doppler.set_data(radar_data)
plt.show(block=False)
plt.pause(0.1)
except KeyboardInterrupt: # press ctrl-c to stop the loop
pass