Ejemplo n.º 1
0
class DataCollector(QtCore.QObject):
    finished = QtCore.pyqtSignal()
    pos_data_ready = QtCore.pyqtSignal(np.ndarray, np.ndarray, np.ndarray)
    pos_scope_data_ready = QtCore.pyqtSignal(np.ndarray, np.ndarray)
    pos_tec_data_ready = QtCore.pyqtSignal(np.ndarray, np.ndarray)
    neg_data_ready = QtCore.pyqtSignal(np.ndarray, np.ndarray, np.ndarray)
    neg_scope_data_ready = QtCore.pyqtSignal(np.ndarray, np.ndarray)
    neg_tec_data_ready = QtCore.pyqtSignal(np.ndarray, np.ndarray)
    finished_res_measurement = QtCore.pyqtSignal(np.ndarray, np.ndarray)
    stable = QtCore.pyqtSignal()

    mutex = QtCore.QMutex()
    mutex.lock()
    is_stopped = False
    mutex.unlock()

    sb = instruments.SwitchBox()
    bb = instruments.BalanceBox()
    dmm = instruments.K2000()
    pg = instruments.K2461()
    scope = instruments.DS1104()
    tec = instruments.TEC1089SV()

    scope_enabled = False
    tec_enabled = False
    # default 8 arms
    # pulse1_assignments = {"I+": "B", "I-": "F"}  # configuration for a pulse from B to F
    # pulse2_assignments = {"I+": "D", "I-": "H"}  # configuration for a pulse from D to H
    # measure_assignments = {"I+": "A", "I-": "E", "V1+": "B", "V1-": "D", "V2+": "C", "V2-": "G"}  # here V1 is Vxx
    # alt 1 8 arms
    # pulse1_assignments = {"I+": "A", "I-": "E"}
    # pulse2_assignments = {"I+": "C", "I-": "G"}
    # measure_assignments = {"I+": "H", "I-": "D", "V1+": "A", "V1-": "C", "V2+": "B", "V2-": "F"}
    # alt 2 8 arms
    # pulse1_assignments = {"I+": "D", "I-": "H"}  # configuration for a pulse from B to F
    # pulse2_assignments = {"I+": "H", "I-": "D"}  # configuration for a pulse from D to H
    # measure_assignments = {"I+": "A", "I-": "E", "V1+": "B", "V1-": "D", "V2+": "C", "V2-": "G"}  # here V1 is Vxx
    # default 4 arms
    pulse1_assignments = {
        "I+": "AG",
        "I-": "CE"
    }  # configuration for a pulse from B to F
    pulse2_assignments = {
        "I+": "AC",
        "I-": "GE"
    }  # configuration for a pulse from D to H
    measure_assignments = {
        "I+": "A",
        "I-": "E",
        "V1+": "A",
        "V1-": "E",
        "V2+": "C",
        "V2-": "G"
    }  # here V1 is Vxx

    resistance_assignments = {
        'A': 0,
        'B': 0,
        'C': 0,
        'D': 0,
        'E': 0,
        'F': 0,
        'G': 0,
        'H': 0
    }
    # 8 arm
    # two_wire_assignments = ({"I+": "A", "I-": "E"},
    #                         {"I+": "B", "I-": "F"},
    #                         {"I+": "C", "I-": "G"},
    #                         {"I+": "D", "I-": "H"},
    #                         )
    # four_wire_assignments = ({"I+": "A", "I-": "E", "V1+": "B", "V1-": "D"},
    #                          {"I+": "B", "I-": "F", "V1+": "C", "V1-": "E"},
    #                          {"I+": "C", "I-": "G", "V1+": "D", "V1-": "F"},
    #                          {"I+": "D", "I-": "H", "V1+": "E", "V1-": "G"},
    #                          {"I+": "E", "I-": "A", "V1+": "F", "V1-": "H"},
    #                          {"I+": "F", "I-": "B", "V1+": "G", "V1-": "A"},
    #                          {"I+": "G", "I-": "C", "V1+": "H", "V1-": "B"},
    #                          {"I+": "H", "I-": "D", "V1+": "A", "V1-": "C"},
    #                          )
    # 4 arm
    two_wire_assignments = ({"I+": "A", "I-": "E"}, {"I+": "C", "I-": "G"})
    four_wire_assignments = ({
        "I+": "A",
        "I-": "C",
        "V1+": "G",
        "V1-": "E"
    }, {
        "I+": "C",
        "I-": "E",
        "V1+": "A",
        "V1-": "G"
    }, {
        "I+": "E",
        "I-": "G",
        "V1+": "C",
        "V1-": "A"
    }, {
        "I+": "G",
        "I-": "A",
        "V1+": "E",
        "V1-": "C"
    })

    # reference_resistance = 10.0154663186062
    reference_resistance = 50.036
    two_wire = 150

    @QtCore.pyqtSlot(str, str, str, str, str, str, str, str, str, tuple)
    def start_measurement(self, mode, sb_port, bb_port, dmm_port, pulse_mag,
                          pulse_width, meas_curr, meas_n, loop_n, checkboxes):
        bb_enabled, scope_enabled = checkboxes
        self.mutex.lock()
        self.is_stopped = False
        self.mutex.unlock()

        error_flag, pulse_volts, pulse_mag, pulse_width, meas_curr, meas_n, loop_n = self.handle_inputs(
            mode, sb_port, bb_port, dmm_port, pulse_mag, pulse_width,
            meas_curr, meas_n, loop_n, bb_enabled, scope_enabled)
        # If flag is true then something failed in parsing the inputs or connecting and the loop will not continue.
        if error_flag:
            return

        self.pulse_and_measure(pulse_volts, pulse_mag, pulse_width, meas_curr,
                               meas_n, loop_n)

        self.sb.close()
        if bb_enabled:
            self.bb.close()
        if scope_enabled:
            self.scope.close()
        self.dmm.close()
        self.pg.close()
        # plt.pause()(1)
        self.finished.emit()

    @QtCore.pyqtSlot(str, str, str, str, str, str, str, str, str, bool)
    def resistance_measurement(self, mode, sb_port, bb_port, dmm_port,
                               pulse_mag, pulse_width, meas_curr, meas_n,
                               loop_n, bb_enabled):
        self.mutex.lock()
        self.is_stopped = False
        self.mutex.unlock()

        # Converts the strings in the gui boxes into appropriate types and then connects and sets up instruments.
        error_flag, pulse_volts, pulse_mag, pulse_width, meas_curr, meas_n, loop_n = self.handle_inputs(
            mode, sb_port, bb_port, dmm_port, pulse_mag, pulse_width,
            meas_curr, meas_n, loop_n, bb_enabled, False)

        # If something fails to connect, the UI doesn't continue
        if error_flag:
            return

        # reset the resistances to measure two wires properly
        if bb_enabled:
            self.bb.reset_resistances()

        two_wires = np.zeros(len(self.two_wire_assignments))
        four_wires = np.zeros(len(self.four_wire_assignments))

        for i in range(len(self.two_wire_assignments)):
            self.sb.switch(self.two_wire_assignments[i])
            time.sleep(0.3)
            self.pg.enable_2_wire_probe(meas_curr)
            time.sleep(0.2)
            c, v = self.pg.read_one()
            two_wires[i] = v / c
            self.pg.disable_probe_current()
        print('Two Wires: ', two_wires)

        for i in range(len(self.four_wire_assignments)):
            self.sb.switch(self.four_wire_assignments[i])
            time.sleep(0.3)
            self.pg.enable_4_wire_probe(meas_curr)
            time.sleep(0.2)
            c, v = self.pg.read_one()
            four_wires[i] = v / c
            self.pg.disable_probe_current()
        print('Four Wires: ', four_wires)

        if bb_enabled:
            self.bb.close()
        self.dmm.close()
        self.pg.close()
        self.sb.close()
        self.finished_res_measurement.emit(two_wires, four_wires)

    @QtCore.pyqtSlot(int, str, str)
    def start_TEC_temperature_control(self, system, port, target):
        # System: 0 -> none, 1-> TEC 2-> anything else, for future (HTS?)
        self.tec_enabled = True
        if system == 0:
            return
        try:
            port = int(port)
            target = float(target)
        except ValueError:
            print(
                'Failed to convert strings to numbers. Check port and target temp boxes'
            )
            return
        if system == 1:
            try:
                self.tec.connect(port)
                self.tec.set_target_temperature(target)
                self.tec.enable_control()
            except visa.VisaIOError:
                print(
                    f'Could not connect to TEC on port {port} or could not set temperature to {target}'
                )
                self.stable.emit()
                return

            a = self.tec.get_temp_stability_state()
            while a is not "stable":
                time.sleep(1)
                a = self.tec.get_temp_stability_state()
            self.stable.emit()
        # if system == 2:
        #     try:
        #         self.hts.connect(port)
        #         self.hts.set_target_temperature(target)
        #         self.hts.enable_control()
        #     except visa.VisaIOError:
        #         print('Could not connect to HTS on port ' + port + ' or could not set temperature to ' + target)
        #         return

    @QtCore.pyqtSlot()
    def stop_TEC_temperature_control(self):
        self.tec_enabled = False
        try:
            self.tec.disable_control()
        except visa.VisaIOError:
            print('Could not send disable output command to TEC')
        self.tec.close()

    def pulse_and_measure(self, volts, pulse_mag, pulse_width, meas_curr,
                          meas_n, loop_n):
        # see footnote on 6-110 in k2461 manual

        self.dmm.prepare_measure_one()

        start_time = time.time()
        for loop_count in range(loop_n):
            self.mutex.lock()
            if self.is_stopped:
                return
            self.mutex.unlock()
            print('Loop count:', loop_count + 1, 'Pulse: 1')
            self.sb.switch(self.pulse1_assignments)
            if self.scope_enabled:
                self.scope.single_trig()
            if volts:
                self.pg.prepare_pulsing_voltage(pulse_mag, pulse_width)
            else:
                self.pg.prepare_pulsing_current(pulse_mag, pulse_width)
            self.pg.set_ext_trig()
            time.sleep(200e-3)
            pulse_t = time.time()

            self.pg.send_pulse()

            time.sleep(200e-3)
            self.sb.switch(self.measure_assignments)
            self.pg.enable_4_wire_probe(meas_curr)
            time.sleep(500e-3)
            t = np.zeros(meas_n)
            vxx = np.zeros(meas_n)
            vxy = np.zeros(meas_n)
            curr = np.zeros(meas_n)
            if self.tec_enabled:
                tec_data = np.zeros(meas_n)
            for meas_count in range(meas_n):
                t[meas_count] = time.time()
                self.pg.trigger_fetch()
                self.dmm.trigger()
                vxx[meas_count], curr[meas_count] = self.pg.fetch_one()
                vxy[meas_count] = self.dmm.fetch_one()
                if self.tec_enabled:
                    tec_data[meas_count] = self.tec.get_object_temperature()
            self.pg.disable_probe_current()
            self.pos_data_ready.emit(t - start_time, vxx / curr, vxy / curr)
            if self.scope_enabled:
                scope_data = self.scope.get_data(30001, 60000)
                time_step = float(self.scope.get_time_inc())
                scope_time = np.array(range(
                    0, len(scope_data))) * time_step + pulse_t - start_time
                self.pos_scope_data_ready.emit(
                    scope_time, scope_data / self.reference_resistance)
            if self.tec_enabled:
                self.pos_tec_data_ready.emit(t - start_time, tec_data)

            self.mutex.lock()
            if self.is_stopped:
                return
            self.mutex.unlock()

            print('Loop count:', loop_count + 1, 'Pulse: 2')
            self.sb.switch(self.pulse2_assignments)
            if self.scope_enabled:
                self.scope.single_trig()
            if volts:
                self.pg.prepare_pulsing_voltage(pulse_mag, pulse_width)
            else:
                self.pg.prepare_pulsing_current(pulse_mag, pulse_width)
            self.pg.set_ext_trig()
            time.sleep(200e-3)
            pulse_t = time.time()

            self.pg.send_pulse()

            time.sleep(200e-3)
            self.sb.switch(self.measure_assignments)
            self.pg.enable_4_wire_probe(meas_curr)
            time.sleep(500e-3)

            t = np.zeros(meas_n)
            vxx = np.zeros(meas_n)
            vxy = np.zeros(meas_n)
            curr = np.zeros(meas_n)
            if self.tec_enabled:
                tec_data = np.zeros(meas_n)
            for meas_count in range(meas_n):
                t[meas_count] = time.time()
                self.pg.trigger_fetch()
                self.dmm.trigger()
                vxx[meas_count], curr[meas_count] = self.pg.fetch_one()
                vxy[meas_count] = self.dmm.fetch_one()
                if self.tec_enabled:
                    tec_data[meas_count] = self.tec.get_object_temperature()
            self.pg.disable_probe_current()
            self.neg_data_ready.emit(t - start_time, vxx / curr, vxy / curr)

            if self.scope_enabled:
                scope_data = self.scope.get_data(30001, 60000)
                time_step = float(self.scope.get_time_inc())
                scope_time = np.array(range(
                    0, len(scope_data))) * time_step + pulse_t - start_time
                self.neg_scope_data_ready.emit(
                    scope_time, scope_data / self.reference_resistance)
            if self.tec_enabled:
                self.neg_tec_data_ready.emit(t - start_time, tec_data)

    def handle_inputs(self, mode, sb_port, bb_port, dmm_port, pulse_mag,
                      pulse_width, meas_curr, meas_n, loop_n, bb_enabled,
                      scope_enabled):
        connection_flag = False
        conversion_flag = False

        if mode == 'Pulse Current':
            pulse_volts = False
        elif mode == 'Pulse Voltage':
            pulse_volts = True
        else:
            print('Pulse mode selection error?')
            pulse_volts = False
            conversion_flag = True

        try:
            sb_port = int(sb_port)
        except ValueError:
            error_sound()
            print('Invalid switchbox port please enter integer value.')
            conversion_flag = True

        if bb_enabled:
            try:
                bb_port = int(bb_port)
            except ValueError:
                error_sound()
                print('Invalid balance box port please enter integer value.')
                conversion_flag = True
            self.bb.enable_all()
            self.bb.set_resistances(self.resistance_assignments)

        try:
            dmm_port = int(dmm_port)
        except ValueError:
            error_sound()
            print('Invalid keithley port please enter integer value.')
            conversion_flag = True

        try:
            if pulse_volts:
                pulse_mag = float(pulse_mag)
            else:
                pulse_mag = float(pulse_mag) * 1e-3
        except ValueError:
            error_sound()
            print('Invalid pulse magnitude. Please enter a valid float')
            conversion_flag = True

        try:
            pulse_width = float(pulse_width) * 1e-3
        except ValueError:
            error_sound()
            print('Invalid pulse width. Please enter a valid float')
            conversion_flag = True

        try:
            meas_curr = float(meas_curr) * 1e-6
        except ValueError:
            error_sound()
            print('Invalid probe current. Please enter a valid float')
            conversion_flag = True

        try:
            meas_n = int(meas_n)
        except ValueError:
            error_sound()
            print(
                'Invalid measurement count per loop. Please enter an integer value'
            )
            conversion_flag = True

        try:
            loop_n = int(loop_n)
        except ValueError:
            error_sound()
            print('Invalid number of loops. Please enter an integer value')
            conversion_flag = True

        try:
            self.sb.connect(sb_port)
        except serial.SerialException:
            error_sound()
            print(f"Could not connect to switch box on port COM{sb_port}.")
            connection_flag = True

        if bb_enabled:
            try:
                self.bb.connect(bb_port)
            except serial.SerialException:
                error_sound()
                print(
                    f"Could not connect to balance box on port COM{bb_port}.")
                connection_flag = True

        if scope_enabled & pulse_volts:
            try:
                self.scope.connect()
                self.scope.prepare_for_pulse(pulse_mag,
                                             self.reference_resistance,
                                             self.two_wire, pulse_width)
                self.scope.set_trig_chan()
                # self.scope.single_trig()
                self.scope_enabled = True
                time.sleep(12)
            except visa.VisaIOError:
                error_sound()
                print("Could not connect to RIGOL DS1104Z.")
                connection_flag = True
        else:
            self.scope_enabled = False

        try:
            self.dmm.connect(dmm_port)
        except visa.VisaIOError:
            error_sound()
            print(f"Could not connect to Keithley2000 on port COM{dmm_port}.")
            connection_flag = True

        try:
            self.pg.connect()
        except visa.VisaIOError:
            error_sound()
            print("Could not connect to keithley 2461.")
            connection_flag = True

        return connection_flag or conversion_flag, pulse_volts, pulse_mag, pulse_width, meas_curr, meas_n, loop_n
Ejemplo n.º 2
0
    "V2+": "C",
    "V2-": "G"
}
probe_current = 200e-6

time_values = np.array([])
Rxx = np.array([])
Rxy = np.array([])
tec_volts = np.array([])

error_sound = instruments.error_sound
alert_sound = instruments.alert_sound

sb = instruments.SwitchBox()
dmm = instruments.K2000()
pg = instruments.K2461()
# tec = instruments.TEC1089SV()
sb.connect(15)
dmm.connect(16)
pg.connect()
# tec.connect(14)

# tec.disable_control()
# tec.set_target_temperature(0)
# tec.enable_control()
# while tec.get_temp_stability_state() is not "stable":
#     time.sleep(0.5)
# print('Temp stable')

sb.switch(measure_assignments)
time.sleep(0.5)
Ejemplo n.º 3
0
pulse_voltage = 30  # set voltage
pulse_width = 1e-3  # set pulse duration
measure_current = 5e-4  # measurement current
measure_number = 200  # number of measurements to store in buffer when calling measure_n and read_buffer. 375 is ~1min
num_loops = 2
measure_delay = measure_number * 0.15  # Not strictly necessary.

pos_time = np.array([])
neg_time = np.array([])
pos_rxx = np.array([])
neg_rxx = np.array([])
pos_rxy = np.array([])
neg_rxy = np.array([])

switch_box = instruments.SwitchBox()  # make a sb object
pulse_generator = instruments.K2461()  # make a k2461 object
keithley = instruments.K2000()  # make a k2000 object
balance_box = instruments.BalanceBox()
start_time = time.time()  # use this for the graphing only

# actually connect to the instruments
pulse_generator.connect()
switch_box.connect(4)
keithley.connect(3)
balance_box.connect(5)
balance_box.enable_all()
balance_box.set_resistances(resistance_assignments)

plt.figure(1)
plt.xlabel('Time (s)')
plt.ylabel('R_xx (Ohms)')