2020-06-09 15:56:53 +00:00
|
|
|
# NanoVNASaver
|
2020-06-25 17:48:03 +00:00
|
|
|
#
|
2020-06-09 15:56:53 +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
|
2021-06-30 05:21:14 +00:00
|
|
|
# Copyright (C) 2020,2021 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-09-16 13:47:37 +00:00
|
|
|
import logging
|
2021-07-05 14:16:33 +00:00
|
|
|
from time import sleep
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2021-07-05 15:32:37 +00:00
|
|
|
from PyQt5 import QtWidgets
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2021-07-05 14:16:33 +00:00
|
|
|
from NanoVNASaver.Hardware.Hardware import Interface, get_interfaces, get_VNA
|
2021-07-05 15:32:37 +00:00
|
|
|
from NanoVNASaver.Controls.Control import Control
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2019-09-16 13:47:37 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2022-05-27 07:03:37 +00:00
|
|
|
|
2021-07-05 15:32:37 +00:00
|
|
|
class SerialControl(Control):
|
2019-09-03 20:04:08 +00:00
|
|
|
|
2021-07-05 15:32:37 +00:00
|
|
|
def __init__(self, app: QtWidgets.QWidget):
|
|
|
|
super().__init__(app, "Serial port control")
|
2021-07-05 14:16:33 +00:00
|
|
|
|
2021-07-05 15:32:37 +00:00
|
|
|
self.interface = Interface("serial", "none")
|
2021-07-05 14:16:33 +00:00
|
|
|
self.inp_port = QtWidgets.QComboBox()
|
|
|
|
self.inp_port.setMinimumHeight(20)
|
2019-11-13 06:44:18 +00:00
|
|
|
self.rescanSerialPort()
|
2021-07-05 14:16:33 +00:00
|
|
|
self.inp_port.setEditable(True)
|
|
|
|
self.btn_rescan = QtWidgets.QPushButton("Rescan")
|
|
|
|
self.btn_rescan.setMinimumHeight(20)
|
|
|
|
self.btn_rescan.setFixedWidth(60)
|
|
|
|
self.btn_rescan.clicked.connect(self.rescanSerialPort)
|
|
|
|
intput_layout = QtWidgets.QHBoxLayout()
|
|
|
|
intput_layout.addWidget(QtWidgets.QLabel("Port"), stretch=0)
|
|
|
|
intput_layout.addWidget(self.inp_port, stretch=1)
|
|
|
|
intput_layout.addWidget(self.btn_rescan, stretch=0)
|
2021-07-05 14:35:36 +00:00
|
|
|
self.layout.addRow(intput_layout)
|
2021-07-05 14:16:33 +00:00
|
|
|
|
|
|
|
button_layout = QtWidgets.QHBoxLayout()
|
|
|
|
|
|
|
|
self.btn_toggle = QtWidgets.QPushButton("Connect to device")
|
|
|
|
self.btn_toggle.setMinimumHeight(20)
|
|
|
|
self.btn_toggle.clicked.connect(self.serialButtonClick)
|
|
|
|
button_layout.addWidget(self.btn_toggle, stretch=1)
|
|
|
|
|
|
|
|
self.btn_settings = QtWidgets.QPushButton("Manage")
|
|
|
|
self.btn_settings.setMinimumHeight(20)
|
|
|
|
self.btn_settings.setFixedWidth(60)
|
|
|
|
self.btn_settings.clicked.connect(
|
|
|
|
lambda: self.app.display_window("device_settings"))
|
|
|
|
|
|
|
|
button_layout.addWidget(self.btn_settings, stretch=0)
|
2021-07-05 14:35:36 +00:00
|
|
|
self.layout.addRow(button_layout)
|
2019-09-16 19:41:01 +00:00
|
|
|
|
2019-09-25 19:50:27 +00:00
|
|
|
def rescanSerialPort(self):
|
2021-07-05 14:16:33 +00:00
|
|
|
self.inp_port.clear()
|
2020-07-04 10:08:54 +00:00
|
|
|
for iface in get_interfaces():
|
2021-07-05 14:16:33 +00:00
|
|
|
self.inp_port.insertItem(1, f"{iface}", iface)
|
|
|
|
self.inp_port.repaint()
|
2019-09-25 19:50:27 +00:00
|
|
|
|
2019-08-28 18:20:07 +00:00
|
|
|
def serialButtonClick(self):
|
2021-07-05 14:16:33 +00:00
|
|
|
if not self.app.vna.connected():
|
2020-07-04 10:08:54 +00:00
|
|
|
self.connect_device()
|
2019-08-28 18:20:07 +00:00
|
|
|
else:
|
2020-07-04 10:08:54 +00:00
|
|
|
self.disconnect_device()
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-04 10:08:54 +00:00
|
|
|
def connect_device(self):
|
|
|
|
with self.interface.lock:
|
2021-07-05 14:16:33 +00:00
|
|
|
self.interface = self.inp_port.currentData()
|
2020-07-04 10:08:54 +00:00
|
|
|
logger.info("Connection %s", self.interface)
|
2019-08-28 18:20:07 +00:00
|
|
|
try:
|
2020-07-04 10:08:54 +00:00
|
|
|
self.interface.open()
|
2020-07-04 18:14:18 +00:00
|
|
|
except (IOError, AttributeError) as exc:
|
2020-07-04 10:08:54 +00:00
|
|
|
logger.error("Tried to open %s and failed: %s",
|
|
|
|
self.interface, exc)
|
2019-08-28 18:20:07 +00:00
|
|
|
return
|
2020-07-04 10:08:54 +00:00
|
|
|
if not self.interface.isOpen():
|
|
|
|
logger.error("Unable to open port %s", self.interface)
|
2020-07-03 11:27:22 +00:00
|
|
|
return
|
2020-12-23 12:27:53 +00:00
|
|
|
self.interface.timeout = 0.05
|
2020-07-04 21:30:14 +00:00
|
|
|
sleep(0.1)
|
2020-07-04 18:14:18 +00:00
|
|
|
try:
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.vna = get_VNA(self.interface)
|
2020-07-04 18:14:18 +00:00
|
|
|
except IOError as exc:
|
|
|
|
logger.error("Unable to connect to VNA: %s", exc)
|
2020-07-04 21:30:14 +00:00
|
|
|
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.vna.validateInput = self.app.settings.value(
|
2020-12-23 12:27:53 +00:00
|
|
|
"SerialInputValidation", True, bool)
|
2020-07-01 17:46:35 +00:00
|
|
|
|
2020-07-04 18:14:18 +00:00
|
|
|
# connected
|
2021-07-05 14:16:33 +00:00
|
|
|
self.btn_toggle.setText("Disconnect")
|
|
|
|
self.btn_toggle.repaint()
|
2020-08-04 15:34:34 +00:00
|
|
|
|
2021-07-05 14:16:33 +00:00
|
|
|
frequencies = self.app.vna.readFrequencies()
|
2020-07-04 18:37:37 +00:00
|
|
|
if not frequencies:
|
2020-07-01 17:46:35 +00:00
|
|
|
logger.warning("No frequencies read")
|
2019-08-28 18:20:07 +00:00
|
|
|
return
|
2020-07-04 18:37:37 +00:00
|
|
|
logger.info("Read starting frequency %s and end frequency %s",
|
|
|
|
frequencies[0], frequencies[-1])
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.sweep_control.set_start(frequencies[0])
|
2020-07-04 18:37:37 +00:00
|
|
|
if frequencies[0] < frequencies[-1]:
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.sweep_control.set_end(frequencies[-1])
|
2020-07-04 18:37:37 +00:00
|
|
|
else:
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.sweep_control.set_end(
|
2020-07-12 21:49:01 +00:00
|
|
|
frequencies[0] +
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.vna.datapoints * self.app.sweep_control.get_segments())
|
2020-07-14 12:52:19 +00:00
|
|
|
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.sweep_control.set_segments(1) # speed up things
|
|
|
|
self.app.sweep_control.update_center_span()
|
|
|
|
self.app.sweep_control.update_step_size()
|
2020-07-04 18:37:37 +00:00
|
|
|
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.windows["sweep_settings"].vna_connected()
|
2021-04-06 09:05:13 +00:00
|
|
|
|
2020-07-01 17:46:35 +00:00
|
|
|
logger.debug("Starting initial sweep")
|
2021-07-05 14:16:33 +00:00
|
|
|
self.app.sweep_start()
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-04 10:08:54 +00:00
|
|
|
def disconnect_device(self):
|
|
|
|
with self.interface.lock:
|
|
|
|
logger.info("Closing connection to %s", self.interface)
|
|
|
|
self.interface.close()
|
2021-07-05 14:16:33 +00:00
|
|
|
self.btn_toggle.setText("Connect to device")
|
|
|
|
self.btn_toggle.repaint()
|