From 92d185d128839e0ab591aa3237b4a065cc89ba74 Mon Sep 17 00:00:00 2001 From: unknown <asoalexandros@gmail.com> Date: Mon, 25 Nov 2024 13:06:06 +0100 Subject: [PATCH] changes memrsistor 1-6 --- hp4155/memristor (Version 4.0)/help.py | 168 +++++++++++++++++--- hp4155/memristor (Version 4.0)/memristor.py | 117 +++++++++++--- 2 files changed, 239 insertions(+), 46 deletions(-) diff --git a/hp4155/memristor (Version 4.0)/help.py b/hp4155/memristor (Version 4.0)/help.py index 96851a5..4421447 100644 --- a/hp4155/memristor (Version 4.0)/help.py +++ b/hp4155/memristor (Version 4.0)/help.py @@ -30,9 +30,11 @@ import os #these are the quick sampling checks -def test_contacts(): +def regular_contact_check(): device = module.HP4155a('GPIB0::17::INSTR') + resistances = {} + smu = [1,2,3,4] for i in range(1,4): # iterate through smus 1-4 for j in range(4,i,-1): @@ -82,12 +84,128 @@ def test_contacts(): V = device.return_data(f'V{i}') I = device.return_data(f'I{i}') R = V[0]/I[0] - print(f"R{i}{j}:{R} Ohm") + print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") + resitances[f"{i}-{j}"] = R #print(f"Contact check of smu{i} and smu{j} failed!") del device + return resistances + +def EBL(): + # EBL are SMUs 1-4 and 2-3 + device = module.HP4155a('GPIB0::17::INSTR') + resistances = {} + + for i,j in zip(range(1,3),range(4,2,-1)): #loop simultaneously 1-4,2-3 pairs + device.reset() + + device.measurement_mode('SAMP') + device.sampling_mode('LIN') + device.number_of_points(1) + device.integration_time('MED') + device.initial_interval(2e-3) + device.filter_status('OFF') + #remove total sampling time + device.auto_sampling_time('ON') + + #disable vmus and vsus + device.disable_vsu(1) + device.disable_vsu(2) + device.disable_vmu(1) + device.disable_vmu(2) + + + + device.smu_mode_meas(i,'V') #one smu is measuring + device.smu_mode_meas(j,'COMM') #one smu is ground + + #set voltage and compliance + device.constant_smu_sampling(i,0.01) + device.constant_smu_comp(i,'MAX') + + #smus to remove + smu_disable = smu.copy() + smu_disable.remove(i) + smu_disable.remove(j) + + for number in smu_disable: + device.smu_disable_sweep(number) + + device.display_variable('X','@TIME') + device.display_variable('Y1',f'I{i}') + device.single_measurement() + while device.operation_completed() == False: + time.sleep(2) + + device.autoscaling() + V = device.return_data(f'V{i}') + I = device.return_data(f'I{i}') + R = V[0]/I[0] + print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") + resitances[f"{i}-{j}"] = R + + del device + return resistances + + +def OL(): + # OL smu 3-4,1-2 + + device = module.HP4155a('GPIB0::17::INSTR') + resistances= {} + + for i,j in zip(range(3,0,-2),range(4,1,-2)): #loop simultaneously 3-4 , 1-2 pairs + device.reset() + + device.measurement_mode('SAMP') + device.sampling_mode('LIN') + device.number_of_points(1) + device.integration_time('MED') + device.initial_interval(2e-3) + device.filter_status('OFF') + #remove total sampling time + device.auto_sampling_time('ON') + + #disable vmus and vsus + device.disable_vsu(1) + device.disable_vsu(2) + device.disable_vmu(1) + device.disable_vmu(2) + + + + device.smu_mode_meas(i,'V') #one smu is measuring + device.smu_mode_meas(j,'COMM') #one smu is ground + #set voltage and compliance + device.constant_smu_sampling(i,0.01) + device.constant_smu_comp(i,'MAX') + + #smus to remove + smu_disable = smu.copy() + smu_disable.remove(i) + smu_disable.remove(j) + + for number in smu_disable: + device.smu_disable_sweep(number) + + device.display_variable('X','@TIME') + device.display_variable('Y1',f'I{i}') + device.single_measurement() + while device.operation_completed() == False: + time.sleep(2) + + device.autoscaling() + V = device.return_data(f'V{i}') + I = device.return_data(f'I{i}') + R = V[0]/I[0] + print(f"R{i}{j}:{'{:.2e}'.format(R)} Ohm") + resitances[f"{i}-{j}"] = R + + del device + return resistances + #double sweep from start to stop and then from start to stop def sweep(start,stop,step,comp,integration,device): @@ -146,6 +264,7 @@ def sweep(start,stop,step,comp,integration,device): #sampling check def sampling_check(voltage,device): + # red color code red = '\033[91m' device.measurement_mode('SAMP') @@ -158,7 +277,7 @@ def sampling_check(voltage,device): device.sampling_mode('LIN') device.number_of_points(5) - device.integration_time('MED') + device.integration_time('LONG') device.initial_interval(2e-3) device.filter_status('OFF') @@ -370,26 +489,6 @@ def choose_folder(): root.destroy() return folder - - -#create or append to file a new measurement(now locally) we dont need that anymore!!! -def create_remote_file(sample_series,field,DUT,folder): - filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" - file=os.path.join(folder,filename)#the whole file with location - date = str(datetime.today().replace(microsecond=0)) - - #check loop (once the return is called the function is over) - while True: - try:#you cannot write in every directory - with open(file,'a') as f: - title = f"Memristor Measurement"+"\n\n"+f"Sample series:{sample_series.value}" +"\n"+f"field:{field.value}"+"\n"+f"DUT:{DUT.value}"+"\n"+f"Date:{date}"+"\n\n" - f.write(title) - return file - except: - information_box(f"You cannot write in the directory: {folder}!") - #again - folder=choose_folder() - file=os.path.join(folder,filename)#the whole file with location #write the header @@ -440,4 +539,25 @@ def setup_memristor(): # R user function device.user_function('R','OHM','V2/I2') - return device \ No newline at end of file + return device + +def save_contact_check(R,file): #save contact check to file + """ + Parameters: + -Resistances list + -File to save + """ + + with open(file,'a') as f: + f.write("\n\nContact Check Results:\n") + + df = pd.DataFrame(R.items(), columns=['SMU pair', 'Resistance (Ohm)']) + f.write(df.to_string()) + f.write("\n\n") + + + + + + + \ No newline at end of file diff --git a/hp4155/memristor (Version 4.0)/memristor.py b/hp4155/memristor (Version 4.0)/memristor.py index 9b4fc48..094bba7 100644 --- a/hp4155/memristor (Version 4.0)/memristor.py +++ b/hp4155/memristor (Version 4.0)/memristor.py @@ -87,6 +87,8 @@ full=widgets.Button(description='FULL SWEEP') number = widgets.BoundedIntText(value=1,min=1,max=sys.maxsize,step=1,description='full sweeps:',disabled=False) #number of measuremts for the full sweep retention_button=widgets.Button(description='RETENTION') contact_check = widgets.Button(description = 'CONTACT CHECK') +qcc = widgets.Button(description = 'QUICK CONTACT CHECK') +qcc_select = widgets.RadioButtons(description = 'QCC type:',options = ['EBL','OL']) #parameter boxes @@ -149,6 +151,12 @@ duration=widgets.BoundedFloatText( description='Duration(s):', ) +auto_qcc = widgets.Checkbox( + description = 'Auto QCC after Reset:', + style = {'description_width': 'initial'}, + value = True +) + #align a button with a checkbox or integer bounded texts horizontaly line1 = widgets.HBox([set,Vset,CC_vset]) line2 = widgets.HBox([reset,Vreset,CC_vreset]) @@ -162,8 +170,8 @@ output = widgets.Output() #help lists for changing state of the buttons information = [sample_series,field,DUT] -buttons = [set,reset,full,new,new_folder,retention_button,contact_check] -parameters = [Vset,CC_vset,Vreset,CC_vreset,step,integration_time,number,sampling,Vretention,period,duration] +buttons = [set,reset,full,new,new_folder,retention_button,contact_check,qcc,qcc_select] +parameters = [Vset,CC_vset,Vreset,CC_vreset,step,integration_time,number,sampling,Vretention,period,duration,auto_qcc] #choose folder directory folder=choose_folder() @@ -171,10 +179,9 @@ folder=choose_folder() #display all at the end display(all_text_boxes) -print() -display(contact_check) -print() +hbox = widgets.HBox([contact_check,qcc,qcc_select]) #HBox wirth contact checks +display(hbox) cons_widgets,cons_dict = constant_pulse() sweep_widgets,sweep_dict = sweep_pulse() @@ -199,19 +206,73 @@ add_widgets_to_list(sweep_dict,all_widgets) """ the above is what happens when the programm starts all the rest have to be written into button trigger functions""" def on_contact_check_clicked(b): + global first,folder,file,temp_file with output: + global first,folder,file,temp_file clear_output(wait = True) change_state(all_widgets) change_state(buttons) change_state(parameters) - test_contacts() + #during first button press + if first == True: + change_state(information)#disable all widgets that are relevant about the information of the sample + filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" + file = os.path.join(folder,filename) + #write header to temp_file + write_header(temp_file,sample_series,field,DUT) + first = False + + R = regular_contact_check() + + save_contact_check(R,temp_file) + + + #upload results + temp_file,file,folder=upload_results(temp_file,file,folder) information_box("Contact Check Completed") change_state(all_widgets) change_state(buttons) change_state(parameters) + +def on_qcc_clicked(b): + global first,folder,file,temp_file + with output: + global first,folder,file,temp_file + clear_output(wait = True) + change_state(all_widgets) + change_state(buttons) + change_state(parameters) + + #during first button press + if first == True: + change_state(information)#disable all widgets that are relevant about the information of the sample + filename=f"{sample_series.value}_{field.value}_{DUT.value}.txt" + file = os.path.join(folder,filename) + #write header to temp_file + write_header(temp_file,sample_series,field,DUT) + first = False + + + if qcc_select.value == 'EBL': + R = EBL() + else: # OL + R = OL() + + save_contact_check(R,temp_file) + + + #upload results + temp_file,file,folder=upload_results(temp_file,file,folder) + + information_box("Quick Contact Check Completed") + + change_state(all_widgets) + change_state(buttons) + change_state(parameters) + def on_set_button_clicked(b): global first,folder,file,temp_file @@ -242,9 +303,8 @@ def on_set_button_clicked(b): if valid == True: if sampling.value == True: #do sampling set before set process(100mV) - R_mean_before = sampling_check(0.1,device) - R_mean_before = round(R_mean_before,1)#round 1 decimal point - print(f"Average Resistance(Sampling Check):{R_mean_before:e} Ohm") + R_mean_before = sampling_check(-0.01,device) + print(f"Average Resistance(Sampling Check):{'{:.2e}'.format(R_mean_before)} Ohm") first_sampling = False #execute measurement,plot results and save them @@ -256,8 +316,7 @@ def on_set_button_clicked(b): if sampling.value == True: #do sampling set after set process(10mV) R_mean_after = sampling_check(0.01,device) - R_mean_after = round(R_mean_after,1) - print(f"Average Resistance(Sampling Check):{R_mean_after:e} Ohm") + print(f"Average Resistance(Sampling Check):{'{:.2e}'.format(R_mean_after)} Ohm") first_sampling = False title = f"SET Memristor:"+"\n\n"+f"Set Voltage={Vset.value}V"+"\n"+f"current compliance={CC_vset.value}A"+"\n" @@ -310,8 +369,7 @@ def on_reset_button_clicked(b): if valid == True: if sampling.value == True: #do sampling set before reset process(10mV) R_mean_before = sampling_check(0.01,device) - R_mean_before = round(R_mean_before,1)#round 1 decimal point - print(f"Average Resistance(Sampling Check):{R_mean_before:e} Ohm") + print(f"Average Resistance(Sampling Check):{'{:.2e}'.format(R_mean_before)} Ohm") first_sampling = False #execute measurement,plot results and save them @@ -321,15 +379,22 @@ def on_reset_button_clicked(b): print(df) if sampling.value == True: #do sampling set after reset process(100mV) - R_mean_after = sampling_check(0.1,device) - R_mean_after = round(R_mean_after,1) - print(f"Average Resistance(Sampling Check):{R_mean_after:e} Ohm") + R_mean_after = sampling_check(-0.01,device) + print(f"Average Resistance(Sampling Check):{'{:.2e}'.format(R_mean_after)} Ohm") first_sampling = False title =f"RESET Memristor:"+"\n\n"+f"Reset Voltage={Vreset.value}V"+"\n"+f"current compliance={CC_vreset.value}A"+"\n" if sampling.value == True: title = title + f"R(Ohm) Before/After"+"\n"+f"{R_mean_before} {R_mean_after}"+"\n" write_to_file(temp_file,title,df) + + #Quick Contact Check after reset Process + if auto_qcc.value == True: + if qcc_select.value == 'EBL': + R=EBL() + else: # OL + R=OL() + save_contact_check(R,temp_file) #upload results temp_file,file,folder=upload_results(temp_file,file,folder) @@ -409,26 +474,30 @@ def on_full_button_clicked(b): #execute number of measurements for i in range(number.value):#here it is easier to implement the sampling checks if sampling.value == True: #before set(100mv) - R_mean_init = sampling_check(0.1,device) - R_mean_init = round(R_mean_init,1) + R_mean_init = sampling_check(-0.01,device) resistances.append(R_mean_init) V12,I12 = sweep(0,Vset.value,step.value,CC_vset.value,integration_time.value,device) #set - #after set/before set + #after set/before reset if sampling.value == True: #before set(10mv) R_mean_set = sampling_check(0.01,device) - R_mean_set = round(R_mean_set,1) resistances.append(R_mean_set) V34,I34 = sweep(0,Vreset.value,step.value,CC_vreset.value,integration_time.value,device) #reset + #Quick Contact Check after reset Process + if auto_qcc.value == True: + if qcc_select.value == 'EBL': + R = EBL() + else: # OL + R = OL() + #no reason to do check at the end because the next loop will do that(not anymore) more sampling checks #after reset if sampling.value == True:#-0.1V - R_mean_reset = sampling_check(-0.1,device) - R_mean_reset = round(R_mean_reset,1) + R_mean_reset = sampling_check(-0.01,device) resistances.append(R_mean_reset) @@ -445,6 +514,9 @@ def on_full_button_clicked(b): f.write(df.to_string()) f.write("\n\n") + if auto_qcc.value == True: + save_contact_check(R,temp_file) + #plot results ax1.plot(V,I) @@ -641,3 +713,4 @@ new.on_click(on_new_sample_button_clicked) new_folder.on_click(on_new_folder_button_clicked) retention_button.on_click(on_retention_button_clicked) contact_check.on_click(on_contact_check_clicked) +qcc.on_click(on_qcc_clicked) -- GitLab