diff --git a/equipment_control/cm110.py b/equipment_control/cm110.py index 3c10e61a006374dc7207fc24288ec5c2bbe43fe3..73db0f557e1e4ccff66731f235634b667cc281cd 100644 --- a/equipment_control/cm110.py +++ b/equipment_control/cm110.py @@ -10,6 +10,11 @@ class cm110(equipment.equipment): url="https://www.spectralproducts.com/CM110" def __init__(self,port): + """ Function called when an instance of the class is created + + args: + - port (string) : the computer port to which the equipment is connected + """ self.serial_resource = serial.Serial( port=port, baudrate=9600, @@ -20,6 +25,13 @@ class cm110(equipment.equipment): def initialize(self,grating_number=1,waiting_time=30): + """ Function to initialize the CM110 + + args: + - grating_number (int) : select the grating (Grating 1 : AG2400-00240-303 (2400 G/mm and 180 nm - 680 nm) and Grating 2 : AG1200-00750-303 (1200 G/mm and 480 nm - 1500 nm)) + - waiting_time (int) : waiting time in seconds after changing the grating and reset to the initial position + + """ reset=[255,255,255] self.serial_resource.write(serial.to_bytes([26,grating_number])) @@ -28,11 +40,18 @@ class cm110(equipment.equipment): time.sleep(waiting_time) def set_wavelength(self, wavelength,waiting_time=10): + """ Function to set the wavelength of the monochromator + + args: + - wavelength (scalar) : targeted wavelength in nm + - waiting_time : waiting time in seconds to let the grating of the monochromator reach the targeted wavelength + """ set_position = [16,int((wavelength-wavelength%256)/256),wavelength%256] # Goto Position : 1000 -> 0x3E8 -> 3 and 232 self.serial_resource.write(serial.to_bytes(set_position)) time.sleep(waiting_time) def close_connection(self): + """ Function to close the serial connection with the equipment """ self.serial_resource.close() diff --git a/equipment_control/dmm.py b/equipment_control/dmm.py index 62256bd1b223e4abc8549f795552b21ade9ca0b3..f0a2c08e21573bfdaa9d06f5abf1490471cf9728 100644 --- a/equipment_control/dmm.py +++ b/equipment_control/dmm.py @@ -3,19 +3,26 @@ import time class dmm(equipment.equipment): - """Class to control DMM multimeter""" + """Class to control digital multimeter""" model="DMM7510, DMM6500 or K2000" company="Keithley" url="https://www.tek.com/en/products/keithley/benchtop-digital-multimeter" - def initialize(self, mode, autozero=True, offset_compensation=True, nplc=1,timeout=10e3,digits=6,k2000=False,continuous_trigger=False,disp_enable=True): - """ - mode: - - "voltage": voltage measurement - - "current": current measurement - - "resistance": resistance measurement - - "4 wires": 4wires measurement + def initialize(self, mode, autozero=True, nplc=1,timeout=10e3,digits=6,continuous_trigger=False,disp_enable=True,k2000=False): + + """ Function to initialize the K2400 SMU with the desired settings + + args: + - mode (string) : measurement mode of the multimeter ("current", "voltage", "resistance" or "4 wires") + - autozero (boolean) : if true, enable autozero of the SMU + - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec + - digits (int) : display resolution in number of bits + - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed + - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed + - k2000 (boolean) : if true send instruction formatted for k2000 multimeter, otherwise send instruction for more recent multimeter such as DMM6500 and DMM7510 """ + + self.continuous_trigger=continuous_trigger self.k2000=k2000 self.pyvisa_resource.write("*RST") @@ -33,28 +40,21 @@ class dmm(equipment.equipment): if disp_enable: self.pyvisa_resource.write(":DISP:ENAB ON") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. else: - self.pyvisa_resource.write(":DISP:ENAB OFF") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + self.pyvisa_resource.write(":DISP:ENAB OFF") if continuous_trigger: self.pyvisa_resource.write("INIT:CONT ON") # able continuous triggering else: - self.pyvisa_resource.write("INIT:CONT OFF") # able continuous triggering + self.pyvisa_resource.write("INIT:CONT OFF") else: if disp_enable: self.pyvisa_resource.write(":DISP:LIGHT:STAT ON100") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. else: - self.pyvisa_resource.write(":DISP:LIGHT:STAT OFF") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + self.pyvisa_resource.write(":DISP:LIGHT:STAT OFF") self.pyvisa_resource.write(":DISP:%s:DIG %d"%(mode_name[mode],digits)) self.pyvisa_resource.write(":SENS:%s:NPLC %d"%(mode_name[mode],nplc)) # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec - - # if mode_name[mode]=="RES" or mode_name[mode]=="FRES": - - # if offset_compensation: - # self.pyvisa_resource.write(":%s:OCOM ON"%mode_name[mode]) # enable offset compensation - # else: - # self.pyvisa_resource.write(":%s:OCOM OFF"%mode_name[mode]) if autozero: self.pyvisa_resource.write(":%s:AZER ON"%mode_name[mode]) # enable auto-zero @@ -67,6 +67,12 @@ class dmm(equipment.equipment): self.pyvisa_resource.write("TRIG:CONT OFF") def read_single(self): + """ Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off + + return: + - data (float) : float with the value of the measurement + """ + if self.k2000: if self.continuous_trigger: data=self.pyvisa_resource.query("FETCH?") @@ -76,10 +82,10 @@ class dmm(equipment.equipment): if self.continuous_trigger: self.pyvisa_resource.write("TRIG:CONT OFF") time.sleep(0.1) - data=self.pyvisa_resource.query("MEAS?") + data=float(self.pyvisa_resource.query("MEAS?")) self.pyvisa_resource.write("TRIG:CONT REST") else: - data=self.pyvisa_resource.query("MEAS?") + data=float(self.pyvisa_resource.query("MEAS?")) - return float(data) + return data diff --git a/equipment_control/equipment.py b/equipment_control/equipment.py index d275b920846371dece200396baac7b90b4fea9c8..b74401c291e06e0d54e3febd6de9fc8cd6e3c341 100644 --- a/equipment_control/equipment.py +++ b/equipment_control/equipment.py @@ -4,29 +4,46 @@ import numpy as np def available_connections(rm=None): + """ Function that return the list of resource connected to the computer """ if rm==None: rm = pyvisa.ResourceManager() return rm.list_resources() def resource_manager(): + """ Function that return a pyvisa resource manager to deal with resources connected to the computer """ + rm = pyvisa.ResourceManager() return rm class equipment(): - """Base for Equipment classes.""" + """ Parent class for all the equipment classes.""" - model = "" - company = "" - url = "" def __init__(self,address,rm=None,timeout=10e3): + """ Function called when an instance of the class is created + + args: + - address (string) : the address of the equipment to be connected + - rm (pyvisa object) : the pyvisa resource manager used to set the communication with the equipment + - timeout (scalar) : the timeout set for the communication with the equipment + + """ + if rm==None: rm = pyvisa.ResourceManager() self.pyvisa_resource = rm.open_resource(address) self.set_connection_parameter("timeout",timeout) def set_connection_parameter(self,key,value): + """ Function to change a parameter of the communication with the equipment + + args: + - key (string) : the parameter to be modifier + - value (scalar) : the value for the parameter + + """ + key_list=["timeout","write_termination","read_termination","send_end","baud_rate"] if key=="timeout": self.pyvisa_resource.timeout=value elif key=="write_termination": @@ -37,10 +54,17 @@ class equipment(): self.pyvisa_resource.send_end=value elif key=="baud_rate": self.pyvisa_resource.baud_rate =value + else: + print("Parameter not valid. Valid parameter are %s"%key_list) def set_connection_parameter_dic(self,connection_parameter): + """ Function to change a parameter of the communication with the equipment + + args: + - connection_parameter (dictionary) = dictionary with key and value to be sent to function set_connection_parameter(key,value) + """ if isinstance(connection_parameter, dict): for key, value in connection_parameter.items(): self.set_connection_parameter(key,value) @@ -49,12 +73,25 @@ class equipment(): def close_connection(self): + """ Function to close the connection with an equipment """ self.pyvisa_resource.close() - def write_in_file(self,file_path,data,delimiter=",",extension="txt",overwrite=False,header=None,date=True): + def write_in_file(self,file_path,data,delimiter=",",overwrite=False,header=None,date=True, comment="#"): + """ Function to write data in a file + args: + - file_path (string) : path for the data file, including the filename with its extension + - data (scalar, list or array) : the data to be written in the file + - delimiter (char) : the delimiter to separate the column of the data + - overwrite (boolean) : if True overwrite the existing file if any, if False, append the data to the existing file if any + - header (string) : header to be written before the data + - date (boolean) : date to be written at the beginning of the file + - comment (char) : char to be written before the header and date to indicate non-data lines + + """ if file_path.split(".")[-1]=="csv": delimiter="," + # Create file and header if overwrite: f = open(file_path, "w") @@ -62,11 +99,11 @@ class equipment(): f = open(file_path, "a") if date: - f.write("# %s\n"%(datetime.datetime.now().strftime("%c"))) + f.write("%s %s\n"%(comment,datetime.datetime.now().strftime("%c"))) if isinstance(header, str): for line in header.split("\n"): - f.write("# "+line+"\n") + f.write(comment+" "+line+"\n") shape=np.shape(data) diff --git a/equipment_control/hp4145.py b/equipment_control/hp4145.py index de71eefed301378424f27f5f4fdbcfa91b812b22..4e4de5904086caefb58958f1ddb454089ac4fb6d 100644 --- a/equipment_control/hp4145.py +++ b/equipment_control/hp4145.py @@ -6,20 +6,34 @@ import numpy as np class hp4145(equipment.equipment): """Class to control HP4145 semiconductor analyzer""" + model="HP4145" company="Keysight" url="https://www.keysight.com/dk/en/assets/9018-07935/service-manuals/9018-07935.pdf" - def initialize(self, smu_type={"SMU1":"voltage","SMU2":"voltage","SMU3":"common","SMU4":"common"}, smu_used={"SMU1":"on","SMU2":"on","SMU3":"on","SMU4":"on"}, - smu_master=1,smu_bias={"SMU1":0,"SMU2":0,"SMU3":0,"SMU4":0}, - smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6},sweep_param={"start":0,"stop":0,"step":0},sweep_type="linear", - integration_mode="IT1",delay_time=0,hold_time=0): + def initialize(self, smu_type={"SMU1":"voltage","SMU2":"voltage","SMU3":"common","SMU4":"common"}, + smu_used={"SMU1":"on","SMU2":"on","SMU3":"on","SMU4":"on"}, + smu_master=1,smu_bias={"SMU1":0,"SMU2":0,"SMU3":0,"SMU4":0}, + smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6}, + sweep_param={"start":0,"stop":0,"step":0},sweep_type="linear", + integration_mode="S",delay_time=0,hold_time=0): + """ Function to initialize the HP4145 equipment with the desired settings + + args: + - smu_type (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias type ("voltage", "current" or "common") + - smu_used (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") if active or not ("on" or "off") + - smu_master (int) : integer to indicate which SMU performs the sweep + - smu_bias (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias point (scalar) + - smu_compliance (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the compliance (scalar) + - sweep_param (dictionary) : dictionary indicated the starting bias ("start"), the stoping bias ("stop") and step ("step") of the sweep + - sweep_type (string) : string to indicate linear ("linear") sweep or logarithmic ("log") sweep + - integration_mode (string) : set the integration time parameter ("S" for short, "M" for medium and "L" for long) + - delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep + - hold_time (scalar) : hold time that delays the start of a sweep """ - mode: - - "voltage sweep": voltage sweep with SMU1 and current measurements on all the SMUs - """ + self.smu_type=smu_type self.sweep_type=sweep_type self.smu_used=smu_used @@ -33,7 +47,7 @@ class hp4145(equipment.equipment): index_measurement_type={"sweep":1, "constant":3} index_smu_type={"voltage":1, "current":2, "common":3} - + integration_dictionnary={"S":"IT1","M":"IT2","L":"IT3"} try: self.pyvisa_resource.write("BC") # clear all buffer. self.pyvisa_resource.write("DR1") # This command enables or disables service request for data ready when communications is set to GPIB. @@ -68,13 +82,12 @@ class hp4145(equipment.equipment): self.pyvisa_resource.write("VC%d, %.2f, %.6E"%(smu_index+1,smu_bias["SMU%d"%(smu_index+1)],smu_compliance["SMU%d"%(smu_index+1)])) elif smu_type["SMU%d"%(smu_index+1)]=="current": self.pyvisa_resource.write("IC%d, %.2f, %.6E"%(smu_index+1,smu_bias["SMU%d"%(smu_index+1)],smu_compliance["SMU%d"%(smu_index+1)])) - time.sleep(20) self.pyvisa_resource.write("HT %f"%hold_time) # Sets a hold time that delays the start of a sweep self.pyvisa_resource.write("DT %f"%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep. - self.pyvisa_resource.write(integration_mode) # integration time, IT1/IT2/IT3 : short/medium/long + self.pyvisa_resource.write(integration_dictionnary[integration_mode]) # integration time, IT1/IT2/IT3 : short/medium/long self.pyvisa_resource.write("SM") - self.pyvisa_resource.write("DM2") + self.pyvisa_resource.write("DM2") # set the data display in list mode list_display="" for smu_index in range(4): @@ -85,28 +98,32 @@ class hp4145(equipment.equipment): list_display+=",'%s%d'"%("V",smu_index+1) self.pyvisa_resource.write("LI %s"%list_display[1:]) - # self.pyvisa_resource.write("DM1") - # self.pyvisa_resource.write("XN 'V1', 1, %.1f, %.1f"%(v_sweep_param["start"],v_sweep_param["stop"])) - # self.pyvisa_resource.write("YA 'I1',2, 1E-15, 1E-12") except pyvisa.VisaIOError: print("/!\ VisaIOError : timeout expired") self.pyvisa_resource.close() - - return 42 - + def launch_measurements(self,activate_segmentation=True): + """ Function to launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration + + args: + - activate_segmentation (boolean) :if True the total number of measurements is subdivide in smaller set of measurments to avoid a connection lost with the equipment. The longer the integration time, the smaller the subdivision segment + return: + - data (array) : array with the measurement data + - header (string) : string with the description of the data column "Vx" or "Ix" for voltage or current measured from SMUx. + + """ number_channel=0 for smu_index in range(4): if self.smu_used["SMU%d"%(smu_index+1)]=="on": number_channel+=1 - if self.integration_mode=="IT1": + if self.integration_mode=="S": Nmax=50 - elif self.integration_mode=="IT2": + elif self.integration_mode=="M": Nmax=30 - elif self.integration_mode=="IT3": + elif self.integration_mode=="L": Nmax=10 diff --git a/equipment_control/k2400.py b/equipment_control/k2400.py index 72d8b9937feb04af0aaffff3252379be7fc2fe27..302016164035e3de262d7b1e20372df9c8d38249 100644 --- a/equipment_control/k2400.py +++ b/equipment_control/k2400.py @@ -2,22 +2,24 @@ import equipment_control.equipment as equipment import time class k2400(equipment.equipment): - """Class to control K2400 or k2450 SMU""" - model="K2400 or K2450" + """Class to control K2400 SMU""" + model="K2400" company="Keithley" url="https://www.tek.com/en/products/keithley/digital-multimeter/dmm7510" - def initialize(self, source_mode,measurement_mode, compliance, autozero=True, offset_compensation=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True): + def initialize(self, source_mode,measurement_mode, compliance, autozero=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True): + """ Function to initialize the K2400 SMU with the desired settings - """ - source_mode: - - "voltage": voltage source - - "current": current source - measurement_mode: - - "voltage": voltage measurement - - "current": current measurement - - "resistance": resistance measurement + args: + - source_mode (string) : source mode of the SMU ("current" or "voltage") + - measurement_mode (string) : measurement mode of the SMU ("current", "voltage" or "resistance") + - compliance (scalar) : compliance of the source + - autozero (boolean) : if true, enable autozero of the SMU + - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec + - digits (int) : display resolution in number of bits + - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed + - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed """ mode_name={"voltage":"VOLT", "current":"CURR", "resistance":"RES"} self.output_state="OFF" @@ -48,18 +50,12 @@ class k2400(equipment.equipment): self.pyvisa_resource.write(":SENS:RES:RANG:AUTO ON") # set automatic range - self.pyvisa_resource.write(":DISP:DIG %d"%digits) # Query largest allowable display resolutio + self.pyvisa_resource.write(":DISP:DIG %d"%digits) # Query largest allowable display resolution if disp_enable: self.pyvisa_resource.write(":DISP:ENAB ON") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. else: - self.pyvisa_resource.write(":DISP:ENAB OFF") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. - - # self.pyvisa_resource.write("INIT:CONT ON") # able continuous triggering + self.pyvisa_resource.write(":DISP:ENAB OFF") - # if offset_compensation: - # self.pyvisa_resource.write(":SENS:FRES:OCOM ON") # enable offset compensation - # else: - # self.pyvisa_resource.write(":SENS:FRES:OCOM OFF") if autozero: self.pyvisa_resource.write(":SYST:AZER:STAT ON") # enable auto-zero @@ -72,29 +68,41 @@ class k2400(equipment.equipment): if continuous_trigger: self.pyvisa_resource.write(":ARM:SOUR TIMer") - self.pyvisa_resource.write(":ARM:TIMer 0.001") + self.pyvisa_resource.write(":ARM:TIMer 0.001") # minimal timer is 1 ms self.pyvisa_resource.write(":ARM:COUNT INF") else: self.pyvisa_resource.write(":ARM:SOUR IMMediate") def read_single(self): + + """ Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off + + return: + - data (float) : float with the value of the measurement + """ self.pyvisa_resource.write(":OUTP ON") if self.continuous_trigger: self.pyvisa_resource.write(":ABORt") self.pyvisa_resource.write(":ARM:COUNT 1") - data=self.pyvisa_resource.query(":READ?") + data=float(self.pyvisa_resource.query(":READ?")) self.pyvisa_resource.write(":ARM:COUNT INF") self.pyvisa_resource.write(":INIT") else: - data=self.pyvisa_resource.query("READ?") + data=float(self.pyvisa_resource.query("READ?")) self.pyvisa_resource.write(":OUTP %s"%self.output_state) - return float(data) + return data def set_source(self,value): + + """ Function to set the source bias + + args: + - value (scalar) : value of the bias point + """ if self.source_mode=="current": self.pyvisa_resource.write(":SOUR:CURR %.2E"%value) #set output voltage elif self.source_mode=="voltage": @@ -102,6 +110,12 @@ class k2400(equipment.equipment): def set_output(self,output_state="ON"): + + """ Function to set the state of the outpute + + args: + - output_state (string) : "ON" and "OFF" to turn the output on or off + """ self.output_state=output_state self.pyvisa_resource.write(":OUTP %s"%output_state) diff --git a/equipment_control/k2450.py b/equipment_control/k2450.py index ab1dedf081d0ee1a5a624842f41671aa9b8e4dfd..69c3cc07b652776e9390706b7ff5fef3001f137c 100644 --- a/equipment_control/k2450.py +++ b/equipment_control/k2450.py @@ -8,16 +8,19 @@ class k2450(equipment.equipment): url="https://www.tek.com/en/products/keithley/digital-multimeter/dmm7510" - def initialize(self, source_mode,measurement_mode, compliance, autozero=True, offset_compensation=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True): + def initialize(self, source_mode,measurement_mode, compliance, autozero=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True): - """ - source_mode: - - "voltage": voltage source - - "current": current source - measurement_mode: - - "voltage": voltage measurement - - "current": current measurement - - "resistance": resistance measurement + """ Function to initialize the K2400 SMU with the desired settings + + args: + - source_mode (string) : source mode of the SMU ("current" or "voltage") + - measurement_mode (string) : measurement mode of the SMU ("current", "voltage" or "resistance") + - compliance (scalar) : compliance of the source + - autozero (boolean) : if true, enable autozero of the SMU + - nplc (scalar) : set NPLC to set the integration time for the measurement. For a NPLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec + - digits (int) : display resolution in number of bits + - continuous_trigger (boolean) : if true, the display of the equipment does not freeze after a measurement. When disabled, the instrument operates at a higher speed + - disp_enable (boolean) : if true, enable the front panel display circuitry. When disabled, the instrument operates at a higher speed """ mode_name={"voltage":"VOLT", "current":"CURR", "resistance":"RES"} self.output_state="OFF" @@ -71,20 +74,30 @@ class k2450(equipment.equipment): def read_single(self): + """ Function to read a single measurement data. The output is turn off at the end of the measurement only if continuous_trigger and output_state have been initialized as false and off + + return: + - data (float) : float with the value of the measurement + """ self.pyvisa_resource.write(":OUTP ON") if self.continuous_trigger: self.pyvisa_resource.write(":ABORt") # able continuous triggering - data=self.pyvisa_resource.query("MEAS?") + data=float(self.pyvisa_resource.query("MEAS?")) self.pyvisa_resource.write(":TRIG:LOAD 'LoopUntilEvent', DISP, 0") # able continuous triggering self.pyvisa_resource.write(":INIT") # able continuous triggering else: - data=self.pyvisa_resource.query("MEAS?") + data=float(self.pyvisa_resource.query("MEAS?")) self.pyvisa_resource.write(":OUTP %s"%self.output_state) - return float(data) + return data def set_source(self,value): + """ Function to set the source bias + + args: + - value (scalar) : value of the bias point + """ if self.source_mode=="current": self.pyvisa_resource.write(":SOUR:CURR %E"%value) #set output voltage elif self.source_mode=="voltage": @@ -92,6 +105,11 @@ class k2450(equipment.equipment): def set_output(self,output_state="ON"): + """ Function to set the state of the outpute + + args: + - output_state (string) : "ON" and "OFF" to turn the output on or off + """ self.output_state=output_state self.pyvisa_resource.write(":OUTP %s"%output_state) if self.continuous_trigger: diff --git a/equipment_control/k4200.py b/equipment_control/k4200.py index 76c251cae53ac95c5975644d0a999fe38e69aeed..39349e1c9fde611ef47df9062a24690ab782f01f 100644 --- a/equipment_control/k4200.py +++ b/equipment_control/k4200.py @@ -5,20 +5,33 @@ import numpy as np class k4200(equipment.equipment): - """Class to control HP4145 semiconductor analyzer""" + """Class to control K4200 semiconductor analyzer""" model="K4200" company="Keysight" url="https://www.tek.com/en/products/keithley/4200a-scs-parameter-analyzer" - def initialize(self, smu_type={"SMU1":"voltage","SMU2":"voltage","SMU3":"common","SMU4":"common"}, smu_used={"SMU1":"on","SMU2":"on","SMU3":"on","SMU4":"on"}, - smu_master=1,smu_bias={"SMU1":0,"SMU2":0,"SMU3":0,"SMU4":0}, - smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6},sweep_param={"start":0,"stop":0,"step":0},sweep_type="linear", - integration_mode="IT1",delay_time=0,hold_time=0): + def initialize(self, smu_type={"SMU1":"voltage","SMU2":"voltage","SMU3":"common","SMU4":"common"}, + smu_used={"SMU1":"on","SMU2":"on","SMU3":"on","SMU4":"on"}, + smu_master=1,smu_bias={"SMU1":0,"SMU2":0,"SMU3":0,"SMU4":0}, + smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6}, + sweep_param={"start":0,"stop":0,"step":0}, sweep_type="linear", + integration_mode="S",delay_time=0,hold_time=0): - """ - mode: - - "voltage sweep": voltage sweep with SMU1 and current measurements on all the SMUs + + """ Function to initialize the K4200 equipment with the desired settings + + args: + - smu_type (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias type ("voltage", "current" or "common") + - smu_used (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") if active or not ("on" or "off") + - smu_master (int) : integer to indicate which SMU performs the sweep + - smu_bias (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the bias point (scalar) + - smu_compliance (dictionary) : dictionary indicated for each SMU ("SMU1","SMU2","SMU3" and "SMU4") the compliance (scalar) + - sweep_param (dictionary) : dictionary indicated the starting bias ("start"), the stoping bias ("stop") and step ("step") of the sweep + - sweep_type (string) : string to indicate linear ("linear") sweep or logarithmic ("log") sweep + - integration_mode (string) : set the integration time parameter ("S" for short, "M" for medium and "L" for long) + - delay_time (scalar) : the time to wait between when the output voltage is set and when the measurement is made in a sweep + - hold_time (scalar) : hold time that delays the start of a sweep """ self.smu_type=smu_type self.sweep_type=sweep_type @@ -33,7 +46,8 @@ class k4200(equipment.equipment): index_measurement_type={"sweep":1, "constant":3} index_smu_type={"voltage":1, "current":2, "common":3} - + integration_dictionnary={"S":"IT1","M":"IT2","L":"IT3"} + try: self.pyvisa_resource.write("BC") # clear all buffer. self.pyvisa_resource.write("DR1") # This command enables or disables service request for data ready when communications is set to GPIB. @@ -69,23 +83,11 @@ class k4200(equipment.equipment): elif smu_type["SMU%d"%(smu_index+1)]=="current": self.pyvisa_resource.write("IC%d, %.2f, %.6E"%(smu_index+1,smu_bias["SMU%d"%(smu_index+1)],smu_compliance["SMU%d"%(smu_index+1)])) - self.pyvisa_resource.write("RS 7") # This command sets the measurement resolution for all channels of a SM in number of bits - self.pyvisa_resource.write("RG 1, 10E-12") # This command sets the measurement resolution for all channels of a SM in number of bits - self.pyvisa_resource.write("RG 2, 10E-12") # This command sets the lowest current range of the SMU to be used when measuring. + self.pyvisa_resource.write("HT %f"%hold_time) # Sets a hold time that delays the start of a sweep + self.pyvisa_resource.write("DT %f"%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep. + self.pyvisa_resource.write(integration_dictionnary[integration_mode]) # integration time, IT1/IT2/IT3 : short/medium/long + -# ============================================================================= -# self.pyvisa_resource.write("SM") -# self.pyvisa_resource.write("DM1") -# self.pyvisa_resource.write("XN '%s%d', 1, %.1f, %.1f"%(smu_type["SMU%d"%smu_master][0].upper(),smu_master,sweep_param["start"],sweep_param["stop"])) -# -# list_display="" -# for smu_index in range(4): -# if self.smu_used["SMU%d"%(smu_index+1)]=="on": -# if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": -# self.pyvisa_resource.write("YA '%s%d', 3, 1e-15, 1e-6"%("I",smu_index+1)) -# elif self.smu_type["SMU%d"%(smu_index+1)]=="current": -# self.pyvisa_resource.write("YA '%s%d', 3, 1e-15, 1e-6"%("V",smu_index+1)) -# ============================================================================= self.pyvisa_resource.write("SM") self.pyvisa_resource.write("DM2") list_display="" @@ -101,10 +103,14 @@ class k4200(equipment.equipment): print("/!\ VisaIOError : timeout expired") self.pyvisa_resource.close() - return 42 def launch_measurements(self): + """ Function that launch the measurement and return the data (in array shape) and the header (string) depending on the measurement configuration + return: + - data (array) : array with the measurement data + - header (string) : string with the description of the data column "Vx" or "Ix" for voltage or current measured from SMUx. + """ number_channel=0 for smu_index in range(4): if self.smu_used["SMU%d"%(smu_index+1)]=="on": diff --git a/equipment_control/kal100.py b/equipment_control/kal100.py index d865a498613177662b4583f52761b31a9a23d646..5e87a1164f8b017377b2ba7208617854a6c86c06 100644 --- a/equipment_control/kal100.py +++ b/equipment_control/kal100.py @@ -9,8 +9,12 @@ class kal100(equipment.equipment): company="halstrup-walcher" url="https://www.halstrup-walcher.de/en/products/KAL100.php" - units_dic={"kPa":0,"Pa":1,"hPa":0} def __init__(self,port): + """ Function called when an instance of the class is created + + args: + - port (string) : the computer port to which the equipment is connected + """ self.serial_resource = serial.Serial( port=port, baudrate=9600, @@ -19,33 +23,49 @@ class kal100(equipment.equipment): bytesize=serial.EIGHTBITS ) - def initialize(self,units="kPa",percentage=100, mode_operation="MS", mode_input="MI0"): + def initialize(self,units="kPa",percentage=100, mode_operation="MS", mode_input="positive"): + """ Function to initialize the KAL100 - self.serial_resource.write(">PD%d"%self.units_dic[units]) + args: + - units (string) : "Pa", "kPa" or "hPa" + - percentage (int) : pressure fixed at "percentage" of the targeted value + - mode_operation (string) : mode test ("MT"), mode zeroing ("MZ"), mode target value ("MS"), mode pressure measurement ("MP") + - mode_input (string) : Positive P-input ("positive"), Negative P-input ("negative"), Differential pressure measurement ("differential") + + """ + units_dic={"kPa":0,"Pa":1,"hPa":0} + mode_dic={"positive":"MI0","negative":"MI1","differential":"MI2"} + + self.units=units + self.serial_resource.write(">PD%d"%units_dic[units]) time.sleep(1) - self.serial_resource.write(">PP%d"%percentage) # always 100% of the target + self.serial_resource.write(">PP%d"%percentage) # percentage of the target time.sleep(1) - self.serial_resource.write("%s"%mode_input) # MI0: Positive P-input, MI1: Negative P-input, MI2: Differential pressure measurement + self.serial_resource.write("%s"%mode_dic[mode_input]) # MI0: Positive P-input, MI1: Negative P-input, MI2: Differential pressure measurement time.sleep(1) self.serial_resource.write("MZ") # mode zeroing time.sleep(1) - self.serial_resource.write("%s"%mode_operation) #MT: mode test, MZ: mode zeroing, MS: mode target value, MS: mode pressure measurement, + self.serial_resource.write("%s"%mode_operation) #MT: mode test, MZ: mode zeroing, MS: mode target value, MP: mode pressure measurement time.sleep(1) if mode_operation=="MS": - self.serial_resource.write("PS%3.5f"%0) #MT: mode test, MZ: mode zeroing, MS: mode target value, MS: mode pressure measurement, + self.serial_resource.write("PS%3.5f"%0) time.sleep(1) - def set_pressure(self,pressure, units="kPa"): + def set_pressure(self,pressure): + """ Function to set pressure level of the KAL100 + + args: + - pressure (scalar) : targeted pressure + """ self.serial_resource.write("MS") time.sleep(1) - self.serial_resource.write(">PD%d"%self.units_dic[units]) - time.sleep(1) - self.serial_resource.write("PS%3.5f"%0) #MT: mode test, MZ: mode zeroing, MS: mode target value, MS: mode pressure measurement, + self.serial_resource.write("PS%3.5f"%pressure) time.sleep(1) def close_connection(self): + """ Function to close the serial connection with the equipment """ self.serial_resource.close() diff --git a/equipment_control/sh242.py b/equipment_control/sh242.py index 7b31140340e4edffc66e346ba6c6c7993c937d98..dff6c7be4fd2d0a8a5b56c9d2bbff7edaebcec87 100644 --- a/equipment_control/sh242.py +++ b/equipment_control/sh242.py @@ -7,19 +7,19 @@ class sh242(equipment.equipment): """Class to control SH242 climatic chamber""" model="SH242" company="ESPEC" - url="https://espec.com/na/products/model/sh_242" - - -# ============================================================================= -# mysh242.read_termination = ';' -# mysh242.write_termination = ';' -# mysh242.timeout=300*1000 -# ============================================================================= - + url="https://espec.com/na/products/model/sh_242" def initialize(self,temperature=True, humidity=False,temperature_dic={"upper":125,"lower":-45,"set":20},humidity_dic={"upper":100,"lower":0,"set":55}): + """ Function to initialize the SH242 + args: + - temperature (boolean) : if True, activate the temperature control + - humidity (boolean) : if True, activate the humidity control + - temperature_dic (dictionary) : dictionnary with the upper ("upper") and lower ("lower") alarm and the initial set point ("set") for the temperature + - humidity_dic (dictionary) : dictionnary with the upper ("upper") and lower ("lower") alarm and the initial set point ("set") for the humidity + """ + self.set_connection_parameter_dic({"write_termination":';',"read_termination":';',"send_end":True}) self.pyvisa_resource.write('POWER, ON') @@ -61,12 +61,23 @@ class sh242(equipment.equipment): self.pyvisa_resource.read() def read_temperature(self): + """ Function to read the temperature of the climatic chamber + + return: + - temperature (scalar) : temperature of the chamber + """ + self.pyvisa_resource.write('TEMP?') time.sleep(0.5) temperature=self.pyvisa_resource.read() return temperature def read_humidity(self): + """ Function to read the humidity of the climatic chamber + + return: + - humidity (scalar) : humidity of the chamber + """ self.pyvisa_resource.write('HUMI?') time.sleep(0.5) humidity=self.pyvisa_resource.read() @@ -74,6 +85,15 @@ class sh242(equipment.equipment): def set_temperature(self,temperature,waiting_time=0,wait_for_stabilization=False,stabilization_tolerance=0.1,stabilization_number=10): + """ Function to set the temperature of the climatic chamber + + return: + - temperature (scalar) : targeted temperature of the chamber + - waiting_time (scalar) : time in seconds to wait before after changing the temperature target. If a waiting for the stabilization is required, the waiting time happens before. + - wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within "stabilization_tolerance" over "stabilization_number" cycles of 5 seconds + - stabilization_tolerance (scalar) : the tolerance in °C to consider the temperature of the chamber close enough to the targeted temperature + - stabilization_number (int) : number of cycles to be checked to consider the temperature as stabilized + """ self.pyvisa_resource.write("TEMP, S%.2f"%temperature) #Changes the temperature set point in constant setup time.sleep(1) self.pyvisa_resource.read() @@ -96,6 +116,15 @@ class sh242(equipment.equipment): def set_humidity(self,humidity,waiting_time=0,wait_for_stabilization=False,stabilization_tolerance=0.5,stabilization_number=1): + """ Function to set the humidity of the climatic chamber + + return: + - humidity (scalar) : targeted humidity of the chamber + - waiting_time (scalar) : time in seconds to wait before after changing the humidity target. If a waiting for the stabilization is required, the waiting time happens before. + - wait_for_stabilization (boolean) : if True, the function wait that the chamber has stabilized within "stabilization_tolerance" over "stabilization_number" cycles of 5 seconds + - stabilization_tolerance (scalar) : the tolerance in % to consider the humidity of the chamber close enough to the targeted humidity + - stabilization_number (int) : number of cycles to be checked to consider the humidity as stabilized + """ self.pyvisa_resource.write("HUMI, S%.2f"%humidity) #Changes the temperature set point in constant setup time.sleep(1) self.pyvisa_resource.read()