diff --git a/NanoVNASaver/Analysis/AntennaAnalysis.py b/NanoVNASaver/Analysis/AntennaAnalysis.py index 84168fc..82e0f90 100644 --- a/NanoVNASaver/Analysis/AntennaAnalysis.py +++ b/NanoVNASaver/Analysis/AntennaAnalysis.py @@ -15,6 +15,9 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . + +from PyQt5.Qt import QTimer + ''' Created on May 30th 2020 @@ -37,28 +40,89 @@ class MagLoopAnalysis(VSWRAnalysis): ''' max_dips_shown = 1 - vswr_limit_value = 2.56 - bandwith = 250000 + + vswr_bandwith_value = 2.56 # -3 dB ?!? + bandwith = 25000 # 25 kHz + + def __init__(self, app): + # app.sweep_control.get_start() return -1 ?!? + # will populate first runAnalysis() + self.min_freq = None # app.sweep_control.get_start() + self.max_freq = None # app.sweep_control.get_end() + self.vswr_limit_value = self.vswr_bandwith_value + + super().__init__(app) def runAnalysis(self): super().runAnalysis() + new_start = self.app.sweep_control.get_start() + new_end = self.app.sweep_control.get_end() + if self.min_freq is None: + self.min_freq = new_start + self.max_freq = new_end + logger.debug("setting hard limits to %s - %s", + self.min_freq, self.max_freq) if len(self.minimums) > 1: self.layout.addRow("", QtWidgets.QLabel( - "Not magloop or try to lower VSWR limit")) - - for m in self.minimums[:1]: - # only one time + "Multiple minimums, not magloop or try to lower VSWR limit")) + return + elif len(self.minimums) == 1: + m = self.minimums[0] start, lowest, end = m if start != end: - Q = self.app.data11[lowest].freq / \ - (self.app.data11[end].freq - self.app.data11[start].freq) - self.layout.addRow( - "Q", QtWidgets.QLabel("{}".format(int(Q)))) - self.app.sweep_control.set_start(self.app.data11[start].freq) - self.app.sweep_control.set_end(self.app.data11[end].freq) + if self.vswr_limit_value == self.vswr_bandwith_value: + Q = self.app.data11[lowest].freq / \ + (self.app.data11[end].freq - + self.app.data11[start].freq) + self.layout.addRow( + "Q", QtWidgets.QLabel("{}".format(int(Q)))) + new_start = self.app.data11[start].freq - self.bandwith + new_end = self.app.data11[end].freq + self.bandwith + logger.debug("Single Spot, new scan on %s-%s", + new_start, new_end) + else: - self.app.sweep_control.set_start( - self.app.data11[start].freq - self.bandwith) - self.app.sweep_control.set_end( - self.app.data11[end].freq + self.bandwith) + new_start = self.app.data11[start].freq - 2 * self.bandwith + new_end = self.app.data11[end].freq + 2 * self.bandwith + logger.debug(" Zoom to %s-%s", new_start, new_end) + + if self.vswr_limit_value > self.vswr_bandwith_value: + self.vswr_limit_value = max( + self.vswr_bandwith_value, self.vswr_limit_value - 1) + self.input_vswr_limit.setValue(self.vswr_limit_value) + logger.debug( + "found higher minimum, lowering vswr search to %s", self.vswr_limit_value) + + else: + new_start = new_start - 5 * self.bandwith + new_end = new_end + 5 * self.bandwith + if all((new_start <= self.min_freq, + new_end >= self.max_freq)): + if self.vswr_limit_value < 10: + self.vswr_limit_value += 2 + self.input_vswr_limit.setValue(self.vswr_limit_value) + logger.debug( + "no minimum found, looking for higher value %s", self.vswr_limit_value) + new_start = max(self.min_freq, new_start) + new_end = min(self.max_freq, new_end) + logger.debug("next search will be %s - %s for vswr %s", + new_start, + new_end, + self.vswr_limit_value) + + self.app.sweep_control.set_start(new_start) + self.app.sweep_control.set_end(new_end) + # set timer to let finish all stuff before new sweep + QTimer.singleShot(2000, self._safe_sweep) + + def _safe_sweep(self): + ''' + sweep only if button enabled + to prevent multiple/concurrent sweep + ''' + + if self.app.sweep_control.btn_start.isEnabled(): + self.app.sweep_start() + else: + logger.error("sweep alredy running") diff --git a/NanoVNASaver/Hardware/Hardware.py b/NanoVNASaver/Hardware/Hardware.py index 0d3a386..776ed05 100644 --- a/NanoVNASaver/Hardware/Hardware.py +++ b/NanoVNASaver/Hardware/Hardware.py @@ -52,6 +52,8 @@ WAIT = 0.05 # incompatible hardware info like: # 'PORTS\\VID_04B4&PID_0008\\DEMO' # This function will fix it. + + def _fix_v2_hwinfo(dev): if dev.hwid == r'PORTS\VID_04B4&PID_0008\DEMO': dev.vid, dev.pid = 0x04b4, 0x0008 @@ -112,12 +114,17 @@ def get_VNA(iface: Interface) -> 'VNA': logger.warning("Did not recognize NanoVNA type from firmware.") return NanoVNA(iface) + def detect_version(serial_port: serial.Serial) -> str: data = "" for i in range(RETRIES): + drain_serial(serial_port) + serial_port.write("\r".encode("ascii")) + # workaround for some UnicodeDecodeError ... repeat ;-) drain_serial(serial_port) serial_port.write("\r".encode("ascii")) sleep(0.05) + data = serial_port.read(128).decode("ascii") if data.startswith("ch> "): return "v1" @@ -130,6 +137,7 @@ def detect_version(serial_port: serial.Serial) -> str: logger.error('No VNA detected. Hardware responded to CR with: %s', data) return "" + def get_info(serial_port: serial.Serial) -> str: for _ in range(RETRIES): drain_serial(serial_port) diff --git a/NanoVNASaver/Hardware/NanoVNA.py b/NanoVNASaver/Hardware/NanoVNA.py index d0cea41..beaa09a 100644 --- a/NanoVNASaver/Hardware/NanoVNA.py +++ b/NanoVNASaver/Hardware/NanoVNA.py @@ -47,16 +47,13 @@ class NanoVNA(VNA): def _get_running_frequencies(self): - if self.name == "NanoVNA": - logger.debug("Reading values: frequencies") - try: - frequencies = super().readValues("frequencies") - return frequencies[0], frequencies[-1] - except Exception as e: - logger.warning("%s reading frequencies", e) - logger.info("falling back to generic") - else: - logger.debug("Name %s, fallback to generic", self.name) + logger.debug("Reading values: frequencies") + try: + frequencies = super().readValues("frequencies") + return frequencies[0], frequencies[-1] + except Exception as e: + logger.warning("%s reading frequencies", e) + logger.info("falling back to generic") return VNA._get_running_frequencies(self) diff --git a/NanoVNASaver/RFTools.py b/NanoVNASaver/RFTools.py index d52429e..200c3b9 100644 --- a/NanoVNASaver/RFTools.py +++ b/NanoVNASaver/RFTools.py @@ -59,7 +59,11 @@ class Datapoint(NamedTuple): mag = abs(self.z) if mag == 1: return 1 - return (1 + mag) / (1 - mag) + else: + vswr = (1 + mag) / (1 - mag) + if vswr < 1: + return 1000 + return vswr @property def wavelength(self) -> float: diff --git a/NanoVNASaver/SweepWorker.py b/NanoVNASaver/SweepWorker.py index 40fc815..d78432e 100644 --- a/NanoVNASaver/SweepWorker.py +++ b/NanoVNASaver/SweepWorker.py @@ -232,8 +232,17 @@ class SweepWorker(QtCore.QRunnable): break logger.warning("Stop during average. Discarding sweep result.") return [], [], [] - logger.debug("Reading average no %d / %d", i+1, averages) - freq, tmp11, tmp21 = self.readSegment(start, stop) + logger.debug("Reading average no %d / %d", i + 1, averages) + retry = 0 + tmp11 = [] + while not tmp11 and retry < 5: + sleep(0.5 * retry) + retry += 1 + freq, tmp11, tmp21 = self.readSegment(start, stop) + if retry > 1: + logger.error("retry %s readSegment(%s,%s)", + retry, start, stop) + sleep(0.5) values11.append(tmp11) values21.append(tmp21) self.percentage += 100 / (self.sweep.segments * averages) @@ -314,7 +323,6 @@ class SweepWorker(QtCore.QRunnable): f"device settings screen.") return returndata - def gui_error(self, message: str): self.error_message = message self.stopped = True