From d6a3ec4beca919a94ac776bdc7791f6a62a3a33b Mon Sep 17 00:00:00 2001 From: Rune Broberg Date: Thu, 26 Sep 2019 15:14:28 +0200 Subject: [PATCH] - Better error handling for unparseable data from the NanoVNA - Fixed a crash bug in formatting frequencies - Made a function for short frequency formatting --- NanoVNASaver/Chart.py | 22 ++++++++++------ NanoVNASaver/NanoVNASaver.py | 30 ++++++++++++++++++++-- NanoVNASaver/SweepWorker.py | 49 ++++++++++++++++++++++++------------ 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/NanoVNASaver/Chart.py b/NanoVNASaver/Chart.py index 3206ffe..8a12792 100644 --- a/NanoVNASaver/Chart.py +++ b/NanoVNASaver/Chart.py @@ -1468,7 +1468,7 @@ class RealImaginaryChart(FrequencyChart): # Scale max_imag to be a whole factor of min_imag num_min = math.floor(min_imag/step_size * -1) num_max = 8 - num_min - logger.debug("Scaling max_imag to be %s times num_min", num_max) + logger.debug("Scaling max_imag to be %s times -min_imag", num_max) max_imag = num_max * (min_imag / num_min) * -1 logger.debug("Scaled RealImaginary to %s - %s", min_imag, max_imag) @@ -1575,13 +1575,19 @@ class RealImaginaryChart(FrequencyChart): qp.setPen(secondary_pen) qp.drawPoint(int(x), int(y_im)) - # if self.drawLines and i > 0: - # logmag = self.logMag(self.reference[i-1]) - # prevx = self.leftMargin + 1 + round(self.chartWidth*(self.reference[i-1].freq - fstart)/fspan) - # prevy = 30 + round((logmag - minValue) / span * (self.chartHeight - 10)) - # qp.setPen(line_pen) - # qp.drawLine(x, y, prevx, prevy) - # qp.setPen(pen) + if self.drawLines and i > 0: + new_re, new_im = NanoVNASaver.normalize50(self.reference[i-1]) + prev_x = self.getXPosition(self.reference[i-1]) + prev_y_re = 30 + round((max_real - new_re) / span_real * (self.chartHeight - 10)) + prev_y_im = 30 + round((max_imag - new_im) / span_imag * (self.chartHeight - 10)) + + if re > 0 and new_re > 0: + line_pen.setColor(self.referenceColor) + qp.setPen(line_pen) + qp.drawLine(x, y_re, prev_x, prev_y_re) + + qp.drawLine(x, y_im, prev_x, prev_y_im) + # Now draw the markers for m in self.markers: if m.location != -1: diff --git a/NanoVNASaver/NanoVNASaver.py b/NanoVNASaver/NanoVNASaver.py index 498b684..aad4fd5 100644 --- a/NanoVNASaver/NanoVNASaver.py +++ b/NanoVNASaver/NanoVNASaver.py @@ -472,6 +472,7 @@ class NanoVNASaver(QtWidgets.QWidget): self.worker.signals.updated.connect(self.dataUpdated) self.worker.signals.finished.connect(self.sweepFinished) + self.worker.signals.sweepError.connect(self.showSweepError) logger.debug("Finished building interface") @@ -855,10 +856,12 @@ class NanoVNASaver(QtWidgets.QWidget): if self.sweepCountInput.text().isdigit(): segments = int(self.sweepCountInput.text()) fstep = fspan / (segments * 101) - self.sweepStepLabel.setText(self.formatFrequency(fstep) + "/step") + self.sweepStepLabel.setText(self.formatShortFrequency(fstep) + "/step") @staticmethod def formatFrequency(freq): + if freq < 1: + return "- Hz" if math.log10(freq) < 3: return str(round(freq)) + " Hz" elif math.log10(freq) < 7: @@ -868,6 +871,25 @@ class NanoVNASaver(QtWidgets.QWidget): else: return "{:.3f}".format(freq/1000000) + " MHz" + @staticmethod + def formatShortFrequency(freq): + if freq < 1: + return "- Hz" + if math.log10(freq) < 3: + return str(round(freq)) + " Hz" + elif math.log10(freq) < 5: + return "{:.3f}".format(freq/1000) + " kHz" + elif math.log10(freq) < 6: + return "{:.2f}".format(freq/1000) + " kHz" + elif math.log10(freq) < 7: + return "{:.1f}".format(freq/1000) + " kHz" + elif math.log10(freq) < 8: + return "{:.3f}".format(freq/1000000) + " MHz" + elif math.log10(freq) < 9: + return "{:.2f}".format(freq/1000000) + " MHz" + else: + return "{:.1f}".format(freq/1000000) + " MHz" + @staticmethod def parseFrequency(freq: str): freq = freq.replace(" ", "") # People put all sorts of weird whitespace in. @@ -989,7 +1011,11 @@ class NanoVNASaver(QtWidgets.QWidget): QtWidgets.QApplication.setActiveWindow(self.tdr_window) def showError(self, text): - QtWidgets.QErrorMessage.showMessage(text) + error_message = QtWidgets.QErrorMessage(self) + error_message.showMessage(text) + + def showSweepError(self): + self.showError(self.worker.error_message) def closeEvent(self, a0: QtGui.QCloseEvent) -> None: self.worker.stopped = True diff --git a/NanoVNASaver/SweepWorker.py b/NanoVNASaver/SweepWorker.py index f8df664..7a45c4f 100644 --- a/NanoVNASaver/SweepWorker.py +++ b/NanoVNASaver/SweepWorker.py @@ -32,6 +32,7 @@ Datapoint = collections.namedtuple('Datapoint', 'freq re im') class WorkerSignals(QtCore.QObject): updated = pyqtSignal() finished = pyqtSignal() + sweepError = pyqtSignal() class SweepWorker(QtCore.QRunnable): @@ -52,6 +53,7 @@ class SweepWorker(QtCore.QRunnable): self.averaging = False self.averages = 3 self.truncates = 0 + self.error_message = "" @pyqtSlot() def run(self): @@ -118,15 +120,20 @@ class SweepWorker(QtCore.QRunnable): logger.debug("Stopping sweeping as signalled") break start = sweep_from + i*101*stepsize - freq, val11, val21 = self.readSegment(start, start+100*stepsize) + try: + freq, val11, val21 = self.readSegment(start, start+100*stepsize) - frequencies += freq - values += val11 - values21 += val21 + frequencies += freq + values += val11 + values21 += val21 - self.percentage = (i+1)*100/self.noSweeps - logger.debug("Saving acquired data") - self.saveData(frequencies, values, values21) + self.percentage = (i+1)*100/self.noSweeps + logger.debug("Saving acquired data") + self.saveData(frequencies, values, values21) + except NanoVNAValueException as e: + self.error_message = str(e) + self.stopped = True + self.signals.sweepError.emit() while self.continuousSweep and not self.stopped: logger.debug("Continuous sweeping") @@ -136,9 +143,14 @@ class SweepWorker(QtCore.QRunnable): logger.debug("Stopping sweeping as signalled") break start = sweep_from + i * 101 * stepsize - _, values, values21 = self.readSegment(start, start + 100 * stepsize) - logger.debug("Updating acquired data") - self.updateData(values, values21, i) + try: + _, values, values21 = self.readSegment(start, start + 100 * stepsize) + logger.debug("Updating acquired data") + self.updateData(values, values21, i) + except NanoVNAValueException as e: + self.error_message = str(e) + self.stopped = True + self.signals.sweepError.emit() # Reset the device to show the full range logger.debug("Resetting NanoVNA sweep to full range: %d to %d", @@ -307,8 +319,9 @@ class SweepWorker(QtCore.QRunnable): if count == 10: logger.error("Tried and failed to read %s %d times.", data, count) if count >= 20: - logger.error("Tried and failed to read %s %d times. Giving up.", data, count) - return None # Put a proper exception in here + logger.critical("Tried and failed to read %s %d times. Giving up.", data, count) + raise NanoVNAValueException("Failed reading " + str(data) + " " + str(count) + " times.\n" + + "Data outside expected valid ranges, or in an unexpected format.") return returndata def readFreq(self): @@ -330,19 +343,23 @@ class SweepWorker(QtCore.QRunnable): if count == 10: logger.error("Tried and failed %d times to read frequencies.", count) if count >= 20: - logger.critical("Tried and failed to read frequencies from the NanoVNA more than %d times.", count) - return None # Put a proper exception in here + logger.critical("Tried and failed to read frequencies from the NanoVNA %d times.", count) + raise NanoVNAValueException("Failed reading frequencies " + str(count) + " times.") else: returnfreq.append(int(f)) return returnfreq - def setContinuousSweep(self, continuousSweep): + def setContinuousSweep(self, continuousSweep: bool): self.continuousSweep = continuousSweep - def setAveraging(self, averaging, averages, truncates): + def setAveraging(self, averaging: bool, averages: str, truncates: str): self.averaging = averaging try: self.averages = int(averages) self.truncates = int(truncates) except: return + + +class NanoVNAValueException(Exception): + pass