Fix custom datapoints on H4

pull/231/head
Holger Müller 2020-07-07 12:33:32 +02:00
rodzic 496494900f
commit 948c04f154
9 zmienionych plików z 83 dodań i 54 usunięć

Wyświetl plik

@ -26,10 +26,11 @@ from serial.tools import list_ports
from NanoVNASaver.Hardware.VNA import VNA
from NanoVNASaver.Hardware.AVNA import AVNA
from NanoVNASaver.Hardware.NanoVNA_F import NanoVNA_F
from NanoVNASaver.Hardware.NanoVNA_H import NanoVNA_H, NanoVNA_H4
from NanoVNASaver.Hardware.NanoVNA import NanoVNA
from NanoVNASaver.Hardware.NanoVNA_V2 import NanoVNAV2
from NanoVNASaver.Hardware.NanoVNA_F import NanoVNA_F
from NanoVNASaver.Hardware.NanoVNA_H import NanoVNA_H
from NanoVNASaver.Hardware.NanoVNA_H4 import NanoVNA_H4
from NanoVNASaver.Hardware.NanoVNA_V2 import NanoVNA_V2
from NanoVNASaver.Hardware.Serial import drain_serial, Interface
logger = logging.getLogger(__name__)
@ -82,7 +83,7 @@ def get_VNA(iface: Interface) -> 'VNA':
if vna_version == 'v2':
logger.info("Type: NanoVNA-V2")
return NanoVNAV2(iface)
return NanoVNA_V2(iface)
logger.info("Finding firmware variant...")
tmp_vna = VNA(iface)
@ -94,16 +95,10 @@ def get_VNA(iface: Interface) -> 'VNA':
if firmware.find("NanoVNA-H 4") > 0:
logger.info("Type: NanoVNA-H4")
vna = NanoVNA_H4(iface)
if vna.readFirmware().find("sweep_points 201") > 0:
logger.info("VNA has 201 datapoints capability")
vna.datapoints = (201, 101)
return vna
if firmware.find("NanoVNA-H") > 0:
logger.info("Type: NanoVNA-H")
vna = NanoVNA_H(iface)
if vna.readFirmware().find("sweep_points 201") > 0:
logger.info("VNA has 201 datapoints capability")
vna.datapoints = (201, 101)
return vna
if firmware.find("NanoVNA-F") > 0:
logger.info("Type: NanoVNA-F")

Wyświetl plik

@ -45,15 +45,6 @@ class NanoVNA(VNA):
self.stop = 30000000
self._sweepdata = []
if self.version >= Version("0.7.1"):
self.features.add("Scan mask command")
self.sweep_method = "scan_mask"
elif self.version >= Version("0.2.0"):
logger.debug("Newer than 0.2.0, using new scan command.")
self.features.add("Scan command")
self.sweep_method = "scan"
self.readFeatures()
def isValid(self):
return True
@ -107,6 +98,17 @@ class NanoVNA(VNA):
elif self.sweep_method == "scan":
self.writeSerial(f"scan {start} {stop} {self.datapoints}")
def read_features(self):
if self.version >= Version("0.7.1"):
self.features.add("Scan mask command")
self.sweep_method = "scan_mask"
elif self.version >= Version("0.2.0"):
logger.debug("Newer than 0.2.0, using new scan command.")
self.features.add("Scan command")
self.sweep_method = "scan"
super().read_features()
def readFrequencies(self) -> List[int]:
if self.sweep_method != "scan_mask":
return super().readFrequencies()

Wyświetl plik

@ -26,8 +26,10 @@ logger = logging.getLogger(__name__)
class NanoVNA_H(NanoVNA):
name = "NanoVNA-H"
class NanoVNA_H4(NanoVNA):
name = "NanoVNA-H4"
screenwidth = 480
screenheight = 320
def read_features(self):
logger.debug("read_features")
if self.readFirmware().find("sweep_points 201") > 0:
logger.info("VNA has 201 datapoints capability")
self.valid_datapoints = (201, 101)
self.datapoints = 201
super().read_features()

Wyświetl plik

@ -0,0 +1,28 @@
# NanoVNASaver
#
# A python program to view and export Touchstone data from a NanoVNA
# Copyright (C) 2020 NanoVNA-Saver Authors
#
# 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/>.
import logging
from NanoVNASaver.Hardware.NanoVNA_H import NanoVNA_H
logger = logging.getLogger(__name__)
class NanoVNA_H4(NanoVNA_H):
name = "NanoVNA-H4"
screenwidth = 480
screenheight = 320

Wyświetl plik

@ -19,6 +19,7 @@
import logging
import platform
from struct import pack, unpack_from
from time import sleep
from typing import List
from NanoVNASaver.Hardware.Serial import Interface
@ -54,9 +55,9 @@ _ADDR_FW_MAJOR = 0xf3
_ADDR_FW_MINOR = 0xf4
class NanoVNAV2(VNA):
class NanoVNA_V2(VNA):
name = "NanoVNA-V2"
_datapoints = (303, 101, 203, 505, 1023)
valid_datapoints = (202, 101, 303, 505, 1023)
screenwidth = 320
screenheight = 240
@ -72,9 +73,6 @@ class NanoVNAV2(VNA):
self.version = self.readVersion()
self.firmware = self.readFirmware()
self.features.add("Customizable data points")
# TODO: more than one dp per freq
self.features.add("Multi data points")
# firmware major version of 0xff indicates dfu mode
if self.firmware.data["major"] == 0xff:
@ -84,11 +82,15 @@ class NanoVNAV2(VNA):
self.sweepStepHz = 1e6
self._sweepdata = []
self._updateSweep()
# self.setSweep(200e6, 300e6)
def getCalibration(self) -> str:
return "Unknown"
def read_features(self):
self.features.add("Customizable data points")
# TODO: more than one dp per freq
self.features.add("Multi data points")
def readFirmware(self) -> str:
# read register 0xf3 and 0xf4 (firmware major and minor version)
cmd = pack("<BBBB",
@ -96,6 +98,7 @@ class NanoVNAV2(VNA):
_CMD_READ, _ADDR_FW_MINOR)
with self.serial.lock:
self.serial.write(cmd)
sleep(0.05)
resp = self.serial.read(2)
if len(resp) != 2:
logger.error("Timeout reading version registers")
@ -130,7 +133,7 @@ class NanoVNAV2(VNA):
pack("<BBB",
_CMD_READFIFO, _ADDR_VALUES_FIFO,
pointstoread))
sleep(0.05)
# each value is 32 bytes
nBytes = pointstoread * 32
@ -141,6 +144,7 @@ class NanoVNAV2(VNA):
nBytes, len(arr))
return []
freq_index = -1
for i in range(pointstoread):
(fwd_real, fwd_imag, rev0_real, rev0_imag, rev1_real,
rev1_imag, freq_index) = unpack_from(
@ -148,8 +152,10 @@ class NanoVNAV2(VNA):
fwd = complex(fwd_real, fwd_imag)
refl = complex(rev0_real, rev0_imag)
thru = complex(rev1_real, rev1_imag)
logger.debug("Freq index: %i", freq_index)
if i == 0:
logger.debug("Freq index from: %i", freq_index)
self._sweepdata[freq_index] = (refl / fwd, thru / fwd)
logger.debug("Freq index to: %i", freq_index)
pointstodo = pointstodo - pointstoread

Wyświetl plik

@ -24,10 +24,12 @@ import serial
logger = logging.getLogger(__name__)
def drain_serial(serial_port: serial.Serial):
"""drain up to 10k outstanding data in the serial incoming buffer"""
for _ in range(80):
if len(serial_port.read(128)) == 0:
break
"""drain up to 64k outstanding data in the serial incoming buffer"""
for _ in range(512):
cnt = len(serial_port.read(128))
if not cnt:
return
logger.warning("unable to drain all data")
class Interface(serial.Serial):
def __init__(self, interface_type: str, comment, *args, **kwargs):

Wyświetl plik

@ -31,16 +31,17 @@ logger = logging.getLogger(__name__)
class VNA:
name = "VNA"
_datapoints = (101, )
valid_datapoints = (101, )
def __init__(self, iface: Interface):
self.serial = iface
self.version = Version("0.0.0")
self.features = set()
self.validateInput = True
self.datapoints = VNA._datapoints[0]
self.datapoints = self.valid_datapoints[0]
self.read_features()
def readFeatures(self) -> List[str]:
def read_features(self):
raw_help = self.readFromCommand("help")
logger.debug("Help command output:")
logger.debug(raw_help)
@ -48,11 +49,9 @@ class VNA:
# Detect features from the help command
if "capture" in raw_help:
self.features.add("Screenshots")
if len(self._datapoints) > 1:
if len(self.valid_datapoints) > 1:
self.features.add("Customizable data points")
return self.features
def readFrequencies(self) -> List[int]:
return [int(f) for f in self.readValues("frequencies")]

Wyświetl plik

@ -125,8 +125,7 @@ class DeviceSettingsWindow(QtWidgets.QWidget):
if "Customizable data points" in features:
self.datapoints.clear()
cur_dps = self.app.vna.datapoints
dplist = self.app.vna._datapoints[:]
for d in sorted(dplist):
for d in sorted(self.app.vna.valid_datapoints):
self.datapoints.addItem(str(d))
self._set_datapoint_index(cur_dps)

Wyświetl plik

@ -77,7 +77,7 @@ class SweepSettingsWindow(QtWidgets.QWidget):
"Averaging allows discarding outlying samples to get better averages."))
settings_layout.addRow(
QtWidgets.QLabel("Common values are 3/0, 5/2, 9/4 and 25/6."))
self.s21att = QtWidgets.QLineEdit("0")
settings_layout.addRow(QtWidgets.QLabel(""))
@ -158,20 +158,16 @@ class SweepSettingsWindow(QtWidgets.QWidget):
f" to {format_frequency_short(stop)}")
def setS21Attenuator(self):
try:
s21att = float(self.s21att.text())
except:
except ValueError:
s21att = 0
if (s21att < 0):
if s21att < 0:
logger.warning("Values for attenuator are absolute and with no minus sign, resetting.")
self.s21att.setText("0")
else:
logger.info("Setting an attenuator of %.2f dB inline with the CH1/S21 input", s21att)
self.app.s21att = s21att
self.app.s21att = 0
logger.info("Setting an attenuator of %.2f dB inline with the CH1/S21 input", s21att)
self.app.s21att = s21att
def setBandSweep(self):
index_start = self.band_list.model().index(self.band_list.currentIndex(), 1)