diff --git a/Python script/README.txt b/Python script/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..8ddcc5eb5678dfe61c74b883b1e82eb9d68d2e5a --- /dev/null +++ b/Python script/README.txt @@ -0,0 +1,8 @@ +Necessary libraries to install- + +$ pip install -U pyvisa + +Recommended software version- + +python3.7 + diff --git a/Python script/VNA.py b/Python script/VNA.py new file mode 100644 index 0000000000000000000000000000000000000000..ada50b4e2eb3d7f3c536548f0cd38c0a091098ed --- /dev/null +++ b/Python script/VNA.py @@ -0,0 +1,91 @@ +import pyvisa +import time + + +class Vna: + def __init__(self): + """ + Implements the basic operation of the VNA + + """ + # open connection here + + # store the credentials so that methods can access them + #self.__ip_address = ip_address + + # we try to connect to the climate chamber just to see if there is an error + self.rm = pyvisa.ResourceManager() + + self.vna = self.rm.open_resource("TCPIP0::192.168.115.39 ::57732::SOCKET") + # self.vna.write_termination = '\r\n' + # self.vna.read_termination = '\r\n' + self.vna.timeout = 5000 + + # Preset the VNA and wait for preset completion via use of *OPC? + self.vna.write("SYST:PRES; *OPC?") + self.vna.read() + + # Clear the event status registers and empty the error queue + self.vna.write("*CLS") + + # Query identification string *IDN? + self.vna.write("*IDN?") + print(self.vna.read()) + + # check the error queue + self.vna.write("SYST:ERR?") + print(self.vna.read()) + + # the communication section + + # Select the default measurement name as assigned on preset. To catalog the measurement names, + # by channel number, use the 'CALCulate[n]:PARameter:CATalog?' command where [n] is the channel + # number. + self.vna.write("CALC:PAR:SEL 'CH1_S11_1'") + + # Set data transfer format to ASCII + self.vna.write("FORM:DATA ASCII") + + # Alter measure from S11 to S21 + self.vna.write("CALC:PAR:MOD S21") + + # Loop to control the number of trace points, provide single sweep synchronization, query the data, + # indicate number of points and indicate number of characters in the trace read. + self.traceData = [] + i = 0 + self.numPointsList = [201, 401, 801, 1601, 3201, 6401, 12801, 20001, 32001, 100001] + + while i < len(self.numPointsList): + # Set number of points by list value + self.numPoints = self.numPointsList[i] + self.vna.write("SENS:SWE:POIN " + str(self.numPoints) + ";*OPC?") + self.vna.read() + + self.startTime = self.time.clock() + # Trigger assertion with hold-off for trigger complete via *OPC? + self.vna.write("SENS:SWE:MODE SING;*OPC?") + self.vna.read() + + self.stopTime = self.time.clock() - self.startTime + + # The SDATA assertion queries underlying real and imaginary pair data + self.vna.write("CALC:DATA? SDATA") + self.traceData = self.vna.read() + + print("Time to sweep = " + str(self.stopTime)) + print("Number of trace points set = " + str(self.numPoints)) + print("Number of characters in returned data " + str(len(self.traceData))) + print(self.traceData) + + i = i + 1 + + # Check the error queue. Initially *CLS asserted in beginning of program. + # The application should run from stem to stern error free. The final error + # queue query should return '+0, No Error', else the application has potentially + # caused a correctable error!. + self.vna.write("SYST:ERR?") + print(self.vna.read()) + + # Close the VISA connection + self.vna.close() + diff --git a/Python script/climate_chamber.py b/Python script/climate_chamber.py new file mode 100644 index 0000000000000000000000000000000000000000..26080d26c7afabe324bf1a600f75a1afa1023db9 --- /dev/null +++ b/Python script/climate_chamber.py @@ -0,0 +1,232 @@ +#!/usr/bin/python3 + +import pyvisa +import time + + +class ClimateChamber: + def __init__(self, ip_address): + """ + Implements the basic operation of the climate chamber + + """ + # open connection here + + # store the credentials so that methods can access them + self.__ip_address = ip_address + + # we try to connect to the climate chamber just to see if there is an error + self.rm = pyvisa.ResourceManager() + + self.chamber = self.rm.open_resource("TCPIP0::" + str(self.__ip_address) + "::57732::SOCKET") + self.chamber.write_termination = '\r\n' + self.chamber.read_termination = '\r\n' + self.chamber.timeout = 5000 + + # the communication section + + def read_temperature(self): + # data format: [current temp, set temp, upper limit, lower limit] + # send the request to the chamber + response = self.chamber.query("TEMP?", delay=2) + + # self.my_socket.send(b'TEMP?\r\n') + # temperature = self.my_socket.recv((1024).decode('utf-8')) + + # convert into float numbers + temperature = [float(i) for i in response.split(sep=',')] + return temperature + + def read_humidity(self): + # data format: [current hum, set hum, upper limit, lower limit] + # send the request to the chamber + response = self.chamber.query("HUMI?", delay=2) + + # convert into float numbers + humidity = [float(i) for i in response.split(sep=',')] + return humidity + + def set_temperature(self, temperature): + # sets the temp of the chamber, (float) temperature + response = self.chamber.query("TEMP, S" + str(temperature)) + + # response = (OK: TEMP, S30\r\n) + return response + + def set_humidity(self, humidity): + # sets the humidity of the chamber, (float) humidity + response = self.chamber.query("HUMI, S" + str(humidity)) + + # response = (OK: HUMI, S30\r\n) + return response + + def close(self): + self.rm.close() + + # additional functionality + + def read_monitor(self): + """ gets the chamber test area state + output data format: [temp, humid, op-state, num. of alarms] + """ + + response = self.chamber.query("MON?", delay=2) + return response + + def set_temperature_limit(self, upper_limit, lower_limit): + """ + Sets the upper and lower temperature limits for the chamber + + Parameters + ---------- + upper_limit : int + Temperature upper limit. + lower_limit : int + Temperature lower limit. + + Returns + ------- + None. + + """ + response = self.chamber.query("TEMP, H" + str(upper_limit)) + response = self.chamber.query("TEMP, L" + str(lower_limit)) + + def set_humidity_limit(self, upper_limit, lower_limit): + """ + Sets the upper and lower humidity limits for the chamber + + Parameters + ---------- + upper_limit : int + humidity upper limit. + lower_limit : int + humidity lower limit. + + Returns + ------- + None. + + """ + response = self.chamber.query("HUMI, H" + str(upper_limit)) + response = self.chamber.query("HUMI, L" + str(lower_limit)) + + def read_mode(self): + """ read the mode of the chamber: + Panel power off "OFF" + All operation stop "STANDBY" + Constant operation "CONSTANT" + Program/remote operation "RUN" + """ + response = self.chamber.query("MODE?", delay=2) + return response + + def set_mode(self, mode): + # sets the mode of the chamber: + response = self.chamber.query("MODE, " + mode, delay=2) + return response + + def _get_const(self, mode): + response = self.chamber.query("CONSTANT SET?" + mode) + return response + + def get_const(self): + """ + combination of read_temperature() and read_humidity() + """ + temp = self.read_temperature() + hum = self.read_humidity() + return [temp, hum] + + def set_const(self, setPoint): + """ + + Parameters + ---------- + setPoint : tuple(float,float) + A tuple of temperature and humidity as setpoint + + Returns + ------- + None. + + """ + # setPoint = (temp,hum) + self.set_temprature(setPoint[0]) + self.set_humidity(setPoint[1]) + + def goto_const(self, setPoint, target_accuracy=(0.2, 1), soaking_time=60): + """ + + Parameters + ---------- + setPoint : tuple(float,float) + A tuple of temperature and humidity as setpoint. + target_accuracy : tuple(float,float), optional + A tuple of temperature and humidity as accuracy. The default is (0.2, 1). + soaking_time : int, optional + Soaking time. The default is 60. + + Returns + ------- + None. + + """ + + current_milli_time = lambda: int(round(time.time() * 1000)) + + # set temperature and humidity + self.set_const(setPoint) + + # set mode to Const + self.set_mode('CONSTANT') + + start_time = current_milli_time() + # wait until setpoint is reached (+soaking time) + while True: + # get the actual temperature & humidity + [temp, hum, mode, alarms] = self.read_monitor().split(',') + + # if it is not within the target range reset start time + if not (setPoint[0] - target_accuracy[0] <= float(temp) <= setPoint[0] + target_accuracy[0]): + start_time = current_milli_time() + + if not (setPoint[1] - target_accuracy[1] <= float(hum) <= setPoint[1] + target_accuracy[1]): + start_time = current_milli_time() + + # if the value is stable long enough + if ((current_milli_time() - start_time) / 1000 > soaking_time): + print('SOAKING FINISHED!') + break + + print('Temp: ' + temp + ' °C' + + '| Humid: ' + hum + '%' + + '|| time soaking:' + str((current_milli_time() - start_time) / 1000) + 's') + + sleep(1) + + # The climate chamber will instantly begin with the heat-up. + # The Python process will instantly continue (so it will not wait until the target temperature is reached). + # This function is blocking until the temperature and humidity setpoint have been reached + + def is_temperature_reached(self): + current_temp = self.read_temperature() + set_temp = self.set_temperature() + + while (not current_temp == set_temp): + print('Target temperature reached =' + str(set_temp)) + break + + def is_humidity_reached(self): + current_hum = self.read_humidity() + set_hum = self.set_humidity() + + while (not current_hum == set_hum): + print('Target humidity reached =' + str(set_hum)) + break + + def wait_for_setpoints_reached(self): + while (not self.is_humiditiy_reached()) or (not self.is_temperature_reached()): + time.sleep(10) + break + diff --git a/Python script/script1.py b/Python script/script1.py new file mode 100644 index 0000000000000000000000000000000000000000..5cf558461b6a062fafadfe98c2991a78cb2ac302 --- /dev/null +++ b/Python script/script1.py @@ -0,0 +1,33 @@ +from climate_chamber import ClimateChamber + +ip_address = '192.168.115.129' +#initiate and connect to humidity chamber +chamber = ClimateChamber(ip_address) +print('connected') + +#Read and print temperature +#temp = [current temp, set temp, upper limit, lower limit] +temp = chamber.read_temperature() +print('Current temperature (°C): ' + str(temp[0])) + +#Read and print humidity +#humi = [current humi, set humi, upper limit, lower limit] +humi = chamber.read_humidity() +print('Current humidity (%): ' + str(humi[0])) + +#to get the mode of the chamber(OFF, STANDBY or CONSTANT) +status = chamber.read_mode() +print('The chamber status is: ' + str(status)) + +#to enable or disable the climate chamber we can use command chamber.set_mode() +#let's heat the chamber to 35 °C and 35% relative humidity +#And after connecting, need to set the setpoint and enable the climate chamber +chamber.set_const((35,35)) +chamber.set_mode('CONSTANT') + +#chamber.goto_const() will block further Python program execution until the target temperature is reached and stable +chamber.goto_const((25,30), (0.2,1), 60) +print('The temperature is stable.') + + + diff --git a/drift.pyw b/drift.pyw deleted file mode 100644 index bfd6a3611b5c3afc8ca884409792e487b762e061..0000000000000000000000000000000000000000 --- a/drift.pyw +++ /dev/null @@ -1,20 +0,0 @@ -import sys - -from PyQt5.QtGui import QWindow -from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget -from PyQt5 import uic - - -class MainWindow(QMainWindow): - def __init__(self, *args, **kwargs): - super(MainWindow, self).__init__(*args, **kwargs) - - uic.loadUi("main.ui", self) - self.show() - - -if __name__ == "__main__": - app = QApplication(sys.argv) - main_window = QMainWindow() - app.exec_() - diff --git a/mainpage.py b/mainpage.py deleted file mode 100644 index 622f954595764760a004025c2dc1e1863e11da1b..0000000000000000000000000000000000000000 --- a/mainpage.py +++ /dev/null @@ -1,38 +0,0 @@ -import sys - -from PyQt5.QtGui import QWindow -from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget - -from ui_startpage import Ui_StartPage -from ui_temperaturesweep import Ui_TemperatureSweep - - -class TempSweepWindow(QWidget, Ui_TemperatureSweep): - def __init__(self, *args, **kwargs): - super(TempSweepWindow, self).__init__(*args, **kwargs) - self.setupUi(self) - - -class MainWindow(QMainWindow, Ui_StartPage): - def __init__(self, *args, **kwargs): - super(MainWindow, self).__init__(*args, **kwargs) - - - self.setupUi(self) - - self.pushButton.pressed.connect(self.__create_temprature_sweep_window) - - - def __create_temprature_sweep_window(self): - self.temp_sweep = TempSweepWindow(self) - self.temp_sweep.show() - - # you could add a signal here that links to another window instead - self.temp_sweep.pushButton.pressed.connect(self.temp_sweep.hide) - - -if __name__ == "__main__": - app = QApplication(sys.argv) - main_window = MainWindow() - main_window.show() - app.exec_() \ No newline at end of file