kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
- 0.0.9 release candidate
- Fixes to calibration: Standard length compensation should be better - Markers now show parallel R & L/C equivalent - The marker data can be hidden, if you want more space for charts - No more debug messages when sweeping.pull/17/head
rodzic
7a7ab0d668
commit
df521f8d8c
|
@ -308,7 +308,10 @@ class Calibration:
|
|||
self.shortL2 * f**2 +
|
||||
self.shortL3 * f**3)
|
||||
gammaShort = ((Zsp/50) - 1) / ((Zsp/50) + 1)
|
||||
g1 = gammaShort * math.exp(2*math.pi*f*self.shortLength)
|
||||
# (lower case) gamma = 2*pi*f
|
||||
# e^j*2*gamma*length
|
||||
# Referencing https://arxiv.org/pdf/1606.02446.pdf (18) - (21)
|
||||
g1 = gammaShort * np.exp(np.complex(0, 1) * 2 * 2 * math.pi * f * self.shortLength)
|
||||
|
||||
if self.useIdealOpen:
|
||||
g2 = self.openIdeal
|
||||
|
@ -317,7 +320,7 @@ class Calibration:
|
|||
if divisor != 0:
|
||||
Zop = np.complex(0, -1) / divisor
|
||||
gammaOpen = ((Zop/50) - 1) / ((Zop/50) + 1)
|
||||
g2 = gammaOpen * math.exp(2 * math.pi * f * self.openLength)
|
||||
g2 = gammaOpen * np.exp(np.complex(0, 1) * 2 * 2 * math.pi * f * self.shortLength)
|
||||
else:
|
||||
g2 = self.openIdeal
|
||||
if self.useIdealLoad:
|
||||
|
|
|
@ -48,6 +48,9 @@ class Marker(QtCore.QObject):
|
|||
self.frequency_label = QtWidgets.QLabel("")
|
||||
self.frequency_label.setMinimumWidth(100)
|
||||
self.impedance_label = QtWidgets.QLabel("")
|
||||
# self.admittance_label = QtWidgets.QLabel("")
|
||||
self.parallel_r_label = QtWidgets.QLabel("")
|
||||
self.parallel_x_label = QtWidgets.QLabel("")
|
||||
self.returnloss_label = QtWidgets.QLabel("")
|
||||
self.returnloss_label.setMinimumWidth(80)
|
||||
self.vswr_label = QtWidgets.QLabel("")
|
||||
|
@ -90,17 +93,20 @@ class Marker(QtCore.QObject):
|
|||
box_layout.addLayout(right_form)
|
||||
|
||||
# Left side
|
||||
left_form.addRow(QtWidgets.QLabel("Frequency:"), self.frequency_label)
|
||||
left_form.addRow(QtWidgets.QLabel("Impedance:"), self.impedance_label)
|
||||
left_form.addRow(QtWidgets.QLabel("L equiv.:"), self.inductance_label)
|
||||
left_form.addRow(QtWidgets.QLabel("C equiv.:"), self.capacitance_label)
|
||||
left_form.addRow(QtWidgets.QLabel("Q:"), self.quality_factor_label)
|
||||
left_form.addRow("Frequency:", self.frequency_label)
|
||||
left_form.addRow("Impedance:", self.impedance_label)
|
||||
# left_form.addRow("Admittance:", self.admittance_label)
|
||||
left_form.addRow("Parallel R:", self.parallel_r_label)
|
||||
left_form.addRow("Parallel X:", self.parallel_x_label)
|
||||
left_form.addRow("L equiv.:", self.inductance_label)
|
||||
left_form.addRow("C equiv.:", self.capacitance_label)
|
||||
|
||||
# Right side
|
||||
right_form.addRow(QtWidgets.QLabel("Return loss:"), self.returnloss_label)
|
||||
right_form.addRow(QtWidgets.QLabel("VSWR:"), self.vswr_label)
|
||||
right_form.addRow(QtWidgets.QLabel("S21 Gain:"), self.gain_label)
|
||||
right_form.addRow(QtWidgets.QLabel("S21 Phase:"), self.phase_label)
|
||||
right_form.addRow("Return loss:", self.returnloss_label)
|
||||
right_form.addRow("VSWR:", self.vswr_label)
|
||||
right_form.addRow("Q:", self.quality_factor_label)
|
||||
right_form.addRow("S21 Gain:", self.gain_label)
|
||||
right_form.addRow("S21 Phase:", self.phase_label)
|
||||
|
||||
def setFrequency(self, frequency):
|
||||
from .NanoVNASaver import NanoVNASaver
|
||||
|
@ -144,6 +150,9 @@ class Marker(QtCore.QObject):
|
|||
def resetLabels(self):
|
||||
self.frequency_label.setText("")
|
||||
self.impedance_label.setText("")
|
||||
self.parallel_r_label.setText("")
|
||||
self.parallel_x_label.setText("")
|
||||
# self.admittance_label.setText("")
|
||||
self.vswr_label.setText("")
|
||||
self.returnloss_label.setText("")
|
||||
self.inductance_label.setText("")
|
||||
|
@ -157,15 +166,27 @@ class Marker(QtCore.QObject):
|
|||
from NanoVNASaver.NanoVNASaver import NanoVNASaver
|
||||
if self.location != -1:
|
||||
im50, re50, vswr = NanoVNASaver.vswr(s11data[self.location])
|
||||
re50 = round(re50, 4 - math.floor(math.log10(abs(re50))))
|
||||
im50 = round(im50, 4 - math.floor(math.log10(abs(im50))))
|
||||
|
||||
rp = (re50 ** 2 + im50 ** 2) / re50
|
||||
xp = (re50 ** 2 + im50 ** 2) / im50
|
||||
re50 = round(re50, 4 - max(0, math.floor(math.log10(abs(re50)))))
|
||||
rp = round(rp, 4 - max(0, math.floor(math.log10(abs(rp)))))
|
||||
im50 = round(im50, 4 - max(0, math.floor(math.log10(abs(im50)))))
|
||||
xp = round(xp, 4 - max(0, math.floor(math.log10(abs(xp)))))
|
||||
if im50 < 0:
|
||||
im50str = " -j" + str(-1 * im50)
|
||||
else:
|
||||
im50str = " +j" + str(im50)
|
||||
im50str += "\N{OHM SIGN}"
|
||||
|
||||
if xp < 0:
|
||||
xpstr = NanoVNASaver.capacitanceEquivalent(xp, s11data[self.location].freq)
|
||||
else:
|
||||
xpstr = NanoVNASaver.inductanceEquivalent(xp, s11data[self.location].freq)
|
||||
|
||||
self.frequency_label.setText(NanoVNASaver.formatFrequency(s11data[self.location].freq))
|
||||
self.impedance_label.setText(str(round(re50, 3)) + im50str)
|
||||
self.impedance_label.setText(str(re50) + im50str)
|
||||
self.parallel_r_label.setText(str(rp) + "\N{OHM SIGN}")
|
||||
self.parallel_x_label.setText(xpstr)
|
||||
self.returnloss_label.setText(str(round(20 * math.log10((vswr - 1) / (vswr + 1)), 3)) + " dB")
|
||||
capacitance = NanoVNASaver.capacitanceEquivalent(im50, s11data[self.location].freq)
|
||||
inductance = NanoVNASaver.inductanceEquivalent(im50, s11data[self.location].freq)
|
||||
|
|
|
@ -37,7 +37,7 @@ PID = 22336
|
|||
|
||||
|
||||
class NanoVNASaver(QtWidgets.QWidget):
|
||||
version = "0.0.8"
|
||||
version = "0.0.9"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
@ -118,12 +118,15 @@ class NanoVNASaver(QtWidgets.QWidget):
|
|||
|
||||
left_column = QtWidgets.QVBoxLayout()
|
||||
marker_column = QtWidgets.QVBoxLayout()
|
||||
self.marker_frame = QtWidgets.QFrame()
|
||||
marker_column.setContentsMargins(0, 0, 0, 0)
|
||||
self.marker_frame.setLayout(marker_column)
|
||||
right_column = QtWidgets.QVBoxLayout()
|
||||
|
||||
right_column.addLayout(self.charts_layout)
|
||||
self.marker_frame.setHidden(not self.settings.value("MarkersVisible", True, bool))
|
||||
|
||||
layout.addLayout(left_column, 0, 0)
|
||||
layout.addLayout(marker_column, 0, 1)
|
||||
layout.addWidget(self.marker_frame, 0, 1)
|
||||
layout.addLayout(right_column, 0, 2)
|
||||
|
||||
################################################################################################################
|
||||
|
@ -214,7 +217,7 @@ class NanoVNASaver(QtWidgets.QWidget):
|
|||
|
||||
marker_control_box = QtWidgets.QGroupBox()
|
||||
marker_control_box.setTitle("Markers")
|
||||
marker_control_box.setMaximumWidth(350)
|
||||
marker_control_box.setMaximumWidth(250)
|
||||
marker_control_layout = QtWidgets.QFormLayout(marker_control_box)
|
||||
|
||||
|
||||
|
@ -238,18 +241,27 @@ class NanoVNASaver(QtWidgets.QWidget):
|
|||
marker3.updated.connect(self.dataUpdated)
|
||||
label, layout = marker3.getRow()
|
||||
marker_control_layout.addRow(label, layout)
|
||||
|
||||
self.markers.append(marker3)
|
||||
|
||||
self.showMarkerButton = QtWidgets.QPushButton()
|
||||
if self.marker_frame.isHidden():
|
||||
self.showMarkerButton.setText("Show data")
|
||||
else:
|
||||
self.showMarkerButton.setText("Hide data")
|
||||
self.showMarkerButton.clicked.connect(self.toggleMarkerFrame)
|
||||
marker_control_layout.addRow(self.showMarkerButton)
|
||||
|
||||
for c in self.charts:
|
||||
c.setMarkers(self.markers)
|
||||
#marker3.frequencyInput.setDisabled(True)
|
||||
marker_column.addWidget(marker_control_box)
|
||||
left_column.addWidget(marker_control_box)
|
||||
|
||||
marker_column.addWidget(self.markers[0].getGroupBox())
|
||||
marker_column.addWidget(self.markers[1].getGroupBox())
|
||||
marker_column.addWidget(self.markers[2].getGroupBox())
|
||||
|
||||
|
||||
################################################################################################################
|
||||
# Statistics/analysis
|
||||
################################################################################################################
|
||||
|
@ -495,7 +507,8 @@ class NanoVNASaver(QtWidgets.QWidget):
|
|||
self.lister = QtWidgets.QPlainTextEdit()
|
||||
self.lister.setFixedHeight(200)
|
||||
self.lister.setMaximumWidth(350)
|
||||
marker_column.addWidget(self.lister)
|
||||
# The lister doesn't really need to be visible for now. Maybe put it in a separate window?
|
||||
#marker_column.addWidget(self.lister)
|
||||
|
||||
self.worker.signals.updated.connect(self.dataUpdated)
|
||||
self.worker.signals.finished.connect(self.sweepFinished)
|
||||
|
@ -776,10 +789,7 @@ class NanoVNASaver(QtWidgets.QWidget):
|
|||
|
||||
@staticmethod
|
||||
def vswr(data: Datapoint):
|
||||
re = data.re
|
||||
im = data.im
|
||||
re50 = 50 * (1 - re * re - im * im) / (1 + re * re + im * im - 2 * re)
|
||||
im50 = 50 * (2 * im) / (1 + re * re + im * im - 2 * re)
|
||||
im50, re50 = NanoVNASaver.normalize50(data)
|
||||
mag = math.sqrt((re50 - 50) * (re50 - 50) + im50 * im50) / math.sqrt((re50 + 50) * (re50 + 50) + im50 * im50)
|
||||
# mag = math.sqrt(re * re + im * im) # Is this even right?
|
||||
vswr = (1 + mag) / (1 - mag)
|
||||
|
@ -806,15 +816,27 @@ class NanoVNASaver(QtWidgets.QWidget):
|
|||
|
||||
@staticmethod
|
||||
def gain(data: Datapoint):
|
||||
re = data.re
|
||||
im = data.im
|
||||
re50 = 50 * (1 - re * re - im * im) / (1 + re * re + im * im - 2 * re)
|
||||
im50 = 50 * (2 * im) / (1 + re * re + im * im - 2 * re)
|
||||
im50, re50 = NanoVNASaver.normalize50(data)
|
||||
# Calculate the gain / reflection coefficient
|
||||
mag = math.sqrt((re50 - 50) * (re50 - 50) + im50 * im50) / math.sqrt(
|
||||
(re50 + 50) * (re50 + 50) + im50 * im50)
|
||||
return 20 * math.log10(mag)
|
||||
|
||||
@staticmethod
|
||||
def normalize50(data):
|
||||
re = data.re
|
||||
im = data.im
|
||||
re50 = 50 * (1 - re * re - im * im) / (1 + re * re + im * im - 2 * re)
|
||||
im50 = 50 * (2 * im) / (1 + re * re + im * im - 2 * re)
|
||||
return im50, re50
|
||||
|
||||
@staticmethod
|
||||
def admittance(data):
|
||||
re50, im50 = NanoVNASaver.normalize50(data)
|
||||
rp = re50 / (re50**2 + im50**2)
|
||||
xp = - im50 / (re50**2 + im50**2)
|
||||
return rp, xp
|
||||
|
||||
def sweepFinished(self):
|
||||
self.sweepProgressBar.setValue(100)
|
||||
self.btnSweep.setDisabled(False)
|
||||
|
@ -964,6 +986,16 @@ class NanoVNASaver(QtWidgets.QWidget):
|
|||
title = title + " (" + insert + ")"
|
||||
self.setWindowTitle(title)
|
||||
|
||||
def toggleMarkerFrame(self):
|
||||
if self.marker_frame.isHidden():
|
||||
self.marker_frame.setHidden(False)
|
||||
self.settings.setValue("MarkersVisible", True)
|
||||
self.showMarkerButton.setText("Hide data")
|
||||
else:
|
||||
self.marker_frame.setHidden(True)
|
||||
self.settings.setValue("MarkersVisible", False)
|
||||
self.showMarkerButton.setText("Show data")
|
||||
|
||||
def resetReference(self):
|
||||
self.referenceS11data = []
|
||||
self.referenceS21data = []
|
||||
|
|
|
@ -69,7 +69,6 @@ class SweepWorker(QtCore.QRunnable):
|
|||
|
||||
span = sweepTo - sweepFrom
|
||||
stepsize = int(span / (100 + (self.noSweeps-1)*101))
|
||||
print("Doing " + str(100 + (self.noSweeps-1)*101) + " steps of size " + str(stepsize))
|
||||
values = []
|
||||
values12 = []
|
||||
frequencies = []
|
||||
|
@ -191,4 +190,4 @@ class SweepWorker(QtCore.QRunnable):
|
|||
return tmpfreq
|
||||
|
||||
def setContinuousSweep(self, continuousSweep):
|
||||
self.continuousSweep = continuousSweep
|
||||
self.continuousSweep = continuousSweep
|
||||
|
|
2
setup.py
2
setup.py
|
@ -35,7 +35,7 @@ with open("README.md", "r") as fh:
|
|||
setup(
|
||||
name='NanoVNASaver',
|
||||
url='https://github.com/mihtjel/nanovna-saver',
|
||||
version='0.0.8',
|
||||
version='0.0.9',
|
||||
author='Rune B. Broberg',
|
||||
author_email='',
|
||||
packages=find_packages(),
|
||||
|
|
Ładowanie…
Reference in New Issue