2020-06-13 08:22:30 +00:00
|
|
|
# NanoVNASaver
|
2020-06-25 17:52:30 +00:00
|
|
|
#
|
2020-06-13 08:22:30 +00:00
|
|
|
# A python program to view and export Touchstone data from a NanoVNA
|
2020-06-25 17:52:30 +00:00
|
|
|
# Copyright (C) 2019, 2020 Rune B. Broberg
|
|
|
|
# Copyright (C) 2020 NanoVNA-Saver Authors
|
2019-08-29 13:10:35 +00:00
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2019-11-20 15:56:09 +00:00
|
|
|
import logging
|
2019-09-10 10:53:09 +00:00
|
|
|
from time import sleep
|
2019-09-03 13:36:42 +00:00
|
|
|
from typing import List
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2019-09-21 10:55:22 +00:00
|
|
|
import numpy as np
|
2020-06-28 09:43:02 +00:00
|
|
|
from PyQt5 import QtCore, QtWidgets
|
2019-08-28 22:56:54 +00:00
|
|
|
from PyQt5.QtCore import pyqtSlot, pyqtSignal
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2019-11-20 14:02:03 +00:00
|
|
|
from NanoVNASaver.Calibration import Calibration
|
2020-06-21 17:54:00 +00:00
|
|
|
from NanoVNASaver.Formatting import parse_frequency
|
|
|
|
from NanoVNASaver.RFTools import Datapoint
|
2019-10-07 19:24:18 +00:00
|
|
|
|
2019-09-16 13:47:37 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
2019-08-28 22:56:54 +00:00
|
|
|
|
|
|
|
|
2020-06-28 09:43:02 +00:00
|
|
|
def truncate(values, count):
|
|
|
|
keep = len(values) - count
|
|
|
|
logger.debug("Truncating from %d values to %d", len(values), keep)
|
|
|
|
if count < 1 or keep < 1:
|
|
|
|
logger.info("Not doing illegal truncate")
|
|
|
|
return values
|
|
|
|
truncated = []
|
|
|
|
for valueset in np.swapaxes(values, 0, 1).tolist():
|
|
|
|
avg = complex(*np.average(valueset, 0))
|
|
|
|
truncated.append(
|
|
|
|
sorted(valueset,
|
|
|
|
key=lambda v: abs(avg - complex(*v)))[:keep])
|
|
|
|
return np.swapaxes(truncated, 0, 1).tolist()
|
|
|
|
|
|
|
|
|
2019-08-28 22:56:54 +00:00
|
|
|
class WorkerSignals(QtCore.QObject):
|
|
|
|
updated = pyqtSignal()
|
|
|
|
finished = pyqtSignal()
|
2019-09-26 13:14:28 +00:00
|
|
|
sweepError = pyqtSignal()
|
2019-11-12 09:36:57 +00:00
|
|
|
fatalSweepError = pyqtSignal()
|
2019-08-28 18:20:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
class SweepWorker(QtCore.QRunnable):
|
2020-06-28 09:43:02 +00:00
|
|
|
def __init__(self, app: QtWidgets.QWidget):
|
2019-08-28 18:20:07 +00:00
|
|
|
super().__init__()
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.info("Initializing SweepWorker")
|
2019-08-28 22:56:54 +00:00
|
|
|
self.signals = WorkerSignals()
|
2019-08-28 18:20:07 +00:00
|
|
|
self.app = app
|
2020-04-07 15:17:22 +00:00
|
|
|
self.vna: app.vna
|
2019-08-28 22:56:54 +00:00
|
|
|
self.noSweeps = 1
|
|
|
|
self.setAutoDelete(False)
|
|
|
|
self.percentage = 0
|
2019-09-03 13:36:42 +00:00
|
|
|
self.data11: List[Datapoint] = []
|
2019-09-10 10:53:09 +00:00
|
|
|
self.data21: List[Datapoint] = []
|
|
|
|
self.rawData11: List[Datapoint] = []
|
|
|
|
self.rawData21: List[Datapoint] = []
|
|
|
|
self.stopped = False
|
2019-12-07 23:07:55 +00:00
|
|
|
self.running = False
|
2019-09-10 10:53:09 +00:00
|
|
|
self.continuousSweep = False
|
2019-09-21 10:55:22 +00:00
|
|
|
self.averaging = False
|
|
|
|
self.averages = 3
|
|
|
|
self.truncates = 0
|
2019-09-26 13:14:28 +00:00
|
|
|
self.error_message = ""
|
2019-11-20 14:02:03 +00:00
|
|
|
self.offsetDelay = 0
|
2019-08-28 18:20:07 +00:00
|
|
|
|
|
|
|
@pyqtSlot()
|
|
|
|
def run(self):
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.info("Initializing SweepWorker")
|
2019-12-07 23:07:55 +00:00
|
|
|
self.running = True
|
2019-08-28 22:56:54 +00:00
|
|
|
self.percentage = 0
|
|
|
|
if not self.app.serial.is_open:
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Attempted to run without being connected to the NanoVNA")
|
2019-12-07 23:07:55 +00:00
|
|
|
self.running = False
|
2019-08-28 22:56:54 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
if int(self.app.sweepCountInput.text()) > 0:
|
|
|
|
self.noSweeps = int(self.app.sweepCountInput.text())
|
|
|
|
|
2019-09-21 10:55:22 +00:00
|
|
|
logger.info("%d sweeps", self.noSweeps)
|
|
|
|
if self.averaging:
|
|
|
|
logger.info("%d averages", self.averages)
|
2019-09-16 13:47:37 +00:00
|
|
|
|
2019-09-01 17:38:01 +00:00
|
|
|
if self.app.sweepStartInput.text() == "" or self.app.sweepEndInput.text() == "":
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("First sweep - standard range")
|
2019-08-28 22:56:54 +00:00
|
|
|
# We should handle the first startup by reading frequencies?
|
2019-09-21 10:55:22 +00:00
|
|
|
sweep_from = 1000000
|
|
|
|
sweep_to = 800000000
|
2019-08-28 22:56:54 +00:00
|
|
|
else:
|
2020-06-21 17:54:00 +00:00
|
|
|
sweep_from = parse_frequency(self.app.sweepStartInput.text())
|
|
|
|
sweep_to = parse_frequency(self.app.sweepEndInput.text())
|
2019-09-21 10:55:22 +00:00
|
|
|
logger.debug("Parsed sweep range as %d to %d", sweep_from, sweep_to)
|
2019-09-22 19:19:08 +00:00
|
|
|
if sweep_from < 0 or sweep_to < 0 or sweep_from == sweep_to:
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.warning("Can't sweep from %s to %s",
|
|
|
|
self.app.sweepStartInput.text(),
|
|
|
|
self.app.sweepEndInput.text())
|
2020-06-13 08:22:30 +00:00
|
|
|
self.error_message = \
|
|
|
|
"Unable to parse frequency inputs - check start and stop fields."
|
2019-11-12 09:36:57 +00:00
|
|
|
self.stopped = True
|
2019-12-07 23:07:55 +00:00
|
|
|
self.running = False
|
2019-11-12 09:36:57 +00:00
|
|
|
self.signals.sweepError.emit()
|
2019-09-01 17:38:01 +00:00
|
|
|
return
|
2019-08-28 22:56:54 +00:00
|
|
|
|
2019-09-21 10:55:22 +00:00
|
|
|
span = sweep_to - sweep_from
|
2020-06-12 01:20:29 +00:00
|
|
|
stepsize = int(span / (self.noSweeps * self.vna.datapoints - 1))
|
2019-09-21 10:55:22 +00:00
|
|
|
|
|
|
|
# Setup complete
|
|
|
|
|
2019-09-10 10:53:09 +00:00
|
|
|
values = []
|
2019-09-16 13:47:37 +00:00
|
|
|
values21 = []
|
2019-09-10 10:53:09 +00:00
|
|
|
frequencies = []
|
2019-09-21 10:55:22 +00:00
|
|
|
|
|
|
|
if self.averaging:
|
|
|
|
for i in range(self.noSweeps):
|
|
|
|
logger.debug("Sweep segment no %d averaged over %d readings", i, self.averages)
|
|
|
|
if self.stopped:
|
|
|
|
logger.debug("Stopping sweeping as signalled")
|
|
|
|
break
|
2020-02-29 07:52:14 +00:00
|
|
|
start = sweep_from + i * self.vna.datapoints * stepsize
|
2020-06-13 08:22:30 +00:00
|
|
|
freq, val11, val21 = self.readAveragedSegment(
|
2020-06-17 17:36:06 +00:00
|
|
|
start, start + (self.vna.datapoints - 1) * stepsize, self.averages)
|
2019-09-21 10:55:22 +00:00
|
|
|
|
|
|
|
frequencies += freq
|
|
|
|
values += val11
|
|
|
|
values21 += val21
|
|
|
|
|
2020-06-17 17:36:06 +00:00
|
|
|
self.percentage = (i + 1) * (self.vna.datapoints - 1) / self.noSweeps
|
2019-09-21 10:55:22 +00:00
|
|
|
logger.debug("Saving acquired data")
|
|
|
|
self.saveData(frequencies, values, values21)
|
|
|
|
|
|
|
|
else:
|
|
|
|
for i in range(self.noSweeps):
|
|
|
|
logger.debug("Sweep segment no %d", i)
|
|
|
|
if self.stopped:
|
|
|
|
logger.debug("Stopping sweeping as signalled")
|
|
|
|
break
|
2020-06-17 17:36:06 +00:00
|
|
|
start = sweep_from + i * self.vna.datapoints * stepsize
|
2019-09-26 13:14:28 +00:00
|
|
|
try:
|
2020-06-13 08:22:30 +00:00
|
|
|
freq, val11, val21 = self.readSegment(
|
2020-06-17 17:36:06 +00:00
|
|
|
start, start + (self.vna.datapoints - 1) * stepsize)
|
2019-09-21 10:55:22 +00:00
|
|
|
|
2019-09-26 13:14:28 +00:00
|
|
|
frequencies += freq
|
|
|
|
values += val11
|
|
|
|
values21 += val21
|
2019-09-21 10:55:22 +00:00
|
|
|
|
2020-06-17 17:36:06 +00:00
|
|
|
self.percentage = (i + 1) * 100 / self.noSweeps
|
2019-09-26 13:14:28 +00:00
|
|
|
logger.debug("Saving acquired data")
|
|
|
|
self.saveData(frequencies, values, values21)
|
|
|
|
except NanoVNAValueException as e:
|
|
|
|
self.error_message = str(e)
|
|
|
|
self.stopped = True
|
2019-12-07 23:07:55 +00:00
|
|
|
self.running = False
|
2019-12-12 14:16:37 +00:00
|
|
|
self.signals.sweepError.emit()
|
|
|
|
except NanoVNASerialException as e:
|
|
|
|
self.error_message = str(e)
|
|
|
|
self.stopped = True
|
|
|
|
self.running = False
|
|
|
|
self.signals.sweepFatalError.emit()
|
2019-09-10 10:53:09 +00:00
|
|
|
|
|
|
|
while self.continuousSweep and not self.stopped:
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Continuous sweeping")
|
2019-08-28 22:56:54 +00:00
|
|
|
for i in range(self.noSweeps):
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Sweep segment no %d", i)
|
2019-09-10 10:53:09 +00:00
|
|
|
if self.stopped:
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Stopping sweeping as signalled")
|
2019-09-10 10:53:09 +00:00
|
|
|
break
|
2020-02-29 07:52:14 +00:00
|
|
|
start = sweep_from + i * self.vna.datapoints * stepsize
|
2019-09-26 13:14:28 +00:00
|
|
|
try:
|
2020-06-13 08:22:30 +00:00
|
|
|
_, values, values21 = self.readSegment(
|
|
|
|
start, start + (self.vna.datapoints-1) * stepsize)
|
2019-09-26 13:14:28 +00:00
|
|
|
logger.debug("Updating acquired data")
|
2020-02-29 07:52:14 +00:00
|
|
|
self.updateData(values, values21, i, self.vna.datapoints)
|
2019-09-26 13:14:28 +00:00
|
|
|
except NanoVNAValueException as e:
|
|
|
|
self.error_message = str(e)
|
|
|
|
self.stopped = True
|
2019-12-07 23:07:55 +00:00
|
|
|
self.running = False
|
2019-12-12 14:16:37 +00:00
|
|
|
self.signals.sweepError.emit()
|
|
|
|
except NanoVNASerialException as e:
|
|
|
|
self.error_message = str(e)
|
|
|
|
self.stopped = True
|
|
|
|
self.running = False
|
|
|
|
self.signals.sweepFatalError.emit()
|
2019-08-28 22:56:54 +00:00
|
|
|
|
2020-06-12 01:20:29 +00:00
|
|
|
# Reset the device to show the full range if we were multisegment
|
2020-06-13 08:22:30 +00:00
|
|
|
if self.noSweeps > 1:
|
2020-06-12 01:20:29 +00:00
|
|
|
logger.debug("Resetting NanoVNA sweep to full range: %d to %d",
|
2020-06-21 17:54:00 +00:00
|
|
|
parse_frequency(
|
2020-06-13 08:22:30 +00:00
|
|
|
self.app.sweepStartInput.text()),
|
2020-06-21 17:54:00 +00:00
|
|
|
parse_frequency(self.app.sweepEndInput.text()))
|
|
|
|
self.vna.resetSweep(parse_frequency(self.app.sweepStartInput.text()),
|
|
|
|
parse_frequency(self.app.sweepEndInput.text()))
|
2019-08-28 22:56:54 +00:00
|
|
|
|
|
|
|
self.percentage = 100
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Sending \"finished\" signal")
|
2019-08-28 22:56:54 +00:00
|
|
|
self.signals.finished.emit()
|
2019-12-07 23:07:55 +00:00
|
|
|
self.running = False
|
2019-08-28 22:56:54 +00:00
|
|
|
return
|
|
|
|
|
2019-12-08 00:54:39 +00:00
|
|
|
def updateData(self, values11, values21, offset, segment_size=101):
|
2019-09-10 10:53:09 +00:00
|
|
|
# Update the data from (i*101) to (i+1)*101
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Calculating data and inserting in existing data at offset %d", offset)
|
2020-06-13 08:22:30 +00:00
|
|
|
for i, val11 in enumerate(values11):
|
|
|
|
re, im = val11
|
2019-09-21 10:55:22 +00:00
|
|
|
re21, im21 = values21[i]
|
2019-11-27 15:41:55 +00:00
|
|
|
freq = self.data11[offset * segment_size + i].freq
|
2019-12-08 00:54:39 +00:00
|
|
|
raw_data11 = Datapoint(freq, re, im)
|
|
|
|
raw_data21 = Datapoint(freq, re21, im21)
|
|
|
|
data11, data21 = self.applyCalibration([raw_data11], [raw_data21])
|
|
|
|
|
2020-01-17 08:19:32 +00:00
|
|
|
self.data11[offset * segment_size + i] = data11[0]
|
|
|
|
self.data21[offset * segment_size + i] = data21[0]
|
2019-12-08 00:54:39 +00:00
|
|
|
self.rawData11[offset * segment_size + i] = raw_data11
|
|
|
|
self.rawData21[offset * segment_size + i] = raw_data21
|
2020-06-13 08:22:30 +00:00
|
|
|
logger.debug("Saving data to application (%d and %d points)",
|
|
|
|
len(self.data11), len(self.data21))
|
2019-09-10 10:53:09 +00:00
|
|
|
self.app.saveData(self.data11, self.data21)
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Sending \"updated\" signal")
|
2019-09-10 10:53:09 +00:00
|
|
|
self.signals.updated.emit()
|
|
|
|
|
2019-09-21 10:55:22 +00:00
|
|
|
def saveData(self, frequencies, values11, values21):
|
2019-12-08 00:54:39 +00:00
|
|
|
raw_data11 = []
|
|
|
|
raw_data21 = []
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Calculating data including corrections")
|
2020-06-17 17:36:06 +00:00
|
|
|
for i, freq in enumerate(frequencies):
|
|
|
|
logger.debug("Freqnr %i, len(%i)", i, len(frequencies))
|
|
|
|
logger.debug("Val11 %s", values11[i])
|
|
|
|
logger.debug("Val21 %s", values21[i])
|
|
|
|
re, im = values11[i]
|
2019-09-21 10:55:22 +00:00
|
|
|
re21, im21 = values21[i]
|
2019-12-08 00:54:39 +00:00
|
|
|
raw_data11 += [Datapoint(freq, re, im)]
|
|
|
|
raw_data21 += [Datapoint(freq, re21, im21)]
|
|
|
|
self.data11, self.data21 = self.applyCalibration(raw_data11, raw_data21)
|
|
|
|
self.rawData11 = raw_data11
|
|
|
|
self.rawData21 = raw_data21
|
2020-06-13 08:22:30 +00:00
|
|
|
logger.debug("Saving data to application (%d and %d points)",
|
|
|
|
len(self.data11), len(self.data21))
|
2019-10-20 13:28:15 +00:00
|
|
|
self.app.saveData(self.data11, self.data21)
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Sending \"updated\" signal")
|
2019-08-28 22:56:54 +00:00
|
|
|
self.signals.updated.emit()
|
2019-08-30 07:43:18 +00:00
|
|
|
|
2019-10-20 13:28:15 +00:00
|
|
|
def applyCalibration(self, raw_data11: List[Datapoint], raw_data21: List[Datapoint]) ->\
|
|
|
|
(List[Datapoint], List[Datapoint]):
|
2019-11-20 14:02:03 +00:00
|
|
|
if self.offsetDelay != 0:
|
|
|
|
tmp = []
|
|
|
|
for d in raw_data11:
|
|
|
|
tmp.append(Calibration.correctDelay11(d, self.offsetDelay))
|
|
|
|
raw_data11 = tmp
|
|
|
|
tmp = []
|
|
|
|
for d in raw_data21:
|
|
|
|
tmp.append(Calibration.correctDelay21(d, self.offsetDelay))
|
|
|
|
raw_data21 = tmp
|
|
|
|
|
2019-10-20 13:28:15 +00:00
|
|
|
if not self.app.calibration.isCalculated:
|
|
|
|
return raw_data11, raw_data21
|
|
|
|
|
|
|
|
data11: List[Datapoint] = []
|
|
|
|
data21: List[Datapoint] = []
|
|
|
|
|
|
|
|
if self.app.calibration.isValid1Port():
|
|
|
|
for d in raw_data11:
|
|
|
|
re, im = self.app.calibration.correct11(d.re, d.im, d.freq)
|
|
|
|
data11.append(Datapoint(d.freq, re, im))
|
|
|
|
else:
|
|
|
|
data11 = raw_data11
|
|
|
|
|
|
|
|
if self.app.calibration.isValid2Port():
|
|
|
|
for d in raw_data21:
|
|
|
|
re, im = self.app.calibration.correct21(d.re, d.im, d.freq)
|
|
|
|
data21.append(Datapoint(d.freq, re, im))
|
|
|
|
else:
|
|
|
|
data21 = raw_data21
|
|
|
|
return data11, data21
|
|
|
|
|
2019-09-21 10:55:22 +00:00
|
|
|
def readAveragedSegment(self, start, stop, averages):
|
|
|
|
val11 = []
|
|
|
|
val21 = []
|
|
|
|
freq = []
|
|
|
|
logger.info("Reading %d averages from %d to %d", averages, start, stop)
|
|
|
|
for i in range(averages):
|
|
|
|
if self.stopped:
|
|
|
|
logger.debug("Stopping averaging as signalled")
|
|
|
|
break
|
|
|
|
logger.debug("Reading average no %d / %d", i+1, averages)
|
|
|
|
freq, tmp11, tmp21 = self.readSegment(start, stop)
|
|
|
|
val11.append(tmp11)
|
|
|
|
val21.append(tmp21)
|
|
|
|
self.percentage += 100/(self.noSweeps*averages)
|
|
|
|
self.signals.updated.emit()
|
|
|
|
|
|
|
|
logger.debug("Post-processing averages")
|
|
|
|
logger.debug("Truncating %d values by %d", len(val11), self.truncates)
|
2020-06-28 09:43:02 +00:00
|
|
|
val11 = truncate(val11, self.truncates)
|
|
|
|
val21 = truncate(val21, self.truncates)
|
2019-09-21 10:55:22 +00:00
|
|
|
logger.debug("Averaging %d values", len(val11))
|
|
|
|
|
|
|
|
return11 = np.average(val11, 0).tolist()
|
|
|
|
return21 = np.average(val21, 0).tolist()
|
|
|
|
|
|
|
|
return freq, return11, return21
|
|
|
|
|
|
|
|
def readSegment(self, start, stop):
|
|
|
|
logger.debug("Setting sweep range to %d to %d", start, stop)
|
2019-10-07 19:24:18 +00:00
|
|
|
self.vna.setSweep(start, stop)
|
2019-10-04 10:51:20 +00:00
|
|
|
|
2019-09-21 10:55:22 +00:00
|
|
|
# Let's check the frequencies first:
|
|
|
|
frequencies = self.readFreq()
|
|
|
|
# S11
|
|
|
|
values11 = self.readData("data 0")
|
|
|
|
# S21
|
|
|
|
values21 = self.readData("data 1")
|
|
|
|
|
|
|
|
return frequencies, values11, values21
|
|
|
|
|
2019-08-30 07:43:18 +00:00
|
|
|
def readData(self, data):
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Reading %s", data)
|
2019-08-30 07:43:18 +00:00
|
|
|
done = False
|
2019-09-21 10:55:22 +00:00
|
|
|
returndata = []
|
2019-09-16 13:47:37 +00:00
|
|
|
count = 0
|
2019-08-30 07:43:18 +00:00
|
|
|
while not done:
|
|
|
|
done = True
|
2019-09-21 10:55:22 +00:00
|
|
|
returndata = []
|
2019-10-07 19:24:18 +00:00
|
|
|
tmpdata = self.vna.readValues(data)
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Read %d values", len(tmpdata))
|
2019-08-30 07:43:18 +00:00
|
|
|
for d in tmpdata:
|
|
|
|
a, b = d.split(" ")
|
|
|
|
try:
|
2019-12-12 14:16:37 +00:00
|
|
|
if self.vna.validateInput and (float(a) < -9.5 or float(a) > 9.5):
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.warning("Got a non-float data value: %s (%s)", d, a)
|
|
|
|
logger.debug("Re-reading %s", data)
|
2019-08-30 07:43:18 +00:00
|
|
|
done = False
|
2019-12-12 14:16:37 +00:00
|
|
|
elif self.vna.validateInput and (float(b) < -9.5 or float(b) > 9.5):
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.warning("Got a non-float data value: %s (%s)", d, b)
|
|
|
|
logger.debug("Re-reading %s", data)
|
2019-08-30 07:43:18 +00:00
|
|
|
done = False
|
2019-09-21 10:55:22 +00:00
|
|
|
else:
|
|
|
|
returndata.append((float(a), float(b)))
|
2019-09-16 20:49:21 +00:00
|
|
|
except Exception as e:
|
|
|
|
logger.exception("An exception occurred reading %s: %s", data, e)
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Re-reading %s", data)
|
2019-08-30 07:43:18 +00:00
|
|
|
done = False
|
2019-09-16 13:47:37 +00:00
|
|
|
if not done:
|
2019-09-16 19:41:01 +00:00
|
|
|
sleep(0.2)
|
2019-09-16 13:47:37 +00:00
|
|
|
count += 1
|
|
|
|
if count == 10:
|
|
|
|
logger.error("Tried and failed to read %s %d times.", data, count)
|
|
|
|
if count >= 20:
|
2019-09-26 13:14:28 +00:00
|
|
|
logger.critical("Tried and failed to read %s %d times. Giving up.", data, count)
|
2020-06-13 08:22:30 +00:00
|
|
|
raise NanoVNAValueException(
|
|
|
|
f"Failed reading {data} {count} times.\n"
|
|
|
|
f"Data outside expected valid ranges, or in an unexpected format.\n\n"
|
|
|
|
f"You can disable data validation on the device settings screen.")
|
2019-09-21 10:55:22 +00:00
|
|
|
return returndata
|
2019-08-30 07:43:18 +00:00
|
|
|
|
|
|
|
def readFreq(self):
|
|
|
|
# TODO: Figure out why frequencies sometimes arrive as non-integers
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.debug("Reading frequencies")
|
2019-09-21 10:55:22 +00:00
|
|
|
returnfreq = []
|
2019-08-30 07:43:18 +00:00
|
|
|
done = False
|
2019-09-16 13:47:37 +00:00
|
|
|
count = 0
|
2019-08-30 07:43:18 +00:00
|
|
|
while not done:
|
|
|
|
done = True
|
2019-09-21 10:55:22 +00:00
|
|
|
returnfreq = []
|
2019-10-08 19:30:45 +00:00
|
|
|
tmpfreq = self.vna.readFrequencies()
|
2019-10-01 11:23:38 +00:00
|
|
|
if not tmpfreq:
|
|
|
|
logger.warning("Read no frequencies")
|
2019-12-12 14:16:37 +00:00
|
|
|
raise NanoVNASerialException("Failed reading frequencies: Returned no values.")
|
2019-08-30 07:43:18 +00:00
|
|
|
for f in tmpfreq:
|
|
|
|
if not f.isdigit():
|
2019-09-16 13:47:37 +00:00
|
|
|
logger.warning("Got a non-digit frequency: %s", f)
|
|
|
|
logger.debug("Re-reading frequencies")
|
2019-08-30 07:43:18 +00:00
|
|
|
done = False
|
2019-09-16 13:47:37 +00:00
|
|
|
count += 1
|
|
|
|
if count == 10:
|
|
|
|
logger.error("Tried and failed %d times to read frequencies.", count)
|
|
|
|
if count >= 20:
|
2020-06-13 08:22:30 +00:00
|
|
|
logger.critical(
|
|
|
|
"Tried and failed to read frequencies from the NanoVNA %d times.",
|
|
|
|
count)
|
|
|
|
raise NanoVNAValueException(
|
|
|
|
f"Failed reading frequencies {count} times.")
|
2019-09-21 10:55:22 +00:00
|
|
|
else:
|
|
|
|
returnfreq.append(int(f))
|
|
|
|
return returnfreq
|
2019-09-10 10:53:09 +00:00
|
|
|
|
2019-12-08 00:54:39 +00:00
|
|
|
def setContinuousSweep(self, continuous_sweep: bool):
|
|
|
|
self.continuousSweep = continuous_sweep
|
2019-09-21 10:55:22 +00:00
|
|
|
|
2019-09-26 13:14:28 +00:00
|
|
|
def setAveraging(self, averaging: bool, averages: str, truncates: str):
|
2019-09-21 10:55:22 +00:00
|
|
|
self.averaging = averaging
|
|
|
|
try:
|
|
|
|
self.averages = int(averages)
|
|
|
|
self.truncates = int(truncates)
|
2019-12-08 00:54:39 +00:00
|
|
|
except ValueError:
|
2019-09-21 10:55:22 +00:00
|
|
|
return
|
2019-09-26 13:14:28 +00:00
|
|
|
|
2019-10-09 12:46:08 +00:00
|
|
|
def setVNA(self, vna):
|
|
|
|
self.vna = vna
|
|
|
|
|
2019-09-26 13:14:28 +00:00
|
|
|
|
|
|
|
class NanoVNAValueException(Exception):
|
|
|
|
pass
|
2019-12-12 14:16:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
class NanoVNASerialException(Exception):
|
|
|
|
pass
|