make vna.py importable

This commit is contained in:
Brendan Haines 2025-01-15 22:23:54 -07:00
parent 22a33c2b84
commit 0c152c337e

View File

@ -4,7 +4,8 @@ from pathlib import Path
from typing import Any, Dict, Tuple from typing import Any, Dict, Tuple
import adi import adi
import iio
# import iio
import numpy as np import numpy as np
import skrf as rf import skrf as rf
import xarray as xr import xarray as xr
@ -229,89 +230,92 @@ class Charon:
# %% # %%
sdr = Charon("ip:192.168.3.1", frequency=np.linspace(1e9, 1.1e9, 11)) if __name__ == "__main__":
pass
# %% initialization # %%
config = sdr.get_config() sdr = Charon("ip:192.168.3.1", frequency=np.linspace(1e9, 1.1e9, 11))
# print(sdr.ctrl.debug_attrs["adi,rx-rf-port-input-select"].value)
# print(sdr.ctrl.debug_attrs["adi,tx-rf-port-input-select"].value)
config
# %% generate tone # %% initialization
fc = 1e9 config = sdr.get_config()
sdr.set_output(frequency=fc + sdr.FREQUENCY_OFFSET, power=-5) # print(sdr.ctrl.debug_attrs["adi,rx-rf-port-input-select"].value)
# print(sdr.ctrl.debug_attrs["adi,tx-rf-port-input-select"].value)
config
# %% capture data # %% generate tone
data = sdr._rx(1, fc=fc) fc = 1e9
sdr.set_output(frequency=fc + sdr.FREQUENCY_OFFSET, power=-5)
# %% Plot in time # %% capture data
fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True) data = sdr._rx(1, fc=fc)
axs[0].plot(np.real(data).T)
axs[1].plot(np.imag(data).T)
axs[0].set_ylabel("Real")
axs[1].set_ylabel("Imag")
axs[0].grid(True)
axs[1].grid(True)
axs[-1].set_xlabel("Sample")
axs[-1].set_xlim(0, data.shape[-1])
fig.show()
# %% # %% Plot in time
fig, ax = plt.subplots(1, 1, tight_layout=True) fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True)
ax.plot(np.real(data).T, np.imag(data).T) axs[0].plot(np.real(data).T)
ax.grid(True) axs[1].plot(np.imag(data).T)
ax.set_aspect("equal") axs[0].set_ylabel("Real")
ax.set_xlabel("Real") axs[1].set_ylabel("Imag")
ax.set_ylabel("Imag") axs[0].grid(True)
ax.set_xlim(np.array([-1, 1]) * (2 ** (12 - 1) - 1)) axs[1].grid(True)
ax.set_ylim(ax.get_xlim()) axs[-1].set_xlabel("Sample")
fig.show() axs[-1].set_xlim(0, data.shape[-1])
fig.show()
# %% Plot in frequency # %%
f = np.fft.fftfreq(data.shape[-1], 1 / sdr.sdr.sample_rate) fig, ax = plt.subplots(1, 1, tight_layout=True)
RX_BITS = 12 # for each of i, q (including sign bit) ax.plot(np.real(data).T, np.imag(data).T)
fft_data = np.fft.fft(data, axis=-1, norm="forward") / (2 ** (RX_BITS - 1)) ax.grid(True)
plt.figure() ax.set_aspect("equal")
for cc, chan in enumerate(sdr.sdr.rx_enabled_channels): ax.set_xlabel("Real")
ax.set_ylabel("Imag")
ax.set_xlim(np.array([-1, 1]) * (2 ** (12 - 1) - 1))
ax.set_ylim(ax.get_xlim())
fig.show()
# %% Plot in frequency
f = np.fft.fftfreq(data.shape[-1], 1 / sdr.sdr.sample_rate)
RX_BITS = 12 # for each of i, q (including sign bit)
fft_data = np.fft.fft(data, axis=-1, norm="forward") / (2 ** (RX_BITS - 1))
plt.figure()
for cc, chan in enumerate(sdr.sdr.rx_enabled_channels):
plt.plot( plt.plot(
np.fft.fftshift(f), np.fft.fftshift(f),
db20(np.fft.fftshift(fft_data[cc])), db20(np.fft.fftshift(fft_data[cc])),
label=f"Channel {chan}", label=f"Channel {chan}",
) )
plt.legend() plt.legend()
plt.ylim(-100, 0) plt.ylim(-100, 0)
plt.xlabel("Frequency [Hz]") plt.xlabel("Frequency [Hz]")
plt.ylabel("Power [dBfs]") plt.ylabel("Power [dBfs]")
plt.title(f"Fc = {sdr.sdr.rx_lo / 1e9} GHz") plt.title(f"Fc = {sdr.sdr.rx_lo / 1e9} GHz")
plt.gca().xaxis.set_major_formatter(EngFormatter()) plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True) plt.grid(True)
plt.show() plt.show()
# %%
s = sdr.vna_capture(frequency=np.linspace(70e6, 200e6, 101))
# %% # %% Plot Logmag
s = sdr.vna_capture(frequency=np.linspace(70e6, 200e6, 101)) fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True)
# %% Plot Logmag axs[0].plot(s.frequency, db20(s), label="Measured")
fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True) axs[1].plot(s.frequency, np.rad2deg(np.angle((s))), label="Measured")
axs[0].plot(s.frequency, db20(s), label="Measured") axs[0].grid(True)
axs[1].plot(s.frequency, np.rad2deg(np.angle((s))), label="Measured") axs[1].grid(True)
axs[0].grid(True) axs[0].set_ylim(-80, 0)
axs[1].grid(True) axs[1].set_ylim(-200, 200)
axs[1].set_xlim(np.min(s.frequency), np.max(s.frequency))
axs[1].xaxis.set_major_formatter(EngFormatter(places=1))
axs[1].set_xlabel("Frequency")
axs[0].set_ylim(-80, 0) axs[0].set_ylabel("|S11| [dB]")
axs[1].set_ylim(-200, 200) axs[1].set_ylabel("∠S11 [deg]")
axs[1].set_xlim(np.min(s.frequency), np.max(s.frequency))
axs[1].xaxis.set_major_formatter(EngFormatter(places=1))
axs[1].set_xlabel("Frequency")
axs[0].set_ylabel("|S11| [dB]") reference_sparams = None
axs[1].set_ylabel("∠S11 [deg]") reference_sparams = dir_ / "RBP-135+_Plus25degC.s2p"
if reference_sparams is not None:
reference_sparams = None
reference_sparams = dir_ / "RBP-135+_Plus25degC.s2p"
if reference_sparams is not None:
ref = rf.Network(reference_sparams) ref = rf.Network(reference_sparams)
rbp135 = net2s(ref) rbp135 = net2s(ref)
@ -320,67 +324,65 @@ if reference_sparams is not None:
axs[0].legend() axs[0].legend()
axs[1].legend() axs[1].legend()
plt.show() plt.show()
# %% SOL calibration
cal_frequency = np.linspace(70e6, 600e6, 101)
ideal_cal_frequency = rf.Frequency(np.min(cal_frequency), np.max(cal_frequency), len(cal_frequency))
input("Connect SHORT and press ENTER...")
short = sdr.vna_capture(frequency=cal_frequency)
input("Connect OPEN and press ENTER...")
open = sdr.vna_capture(frequency=cal_frequency)
input("Connect LOAD and press ENTER...")
load = sdr.vna_capture(frequency=cal_frequency)
# %% SOL calibration short_net = s2net(short)
cal_frequency = np.linspace(70e6, 600e6, 101) open_net = s2net(open)
ideal_cal_frequency = rf.Frequency(np.min(cal_frequency), np.max(cal_frequency), len(cal_frequency)) load_net = s2net(load)
input("Connect SHORT and press ENTER...")
short = sdr.vna_capture(frequency=cal_frequency)
input("Connect OPEN and press ENTER...")
open = sdr.vna_capture(frequency=cal_frequency)
input("Connect LOAD and press ENTER...")
load = sdr.vna_capture(frequency=cal_frequency)
short_net = s2net(short) cal_ideal = rf.media.DefinedGammaZ0(frequency=ideal_cal_frequency)
open_net = s2net(open) calibration = rf.calibration.OnePort(
load_net = s2net(load)
cal_ideal = rf.media.DefinedGammaZ0(frequency=ideal_cal_frequency)
calibration = rf.calibration.OnePort(
[short_net, open_net, load_net], [short_net, open_net, load_net],
[cal_ideal.short(), cal_ideal.open(), cal_ideal.load(0)], [cal_ideal.short(), cal_ideal.open(), cal_ideal.load(0)],
) )
# %%
s = sdr.vna_capture(frequency=cal_frequency)
# %% # %%
s = sdr.vna_capture(frequency=cal_frequency) s_calibrated = calibration.apply_cal(s2net(s))
# %% plt.figure()
s_calibrated = calibration.apply_cal(s2net(s)) s_calibrated.plot_s_smith()
# ref.plot_s_smith(m=1, n=1)
plt.show()
plt.figure() plt.figure()
s_calibrated.plot_s_smith() for start, stop in HAM_BANDS:
# ref.plot_s_smith(m=1, n=1)
plt.show()
plt.figure()
for start, stop in HAM_BANDS:
plt.axvspan(start, stop, alpha=0.1, color="k") plt.axvspan(start, stop, alpha=0.1, color="k")
s_calibrated.plot_s_db() s_calibrated.plot_s_db()
# ref.plot_s_db(m=1, n=1) # ref.plot_s_db(m=1, n=1)
plt.gca().xaxis.set_major_formatter(EngFormatter()) plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True) plt.grid(True)
plt.xlim(s_calibrated.f[0], s_calibrated.f[-1]) plt.xlim(s_calibrated.f[0], s_calibrated.f[-1])
plt.show() plt.show()
plt.figure() plt.figure()
for start, stop in HAM_BANDS: for start, stop in HAM_BANDS:
plt.axvspan(start, stop, alpha=0.1, color="k") plt.axvspan(start, stop, alpha=0.1, color="k")
# s_calibrated.plot_s_vswr() # s_calibrated.plot_s_vswr()
# drop invalid points # drop invalid points
vswr = copy.deepcopy(s_calibrated.s_vswr[:, 0, 0]) vswr = copy.deepcopy(s_calibrated.s_vswr[:, 0, 0])
vswr[vswr < 1] = np.nan vswr[vswr < 1] = np.nan
plt.plot(s_calibrated.f, vswr) plt.plot(s_calibrated.f, vswr)
plt.axhline(1, color="k", linestyle="--") plt.axhline(1, color="k", linestyle="--")
plt.ylabel("VSWR") plt.ylabel("VSWR")
plt.xlabel("Frequency [Hz]") plt.xlabel("Frequency [Hz]")
# ref.plot_s_vswr(m=1, n=1) # ref.plot_s_vswr(m=1, n=1)
plt.gca().xaxis.set_major_formatter(EngFormatter()) plt.gca().xaxis.set_major_formatter(EngFormatter())
plt.grid(True) plt.grid(True)
plt.ylim(0, 10) plt.ylim(0, 10)
plt.xlim(s_calibrated.f[0], s_calibrated.f[-1]) plt.xlim(s_calibrated.f[0], s_calibrated.f[-1])
plt.show() plt.show()
# %% # %%