kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
commit
da3bb3a0b8
|
@ -15,6 +15,9 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue