This commit is contained in:
jupfi 2023-08-16 13:11:22 +02:00
commit 224417687b
4 changed files with 64 additions and 72 deletions

View file

@ -3,7 +3,7 @@ import numpy as np
import json import json
from serial.tools.list_ports import comports from serial.tools.list_ports import comports
from PyQt6 import QtSerialPort from PyQt6 import QtSerialPort
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot from PyQt6.QtCore import QThread, pyqtSignal, pyqtSlot
from nqrduck.module.module_controller import ModuleController from nqrduck.module.module_controller import ModuleController
from .model import S11Data from .model import S11Data
@ -51,6 +51,8 @@ class AutoTMController(ModuleController):
MAX_FREQUENCY = 300e6 # Hz MAX_FREQUENCY = 300e6 # Hz
try: try:
start_frequence = start_frequency.replace(",", ".")
stop_frequency = stop_frequency.replace(",", ".")
start_frequency = float(start_frequency) * 1e6 start_frequency = float(start_frequency) * 1e6
stop_frequency = float(stop_frequency) * 1e6 stop_frequency = float(stop_frequency) * 1e6
except ValueError: except ValueError:
@ -286,6 +288,8 @@ class AutoTMController(ModuleController):
logger.debug("Setting voltages") logger.debug("Setting voltages")
MAX_VOLTAGE = 5 # V MAX_VOLTAGE = 5 # V
try: try:
tuning_voltage = tuning_voltage.replace(",", ".")
matching_voltage = matching_voltage.replace(",", ".")
tuning_voltage = float(tuning_voltage) tuning_voltage = float(tuning_voltage)
matching_voltage = float(matching_voltage) matching_voltage = float(matching_voltage)
except ValueError: except ValueError:

View file

@ -26,7 +26,6 @@
<widget class="QLabel" name="titleconnectionLabel"> <widget class="QLabel" name="titleconnectionLabel">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight>
<bold>true</bold> <bold>true</bold>
</font> </font>
</property> </property>
@ -81,7 +80,6 @@
<widget class="QLabel" name="titletypeLabel"> <widget class="QLabel" name="titletypeLabel">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight>
<bold>true</bold> <bold>true</bold>
</font> </font>
</property> </property>
@ -93,13 +91,13 @@
<item> <item>
<widget class="QTabWidget" name="typeTab"> <widget class="QTabWidget" name="typeTab">
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="mechTab"> <widget class="QWidget" name="mechTab">
<attribute name="title"> <attribute name="title">
<string>Mechanical</string> <string>Mechanical</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout" stretch="0">
<item> <item>
<widget class="QPushButton" name="pushButton"> <widget class="QPushButton" name="pushButton">
<property name="text"> <property name="text">
@ -113,7 +111,7 @@
<attribute name="title"> <attribute name="title">
<string>Electrical</string> <string>Electrical</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,1">
<item row="1" column="1"> <item row="1" column="1">
<widget class="QDoubleSpinBox" name="matchingBox"/> <widget class="QDoubleSpinBox" name="matchingBox"/>
</item> </item>
@ -159,7 +157,6 @@
<widget class="QLabel" name="titlefrequencyLabel"> <widget class="QLabel" name="titlefrequencyLabel">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight>
<bold>true</bold> <bold>true</bold>
</font> </font>
</property> </property>
@ -231,7 +228,6 @@
<widget class="QLabel" name="titleinfoLabel"> <widget class="QLabel" name="titleinfoLabel">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight>
<bold>true</bold> <bold>true</bold>
</font> </font>
</property> </property>
@ -250,8 +246,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>273</width> <width>297</width>
<height>83</height> <height>169</height>
</rect> </rect>
</property> </property>
</widget> </widget>

View file

@ -1,18 +1,17 @@
import logging import logging
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
import smithplot
from smithplot import SmithAxes
from PyQt6.QtGui import QMovie from PyQt6.QtGui import QMovie
from PyQt6.QtSerialPort import QSerialPort from PyQt6.QtSerialPort import QSerialPort
from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout, QApplication, QHBoxLayout, QLineEdit, QPushButton, QDialog, QFileDialog from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout, QApplication, QHBoxLayout, QLineEdit, QPushButton, QDialog, QFileDialog
from PyQt6.QtCore import pyqtSlot, Qt from PyQt6.QtCore import pyqtSlot, Qt
from nqrduck.module.module_view import ModuleView from nqrduck.module.module_view import ModuleView
from nqrduck.contrib.mplwidget import MplWidget from nqrduck.contrib.mplwidget import MplWidget
from .widget import Ui_Form from .widget import Ui_Form
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class AutoTMView(ModuleView): class AutoTMView(ModuleView):
def __init__(self, module): def __init__(self, module):
@ -27,16 +26,19 @@ class AutoTMView(ModuleView):
self._ui_form.connectButton.setDisabled(True) self._ui_form.connectButton.setDisabled(True)
# On clicking of the refresh button scan for available usb devices # On clicking of the refresh button scan for available usb devices
self._ui_form.refreshButton.clicked.connect(self.module.controller.find_devices) self._ui_form.refreshButton.clicked.connect(
self.module.controller.find_devices)
# Connect the available devices changed signal to the on_available_devices_changed slot # Connect the available devices changed signal to the on_available_devices_changed slot
self.module.model.available_devices_changed.connect(self.on_available_devices_changed) self.module.model.available_devices_changed.connect(
self.on_available_devices_changed)
# Connect the serial changed signal to the on_serial_changed slot # Connect the serial changed signal to the on_serial_changed slot
self.module.model.serial_changed.connect(self.on_serial_changed) self.module.model.serial_changed.connect(self.on_serial_changed)
# On clicking of the connect button call the connect method # On clicking of the connect button call the connect method
self._ui_form.connectButton.clicked.connect(self.on_connect_button_clicked) self._ui_form.connectButton.clicked.connect(
self.on_connect_button_clicked)
# On clicking of the start button call the start_frequency_sweep method # On clicking of the start button call the start_frequency_sweep method
self._ui_form.startButton.clicked.connect(lambda: self.module.controller.start_frequency_sweep( self._ui_form.startButton.clicked.connect(lambda: self.module.controller.start_frequency_sweep(
@ -51,15 +53,16 @@ class AutoTMView(ModuleView):
)) ))
# On clicking of the calibration button call the on_calibration_button_clicked method # On clicking of the calibration button call the on_calibration_button_clicked method
self._ui_form.calibrationButton.clicked.connect(self.on_calibration_button_clicked) self._ui_form.calibrationButton.clicked.connect(
self.on_calibration_button_clicked)
# Connect the measurement finished signal to the plot_measurement slot # Connect the measurement finished signal to the plot_measurement slot
self.module.model.measurement_finished.connect(self.plot_measurement) self.module.model.measurement_finished.connect(self.plot_measurement)
# Add a vertical layout to the info box # Add a vertical layout to the info box
self._ui_form.scrollAreaWidgetContents.setLayout(QVBoxLayout()) self._ui_form.scrollAreaWidgetContents.setLayout(QVBoxLayout())
self._ui_form.scrollAreaWidgetContents.layout().setAlignment(Qt.AlignmentFlag.AlignTop) self._ui_form.scrollAreaWidgetContents.layout(
).setAlignment(Qt.AlignmentFlag.AlignTop)
self.init_plot() self.init_plot()
self.init_labels() self.init_labels()
@ -92,7 +95,7 @@ class AutoTMView(ModuleView):
self.calibration_window.show() self.calibration_window.show()
@pyqtSlot(list) @pyqtSlot(list)
def on_available_devices_changed(self, available_devices : list) -> None: def on_available_devices_changed(self, available_devices: list) -> None:
"""Update the available devices list in the view. """ """Update the available devices list in the view. """
logger.debug("Updating available devices list") logger.debug("Updating available devices list")
self._ui_form.portBox.clear() self._ui_form.portBox.clear()
@ -114,22 +117,22 @@ class AutoTMView(ModuleView):
self.module.controller.connect(selected_device) self.module.controller.connect(selected_device)
@pyqtSlot(QSerialPort) @pyqtSlot(QSerialPort)
def on_serial_changed(self, serial : QSerialPort) -> None: def on_serial_changed(self, serial: QSerialPort) -> None:
"""Update the serial 'connectionLabel' according to the current serial connection. """Update the serial 'connectionLabel' according to the current serial connection.
Args: Args:
serial (serial.Serial): The current serial connection.""" serial (serial.Serial): The current serial connection."""
logger.debug("Updating serial connection label") logger.debug("Updating serial connection label")
if serial.isOpen(): if serial:
self._ui_form.connectionLabel.setText(serial.portName()) self._ui_form.connectionLabel.setText(serial.portName())
self.add_info_text("Connected to device %s" % serial.portName()) self.add_info_text("Connected to device %s" % serial.portName())
else: else:
self._ui_form.connectionLabel.setText("Disconnected") self._ui_form.connectionLabel.setText("Disconnected")
logger.debug("Updated serial connection label") logger.debug("Updated serial connection label")
def plot_measurement(self, data : "S11Data") -> None: def plot_measurement(self, data: "S11Data") -> None:
"""Update the S11 plot with the current data points. """Update the S11 plot with the current data points.
Args: Args:
data_points (list): List of data points to plot. data_points (list): List of data points to plot.
@ -151,10 +154,10 @@ class AutoTMView(ModuleView):
ax.set_ylabel("Imaginary") ax.set_ylabel("Imaginary")
plt.show() plt.show()
""" """
self._ui_form.S11Plot.canvas.ax.clear()
magnitude_ax = self._ui_form.S11Plot.canvas.ax magnitude_ax = self._ui_form.S11Plot.canvas.ax
magnitude_ax.clear() magnitude_ax.clear()
phase_ax = self._ui_form.S11Plot.canvas.ax.twinx() phase_ax = self._ui_form.S11Plot.canvas.ax.twinx()
phase_ax.clear() phase_ax.clear()
@ -168,7 +171,8 @@ class AutoTMView(ModuleView):
E_t = calibration[2] E_t = calibration[2]
# gamma_corr = [(data_point - e_00[i]) / (data_point * e11[i] - delta_e[i]) for i, data_point in enumerate(gamma)] # gamma_corr = [(data_point - e_00[i]) / (data_point * e11[i] - delta_e[i]) for i, data_point in enumerate(gamma)]
gamma_corr = [(data_point - E_D[i]) / (E_S[i] * (data_point - E_D[i]) + E_t[i]) for i, data_point in enumerate(gamma)] gamma_corr = [(data_point - E_D[i]) / (E_S[i] * (data_point - E_D[i]) + E_t[i])
for i, data_point in enumerate(gamma)]
""" fig, ax = plt.subplots() """ fig, ax = plt.subplots()
ax.plot([g.real for g in gamma_corr], [g.imag for g in gamma_corr]) ax.plot([g.real for g in gamma_corr], [g.imag for g in gamma_corr])
ax.set_aspect('equal') ax.set_aspect('equal')
@ -177,23 +181,10 @@ class AutoTMView(ModuleView):
ax.set_xlabel("Real") ax.set_xlabel("Real")
ax.set_ylabel("Imaginary") ax.set_ylabel("Imaginary")
plt.show() """ plt.show() """
return_loss_db_corr = [-20 * cmath.log10(abs(g + 1e-12)) for g in gamma_corr] return_loss_db_corr = [-20 *
cmath.log10(abs(g + 1e-12)) for g in gamma_corr]
magnitude_ax.plot(frequency, return_loss_db_corr, color="red") magnitude_ax.plot(frequency, return_loss_db_corr, color="red")
""" open_calibration = self.module.model.open_calibration
short_calibration = self.module.model.short_calibration
load_calibration = self.module.model.load_calibration
phase_difference = short_calibration.phase_deg - open_calibration.phase_deg
phase = (phase - open_calibration.phase_deg) / phase_difference
amplitude_difference = open_calibration.return_loss_db - load_calibration.return_loss_db
amplitude = (return_loss_db - open_calibration.return_loss_db) / amplitude_difference
magnitude_ax.plot(frequency, amplitude, color="green")
phase_ax.plot(frequency, phase, color="orange", linestyle="--") """
phase_ax.set_ylabel("|Phase (deg)|") phase_ax.set_ylabel("|Phase (deg)|")
phase_ax.plot(frequency, phase, color="orange", linestyle="--") phase_ax.plot(frequency, phase, color="orange", linestyle="--")
phase_ax.set_ylim(-180, 180) phase_ax.set_ylim(-180, 180)
@ -212,9 +203,9 @@ class AutoTMView(ModuleView):
# Wait for the signals to be processed before adding the info text # Wait for the signals to be processed before adding the info text
QApplication.processEvents() QApplication.processEvents()
def add_info_text(self, text : str) -> None: def add_info_text(self, text: str) -> None:
""" Adds text to the info text box. """ Adds text to the info text box.
Args: Args:
text (str): Text to add to the info text box. text (str): Text to add to the info text box.
""" """
@ -224,11 +215,12 @@ class AutoTMView(ModuleView):
text_label = QLabel(text) text_label = QLabel(text)
text_label.setStyleSheet("font-size: 25px;") text_label.setStyleSheet("font-size: 25px;")
self._ui_form.scrollAreaWidgetContents.layout().addWidget(text_label) self._ui_form.scrollAreaWidgetContents.layout().addWidget(text_label)
self._ui_form.scrollArea.verticalScrollBar().setValue(self._ui_form.scrollArea.verticalScrollBar().maximum()) self._ui_form.scrollArea.verticalScrollBar().setValue(
self._ui_form.scrollArea.verticalScrollBar().maximum())
def add_error_text(self, text : str) -> None: def add_error_text(self, text: str) -> None:
""" Adds text to the error text box. """ Adds text to the error text box.
Args: Args:
text (str): Text to add to the error text box. text (str): Text to add to the error text box.
""" """
@ -238,7 +230,8 @@ class AutoTMView(ModuleView):
text_label = QLabel(text) text_label = QLabel(text)
text_label.setStyleSheet("font-size: 25px; color: red;") text_label.setStyleSheet("font-size: 25px; color: red;")
self._ui_form.scrollAreaWidgetContents.layout().addWidget(text_label) self._ui_form.scrollAreaWidgetContents.layout().addWidget(text_label)
self._ui_form.scrollArea.verticalScrollBar().setValue(self._ui_form.scrollArea.verticalScrollBar().maximum()) self._ui_form.scrollArea.verticalScrollBar().setValue(
self._ui_form.scrollArea.verticalScrollBar().maximum())
def create_frequency_sweep_spinner_dialog(self) -> None: def create_frequency_sweep_spinner_dialog(self) -> None:
"""Creates a frequency sweep spinner dialog. """ """Creates a frequency sweep spinner dialog. """
@ -265,7 +258,6 @@ class AutoTMView(ModuleView):
self.spinner_movie.start() self.spinner_movie.start()
class CalibrationWindow(QWidget): class CalibrationWindow(QWidget):
def __init__(self, module, parent=None): def __init__(self, module, parent=None):
@ -290,7 +282,7 @@ class AutoTMView(ModuleView):
frequency_layout.addWidget(stop_edit) frequency_layout.addWidget(stop_edit)
unit_label = QLabel("MHz") unit_label = QLabel("MHz")
frequency_layout.addWidget(unit_label) frequency_layout.addWidget(unit_label)
# Add horizontal layout for the calibration type # Add horizontal layout for the calibration type
type_layout = QHBoxLayout() type_layout = QHBoxLayout()
main_layout.addLayout(type_layout) main_layout.addLayout(type_layout)
@ -350,24 +342,30 @@ class AutoTMView(ModuleView):
data_layout.addWidget(apply_button) data_layout.addWidget(apply_button)
main_layout.addLayout(data_layout) main_layout.addLayout(data_layout)
self.setLayout(main_layout) self.setLayout(main_layout)
# Connect the calibration finished signals to the on_calibration_finished slot # Connect the calibration finished signals to the on_calibration_finished slot
self.module.model.short_calibration_finished.connect(self.on_short_calibration_finished) self.module.model.short_calibration_finished.connect(
self.module.model.open_calibration_finished.connect(self.on_open_calibration_finished) self.on_short_calibration_finished)
self.module.model.load_calibration_finished.connect(self.on_load_calibration_finished) self.module.model.open_calibration_finished.connect(
self.on_open_calibration_finished)
self.module.model.load_calibration_finished.connect(
self.on_load_calibration_finished)
def on_short_calibration_finished(self, short_calibration : "S11Data") -> None: def on_short_calibration_finished(self, short_calibration: "S11Data") -> None:
self.on_calibration_finished("short", self.short_plot, short_calibration) self.on_calibration_finished(
"short", self.short_plot, short_calibration)
def on_open_calibration_finished(self, open_calibration : "S11Data") -> None: def on_open_calibration_finished(self, open_calibration: "S11Data") -> None:
self.on_calibration_finished("open", self.open_plot, open_calibration) self.on_calibration_finished(
"open", self.open_plot, open_calibration)
def on_load_calibration_finished(self, load_calibration : "S11Data") -> None: def on_load_calibration_finished(self, load_calibration: "S11Data") -> None:
self.on_calibration_finished("load", self.load_plot, load_calibration) self.on_calibration_finished(
"load", self.load_plot, load_calibration)
def on_calibration_finished(self, type : str, widget: MplWidget, data :"S11Data") -> None: def on_calibration_finished(self, type: str, widget: MplWidget, data: "S11Data") -> None:
"""This method is called when a calibration has finished. """This method is called when a calibration has finished.
It plots the calibration data on the given widget. It plots the calibration data on the given widget.
""" """
@ -420,6 +418,3 @@ class AutoTMView(ModuleView):
self.module.controller.calculate_calibration() self.module.controller.calculate_calibration()
# Close the calibration window # Close the calibration window
self.close() self.close()

View file

@ -1,6 +1,6 @@
# Form implementation generated from reading ui file '../Modules/nqrduck-autotm/src/nqrduck_autotm/resources/autotm_widget.ui' # Form implementation generated from reading ui file '../Modules/nqrduck-autotm/src/nqrduck_autotm/resources/autotm_widget.ui'
# #
# Created by: PyQt6 UI code generator 6.5.1 # Created by: PyQt6 UI code generator 6.4.2
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.
@ -25,7 +25,6 @@ class Ui_Form(object):
self.titleconnectionLabel = QtWidgets.QLabel(parent=Form) self.titleconnectionLabel = QtWidgets.QLabel(parent=Form)
font = QtGui.QFont() font = QtGui.QFont()
font.setBold(True) font.setBold(True)
font.setWeight(75)
self.titleconnectionLabel.setFont(font) self.titleconnectionLabel.setFont(font)
self.titleconnectionLabel.setObjectName("titleconnectionLabel") self.titleconnectionLabel.setObjectName("titleconnectionLabel")
self.verticalLayout_2.addWidget(self.titleconnectionLabel) self.verticalLayout_2.addWidget(self.titleconnectionLabel)
@ -54,7 +53,6 @@ class Ui_Form(object):
self.titletypeLabel = QtWidgets.QLabel(parent=Form) self.titletypeLabel = QtWidgets.QLabel(parent=Form)
font = QtGui.QFont() font = QtGui.QFont()
font.setBold(True) font.setBold(True)
font.setWeight(75)
self.titletypeLabel.setFont(font) self.titletypeLabel.setFont(font)
self.titletypeLabel.setObjectName("titletypeLabel") self.titletypeLabel.setObjectName("titletypeLabel")
self.verticalLayout_2.addWidget(self.titletypeLabel) self.verticalLayout_2.addWidget(self.titletypeLabel)
@ -93,12 +91,12 @@ class Ui_Form(object):
self.resolutionBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab) self.resolutionBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
self.resolutionBox.setObjectName("resolutionBox") self.resolutionBox.setObjectName("resolutionBox")
self.gridLayout_3.addWidget(self.resolutionBox, 3, 1, 1, 1) self.gridLayout_3.addWidget(self.resolutionBox, 3, 1, 1, 1)
self.gridLayout_3.setRowStretch(3, 1)
self.typeTab.addTab(self.elecTab, "") self.typeTab.addTab(self.elecTab, "")
self.verticalLayout_2.addWidget(self.typeTab) self.verticalLayout_2.addWidget(self.typeTab)
self.titlefrequencyLabel = QtWidgets.QLabel(parent=Form) self.titlefrequencyLabel = QtWidgets.QLabel(parent=Form)
font = QtGui.QFont() font = QtGui.QFont()
font.setBold(True) font.setBold(True)
font.setWeight(75)
self.titlefrequencyLabel.setFont(font) self.titlefrequencyLabel.setFont(font)
self.titlefrequencyLabel.setObjectName("titlefrequencyLabel") self.titlefrequencyLabel.setObjectName("titlefrequencyLabel")
self.verticalLayout_2.addWidget(self.titlefrequencyLabel) self.verticalLayout_2.addWidget(self.titlefrequencyLabel)
@ -135,7 +133,6 @@ class Ui_Form(object):
self.titleinfoLabel = QtWidgets.QLabel(parent=Form) self.titleinfoLabel = QtWidgets.QLabel(parent=Form)
font = QtGui.QFont() font = QtGui.QFont()
font.setBold(True) font.setBold(True)
font.setWeight(75)
self.titleinfoLabel.setFont(font) self.titleinfoLabel.setFont(font)
self.titleinfoLabel.setObjectName("titleinfoLabel") self.titleinfoLabel.setObjectName("titleinfoLabel")
self.verticalLayout_2.addWidget(self.titleinfoLabel) self.verticalLayout_2.addWidget(self.titleinfoLabel)
@ -143,7 +140,7 @@ class Ui_Form(object):
self.scrollArea.setWidgetResizable(True) self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea") self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget() self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 273, 83)) self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 297, 169))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout_2.addWidget(self.scrollArea) self.verticalLayout_2.addWidget(self.scrollArea)
@ -162,7 +159,7 @@ class Ui_Form(object):
self.horizontalLayout_2.setStretch(1, 1) self.horizontalLayout_2.setStretch(1, 1)
self.retranslateUi(Form) self.retranslateUi(Form)
self.typeTab.setCurrentIndex(1) self.typeTab.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(Form) QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form): def retranslateUi(self, Form):