kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
Fix merge conflict.
commit
0ecbad1833
|
@ -42,3 +42,5 @@ Contributors
|
||||||
* Thomas de Lellis <24543390+t52ta6ek@users.noreply.github.com>
|
* Thomas de Lellis <24543390+t52ta6ek@users.noreply.github.com>
|
||||||
* zstadler <zeev.stadler@gmail.com>
|
* zstadler <zeev.stadler@gmail.com>
|
||||||
* tbergkvist <bergkvist.teo@protonmail.com>
|
* tbergkvist <bergkvist.teo@protonmail.com>
|
||||||
|
* timmythetank <maans.jacobsson@gmail.com>
|
||||||
|
* ottoedgren <edgrenotto@gmail.com>
|
||||||
|
|
1
main.py
1
main.py
|
@ -6,4 +6,5 @@ vna = NanoVNASaverHeadless(vna_index=0, verbose=True)
|
||||||
vna.set_sweep(2.9e9, 3.1e9)
|
vna.set_sweep(2.9e9, 3.1e9)
|
||||||
vna.calibrate()
|
vna.calibrate()
|
||||||
vna.stream_data()
|
vna.stream_data()
|
||||||
|
# vna.calibrate()
|
||||||
vna.kill()
|
vna.kill()
|
||||||
|
|
|
@ -149,29 +149,22 @@ class CalDataSet(UserDict):
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "# Hz ShortR ShortI OpenR OpenI LoadR LoadI"
|
+ "# Hz ShortR ShortI OpenR OpenI LoadR LoadI"
|
||||||
+ (
|
+ (
|
||||||
" ThroughR ThroughI ThrureflR"
|
" ThroughR ThroughI ThrureflR" " ThrureflI IsolationR IsolationI\n"
|
||||||
" ThrureflI IsolationR IsolationI\n"
|
|
||||||
if self.complete2port()
|
if self.complete2port()
|
||||||
else "\n"
|
else "\n"
|
||||||
)
|
)
|
||||||
+ "\n".join(
|
+ "\n".join([f"{self.data.get(freq)}" for freq in self.frequencies()])
|
||||||
[f"{self.data.get(freq)}" for freq in self.frequencies()]
|
|
||||||
)
|
|
||||||
+ "\n"
|
+ "\n"
|
||||||
)
|
)
|
||||||
if self.complete1port()
|
if self.complete1port()
|
||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
|
|
||||||
def _append_match(
|
def _append_match(self, m: re.Match, header: str, line_nr: int, line: str) -> None:
|
||||||
self, m: re.Match, header: str, line_nr: int, line: str
|
|
||||||
) -> None:
|
|
||||||
cal = m.groupdict()
|
cal = m.groupdict()
|
||||||
columns = {col[:-1] for col in cal.keys() if cal[col] and col != "freq"}
|
columns = {col[:-1] for col in cal.keys() if cal[col] and col != "freq"}
|
||||||
if "through" in columns and header == "sol":
|
if "through" in columns and header == "sol":
|
||||||
logger.warning(
|
logger.warning("Through data with sol header. %i: %s", line_nr, line)
|
||||||
"Through data with sol header. %i: %s", line_nr, line
|
|
||||||
)
|
|
||||||
# fix short data (without thrurefl)
|
# fix short data (without thrurefl)
|
||||||
if "thrurefl" in columns and "isolation" not in columns:
|
if "thrurefl" in columns and "isolation" not in columns:
|
||||||
cal["isolationr"] = cal["thrureflr"]
|
cal["isolationr"] = cal["thrureflr"]
|
||||||
|
@ -201,9 +194,7 @@ class CalDataSet(UserDict):
|
||||||
continue
|
continue
|
||||||
if m := RXP_CAL_HEADER.search(line):
|
if m := RXP_CAL_HEADER.search(line):
|
||||||
if header:
|
if header:
|
||||||
logger.warning(
|
logger.warning("Duplicate header in cal data. %i: %s", i, line)
|
||||||
"Duplicate header in cal data. %i: %s", i, line
|
|
||||||
)
|
|
||||||
header = "through" if m.group("through") else "sol"
|
header = "through" if m.group("through") else "sol"
|
||||||
continue
|
continue
|
||||||
if not line or line.startswith("#"):
|
if not line or line.startswith("#"):
|
||||||
|
@ -214,9 +205,7 @@ class CalDataSet(UserDict):
|
||||||
logger.warning("Illegal caldata. Line %i: %s", i, line)
|
logger.warning("Illegal caldata. Line %i: %s", i, line)
|
||||||
continue
|
continue
|
||||||
if not header:
|
if not header:
|
||||||
logger.warning(
|
logger.warning("Caldata without having read header: %i: %s", i, line)
|
||||||
"Caldata without having read header: %i: %s", i, line
|
|
||||||
)
|
|
||||||
self._append_match(m, header, line, i)
|
self._append_match(m, header, line, i)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -290,7 +279,7 @@ class Calibration:
|
||||||
|
|
||||||
def isValid2Port(self) -> bool:
|
def isValid2Port(self) -> bool:
|
||||||
return self.dataset.complete2port()
|
return self.dataset.complete2port()
|
||||||
|
|
||||||
def _calc_port_1(self, freq: int, cal: CalData):
|
def _calc_port_1(self, freq: int, cal: CalData):
|
||||||
g1 = self.gamma_short(freq)
|
g1 = self.gamma_short(freq)
|
||||||
g2 = self.gamma_open(freq)
|
g2 = self.gamma_open(freq)
|
||||||
|
@ -309,8 +298,7 @@ class Calibration:
|
||||||
cal.e00 = (
|
cal.e00 = (
|
||||||
-(
|
-(
|
||||||
(g2 * gm3 - g3 * gm3) * g1 * gm2
|
(g2 * gm3 - g3 * gm3) * g1 * gm2
|
||||||
- (g2 * g3 * gm2 - g2 * g3 * gm3 - (g3 * gm2 - g2 * gm3) * g1)
|
- (g2 * g3 * gm2 - g2 * g3 * gm3 - (g3 * gm2 - g2 * gm3) * g1) * gm1
|
||||||
* gm1
|
|
||||||
)
|
)
|
||||||
/ denominator
|
/ denominator
|
||||||
)
|
)
|
||||||
|
@ -388,9 +376,7 @@ class Calibration:
|
||||||
return (
|
return (
|
||||||
(Zsp / 50.0 - 1.0)
|
(Zsp / 50.0 - 1.0)
|
||||||
/ (Zsp / 50.0 + 1.0)
|
/ (Zsp / 50.0 + 1.0)
|
||||||
* cmath.exp(
|
* cmath.exp(complex(0.0, -4.0 * math.pi * freq * cal_element.short_length))
|
||||||
complex(0.0, -4.0 * math.pi * freq * cal_element.short_length)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def gamma_open(self, freq: int) -> complex:
|
def gamma_open(self, freq: int) -> complex:
|
||||||
|
@ -430,9 +416,7 @@ class Calibration:
|
||||||
return (
|
return (
|
||||||
(Zl / 50.0 - 1.0)
|
(Zl / 50.0 - 1.0)
|
||||||
/ (Zl / 50.0 + 1.0)
|
/ (Zl / 50.0 + 1.0)
|
||||||
* cmath.exp(
|
* cmath.exp(complex(0.0, -4 * math.pi * freq * cal_element.load_length))
|
||||||
complex(0.0, -4 * math.pi * freq * cal_element.load_length)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def gamma_through(self, freq: int) -> complex:
|
def gamma_through(self, freq: int) -> complex:
|
||||||
|
@ -524,8 +508,7 @@ class Calibration:
|
||||||
i = self.interp
|
i = self.interp
|
||||||
s21 = (dp.z - i["e30"](dp.freq)) / i["e10e32"](dp.freq)
|
s21 = (dp.z - i["e30"](dp.freq)) / i["e10e32"](dp.freq)
|
||||||
s21 = s21 * (
|
s21 = s21 * (
|
||||||
i["e10e01"](dp.freq)
|
i["e10e01"](dp.freq) / (i["e11"](dp.freq) * dp11.z - i["delta_e"](dp.freq))
|
||||||
/ (i["e11"](dp.freq) * dp11.z - i["delta_e"](dp.freq))
|
|
||||||
)
|
)
|
||||||
return Datapoint(dp.freq, s21.real, s21.imag)
|
return Datapoint(dp.freq, s21.real, s21.imag)
|
||||||
|
|
||||||
|
|
|
@ -84,11 +84,7 @@ def _fix_v2_hwinfo(dev):
|
||||||
|
|
||||||
def usb_typename(device: ListPortInfo) -> str:
|
def usb_typename(device: ListPortInfo) -> str:
|
||||||
return next(
|
return next(
|
||||||
(
|
(t.name for t in USBDEVICETYPES if device.vid == t.vid and device.pid == t.pid),
|
||||||
t.name
|
|
||||||
for t in USBDEVICETYPES
|
|
||||||
if device.vid == t.vid and device.pid == t.pid
|
|
||||||
),
|
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -135,9 +131,11 @@ def get_portinfos() -> list[str]:
|
||||||
portinfos.append(version)
|
portinfos.append(version)
|
||||||
return portinfos
|
return portinfos
|
||||||
|
|
||||||
|
|
||||||
def get_VNA(iface: Interface) -> VNA:
|
def get_VNA(iface: Interface) -> VNA:
|
||||||
return NAME2DEVICE[iface.comment](iface)
|
return NAME2DEVICE[iface.comment](iface)
|
||||||
|
|
||||||
|
|
||||||
def get_comment(iface: Interface) -> str:
|
def get_comment(iface: Interface) -> str:
|
||||||
logger.info("Finding correct VNA type...")
|
logger.info("Finding correct VNA type...")
|
||||||
with iface.lock:
|
with iface.lock:
|
||||||
|
|
|
@ -62,9 +62,7 @@ class NanoVNA(VNA):
|
||||||
self.serial.write("capture\r".encode("ascii"))
|
self.serial.write("capture\r".encode("ascii"))
|
||||||
self.serial.readline()
|
self.serial.readline()
|
||||||
self.serial.timeout = 4
|
self.serial.timeout = 4
|
||||||
image_data = self.serial.read(
|
image_data = self.serial.read(self.screenwidth * self.screenheight * 2)
|
||||||
self.screenwidth * self.screenheight * 2
|
|
||||||
)
|
|
||||||
self.serial.timeout = timeout
|
self.serial.timeout = timeout
|
||||||
self.serial.timeout = timeout
|
self.serial.timeout = timeout
|
||||||
return image_data
|
return image_data
|
||||||
|
@ -145,9 +143,7 @@ class NanoVNA(VNA):
|
||||||
f"scan {self.start} {self.stop} {self.datapoints} 0b110"
|
f"scan {self.start} {self.stop} {self.datapoints} 0b110"
|
||||||
):
|
):
|
||||||
data = line.split()
|
data = line.split()
|
||||||
self._sweepdata.append(
|
self._sweepdata.append((f"{data[0]} {data[1]}", f"{data[2]} {data[3]}"))
|
||||||
(f"{data[0]} {data[1]}", f"{data[2]} {data[3]}")
|
|
||||||
)
|
|
||||||
if value == "data 0":
|
if value == "data 0":
|
||||||
return [x[0] for x in self._sweepdata]
|
return [x[0] for x in self._sweepdata]
|
||||||
if value == "data 1":
|
if value == "data 1":
|
||||||
|
|
|
@ -121,10 +121,7 @@ class NanoVNA_V2(VNA):
|
||||||
self.txPowerRanges = [
|
self.txPowerRanges = [
|
||||||
(
|
(
|
||||||
(140e6, self.sweep_max_freq_Hz),
|
(140e6, self.sweep_max_freq_Hz),
|
||||||
[
|
[_ADF4350_TXPOWER_DESC_MAP[value] for value in (3, 2, 1, 0)],
|
||||||
_ADF4350_TXPOWER_DESC_MAP[value]
|
|
||||||
for value in (3, 2, 1, 0)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -172,14 +169,10 @@ class NanoVNA_V2(VNA):
|
||||||
self.serial.write(pack("<Q", 0))
|
self.serial.write(pack("<Q", 0))
|
||||||
sleep(WRITE_SLEEP)
|
sleep(WRITE_SLEEP)
|
||||||
# cmd: write register 0x30 to clear FIFO
|
# cmd: write register 0x30 to clear FIFO
|
||||||
self.serial.write(
|
self.serial.write(pack("<BBB", _CMD_WRITE, _ADDR_VALUES_FIFO, 0))
|
||||||
pack("<BBB", _CMD_WRITE, _ADDR_VALUES_FIFO, 0)
|
|
||||||
)
|
|
||||||
sleep(WRITE_SLEEP)
|
sleep(WRITE_SLEEP)
|
||||||
# clear sweepdata
|
# clear sweepdata
|
||||||
self._sweepdata = [(complex(), complex())] * (
|
self._sweepdata = [(complex(), complex())] * (self.datapoints + s21hack)
|
||||||
self.datapoints + s21hack
|
|
||||||
)
|
|
||||||
pointstodo = self.datapoints + s21hack
|
pointstodo = self.datapoints + s21hack
|
||||||
# we read at most 255 values at a time and the time required
|
# we read at most 255 values at a time and the time required
|
||||||
# empirically is just over 3 seconds for 101 points or
|
# empirically is just over 3 seconds for 101 points or
|
||||||
|
@ -205,9 +198,7 @@ class NanoVNA_V2(VNA):
|
||||||
# timeout secs
|
# timeout secs
|
||||||
arr = self.serial.read(nBytes)
|
arr = self.serial.read(nBytes)
|
||||||
if nBytes != len(arr):
|
if nBytes != len(arr):
|
||||||
logger.warning(
|
logger.warning("expected %d bytes, got %d", nBytes, len(arr))
|
||||||
"expected %d bytes, got %d", nBytes, len(arr)
|
|
||||||
)
|
|
||||||
# the way to retry on timeout is keep the data
|
# the way to retry on timeout is keep the data
|
||||||
# already read then try to read the rest of
|
# already read then try to read the rest of
|
||||||
# the data into the array
|
# the data into the array
|
||||||
|
@ -225,9 +216,7 @@ class NanoVNA_V2(VNA):
|
||||||
self._sweepdata = self._sweepdata[1:]
|
self._sweepdata = self._sweepdata[1:]
|
||||||
|
|
||||||
idx = 1 if value == "data 1" else 0
|
idx = 1 if value == "data 1" else 0
|
||||||
return [
|
return [f"{str(x[idx].real)} {str(x[idx].imag)}" for x in self._sweepdata]
|
||||||
f"{str(x[idx].real)} {str(x[idx].imag)}" for x in self._sweepdata
|
|
||||||
]
|
|
||||||
|
|
||||||
def resetSweep(self, start: int, stop: int):
|
def resetSweep(self, start: int, stop: int):
|
||||||
self.setSweep(start, stop)
|
self.setSweep(start, stop)
|
||||||
|
@ -251,9 +240,7 @@ class NanoVNA_V2(VNA):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def read_board_revision(self) -> "Version":
|
def read_board_revision(self) -> "Version":
|
||||||
result = self._read_version(
|
result = self._read_version(_ADDR_DEVICE_VARIANT, _ADDR_HARDWARE_REVISION)
|
||||||
_ADDR_DEVICE_VARIANT, _ADDR_HARDWARE_REVISION
|
|
||||||
)
|
|
||||||
logger.debug("read_board_revision: %s", result)
|
logger.debug("read_board_revision: %s", result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -279,12 +266,8 @@ class NanoVNA_V2(VNA):
|
||||||
_ADDR_SWEEP_START,
|
_ADDR_SWEEP_START,
|
||||||
max(50000, int(self.sweepStartHz - (self.sweepStepHz * s21hack))),
|
max(50000, int(self.sweepStartHz - (self.sweepStepHz * s21hack))),
|
||||||
)
|
)
|
||||||
cmd += pack(
|
cmd += pack("<BBQ", _CMD_WRITE8, _ADDR_SWEEP_STEP, int(self.sweepStepHz))
|
||||||
"<BBQ", _CMD_WRITE8, _ADDR_SWEEP_STEP, int(self.sweepStepHz)
|
cmd += pack("<BBH", _CMD_WRITE2, _ADDR_SWEEP_POINTS, self.datapoints + s21hack)
|
||||||
)
|
|
||||||
cmd += pack(
|
|
||||||
"<BBH", _CMD_WRITE2, _ADDR_SWEEP_POINTS, self.datapoints + s21hack
|
|
||||||
)
|
|
||||||
cmd += pack("<BBH", _CMD_WRITE2, _ADDR_SWEEP_VALS_PER_FREQ, 1)
|
cmd += pack("<BBH", _CMD_WRITE2, _ADDR_SWEEP_VALS_PER_FREQ, 1)
|
||||||
with self.serial.lock:
|
with self.serial.lock:
|
||||||
self.serial.write(cmd)
|
self.serial.write(cmd)
|
||||||
|
|
|
@ -62,9 +62,7 @@ class TinySA(VNA):
|
||||||
self.serial.write("capture\r".encode("ascii"))
|
self.serial.write("capture\r".encode("ascii"))
|
||||||
self.serial.readline()
|
self.serial.readline()
|
||||||
self.serial.timeout = 4
|
self.serial.timeout = 4
|
||||||
image_data = self.serial.read(
|
image_data = self.serial.read(self.screenwidth * self.screenheight * 2)
|
||||||
self.screenwidth * self.screenheight * 2
|
|
||||||
)
|
|
||||||
self.serial.timeout = timeout
|
self.serial.timeout = timeout
|
||||||
self.serial.timeout = timeout
|
self.serial.timeout = timeout
|
||||||
return image_data
|
return image_data
|
||||||
|
@ -122,8 +120,7 @@ class TinySA(VNA):
|
||||||
logger.debug("Read: %s", value)
|
logger.debug("Read: %s", value)
|
||||||
if value == "data 0":
|
if value == "data 0":
|
||||||
self._sweepdata = [
|
self._sweepdata = [
|
||||||
f"{conv2float(line)} 0.0"
|
f"{conv2float(line)} 0.0" for line in self.exec_command("data 0")
|
||||||
for line in self.exec_command("data 0")
|
|
||||||
]
|
]
|
||||||
return self._sweepdata
|
return self._sweepdata
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,7 @@ WAIT = 0.05
|
||||||
|
|
||||||
def _max_retries(bandwidth: int, datapoints: int) -> int:
|
def _max_retries(bandwidth: int, datapoints: int) -> int:
|
||||||
return round(
|
return round(
|
||||||
20
|
20 + 20 * (datapoints / 101) + (1000 / bandwidth) ** 1.30 * (datapoints / 101)
|
||||||
+ 20 * (datapoints / 101)
|
|
||||||
+ (1000 / bandwidth) ** 1.30 * (datapoints / 101)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,9 +147,7 @@ class VNA:
|
||||||
]
|
]
|
||||||
|
|
||||||
def set_bandwidth(self, bandwidth: int):
|
def set_bandwidth(self, bandwidth: int):
|
||||||
bw_val = (
|
bw_val = DISLORD_BW[bandwidth] if self.bw_method == "dislord" else bandwidth
|
||||||
DISLORD_BW[bandwidth] if self.bw_method == "dislord" else bandwidth
|
|
||||||
)
|
|
||||||
result = " ".join(self.exec_command(f"bandwidth {bw_val}"))
|
result = " ".join(self.exec_command(f"bandwidth {bw_val}"))
|
||||||
if self.bw_method == "ttrftech" and result:
|
if self.bw_method == "ttrftech" and result:
|
||||||
raise IOError(f"set_bandwith({bandwidth}: {result}")
|
raise IOError(f"set_bandwith({bandwidth}: {result}")
|
||||||
|
|
|
@ -22,13 +22,16 @@ import typing
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
_RXP = re.compile(r"""^
|
_RXP = re.compile(
|
||||||
|
r"""^
|
||||||
\D*
|
\D*
|
||||||
(?P<major>\d+)\.
|
(?P<major>\d+)\.
|
||||||
(?P<minor>\d+)\.?
|
(?P<minor>\d+)\.?
|
||||||
(?P<revision>\d+)?
|
(?P<revision>\d+)?
|
||||||
(?P<note>.*)
|
(?P<note>.*)
|
||||||
$""", re.VERBOSE)
|
$""",
|
||||||
|
re.VERBOSE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class _Version(typing.NamedTuple):
|
class _Version(typing.NamedTuple):
|
||||||
|
@ -38,18 +41,17 @@ class _Version(typing.NamedTuple):
|
||||||
note: str
|
note: str
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return (
|
return f"{self.major}.{self.minor}" f".{self.revision}{self.note}"
|
||||||
f'{self.major}.{self.minor}'
|
|
||||||
f'.{self.revision}{self.note}'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def Version(vstring: str = "0.0.0") -> '_Version':
|
def Version(vstring: str = "0.0.0") -> "_Version":
|
||||||
if (match := _RXP.search(vstring)) is None:
|
if (match := _RXP.search(vstring)) is None:
|
||||||
logger.error("Unable to parse version: %s", vstring)
|
logger.error("Unable to parse version: %s", vstring)
|
||||||
return _Version(0, 0, 0, '')
|
return _Version(0, 0, 0, "")
|
||||||
|
|
||||||
return _Version(int(match.group('major')),
|
return _Version(
|
||||||
int(match.group('minor')),
|
int(match.group("major")),
|
||||||
int(match.group('revision') or '0'),
|
int(match.group("minor")),
|
||||||
match.group('note'))
|
int(match.group("revision") or "0"),
|
||||||
|
match.group("note"),
|
||||||
|
)
|
||||||
|
|
|
@ -5,6 +5,7 @@ from .RFTools import Datapoint
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
|
||||||
class NanoVNASaverHeadless:
|
class NanoVNASaverHeadless:
|
||||||
def __init__(self, vna_index=0, verbose=False):
|
def __init__(self, vna_index=0, verbose=False):
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
|
@ -39,7 +40,14 @@ class NanoVNASaverHeadless:
|
||||||
|
|
||||||
def set_sweep(self, start, stop):
|
def set_sweep(self, start, stop):
|
||||||
self.vna.setSweep(start, stop)
|
self.vna.setSweep(start, stop)
|
||||||
print("Sweep set from " + str(self.vna.readFrequencies()[0]/1e9) + "e9" + " to " + str(self.vna.readFrequencies()[-1]/1e9) + "e9")
|
print(
|
||||||
|
"Sweep set from "
|
||||||
|
+ str(self.vna.readFrequencies()[0] / 1e9)
|
||||||
|
+ "e9"
|
||||||
|
+ " to "
|
||||||
|
+ str(self.vna.readFrequencies()[-1] / 1e9)
|
||||||
|
+ "e9"
|
||||||
|
)
|
||||||
|
|
||||||
def stream_data(self):
|
def stream_data(self):
|
||||||
data = self.get_data()
|
data = self.get_data()
|
||||||
|
@ -80,7 +88,7 @@ class NanoVNASaverHeadless:
|
||||||
values = item.split()
|
values = item.split()
|
||||||
real.append(float(values[0]))
|
real.append(float(values[0]))
|
||||||
imaginary.append(float(values[1]))
|
imaginary.append(float(values[1]))
|
||||||
#add exception handling
|
# add exception handling
|
||||||
return real, imaginary
|
return real, imaginary
|
||||||
|
|
||||||
def kill(self):
|
def kill(self):
|
||||||
|
@ -90,4 +98,4 @@ class NanoVNASaverHeadless:
|
||||||
else:
|
else:
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print("Disconnected VNA.")
|
print("Disconnected VNA.")
|
||||||
return
|
return
|
||||||
|
|
|
@ -76,9 +76,7 @@ class Datapoint(NamedTuple):
|
||||||
return -1 if imp.real == 0.0 else abs(imp.imag / imp.real)
|
return -1 if imp.real == 0.0 else abs(imp.imag / imp.real)
|
||||||
|
|
||||||
def capacitiveEquivalent(self, ref_impedance: float = 50) -> float:
|
def capacitiveEquivalent(self, ref_impedance: float = 50) -> float:
|
||||||
return impedance_to_capacitance(
|
return impedance_to_capacitance(self.impedance(ref_impedance), self.freq)
|
||||||
self.impedance(ref_impedance), self.freq
|
|
||||||
)
|
|
||||||
|
|
||||||
def inductiveEquivalent(self, ref_impedance: float = 50) -> float:
|
def inductiveEquivalent(self, ref_impedance: float = 50) -> float:
|
||||||
return impedance_to_inductance(self.impedance(ref_impedance), self.freq)
|
return impedance_to_inductance(self.impedance(ref_impedance), self.freq)
|
||||||
|
@ -125,9 +123,7 @@ def norm_to_impedance(z: complex, ref_impedance: float = 50) -> complex:
|
||||||
def parallel_to_serial(z: complex) -> complex:
|
def parallel_to_serial(z: complex) -> complex:
|
||||||
"""Convert parallel impedance to serial impedance equivalent"""
|
"""Convert parallel impedance to serial impedance equivalent"""
|
||||||
z_sq_sum = z.real**2 + z.imag**2 or 10.0e-30
|
z_sq_sum = z.real**2 + z.imag**2 or 10.0e-30
|
||||||
return complex(
|
return complex(z.real * z.imag**2 / z_sq_sum, z.real**2 * z.imag / z_sq_sum)
|
||||||
z.real * z.imag**2 / z_sq_sum, z.real**2 * z.imag / z_sq_sum
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def reflection_coefficient(z: complex, ref_impedance: float = 50) -> complex:
|
def reflection_coefficient(z: complex, ref_impedance: float = 50) -> complex:
|
||||||
|
|
|
@ -116,9 +116,7 @@ class Value:
|
||||||
fmt = self.fmt
|
fmt = self.fmt
|
||||||
if math.isnan(self._value):
|
if math.isnan(self._value):
|
||||||
return f"-{fmt.space_str}{self._unit}"
|
return f"-{fmt.space_str}{self._unit}"
|
||||||
if fmt.assume_infinity and abs(self._value) >= 10 ** (
|
if fmt.assume_infinity and abs(self._value) >= 10 ** ((fmt.max_offset + 1) * 3):
|
||||||
(fmt.max_offset + 1) * 3
|
|
||||||
):
|
|
||||||
return (
|
return (
|
||||||
("-" if self._value < 0 else "")
|
("-" if self._value < 0 else "")
|
||||||
+ "\N{INFINITY}"
|
+ "\N{INFINITY}"
|
||||||
|
|
Ładowanie…
Reference in New Issue