mirror of
https://github.com/nqrduck/nqrduck-autotm.git
synced 2024-12-21 15:20:27 +00:00
Implemented basic measurement of RL.
This commit is contained in:
parent
2cf6219f84
commit
4859763b3c
6 changed files with 105 additions and 22 deletions
|
@ -0,0 +1,5 @@
|
|||
# nqrduck-autotm
|
||||
A module for the [nqrduck](https://github.com/nqrduck/nqrduck) project. This module is used to automatically tune and match mechanical and electrical probes.
|
||||
|
||||
### Notes
|
||||
- The active user needs to be in the correct group to use serial ports. For example 'uucp' in Arch Linux and 'dialout' in Ubuntu.
|
|
@ -1,6 +1,7 @@
|
|||
import logging
|
||||
import serial
|
||||
from serial.tools.list_ports import comports
|
||||
from PyQt6 import QtSerialPort
|
||||
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
|
||||
from nqrduck.module.module_controller import ModuleController
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -21,12 +22,33 @@ class AutoTMController(ModuleController):
|
|||
"""Connect to the specified device. """
|
||||
logger.debug("Connecting to device %s", device)
|
||||
try:
|
||||
self.module.model.serial = serial.Serial(device, self.BAUDRATE, timeout=0.1)
|
||||
self.module.model.serial = QtSerialPort.QSerialPort(device, baudRate=self.BAUDRATE, readyRead=self.on_ready_read)
|
||||
self.module.model.serial.open(QtSerialPort.QSerialPort.OpenModeFlag.ReadWrite)
|
||||
|
||||
|
||||
|
||||
logger.debug("Connected to device %s", device)
|
||||
except serial.SerialException as e:
|
||||
logger.error("Failed to connect to device %s", device)
|
||||
logger.error(e)
|
||||
except Exception as e:
|
||||
logger.error("Could not connect to device %s: %s", device, e)
|
||||
|
||||
def start_frequency_sweep(self, start_frequency : float, stop_frequency : float) -> None:
|
||||
""" This starts a frequency sweep on the device in the specified range."""
|
||||
pass
|
||||
logger.debug("Starting frequency sweep from %s to %s", start_frequency, stop_frequency)
|
||||
# Print the command 'f <start> <stop>' to the serial connection
|
||||
command = "f %s %s" % (start_frequency, stop_frequency)
|
||||
self.module.model.serial.write(command.encode('utf-8'))
|
||||
|
||||
def on_ready_read(self) -> None:
|
||||
"""This method is called when data is received from the serial connection. """
|
||||
serial = self.module.model.serial
|
||||
while serial.canReadLine():
|
||||
text = serial.readLine().data().decode()
|
||||
text = text.rstrip('\r\n')
|
||||
logger.debug("Received data: %s", text)
|
||||
if text.startswith("f"):
|
||||
text = text[1:].split("r")
|
||||
frequency = float(text[0])
|
||||
return_loss = float(text[1])
|
||||
self.module.model.add_data_point(frequency, return_loss)
|
||||
else:
|
||||
self.module.view.add_info_text(text)
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
import serial
|
||||
from PyQt6.QtCore import pyqtSignal
|
||||
from PyQt6.QtSerialPort import QSerialPort
|
||||
from nqrduck.module.module_model import ModuleModel
|
||||
|
||||
class AutoTMModel(ModuleModel):
|
||||
available_devices_changed = pyqtSignal(list)
|
||||
serial_changed = pyqtSignal(serial.Serial)
|
||||
serial_changed = pyqtSignal(QSerialPort)
|
||||
data_points_changed = pyqtSignal(list)
|
||||
|
||||
|
||||
def __init__(self, module) -> None:
|
||||
super().__init__(module)
|
||||
self.data_points = []
|
||||
|
||||
@property
|
||||
def available_devices(self):
|
||||
|
@ -23,3 +30,13 @@ class AutoTMModel(ModuleModel):
|
|||
def serial(self, value):
|
||||
self._serial = value
|
||||
self.serial_changed.emit(value)
|
||||
|
||||
def add_data_point(self, frequency : float, return_loss : float) -> None:
|
||||
"""Add a data point to the model. """
|
||||
self.data_points.append((frequency, return_loss))
|
||||
self.data_points_changed.emit(self.data_points)
|
||||
|
||||
def clear_data_points(self) -> None:
|
||||
"""Clear all data points from the model. """
|
||||
self.data_points.clear()
|
||||
self.data_points_changed.emit(self.data_points)
|
||||
|
|
|
@ -156,12 +156,19 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<widget class="QPushButton" name="startButton">
|
||||
<property name="text">
|
||||
<string>Start Sweep</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Calibrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<property name="text">
|
||||
|
@ -193,7 +200,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>273</width>
|
||||
<height>229</height>
|
||||
<height>189</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import logging
|
||||
import serial
|
||||
from datetime import datetime
|
||||
from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout
|
||||
from PyQt6.QtCore import pyqtSlot, Qt
|
||||
from PyQt6.QtSerialPort import QSerialPort
|
||||
from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout, QApplication
|
||||
from PyQt6.QtCore import pyqtSlot, Qt
|
||||
from nqrduck.module.module_view import ModuleView
|
||||
from .widget import Ui_Form
|
||||
|
||||
|
@ -33,6 +33,15 @@ class AutoTMView(ModuleView):
|
|||
# On clicking of the connect button call the connect method
|
||||
self._ui_form.connectButton.clicked.connect(self.on_connect_button_clicked)
|
||||
|
||||
# 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(
|
||||
float(self._ui_form.startEdit.text()),
|
||||
float(self._ui_form.stopEdit.text())
|
||||
))
|
||||
|
||||
# Connect the data points changed signal to the on_data_points_changed slot
|
||||
self.module.model.data_points_changed.connect(self.on_data_points_changed)
|
||||
|
||||
# Add a vertical layout to the info box
|
||||
self._ui_form.scrollAreaWidgetContents.setLayout(QVBoxLayout())
|
||||
self._ui_form.scrollAreaWidgetContents.layout().setAlignment(Qt.AlignmentFlag.AlignTop)
|
||||
|
@ -81,20 +90,43 @@ class AutoTMView(ModuleView):
|
|||
selected_device = self._ui_form.portBox.currentText()
|
||||
self.module.controller.connect(selected_device)
|
||||
|
||||
@pyqtSlot(serial.Serial)
|
||||
def on_serial_changed(self, serial : serial.Serial) -> None:
|
||||
@pyqtSlot(QSerialPort)
|
||||
def on_serial_changed(self, serial : QSerialPort) -> None:
|
||||
"""Update the serial 'connectionLabel' according to the current serial connection.
|
||||
|
||||
Args:
|
||||
serial (serial.Serial): The current serial connection."""
|
||||
logger.debug("Updating serial connection label")
|
||||
if serial.is_open:
|
||||
self._ui_form.connectionLabel.setText(serial.port)
|
||||
self.add_info_text("Connected to device %s" % serial.port)
|
||||
if serial.isOpen():
|
||||
self._ui_form.connectionLabel.setText(serial.portName())
|
||||
self.add_info_text("Connected to device %s" % serial.portName())
|
||||
else:
|
||||
self._ui_form.connectionLabel.setText("Disconnected")
|
||||
logger.debug("Updated serial connection label")
|
||||
|
||||
@pyqtSlot(list)
|
||||
def on_data_points_changed(self, data_points : list) -> None:
|
||||
"""Update the S11 plot with the current data points.
|
||||
|
||||
Args:
|
||||
data_points (list): List of data points to plot.
|
||||
"""
|
||||
x = [data_point[0] for data_point in data_points]
|
||||
y = [data_point[1] for data_point in data_points]
|
||||
ax = self._ui_form.S11Plot.canvas.ax
|
||||
ax.clear()
|
||||
ax.set_xlabel("Frequency (MHz)")
|
||||
ax.set_ylabel("S11 (dB)")
|
||||
ax.set_title("S11")
|
||||
ax.grid(True)
|
||||
ax.plot(x, y)
|
||||
# make the y axis go down instead of up
|
||||
ax.invert_yaxis()
|
||||
self._ui_form.S11Plot.canvas.draw()
|
||||
self._ui_form.S11Plot.canvas.flush_events()
|
||||
# Wait for the signals to be processed before adding the info text
|
||||
QApplication.processEvents()
|
||||
|
||||
def add_info_text(self, text : str) -> None:
|
||||
""" Adds text to the info text box.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 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.2
|
||||
# Created by: PyQt6 UI code generator 6.5.1
|
||||
#
|
||||
# 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.
|
||||
|
@ -91,9 +91,9 @@ class Ui_Form(object):
|
|||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout.addWidget(self.label_5, 0, 0, 1, 1)
|
||||
self.verticalLayout_2.addLayout(self.gridLayout)
|
||||
self.pushButton_2 = QtWidgets.QPushButton(parent=Form)
|
||||
self.pushButton_2.setObjectName("pushButton_2")
|
||||
self.verticalLayout_2.addWidget(self.pushButton_2)
|
||||
self.startButton = QtWidgets.QPushButton(parent=Form)
|
||||
self.startButton.setObjectName("startButton")
|
||||
self.verticalLayout_2.addWidget(self.startButton)
|
||||
self.pushButton_3 = QtWidgets.QPushButton(parent=Form)
|
||||
self.pushButton_3.setObjectName("pushButton_3")
|
||||
self.verticalLayout_2.addWidget(self.pushButton_3)
|
||||
|
@ -145,7 +145,7 @@ class Ui_Form(object):
|
|||
self.label_6.setText(_translate("Form", "MHz"))
|
||||
self.label_7.setText(_translate("Form", "Stop Frequency:"))
|
||||
self.label_5.setText(_translate("Form", "Start Frequency:"))
|
||||
self.pushButton_2.setText(_translate("Form", "Start Sweep"))
|
||||
self.startButton.setText(_translate("Form", "Start Sweep"))
|
||||
self.pushButton_3.setText(_translate("Form", "T&M Settings"))
|
||||
self.titleinfoLabel.setText(_translate("Form", "Info Box:"))
|
||||
from nqrduck.contrib.mplwidget import MplWidget
|
||||
|
|
Loading…
Reference in a new issue