Source code for qcodes.calibrations.keithley

from __future__ import annotations

import time
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from qcodes.instrument import Instrument
    from qcodes.instrument_drivers.Keithley import Keithley26xx
    from qcodes.parameters import Parameter

src_FS_map = {
    "200e-3": 180e-3, "2": 1.8, "20": 18, "200": 180,
    "100e-3": 80e-3, "1": 0.8, "6": 5.6, "40": 38,
}


def setup_dmm(dmm: Instrument) -> None:
    dmm.aperture_time(1.0)
    dmm.autozero("OFF")
    dmm.autorange("OFF")


def save_calibration(smu: Keithley26xx) -> None:
    calibration_date = int(time.time())
    for smu_channel in smu.channels:
        smu.write(f"{smu_channel.channel}.cal.adjustdate = {calibration_date}")
        smu.write(f"{smu_channel.channel}.cal.save()")


[docs] def calibrate_keithley_smu_v( smu: Keithley26xx, dmm: Instrument, src_Z: float = 1e-30, time_delay: float = 3.0, save_calibrations: bool = False, dmm_range_per_smu_range_mapping: dict[str, float] | None = None, ) -> None: if dmm_range_per_smu_range_mapping is None: dmm_range_per_smu_range_mapping = { "200e-3": 1, "2": 10, "20": 100, } else: wrong_smu_range_keys = set(dmm_range_per_smu_range_mapping.keys()) - set(src_FS_map.keys()) if len(wrong_smu_range_keys) > 0: raise ValueError( f"dmm_range_per_smu_range_mapping contains unknown keys {wrong_smu_range_keys}, " f"the possible keys are {set(src_FS_map.keys())}" ) setup_dmm(dmm) for smu_channel in smu.channels: input(f"Please connect channel {smu_channel.channel} to V input on calibrated DMM.") for smu_range, dmm_range in dmm_range_per_smu_range_mapping.items(): dmm.range(dmm_range) calibrate_keithley_smu_v_single( smu, smu_channel.channel, dmm.volt, smu_range, src_Z, time_delay ) if save_calibrations: save_calibration(smu)
def calibrate_keithley_smu_v_single( smu: Keithley26xx, channel: str, dmm_param_volt: Parameter, v_range: str, src_Z: float = 1e-30, time_delay: float = 3.0, ) -> None: assert channel in {smu_channel.channel for smu_channel in smu.channels} assert v_range in src_FS_map.keys() src_FS = src_FS_map[v_range] sense_modes = ["SENSE_LOCAL"] for sense_mode in sense_modes: print("Sense mode: " + sense_mode) smu.write(f'{channel}.cal.unlock("KI0026XX")') smu.write(f"{channel}.reset()") smu.write(f"{channel}.source.func = {channel}.OUTPUT_DCVOLTS") smu.write(f"{channel}.source.rangev = {v_range}") smu.write(f"{channel}.source.output = {channel}.OUTPUT_OFF") smu.write(f"{channel}.sense = {channel}." + sense_mode) time.sleep(time_delay) # Start positive calibration: smu.write(f"{channel}.cal.polarity = {channel}.CAL_POSITIVE") smu.write(f"{channel}.source.levelv = {src_Z}") smu.write(f"{channel}.source.output = {channel}.OUTPUT_ON") # Measure positive zero voltage with SMU and DMM: time.sleep(time_delay) smu.write(f"Z_rdg = {channel}.measure.v()") DMM_Z_rdg = dmm_param_volt() smu.write(f"{channel}.source.output = {channel}.OUTPUT_OFF") smu.write(f"{channel}.source.levelv = {src_FS:.8e}") smu.write(f"{channel}.source.output = {channel}.OUTPUT_ON") # Measure positive full scale voltage with SMU and DMM: time.sleep(time_delay) smu.write(f"FS_rdg = {channel}.measure.v()") DMM_FS_rdg = dmm_param_volt() # Write positive v_range calibration to SMU: smu.write(f"{channel}.source.output = {channel}.OUTPUT_OFF") time.sleep(time_delay) smu.write( f"{channel}.source.calibratev({v_range}, {src_Z}, {DMM_Z_rdg:.8e}, {src_FS:.8e}, {DMM_FS_rdg:.8e})" ) if sense_mode != "SENSE_CALA": time.sleep(time_delay) smu.write( f"{channel}.measure.calibratev({v_range}, Z_rdg, {DMM_Z_rdg:.8e}, FS_rdg, {DMM_FS_rdg:.8e})" ) time.sleep(time_delay) # Start negative calibration: smu.write(f"{channel}.cal.polarity = {channel}.CAL_NEGATIVE") smu.write(f"{channel}.source.levelv = -{src_Z}") smu.write(f"{channel}.source.output = {channel}.OUTPUT_ON") # Measure negative zero voltage with SMU and DMM: time.sleep(time_delay) smu.write(f"Z_rdg = {channel}.measure.v()") DMM_Z_rdg = dmm_param_volt() smu.write(f"{channel}.source.output = {channel}.OUTPUT_OFF") smu.write(f"{channel}.source.levelv = -{src_FS:.8e}") smu.write(f"{channel}.source.output = {channel}.OUTPUT_ON") # Measure negative full scale voltage with DMM: time.sleep(time_delay) smu.write(f"FS_rdg = {channel}.measure.v()") DMM_FS_rdg = dmm_param_volt() # Write negative v_range calibration to SMU: smu.write(f"{channel}.source.output = {channel}.OUTPUT_OFF") time.sleep(time_delay) smu.write( f"{channel}.source.calibratev(-{v_range}, -{src_Z}, {DMM_Z_rdg:.8e}, -{src_FS:.8e}, {DMM_FS_rdg:.8e})" ) if sense_mode != "SENSE_CALA": time.sleep(time_delay) smu.write( f"{channel}.measure.calibratev(-{v_range}, Z_rdg, {DMM_Z_rdg:.8e}, FS_rdg, {DMM_FS_rdg:.8e})" ) time.sleep(time_delay) smu.write(f"{channel}.cal.polarity = {channel}.CAL_AUTO") # Reset the smu to default state smu.write(f"{channel}.source.levelv = {src_Z}")