mirror of
https://github.com/jonkraft/PhaserRadarLabs.git
synced 2026-01-09 04:27:55 -05:00
Add files via upload
This commit is contained in:
@@ -33,8 +33,8 @@
|
||||
# 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 Radar Demo with Phaser (CN0566)
|
||||
Jon Kraft, Nov 19 2023'''
|
||||
'''CFAR Radar Demo with Phaser (CN0566)
|
||||
Jon Kraft, Jan 20 2024'''
|
||||
|
||||
# Imports
|
||||
import adi
|
||||
@@ -79,8 +79,9 @@ except:
|
||||
sample_rate = 0.6e6
|
||||
center_freq = 2.1e9
|
||||
signal_freq = 100e3
|
||||
num_slices = 50
|
||||
fft_size = 1024 * 16
|
||||
num_slices = 20 # this sets how much time will be displayed on the waterfall plot
|
||||
fft_size = 1024 * 4
|
||||
plot_freq = 100e3 # x-axis freq range to plot
|
||||
img_array = np.ones((num_slices, fft_size))*(-100)
|
||||
|
||||
# Configure SDR Rx
|
||||
@@ -102,9 +103,8 @@ my_sdr.tx_hardwaregain_chan1 = -0 # must be between 0 and -88
|
||||
# Configure the ADF4159 Rampling PLL
|
||||
output_freq = 12.145e9
|
||||
BW = 500e6
|
||||
num_steps = 1000
|
||||
ramp_time = 1.2e3 # us
|
||||
ramp_time_s = ramp_time / 1e6
|
||||
num_steps = 500
|
||||
ramp_time = 0.5e3 # us
|
||||
my_phaser.frequency = int(output_freq / 4) # Output frequency divided by 4
|
||||
my_phaser.freq_dev_range = int(
|
||||
BW / 4
|
||||
@@ -116,7 +116,9 @@ my_phaser.freq_dev_time = int(
|
||||
ramp_time
|
||||
) # total time (in us) of the complete frequency ramp
|
||||
print("requested freq dev time = ", ramp_time)
|
||||
print("actual freq dev time = ", my_phaser.freq_dev_time)
|
||||
ramp_time = my_phaser.freq_dev_time
|
||||
ramp_time_s = ramp_time / 1e6
|
||||
print("actual freq dev time = ", 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
|
||||
@@ -151,7 +153,6 @@ IF: {signal_freq}kHz
|
||||
|
||||
# Create a sinewave waveform
|
||||
fs = int(my_sdr.sample_rate)
|
||||
print("sample_rate:", fs)
|
||||
N = int(my_sdr.rx_buffer_size)
|
||||
fc = int(signal_freq / (fs / N)) * (fs / N)
|
||||
ts = 1 / float(fs)
|
||||
@@ -165,7 +166,7 @@ my_sdr._ctx.set_timeout(0)
|
||||
my_sdr.tx([iq * 0.5, iq]) # only send data to the 2nd channel (that's all we need)
|
||||
|
||||
c = 3e8
|
||||
default_rf_bw = 500e6
|
||||
default_chirp_bw = 500e6
|
||||
N_frame = fft_size
|
||||
freq = np.linspace(-fs / 2, fs / 2, int(N_frame))
|
||||
slope = BW / ramp_time_s
|
||||
@@ -179,23 +180,23 @@ class Window(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("Interactive FFT")
|
||||
self.setGeometry(100, 100, 800, 800) # (x,y, width, height)
|
||||
self.setFixedWidth(1600)
|
||||
self.setGeometry(0, 0, 400, 400) # (x,y, width, height)
|
||||
#self.setFixedWidth(600)
|
||||
self.setWindowState(QtCore.Qt.WindowMaximized)
|
||||
self.num_rows = 12
|
||||
self.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, False) #remove the window's close button
|
||||
self.UiComponents()
|
||||
# showing all the widgets
|
||||
self.show()
|
||||
|
||||
# method for components
|
||||
def UiComponents(self):
|
||||
widget = QWidget()
|
||||
|
||||
global layout
|
||||
global layout, signal_freq, plot_freq
|
||||
layout = QGridLayout()
|
||||
|
||||
# Control Panel
|
||||
control_label = QLabel("PHASER Simple FMCW Radar")
|
||||
control_label = QLabel("PHASER CFAR Targeting")
|
||||
font = control_label.font()
|
||||
font.setPointSize(24)
|
||||
control_label.setFont(font)
|
||||
@@ -217,18 +218,18 @@ class Window(QMainWindow):
|
||||
self.cfar_check.stateChanged.connect(self.change_cfar)
|
||||
layout.addWidget(self.cfar_check, 2, 1)
|
||||
|
||||
# RF bandwidth slider
|
||||
# Chirp bandwidth slider
|
||||
self.bw_slider = QSlider(Qt.Horizontal)
|
||||
self.bw_slider.setMinimum(100)
|
||||
self.bw_slider.setMaximum(500)
|
||||
self.bw_slider.setValue(int(default_rf_bw / 1e6))
|
||||
self.bw_slider.setValue(int(default_chirp_bw / 1e6))
|
||||
self.bw_slider.setTickInterval(50)
|
||||
self.bw_slider.setMaximumWidth(200)
|
||||
self.bw_slider.setTickPosition(QSlider.TicksBelow)
|
||||
self.bw_slider.valueChanged.connect(self.get_range_res)
|
||||
layout.addWidget(self.bw_slider, 4, 0)
|
||||
|
||||
self.set_bw = QPushButton("Set RF Bandwidth")
|
||||
self.set_bw = QPushButton("Set Chirp Bandwidth")
|
||||
self.set_bw.setMaximumWidth(200)
|
||||
self.set_bw.pressed.connect(self.set_range_res)
|
||||
layout.addWidget(self.set_bw, 5, 0, 1, 1)
|
||||
@@ -240,9 +241,9 @@ class Window(QMainWindow):
|
||||
#CFAR Sliders
|
||||
self.cfar_bias = QSlider(Qt.Horizontal)
|
||||
self.cfar_bias.setMinimum(0)
|
||||
self.cfar_bias.setMaximum(50)
|
||||
self.cfar_bias.setValue(36)
|
||||
self.cfar_bias.setTickInterval(2)
|
||||
self.cfar_bias.setMaximum(100)
|
||||
self.cfar_bias.setValue(40)
|
||||
self.cfar_bias.setTickInterval(5)
|
||||
self.cfar_bias.setMaximumWidth(200)
|
||||
self.cfar_bias.setTickPosition(QSlider.TicksBelow)
|
||||
self.cfar_bias.valueChanged.connect(self.get_cfar_values)
|
||||
@@ -353,15 +354,15 @@ class Window(QMainWindow):
|
||||
self.fft_plot = pg.plot()
|
||||
self.fft_plot.setMinimumWidth(600)
|
||||
self.fft_curve = self.fft_plot.plot(freq, pen={'color':'y', 'width':2})
|
||||
self.fft_threshold = self.fft_plot.plot(freq, pen={'color':'r', 'width':8})
|
||||
self.fft_threshold = self.fft_plot.plot(freq, pen={'color':'r', 'width':2})
|
||||
title_style = {"size": "20pt"}
|
||||
label_style = {"color": "#FFF", "font-size": "14pt"}
|
||||
self.fft_plot.setLabel("bottom", text="Frequency", units="Hz", **label_style)
|
||||
self.fft_plot.setLabel("left", text="Magnitude", units="dB", **label_style)
|
||||
self.fft_plot.setTitle("Received Signal - Frequency Spectrum", **title_style)
|
||||
layout.addWidget(self.fft_plot, 0, 2, self.num_rows, 1)
|
||||
self.fft_plot.setYRange(-100, -20)
|
||||
self.fft_plot.setXRange(100e3, 130e3)
|
||||
self.fft_plot.setYRange(-60, 0)
|
||||
self.fft_plot.setXRange(signal_freq, signal_freq+plot_freq)
|
||||
|
||||
# Waterfall plot
|
||||
self.waterfall = pg.PlotWidget()
|
||||
@@ -378,7 +379,7 @@ class Window(QMainWindow):
|
||||
tr.translate(0,-sample_rate/2)
|
||||
tr.scale(0.35, sample_rate / (N))
|
||||
self.imageitem.setTransform(tr)
|
||||
zoom_freq = 20e3
|
||||
zoom_freq = 35e3
|
||||
self.waterfall.setRange(yRange=(signal_freq, signal_freq + zoom_freq))
|
||||
self.waterfall.setTitle("Waterfall Spectrum", **title_style)
|
||||
self.waterfall.setLabel("left", "Frequency", units="Hz", **label_style)
|
||||
@@ -391,7 +392,7 @@ class Window(QMainWindow):
|
||||
self.setCentralWidget(widget)
|
||||
|
||||
def get_range_res(self):
|
||||
""" Updates the slider bar label with RF bandwidth and range resolution
|
||||
""" Updates the slider bar label with Chirp bandwidth and range resolution
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
@@ -408,8 +409,6 @@ class Window(QMainWindow):
|
||||
self.cfar_ref_label.setText("Num Ref Cells: %0.0f" % (self.cfar_ref.value()))
|
||||
|
||||
|
||||
|
||||
|
||||
def get_water_levels(self):
|
||||
""" Updates the waterfall intensity levels
|
||||
Returns:
|
||||
@@ -437,11 +436,11 @@ class Window(QMainWindow):
|
||||
my_phaser.set_beam_phase_diff(np.degrees(phase_delta))
|
||||
|
||||
def set_range_res(self):
|
||||
""" Sets the RF bandwidth
|
||||
""" Sets the Chirp bandwidth
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
global dist, slope
|
||||
global dist, slope, signal_freq, plot_freq
|
||||
bw = self.bw_slider.value() * 1e6
|
||||
slope = bw / ramp_time_s
|
||||
dist = (freq - signal_freq) * c / (4 * slope)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''CW Radar Demo with Phaser (CN0566)
|
||||
Jon Kraft, Nov 19 2023'''
|
||||
Jon Kraft, Jan 19 2024'''
|
||||
|
||||
# Imports
|
||||
import adi
|
||||
@@ -76,7 +76,7 @@ except:
|
||||
my_phaser.gpios.gpio_vctrl_2 = 1 # 1=Send LO to transmit circuitry (0=disable Tx path, and send LO to LO_OUT)
|
||||
|
||||
sample_rate = 0.6e6
|
||||
center_freq = 2.1e9
|
||||
center_freq = 2.2e9
|
||||
signal_freq = 100e3
|
||||
num_slices = 50
|
||||
fft_size = 1024 * 64
|
||||
@@ -100,7 +100,7 @@ my_sdr.tx_hardwaregain_chan1 = -0 # must be between 0 and -88
|
||||
|
||||
|
||||
# Configure the ADF4159 Rampling PLL
|
||||
output_freq = 12.145e9
|
||||
output_freq = 12.2e9
|
||||
my_phaser.frequency = int(output_freq / 4) # Output frequency divided by 4
|
||||
my_phaser.ramp_mode = "disabled" # ramp_mode can be: "disabled", "continuous_sawtooth", "continuous_triangular", "single_sawtooth_burst", "single_ramp_burst"
|
||||
my_phaser.enable = 0 # 0 = PLL enable. Write this last to update all the registers
|
||||
@@ -132,7 +132,6 @@ class Window(QMainWindow):
|
||||
self.num_rows = 12
|
||||
self.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, False) #remove the window's close button
|
||||
self.UiComponents()
|
||||
# showing all the widgets
|
||||
self.show()
|
||||
|
||||
# method for components
|
||||
@@ -161,7 +160,7 @@ class Window(QMainWindow):
|
||||
self.low_slider = QSlider(Qt.Horizontal)
|
||||
self.low_slider.setMinimum(-100)
|
||||
self.low_slider.setMaximum(0)
|
||||
self.low_slider.setValue(-40)
|
||||
self.low_slider.setValue(-66)
|
||||
self.low_slider.setTickInterval(20)
|
||||
self.low_slider.setMaximumWidth(200)
|
||||
self.low_slider.setTickPosition(QSlider.TicksBelow)
|
||||
@@ -171,7 +170,7 @@ class Window(QMainWindow):
|
||||
self.high_slider = QSlider(Qt.Horizontal)
|
||||
self.high_slider.setMinimum(-100)
|
||||
self.high_slider.setMaximum(0)
|
||||
self.high_slider.setValue(-28)
|
||||
self.high_slider.setValue(-42)
|
||||
self.high_slider.setTickInterval(20)
|
||||
self.high_slider.setMaximumWidth(200)
|
||||
self.high_slider.setTickPosition(QSlider.TicksBelow)
|
||||
@@ -260,6 +259,7 @@ App = QApplication(sys.argv)
|
||||
|
||||
# create the instance of our Window
|
||||
win = Window()
|
||||
win.setWindowState(QtCore.Qt.WindowMaximized)
|
||||
index = 0
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''FMCW Radar Demo with Phaser (CN0566)
|
||||
Jon Kraft, Nov 19 2023'''
|
||||
Jon Kraft, Jan 20 2024'''
|
||||
|
||||
# Imports
|
||||
import adi
|
||||
@@ -78,8 +78,9 @@ except:
|
||||
sample_rate = 0.6e6
|
||||
center_freq = 2.1e9
|
||||
signal_freq = 100e3
|
||||
num_slices = 400
|
||||
num_slices = 400 # this sets how much time will be displayed on the waterfall plot
|
||||
fft_size = 1024 * 4
|
||||
plot_freq = 100e3 # x-axis freq range to plot
|
||||
img_array = np.ones((num_slices, fft_size))*(-100)
|
||||
|
||||
# Configure SDR Rx
|
||||
@@ -101,9 +102,8 @@ my_sdr.tx_hardwaregain_chan1 = -0 # must be between 0 and -88
|
||||
# Configure the ADF4159 Rampling PLL
|
||||
output_freq = 12.145e9
|
||||
BW = 500e6
|
||||
num_steps = 1000
|
||||
ramp_time = 1.2e3 # us
|
||||
ramp_time_s = ramp_time / 1e6
|
||||
num_steps = 500
|
||||
ramp_time = 0.5e3 # us
|
||||
my_phaser.frequency = int(output_freq / 4) # Output frequency divided by 4
|
||||
my_phaser.freq_dev_range = int(
|
||||
BW / 4
|
||||
@@ -115,7 +115,9 @@ my_phaser.freq_dev_time = int(
|
||||
ramp_time
|
||||
) # total time (in us) of the complete frequency ramp
|
||||
print("requested freq dev time = ", ramp_time)
|
||||
print("actual freq dev time = ", my_phaser.freq_dev_time)
|
||||
ramp_time = my_phaser.freq_dev_time
|
||||
ramp_time_s = ramp_time / 1e6
|
||||
print("actual freq dev time = ", 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
|
||||
@@ -150,7 +152,6 @@ IF: {signal_freq}kHz
|
||||
|
||||
# Create a sinewave waveform
|
||||
fs = int(my_sdr.sample_rate)
|
||||
print("sample_rate:", fs)
|
||||
N = int(my_sdr.rx_buffer_size)
|
||||
fc = int(signal_freq / (fs / N)) * (fs / N)
|
||||
ts = 1 / float(fs)
|
||||
@@ -164,7 +165,7 @@ my_sdr._ctx.set_timeout(0)
|
||||
my_sdr.tx([iq * 0.5, iq]) # only send data to the 2nd channel (that's all we need)
|
||||
|
||||
c = 3e8
|
||||
default_rf_bw = 500e6
|
||||
default_chirp_bw = 500e6
|
||||
N_frame = fft_size
|
||||
freq = np.linspace(-fs / 2, fs / 2, int(N_frame))
|
||||
slope = BW / ramp_time_s
|
||||
@@ -177,19 +178,19 @@ class Window(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("Interactive FFT")
|
||||
self.setGeometry(100, 100, 800, 800) # (x,y, width, height)
|
||||
self.setFixedWidth(1600)
|
||||
self.setGeometry(0, 0, 400, 400) # (x,y, width, height)
|
||||
#self.setFixedWidth(600)
|
||||
self.setWindowState(QtCore.Qt.WindowMaximized)
|
||||
self.num_rows = 12
|
||||
self.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, False) #remove the window's close button
|
||||
self.UiComponents()
|
||||
# showing all the widgets
|
||||
self.show()
|
||||
|
||||
# method for components
|
||||
def UiComponents(self):
|
||||
widget = QWidget()
|
||||
|
||||
global layout
|
||||
global layout, signal_freq
|
||||
layout = QGridLayout()
|
||||
|
||||
# Control Panel
|
||||
@@ -211,10 +212,10 @@ class Window(QMainWindow):
|
||||
layout.addWidget(self.x_axis_check, 2, 0)
|
||||
|
||||
# Range resolution
|
||||
# Changes with the RF BW slider
|
||||
# Changes with the Chirp BW slider
|
||||
self.range_res_label = QLabel(
|
||||
"B<sub>RF</sub>: %0.2f MHz - R<sub>res</sub>: %0.2f m"
|
||||
% (default_rf_bw / 1e6, c / (2 * default_rf_bw))
|
||||
"B: %0.2f MHz - R<sub>res</sub>: %0.2f m"
|
||||
% (default_chirp_bw / 1e6, c / (2 * default_chirp_bw))
|
||||
)
|
||||
font = self.range_res_label.font()
|
||||
font.setPointSize(10)
|
||||
@@ -224,18 +225,18 @@ class Window(QMainWindow):
|
||||
self.range_res_label.setMinimumWidth(100)
|
||||
layout.addWidget(self.range_res_label, 4, 1)
|
||||
|
||||
# RF bandwidth slider
|
||||
# Chirp bandwidth slider
|
||||
self.bw_slider = QSlider(Qt.Horizontal)
|
||||
self.bw_slider.setMinimum(100)
|
||||
self.bw_slider.setMaximum(500)
|
||||
self.bw_slider.setValue(int(default_rf_bw / 1e6))
|
||||
self.bw_slider.setValue(int(default_chirp_bw / 1e6))
|
||||
self.bw_slider.setTickInterval(50)
|
||||
self.bw_slider.setMaximumWidth(200)
|
||||
self.bw_slider.setTickPosition(QSlider.TicksBelow)
|
||||
self.bw_slider.valueChanged.connect(self.get_range_res)
|
||||
layout.addWidget(self.bw_slider, 4, 0)
|
||||
|
||||
self.set_bw = QPushButton("Set RF Bandwidth")
|
||||
self.set_bw = QPushButton("Set Chirp Bandwidth")
|
||||
self.set_bw.setMaximumWidth(200)
|
||||
self.set_bw.pressed.connect(self.set_range_res)
|
||||
layout.addWidget(self.set_bw, 5, 0, 1, 1)
|
||||
@@ -249,7 +250,7 @@ class Window(QMainWindow):
|
||||
self.low_slider = QSlider(Qt.Horizontal)
|
||||
self.low_slider.setMinimum(-100)
|
||||
self.low_slider.setMaximum(0)
|
||||
self.low_slider.setValue(-43)
|
||||
self.low_slider.setValue(-40)
|
||||
self.low_slider.setTickInterval(20)
|
||||
self.low_slider.setMaximumWidth(200)
|
||||
self.low_slider.setTickPosition(QSlider.TicksBelow)
|
||||
@@ -259,7 +260,7 @@ class Window(QMainWindow):
|
||||
self.high_slider = QSlider(Qt.Horizontal)
|
||||
self.high_slider.setMinimum(-100)
|
||||
self.high_slider.setMaximum(0)
|
||||
self.high_slider.setValue(-23)
|
||||
self.high_slider.setValue(-5)
|
||||
self.high_slider.setTickInterval(20)
|
||||
self.high_slider.setMaximumWidth(200)
|
||||
self.high_slider.setTickPosition(QSlider.TicksBelow)
|
||||
@@ -318,7 +319,7 @@ class Window(QMainWindow):
|
||||
self.fft_plot.setTitle("Received Signal - Frequency Spectrum", **title_style)
|
||||
layout.addWidget(self.fft_plot, 0, 2, self.num_rows, 1)
|
||||
self.fft_plot.setYRange(-60, 0)
|
||||
self.fft_plot.setXRange(100e3, 200e3)
|
||||
self.fft_plot.setXRange(signal_freq, signal_freq+plot_freq)
|
||||
|
||||
# Waterfall plot
|
||||
self.waterfall = pg.PlotWidget()
|
||||
@@ -335,7 +336,7 @@ class Window(QMainWindow):
|
||||
tr.translate(0,-sample_rate/2)
|
||||
tr.scale(0.35, sample_rate / (N))
|
||||
self.imageitem.setTransform(tr)
|
||||
zoom_freq = 20e3
|
||||
zoom_freq = 35e3
|
||||
self.waterfall.setRange(yRange=(signal_freq, signal_freq + zoom_freq))
|
||||
self.waterfall.setTitle("Waterfall Spectrum", **title_style)
|
||||
self.waterfall.setLabel("left", "Frequency", units="Hz", **label_style)
|
||||
@@ -355,7 +356,7 @@ class Window(QMainWindow):
|
||||
bw = self.bw_slider.value() * 1e6
|
||||
range_res = c / (2 * bw)
|
||||
self.range_res_label.setText(
|
||||
"B<sub>RF</sub>: %0.2f MHz - R<sub>res</sub>: %0.2f m"
|
||||
"B: %0.2f MHz - R<sub>res</sub>: %0.2f m"
|
||||
% (bw / 1e6, c / (2 * bw))
|
||||
)
|
||||
|
||||
@@ -386,24 +387,21 @@ class Window(QMainWindow):
|
||||
my_phaser.set_beam_phase_diff(np.degrees(phase_delta))
|
||||
|
||||
def set_range_res(self):
|
||||
""" Sets the RF bandwidth
|
||||
""" Sets the Chirp bandwidth
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
global dist, slope
|
||||
global dist, slope, signal_freq, plot_freq
|
||||
bw = self.bw_slider.value() * 1e6
|
||||
slope = bw / ramp_time_s
|
||||
dist = (freq - signal_freq) * c / (4 * slope)
|
||||
print("New slope: %0.2fMHz/s" % (slope / 1e6))
|
||||
if self.x_axis_check.isChecked() == True:
|
||||
print("Range axis")
|
||||
plot_dist = True
|
||||
range_x = (100e3) * c / (4 * slope)
|
||||
range_x = (plot_freq) * c / (4 * slope)
|
||||
self.fft_plot.setXRange(0, range_x)
|
||||
else:
|
||||
print("Frequency axis")
|
||||
plot_dist = False
|
||||
self.fft_plot.setXRange(100e3, 140e3)
|
||||
self.fft_plot.setXRange(signal_freq, signal_freq+plot_freq)
|
||||
my_phaser.freq_dev_range = int(bw / 4) # frequency deviation range in Hz
|
||||
my_phaser.enable = 0
|
||||
|
||||
@@ -422,17 +420,15 @@ class Window(QMainWindow):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
global plot_dist, slope
|
||||
global plot_dist, slope, signal_freq, plot_freq
|
||||
plot_state = win.fft_plot.getViewBox().state
|
||||
if state == QtCore.Qt.Checked:
|
||||
print("Range axis")
|
||||
plot_dist = True
|
||||
range_x = (100e3) * c / (4 * slope)
|
||||
range_x = (plot_freq) * c / (4 * slope)
|
||||
self.fft_plot.setXRange(0, range_x)
|
||||
else:
|
||||
print("Frequency axis")
|
||||
plot_dist = False
|
||||
self.fft_plot.setXRange(100e3, 200e3)
|
||||
self.fft_plot.setXRange(signal_freq, signal_freq+plot_freq)
|
||||
|
||||
|
||||
# create pyqt5 app
|
||||
|
||||
@@ -32,21 +32,31 @@
|
||||
# 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.
|
||||
|
||||
'''This script uses the new Pluto TDD engine
|
||||
As of Nov 2023, this is in the "dev_phaser_merge" branch of https://github.com/analogdevicesinc/pyadi-iio
|
||||
Also, make sure your Pluto firmware is updated to rev 0.38 (or later)
|
||||
To view the plot properly in Spyder, select Tools->Preferences, IPython Console, and change Graphics backend from Inline to Automatic
|
||||
'''
|
||||
'''FMCW Range Doppler Demo with Phaser (CN0566)
|
||||
Jon Kraft, Jan 20 2024'''
|
||||
|
||||
# Imports
|
||||
import adi
|
||||
|
||||
import sys
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.animation import FuncAnimation
|
||||
import numpy as np
|
||||
import time
|
||||
|
||||
'''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
|
||||
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
|
||||
sample_rate = 5e6
|
||||
center_freq = 2.1e9
|
||||
signal_freq = int(sample_rate/10)
|
||||
ramp_time = 200 # us
|
||||
num_chirps = 128
|
||||
|
||||
# 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
|
||||
@@ -74,11 +84,6 @@ except:
|
||||
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)
|
||||
|
||||
# Parameters
|
||||
sample_rate = 20e6
|
||||
center_freq = 2.1e9
|
||||
signal_freq = 0.1e6
|
||||
|
||||
# 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)
|
||||
@@ -100,8 +105,7 @@ print("RX LO %s" % (my_sdr.rx_lo))
|
||||
# Configure the ADF4159 Rampling PLL
|
||||
output_freq = 12.145e9
|
||||
BW = 500e6
|
||||
num_steps = 200
|
||||
ramp_time = 0.2e3 # us
|
||||
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
|
||||
@@ -137,7 +141,7 @@ 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.burst_count = 128 # number of chirps in one continuous receive buffer
|
||||
tdd.burst_count = num_chirps # number of chirps in one continuous receive buffer
|
||||
|
||||
tdd.out_channel0_enable = True
|
||||
tdd.out_channel0_polarity = False
|
||||
@@ -219,7 +223,7 @@ start_offset_samples = int((start_offset_time+begin_offset_time)*fs)
|
||||
|
||||
|
||||
# %%
|
||||
range_doppler_fig, ax = plt.subplots(figsize=(16, 16))
|
||||
range_doppler_fig, ax = plt.subplots(figsize=(14, 7))
|
||||
|
||||
extent = [-max_doppler_vel, max_doppler_vel, dist.min(), dist.max()]
|
||||
|
||||
@@ -247,7 +251,7 @@ rx_bursts_fft = np.fft.fftshift(abs(np.fft.fft2(rx_bursts)))
|
||||
# %%
|
||||
i = 0
|
||||
cmn = ''
|
||||
def get_radar_data(frame):
|
||||
def get_radar_data():
|
||||
global range_doppler
|
||||
# Collect data
|
||||
my_phaser.gpios.gpio_burst = 0
|
||||
@@ -267,35 +271,45 @@ def get_radar_data(frame):
|
||||
rx_bursts[burst] = sum_data[start_index:stop_index]
|
||||
|
||||
rx_bursts_fft = np.fft.fftshift(abs(np.fft.fft2(rx_bursts)))
|
||||
range_doppler.set_data(np.log10(rx_bursts_fft).T)
|
||||
return [range_doppler]
|
||||
|
||||
|
||||
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
|
||||
# %%
|
||||
|
||||
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
|
||||
|
||||
cmaps = ['inferno', 'plasma']
|
||||
cmn = cmaps[0]
|
||||
plot_data = np.log10(rx_bursts_fft).T
|
||||
plot_data = np.clip(plot_data, 0, 6)
|
||||
|
||||
range_doppler = ax.imshow(plot_data, aspect='auto',
|
||||
extent=extent, origin='lower', cmap=matplotlib.colormaps.get_cmap(cmn),
|
||||
)
|
||||
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 = 40
|
||||
ax.set_xlim([-15, 15])
|
||||
max_range = 10
|
||||
ax.set_xlim([-6, 6])
|
||||
ax.set_ylim([0, max_range])
|
||||
ax.set_yticks(np.arange(0, max_range, 4))
|
||||
ax.set_yticks(np.arange(2, max_range, 2))
|
||||
plt.xticks(fontsize=20)
|
||||
plt.yticks(fontsize=20)
|
||||
|
||||
print("Press CTRL+C to stop the loop")
|
||||
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:
|
||||
FuncAnimation(range_doppler_fig, get_radar_data, blit=True, frames=1, repeat=False)
|
||||
plt.show()
|
||||
plot_data = get_radar_data()
|
||||
range_doppler.set_data(plot_data)
|
||||
plt.show(block=False)
|
||||
plt.pause(.1)
|
||||
except KeyboardInterrupt: # press ctrl-c to stop the loop
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user