diff --git a/hp4155/hp4155a.py b/hp4155/hp4155a.py index e6d32d16809b195bf4f3351501e7a277ed8239d1..854256c527ba72d25feb234d54360736024beb66 100644 --- a/hp4155/hp4155a.py +++ b/hp4155/hp4155a.py @@ -101,6 +101,15 @@ class HP4155a(object): command = f":PAGE:MEAS:VARD:OFFS {vard['offset']};RAT {vard['ratio']};COMP {vard['comp']};PCOM {vard['pcomp']}" self.inst.write(command) + def setup_pulse(self,pulse:dict): + command = f":PAGE:MEAS:PULS:BASE {pulse['base']};PER {pulse['period']};WIDTH {pulse['width']}" + self.inst.write(command) + + #for pulse + def range_mode(self,smu_number,range): + command = f":PAGE:MEAS:MSET:SMU{smu_number}:RANG:MODE {range}" + self.inst.write(command) + #----------------------------------------------------------------------sampling measure functions part2 first goal---------------------------- def setup_sampling(self,parameters:dict): command = f"PAGE:MEAS:SAMP:MODE {parameters['mode']};HTIM {parameters['hold']};IINT {parameters['interval']};POIN {parameters['points']};FILT {parameters['filter']}" @@ -250,6 +259,11 @@ class HP4155a(object): keys =('mode','interval','hold','points','filter') parameters = dict.fromkeys(keys) return parameters + + def pulse_dict(self): + keys = ('base','width','period') + parameters = dict.fromkeys(keys) + return parameters diff --git a/hp4155/memristor (Version 4.0)/help.py b/hp4155/memristor (Version 4.0)/help.py index 5235e0710e17554b787559605811737ee5db2452..c8560119cb55cf35231537fde39a8a5b8cb3861b 100644 --- a/hp4155/memristor (Version 4.0)/help.py +++ b/hp4155/memristor (Version 4.0)/help.py @@ -14,7 +14,6 @@ import sys sys.path.insert(0, '..') #append parent directory import hp4155a -import module import matplotlib.pyplot as plt import tkinter as tk @@ -30,260 +29,144 @@ import time import os -#these are the quick sampling checks +#contact check between two SMUs (i,j) +def contact_check(i,j,device): + smu = [1,2,3,4] + device.measurement_mode('SAMP') + parameters ={ + 'mode' : 'LIN', + 'hold': 0, + 'interval':2e-3, + 'points': 1, + 'filter': 'OFF', + 'value':0.01, #voltage value + 'comp':0.1 #compliance value + } + + device.setup_sampling(parameters) + + device.auto_sampling_time('ON') + device.integration_time('MED') + + smu_v = device.smu_dict() + smu_v.update( + vname = f'V{i}', + iname = f'I{i}', + mode = 'V', + func = 'CONS' + ) + device.setup_smu(i,smu_v) + + smu_ground = device.smu_dict() + smu_ground.update( + vname =f'V{j}', + iname = f'I{j}', + mode = 'COMM', + func='CONS' + ) + device.setup_smu(j,smu_ground) + + #one smu is measuring + #one smu is ground + + #set voltage and compliance + device.setup_smu_sampling(i,parameters) + + #smus to remove + smu_disable = smu.copy() + smu_disable.remove(i) + smu_disable.remove(j) + + for number in smu_disable: + device.smu_disable(number) + + device.user_function(f'R{i}{j}','OHM',f'V{i}/I{i}') + device.display_variable('X','@TIME') + device.display_variable('Y1',f'R{i}{j}') + device.single_measurement() + while device.operation_completed() == False: + time.sleep(2) + + device.autoscaling() + R = device.return_values(f'R{i}{j}')[0] #only the first value + print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") + device.del_user_functions() + return R + + +#these are all the sampling checks def regular_contact_check(device): resistances = {} - - smu = [1,2,3,4] for i in range(1,4): # iterate through smus 1-4 for j in range(4,i,-1): """ We have the following pairs in order 1-4,1-3,1-2,2-4,2-3,3-4 """ - - device.measurement_mode('SAMP') - parameters ={ - 'mode' : 'LIN', - 'hold': 0, - 'interval':2e-3, - 'points': 1, - 'filter': 'OFF', - 'value':0.01, #voltage value - 'comp':0.1 #compliance value - } - - device.setup_sampling(parameters) - - device.auto_sampling_time('ON') - device.integration_time('MED') - - smu_v = device.smu_dict() - smu_v.update( - vname = f'V{i}', - iname = f'I{i}', - mode = 'V', - func = 'CONS' - ) - device.setup_smu(i,smu_v) - - smu_ground = device.smu_dict() - smu_ground.update( - vname =f'V{j}', - iname = f'I{j}', - mode = 'COMM', - func='CONS' - ) - device.setup_smu(j,smu_ground) - - #one smu is measuring - #one smu is ground - - #set voltage and compliance - device.setup_smu_sampling(i,parameters) - - #smus to remove - smu_disable = smu.copy() - smu_disable.remove(i) - smu_disable.remove(j) - - for number in smu_disable: - device.smu_disable(number) - - device.user_function(f'R{i}{j}','OHM',f'V{i}/I{i}') - device.display_variable('X','@TIME') - device.display_variable('Y1',f'R{i}{j}') - device.single_measurement() - while device.operation_completed() == False: - time.sleep(2) - - device.autoscaling() - R = device.return_values(f'R{i}{j}')[0] #only the first value - print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") + R=contact_check(i,j,device) resistances[f"{i}-{j}"] = R - - device.del_user_functions() - return resistances def EBL(device): # EBL are SMUs 1-4 and 2-3 resistances = {} - smu = [1,2,3,4] - for i,j in zip(range(1,3),range(4,2,-1)): #loop simultaneously 1-4,2-3 pairs - device.measurement_mode('SAMP') - parameters ={ - 'mode' : 'LIN', - 'hold': 0, - 'interval':2e-3, - 'points': 1, - 'filter': 'OFF', - 'value':0.01, #voltage value - 'comp':0.1 #compliance value - } - - device.setup_sampling(parameters) - - device.auto_sampling_time('ON') - device.integration_time('MED') - - smu_v = device.smu_dict() - smu_v.update( - vname = f'V{i}', - iname = f'I{i}', - mode = 'V', - func = 'CONS' - ) - device.setup_smu(i,smu_v) - - smu_ground = device.smu_dict() - smu_ground.update( - vname =f'V{j}', - iname = f'I{j}', - mode = 'COMM', - func='CONS' - ) - device.setup_smu(j,smu_ground) - - #one smu is measuring - #one smu is ground - - #set voltage and compliance - device.setup_smu_sampling(i,parameters) - - #smus to remove - smu_disable = smu.copy() - smu_disable.remove(i) - smu_disable.remove(j) - - for number in smu_disable: - device.smu_disable(number) - - device.user_function(f'R{i}{j}','OHM',f'V{i}/I{i}') - device.display_variable('X','@TIME') - device.display_variable('Y1',f'R{i}{j}') - device.single_measurement() - while device.operation_completed() == False: - time.sleep(2) - - device.autoscaling() - R = device.return_values(f'R{i}{j}')[0] #only the first value - print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") + R = contact_check(i,j,device) resistances[f"{i}-{j}"] = R - - device.del_user_functions() - return resistances - - - + def OL(device): # OL smu 3-4,1-2 - resistances= {} - smu = [1,2,3,4] - for i,j in zip(range(3,0,-2),range(4,1,-2)): #loop simultaneously 3-4 , 1-2 pairs - device.measurement_mode('SAMP') - parameters ={ - 'mode' : 'LIN', - 'hold': 0, - 'interval':2e-3, - 'points': 1, - 'filter': 'OFF', - 'value':0.01, #voltage value - 'comp':0.1 #compliance value - } - - device.setup_sampling(parameters) - - device.auto_sampling_time('ON') - device.integration_time('MED') - - smu_v = device.smu_dict() - smu_v.update( - vname = f'V{i}', - iname = f'I{i}', - mode = 'V', - func = 'CONS' - ) - device.setup_smu(i,smu_v) - - smu_ground = device.smu_dict() - smu_ground.update( - vname =f'V{j}', - iname = f'I{j}', - mode = 'COMM', - func='CONS' - ) - device.setup_smu(j,smu_ground) - - #one smu is measuring - #one smu is ground - - #set voltage and compliance - device.setup_smu_sampling(i,parameters) - - #smus to remove - smu_disable = smu.copy() - smu_disable.remove(i) - smu_disable.remove(j) - - for number in smu_disable: - device.smu_disable(number) - - device.user_function(f'R{i}{j}','OHM',f'V{i}/I{i}') - device.display_variable('X','@TIME') - device.display_variable('Y1',f'R{i}{j}') - device.single_measurement() - while device.operation_completed() == False: - time.sleep(2) - - device.autoscaling() - R = device.return_values(f'R{i}{j}')[0] #only the first value - print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") - resistances[f"{i}-{j}"] = R - - device.del_user_functions() - + R = contact_check(i,j,device) + resistances[f"{i}-{j}"] = R return resistances #double sweep from start to stop and then from start to stop -def sweep(start,stop,step,comp,integration,device): - device.measurement_mode('SWE') - - #changed smu2 is source and 4 is ground - #smu2 is constant and common - device.smu_mode_meas(4,'COMM') - device.smu_function_sweep(4,'CONS') - - #smu4 is VAR1 and V - device.smu_mode_meas(2,'V') - device.smu_function_sweep(2,'VAR1') - - device.integration_time(integration) - - #define double sweep - device.var1_mode('DOUB') - - #start stop step and comp - device.start_value_sweep(start) - #time.sleep(5) - device.stop_value_sweep(stop) - #time.sleep(5) - +def sweep(start,stop,step,comp,integration,device): #step cannot be negative if start < stop and step < 0 : step = -step elif start > stop and step > 0 : step = -step - - device.step_sweep(step) - #time.sleep(5) - device.comp('VAR1',comp) + smu_v = device.smu_dict() + smu_ground = device.smu_dict() + parameters = device.var1_dict() + + smu_v.update( + iname = 'I2', + vname = 'V2', + mode = 'V', + func = 'VAR1' + ) + smu_ground.update( + iname ='I4', + vname = 'V4', + mode = 'COMM', + func = 'CONS' + ) + parameters.update( + mode ='DOUB', + start = start, + stop = stop, + step = step, + comp = comp, + pcomp = 0 + ) + + #disable smus 1 and 3 + device.measurement_mode('SWE') + device.smu_disable(1) + device.smu_disable(3) + + device.setup_smu(2,smu_v) + device.setup_smu(4,smu_ground) + device.setup_var1(parameters) + device.integration_time(integration) + #display variables device.display_variable('X','V2') device.display_variable('Y1','I2') @@ -296,8 +179,8 @@ def sweep(start,stop,step,comp,integration,device): device.autoscaling() #return values - V=device.return_data('V2') - I=device.return_data('I2') + V=device.return_values('V2') + I=device.return_values('I2') #convert the list to np.array to return the absolute values for the logarithmic scale V = np.array(V) @@ -309,25 +192,48 @@ def sweep(start,stop,step,comp,integration,device): #sampling check def sampling_check(voltage,device): # red color code red = '\033[91m' + parameters ={ + 'mode' : 'LIN', + 'hold': 0, + 'interval':2e-3, + 'points': 5, + 'filter': 'OFF', + 'value':voltage, #voltage value + 'comp':0.1 #compliance value + } + smu_v = device.smu_dict() + smu_ground = device.smu_dict() + + + smu_v.update( + iname = 'I2', + vname = 'V2', + mode = 'V', + func = 'CONS' + ) + smu_ground.update( + iname ='I4', + vname = 'V4', + mode = 'COMM', + func = 'CONS' + ) device.measurement_mode('SAMP') - - device.smu_mode_meas(2,'V') - device.smu_mode_meas(4,'COMM') + device.smu_disable(1) + device.smu_disable(3) + device.setup_smu(2,smu_v) + device.setup_smu(4,smu_ground) - #set voltage and compliance - device.constant_smu_sampling(2,voltage) - device.constant_smu_comp(2,'MAX') + device.setup_smu_sampling(2,parameters) + device.setup_sampling(parameters) - device.sampling_mode('LIN') - device.number_of_points(5) device.integration_time('LONG') - device.initial_interval(2e-3) - device.filter_status('OFF') - + #remove total sampling time device.auto_sampling_time('ON') + device.user_function('R','OHM','V2/I2') + device.display_variable('X','@TIME') device.display_variable('Y1','R') device.single_measurement() @@ -335,39 +241,61 @@ def sampling_check(voltage,device): time.sleep(2) device.autoscaling() - try: - TIME = device.return_data('@TIME') - R = device.return_data('R') - TIME = np.array(TIME) - R = np.array(R) - R_mean = np.average(R) - return R_mean - except: - return 0 + R = device.return_values('R') + R = np.array(R) + R_mean = np.average(R) + device.del_user_functions() + return R_mean + #new (retention) def retention(voltage,period,duration,device): - device.measurement_mode('SAMP') + parameters ={ + 'mode' : 'LIN', + 'hold': 0, + 'interval':2e-3, + 'points': 0, + 'filter': 'OFF', + 'value':voltage, #voltage value + 'comp':0.1 #compliance value + } + smu_v = device.smu_dict() + smu_ground = device.smu_dict() + + smu_v.update( + iname = 'I2', + vname = 'V2', + mode = 'V', + func = 'CONS' + ) + smu_ground.update( + iname ='I4', + vname = 'V4', + mode = 'COMM', + func = 'CONS' + ) - device.smu_mode_meas(2,'V') - device.smu_mode_meas(4,'COMM') - - #set voltage and compliance - device.constant_smu_sampling(2,voltage) - device.constant_smu_comp(2,'MAX') + device.measurement_mode('SAMP') + device.smu_disable(1) + device.smu_disable(3) + device.setup_smu(2,smu_v) + device.setup_smu(4,smu_ground) - device.sampling_mode('LIN') - device.initial_interval(period) + device.setup_smu_sampling(2,parameters) + device.integration_time('LONG') device.total_sampling_time(duration) if int(duration/period)+1<=10001: - device.number_of_points(int(duration/period)+1) + parameters.update(points=int(duration/period)+1) else: - device.number_of_points('MAX') + parameters.update(points = 'MAX') + device.setup_sampling(parameters) + device.integration_time('MED') - device.filter_status('OFF') - + device.user_function('R','OHM','V2/I2') + + device.display_variable('X','@TIME') device.display_variable('Y1','R') device.single_measurement() @@ -375,14 +303,12 @@ def retention(voltage,period,duration,device): time.sleep(2) device.autoscaling() - try: - TIME = device.return_data('@TIME') - R = device.return_data('R') - TIME = np.array(TIME) - R = np.array(R) - return TIME,R - except: - return 0,0 + TIME = device.return_values('@TIME') + R = device.return_values('R') + TIME = np.array(TIME) + R = np.array(R) + device.del_user_functions() + return TIME,R #plot sweep results @@ -563,28 +489,6 @@ def upload_results(source_file,target_file,target_file_dir): #and then try again -#setup device for regular memristor measurement -def setup_memristor(): - #connect to the device - device = module.HP4155a('GPIB0::17::INSTR') - device.reset() - - #disable all irrelevant units for the measurement - #smu1 and smu3 are disabled - device.smu_disable_sweep(1) - device.smu_disable_sweep(3) - - #disable vmus and vsus - device.disable_vsu(1) - device.disable_vsu(2) - device.disable_vmu(1) - device.disable_vmu(2) - - # R user function - device.user_function('R','OHM','V2/I2') - - return device - def save_contact_check(R,file): #save contact check to file """ Parameters: diff --git a/hp4155/memristor (Version 4.0)/help_pulse.py b/hp4155/memristor (Version 4.0)/help_pulse.py index ce69d42678070a3ececb8519c5050cef52678813..dac0bb619e6e5c0ece49eeeb5a7c0bd252e2265e 100644 --- a/hp4155/memristor (Version 4.0)/help_pulse.py +++ b/hp4155/memristor (Version 4.0)/help_pulse.py @@ -36,33 +36,42 @@ def check_pulse(dictionary): #sweep pulse measurement -def sweep_meas(dict): - device = module.HP4155a('GPIB0::17::INSTR') - device.reset() - device.smu_disable_sweep(1) - device.smu_disable_sweep(3) - - #disable vmus and vsus - device.disable_vsu(1) - device.disable_vsu(2) - device.disable_vmu(1) - device.disable_vmu(2) - - device.measurement_mode("SWE") - device.smu_function_sweep(2,"VAR1") - device.smu_mode_meas(4,"COMMON") - device.smu_function_sweep(4,"CONS") - - device.smu_mode_meas(2,"VPULSE") - device.start_value_sweep(dict["start"].value) - device.stop_value_sweep(dict["stop"].value) +def sweep_meas(dict,device): + smu_v = device.smu_dict() + smu_ground = device.smu_dict() + parameters = device.var1_dict() + + smu_v.update( + iname = 'I2', + vname = 'V2', + mode = 'VPULSE', + func = 'VAR1' + ) + smu_ground.update( + iname ='I4', + vname = 'V4', + mode = 'COMM', + func = 'CONS' + ) + parameters.update( + mode ='SING', + start = dict['start'].value, + stop = dict['stop'].value, + step = dict["stop"].value-dict["start"].value)/(dict["pulses"].value-1, #define the number of steps given specific pulses + comp = dict["comp"].value, + pcomp = 0, + base = dict["base"].value, + width = dict["width"].value, + period= dict["period"].value + ) + device.smu_disable(1) + device.smu_disable(3) - #define the number of steps given specific pulses - - step = (dict["stop"].value-dict["start"].value)/(dict["pulses"].value-1) - device.step_sweep(step) - device.comp("VAR1",dict["comp"].value) + device.measurement_mode("SWE") + device.setup_smu(2,smu_v) + device.setup_smu(4,smu_ground) + device.setup_var1(parameters) device.display_variable("X","V2") device.display_variable("Y1",'I2') @@ -70,9 +79,8 @@ def sweep_meas(dict): device.range_mode(4,"AUTO") device.range_mode(2,"AUTO") - device.pulse_base(dict["base"].value) - device.pulse_width(dict["width"].value) - device.pulse_period(dict["period"].value) + device.setup_pulse(parameters) + device.integration_time(dict["integration"].value) t0 = time.time() @@ -85,8 +93,8 @@ def sweep_meas(dict): elapsed_time = t1 - t0 device.autoscaling() - I_i=device.return_data("I2") - V_i=device.return_data("V2") + I_i=device.return_values("I2") + V_i=device.return_values("V2") R_i = np.divide(V_i,I_i) @@ -149,55 +157,70 @@ def save_sweep(folder,sample_dict,values,times,sweep_dict): f.write(df.to_string()) f.write("\n\n\n") -def constant_meas(dict): - device = module.HP4155a('GPIB0::17::INSTR') - device.reset() - device.user_function('V','V','V2') - device.user_function('I','A','I2') - - #disable vmus and vsus - device.disable_vsu(1) - device.disable_vsu(2) - device.disable_vmu(1) - device.disable_vmu(2) - device.smu_disable_sweep(1) - #device.smu_disable_sweep(3) +def constant_meas(dict,device): + smu_v = device.smu_dict() + smu_ground = device.smu_dict() + sweep_params = device.var1_dict() + smu_help = device.smu_dict() #this is the uncontacted smu + + smu_v.update( + iname = 'I2', + vname = 'V2', + mode = 'V', + func = 'CONS' + ) + smu_help.update( + iname = 'I3', + vname = 'V3', + mode = 'V', + func = 'VAR1' + ) + smu_ground.update( + iname ='I4', + vname = 'V4', + mode = 'COMM', + func = 'CONS' + ) + sweep_params.update( + mode ='SING', + start = 0, + stop = 10, + step = 10/(dict["pulses"].value-1, #define the number of steps given specific pulses + comp = 0.1, + pcomp = 0, + base = dict["base"].value, + width = dict["width"].value, + period= dict["period"].value + ) + #the constant smu + cons = { + 'value':dict["voltage"].value, + 'comp':dict["comp"].value + } device.measurement_mode("SWE") - device.smu_mode_meas(2,"VPULSE") - device.smu_function_sweep(2,'CONS') - device.smu_mode_meas(4,"COMM") - device.smu_function_sweep(2,"CONS") - device.smu_function_sweep(4,'CONS') - - #smu 3 is used to define the number of pulses not contacted - device.smu_mode_meas(3,'V') - device.smu_function_sweep(3,"VAR1") - - device.start_value_sweep(0) - device.stop_value_sweep(10) - - #define the number of steps given specific pulses - step = 10/(dict["pulses"].value-1) - device.step_sweep(step) + device.smu_disable(1) + device.setup_smu(2,smu_v) + device.setup_smu(3,smu_help) + device.setup_smu(4,smu_ground) + device.setup_var1(sweep_params) + device.setup_pulse(sweep_params) + device.setup_cons_smu(2,cons) - device.comp("VAR1","MAX") - device.const_comp(2,dict["comp"].value) - - device.cons_smu_value(2,dict["voltage"].value) + device.user_function('R','OHM','V2/I2') device.display_variable("X","@INDEX") - device.display_variable("Y1",'I') + device.display_variable("Y1",'R') device.range_mode(4,"AUTO") device.range_mode(2,"AUTO") device.range_mode(3,"AUTO") - device.pulse_base(dict["base"].value) - device.pulse_width(dict["width"].value) - device.pulse_period(dict["period"].value) + device.integration_time(dict["integration"].value) + device.variables_to_save(['@INDEX','V2','I2','R']) + t0 = time.time() device.single_measurement() while device.operation_completed()== False: @@ -208,9 +231,9 @@ def constant_meas(dict): elapsed_time = t1 - t0 device.autoscaling() - I_i=device.return_data("I") - V_i=device.return_data("V") - R_i = np.divide(V_i,I_i) + I_i=device.return_values("I2") + V_i=device.return_values("V2") + R_i = device.return_values('R') expected_time = dict["period"].value*dict["pulses"].value @@ -218,7 +241,7 @@ def constant_meas(dict): times = (elapsed_time,expected_time) values = (V_i,I_i,R_i) - del device + device.del_user_functions() return times,values