Skip to content
Snippets Groups Projects
Commit f1aac102 authored by Martin Killenberg's avatar Martin Killenberg
Browse files

feat: separate VNA into generic DUT class

All notions of VNA, magnitude and phase in prototype.py and the GUI have been
removed and generalised.
This is just refactoring, no functional change. However, the syntax of the
config file has been adapted.
parent 02959132
No related branches found
No related tags found
1 merge request!5feat: separate VNA into generic DUT class
......@@ -74,8 +74,7 @@ class TestStandMainWindow(QMainWindow):
self.setEnabled(True)
return
meas = prototype.Measurements(config_data['chamber_ip'], config_data['vna_ip'], output_basename,
False, config_data, ext_sensor_channels, config_data['logger_ip'])
meas = prototype.Measurements(config_data, output_basename,False, ext_sensor_channels)
try:
if self.tempSweepButton.isChecked():
temperatures = meas.perform_sweep(self.startParameter.value(), self.stopParameter.value(),
......
from abc import ABC, abstractmethod
class DutMeasurement(ABC):
"""
Interface for DUT measurements
"""
@abstractmethod
def get_dut_measurements(self):
"""
Returns a dictionary with column names a keys and scalar values
"""
pass
@abstractmethod
def get_dut_signal_names(self):
"""
Returns a list of names used as keys used in the dut measurements dictionary
"""
pass
@abstractmethod
def get_dut_reference_signal_names(self):
"""
Returns a list of signal names used for stability checks
"""
pass
@abstractmethod
def get_dut_max_delta_signals(self):
"""
Return the maximum deltas of the reference signals
"""
This diff is collapsed.
{"delta_temp": 0.1, "delta_hum": 1, "delta_mag": 0.13 , "delta_phase": 1.5, "sleep_time": 10.0, "frequency": 1300000000, "vna_config_file": "CalSetup2.znxml","chamber_ip":"192.168.115.186", "instr_chamber_ip": "192.168.115.187", "vna_ip":"192.168.115.39", "data_folder":"measurements", "logger_ip": "192.168.115.94", "time_unit": "min", "trace_subplot5": "logger_sens", "logger_model": "710"}
{
"delta_temp": 0.1,
"delta_hum": 1,
"dut": {
"type": "VNA",
"delta_mag": 0.13,
"delta_phase": 1.5,
"frequency": 1300000000,
"vna_ip": "192.168.115.39",
"vna_config_file": "CalSetup2.znxml"
},
"sleep_time": 10,
"chamber_ip": "192.168.115.186",
"instr_chamber_ip": "192.168.115.187",
"data_folder": "measurements",
"logger_ip": "192.168.115.94",
"time_unit": "min",
"trace_subplot5": "logger_sens",
"logger_model": "710"
}
import VNA
import pyvisa
import time
import numpy
import math
import cmath
import dut_measurement
class VnaData:
def __init__(self, power, frequency, s11, s21, s12, s22):
self.power = power
self.frequency = frequency
self.s11 = s11
self.s21 = s21
self.s12 = s12
self.s22 = s22
class VnaMeasurement(dut_measurement.DutMeasurement):
def __init__(self, config_data, target_accuracy):
self.delta_mag = config_data['delta_mag']
self.delta_phase = config_data['delta_phase']
self.vna = VNA.create_vna(config_data['vna_ip'], target_accuracy)
self.vna.load_config(config_data['vna_config_file'], config_data['frequency'])
self.vna.create_new_trace("Trace1", "S11")
self.vna.create_new_trace("Trace2", "S12")
self.vna.create_new_trace("Trace3", "S21")
self.vna.create_new_trace("Trace4", "S22")
def _get_trace_data(self, trace):
return self.vna.get_list_of_measurement_values(trace, "SDAT")
def get_dut_measurements(self):
# FIXME: The try/catch should be way down in the VNA class
for iteration in range(10):
try:
power = self.vna.get_current_power()
frequency = self.vna.get_current_cw_frequency()
self.vna.do_single_sweep()
s11 = self._get_trace_data("Trace1")
s12 = self._get_trace_data("Trace2")
s21 = self._get_trace_data("Trace3")
s22 = self._get_trace_data("Trace4")
return {'RF_POWER': power, 'RF_FREQUENCY': frequency,
'S11_MAGNITUDE': self.calculate_mean_magnitude_db(s11),
'S11_PHASE': self.calculate_mean_phase(s11),
'S12_MAGNITUDE': self.calculate_mean_magnitude_db(s12),
'S12_PHASE': self.calculate_mean_phase(s12),
'S21_MAGNITUDE': self.calculate_mean_magnitude_db(s21),
'S21_PHASE': self.calculate_mean_phase(s21),
'S22_MAGNITUDE': self.calculate_mean_magnitude_db(s22),
'S22_PHASE': self.calculate_mean_phase(s21)}
# exception for pyvisa error or timeout
except pyvisa.errors.VisaIOError:
# call reset function for VNA status register and error queue
self.vna.reset_status()
print('An error occurred during VNA read out')
# wait one second for next try
time.sleep(1)
# FIXME: In case we did not succeed we need something like a stop_measurement exception
raise Exception('FIXME: Throw stop_measurement here, and handle it. Don\'t crash!')
def get_dut_signal_names(self):
return ['RF_POWER', 'RF_FREQUENCY', 'S11_MAGNITUDE', 'S11_PHASE', 'S12_MAGNITUDE',
'S12_PHASE', 'S21_MAGNITUDE', 'S21_PHASE', 'S22_MAGNITUDE', 'S22_PHASE']
def get_dut_reference_signal_names(self):
return ['S21_MAGNITUDE', 'S21_PHASE']
def get_dut_max_delta_signals(self):
return [self.delta_mag, self.delta_phase]
def calculate_complex_numbers(self, values_list):
real_num = values_list[::2]
imaginary_num = values_list[1::2]
complex_numbers = []
for i, q in zip(real_num, imaginary_num):
complex_numbers.append(complex(i, q))
return complex_numbers
def calculate_magnitudes(self, values_list):
complex_numbers = self.calculate_complex_numbers(values_list)
magnitudes = [abs(val) for val in complex_numbers]
return magnitudes
def calculate_mean_magnitude(self, values_list):
magnitudes = self.calculate_magnitudes(values_list)
return numpy.mean(magnitudes)
def calculate_mean_magnitude_db(self, values_list):
return 20*math.log10(self.calculate_mean_magnitude(values_list))
def calculate_phases(self, values_list):
complex_numbers = self.calculate_complex_numbers(values_list)
phases = [math.degrees(cmath.phase(val)) for val in complex_numbers]
return phases
def calculate_mean_phase(self, values_list):
phases = self.calculate_phases(values_list)
return numpy.mean(phases)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment