• Queue full error in 2636A SUM

    Hello there,
    I am doing Four point measurements by using SMU 2636A with python. Earlier I was using Python 2.7 and I switched to Python 3.8. With 3.8 I am getting error -350 Queue full error which is showing in SMU's display. I tried to write function in Python for Queue error however still getting same error. Here I am attaching both Python files as a text as well as zip. Could you please help me in this situation?

    Python 2.7 original file:

    # *-* coding:utf-8 *-*

    import visa
    import numpy as np
    import time
    import os
    import matplotlib.pyplot as plt

    class Keithley2636A(object):
        
        def __init__(self):
            try:
                self.__device = visa.instrument('GPIB0::18')
            except:
                print 'Could not attach to Keithley!'
                
            self.__intTime = 1.0 # standart integration time 20ms = 1 plc
            self.__waitingTime = 0.0 # in ms --> minimum waiting time to measure after setting voltage
            self.__maxPower = 1.0 # in Watt
            self.__average = 1 # number of averages for each data point measurement
            
            self.__send(['reset()'])
            
        def __send(self, cmds):
            '''sends a list of commands to the device'''
            for cmd in cmds:
                self.__device.write(cmd)
            
        def init4pt(self):
            optns = []
            #optns.append('display.screen = display.SMUA')
            #optns.append('smua.source.func = smua.OUTPUT_DCAMPS') #current source
            #optns.append('smua.source.autorangei = smua.AUTORANGE_ON') #current source AutoRange
            #optns.append('display.smua.measure.func =  display.MEASURE_DCVOLTS')
            #optns.append('smua.sense = smua.SENSE_REMOTE') #4 wire measurement
            #optns.append('smua.measure.autorangev = smua.AUTORANGE_ON') #voltage measurement AutoRange
            #optns.append('smua.measure.nplc = %f' % self.__intTime) # integration time in Number of Power Line Cycles (range from 0.001 to 25) 25 MAYBE HAS A BUG
            
            optns.append('display.screen = display.SMUA_SMUB')
            optns.append('smua.source.func = smua.OUTPUT_DCVOLTS') #voltage source
            optns.append('smub.source.func = smub.OUTPUT_DCAMPS') #current source
            optns.append('smua.source.autorangev = smua.AUTORANGE_ON') #voltage source AutoRange
            optns.append('smub.source.autorangei = smua.AUTORANGE_ON') #current source AutoRange
            optns.append('display.smua.measure.func =  display.MEASURE_DCAMPS')
            optns.append('display.smub.measure.func =  display.MEASURE_DCVOLTS')
            optns.append('smua.sense = smub.SENSE_LOCAL') #2 wire measurement
            optns.append('smub.sense = smub.SENSE_LOCAL') #2 wire measurement
            optns.append('smua.measure.autorangei = smua.AUTORANGE_ON') #voltage measurement AutoRange
            optns.append('smub.measure.autorangev = smua.AUTORANGE_ON') #voltage measurement AutoRange
            optns.append('smua.measure.nplc = %f' % self.__intTime) # integration time in Number of Power Line Cycles (range from 0.001 to 25) 25 MAYBE HAS A BUG
            optns.append('smub.measure.nplc = %f' % self.__intTime) # integration time in Number of Power Line Cycles (range from 0.001 to 25) 25 MAYBE HAS A BUG
            self.__send(optns)
        
        def __getVoltageLimit(self, cur):
            '''calculates the voltage limit for current source to avoid too high powers in the DUT'''
            if cur == 0.0:
                #lim = 200.0 #only in interlock mode
                lim = 20.0
            else:
                lim = self.__maxPower / cur
                if np.abs(cur) < 0.1:
                    #lim = np.clip(np.abs(lim), 0.02, 200.0) #only in interlock mode
                    lim = np.clip(np.abs(lim), 0.02, 20.0)
                else:
                    lim = np.clip(np.abs(lim), 0.02, 20.0)
            return lim
            
        def __getCurrentLimit(self, vol):
            '''calculates the current limit for voltage source to avoid too high powers in the DUT'''
            if vol == 0.0:
                lim = 1.5
            else:
                lim = self.__maxPower / vol
                if np.abs(vol) < 20.0:
                    lim = np.clip(np.abs(lim), 100e-12, 1.5)
                else:
                    lim = np.clip(np.abs(lim), 100e-12, 0.1)
            return lim
        
        def setCurrent(self, cur, cha): #cha = channel A/B
            '''sets the current source value for channel A/B'''
            optns = []
            optns.append('smu%s.source.limitv = %f' % (cha, self.__getVoltageLimit(cur)))
            optns.append('smu%s.source.leveli = %f' % (cha, cur))
            self.__send(optns)
            return True
        
        def setVoltage(self, vol, cha): #cha = channel A/B
            '''sets the voltage source value for channel A/B'''
            optns = []
            optns.append('smu%s.source.limiti = %f' % (cha, self.__getCurrentLimit(vol)))
            optns.append('smu%s.source.levelv = %f' % (cha, vol))
            self.__send(optns)
            return True
        
        def __measureCurrent(self, cha):
            '''measures the current on channel A/B'''
            optns = []
            optns.append('smu%s.measure.count = 1' % cha)
            optns.append('print(smu%s.measure.i())' % cha)
            self.__send(optns)
            return self.__device.read_values()[0]
        
        def getCurrent(self, cha): #cha = channel A/B
            cur = 0.0
            for i in range(self.__average):
                time.sleep(self.__waitingTime/1000.0)
                cur = cur + self.__measureCurrent(cha)
            return cur / self.__average, self.__checkCompliance(cha), True
        
        def __measureVoltage(self, cha):
            optns = []
            optns.append('smu%s.measure.count = 1' % cha)
            optns.append('print(smu%s.measure.v())' % cha)
            self.__send(optns)
            return self.__device.read_values()[0]
        
        def getVoltage(self, cha): #cha = channel A/B
            vol = 0.0
            for i in range(self.__average):
                time.sleep(self.__waitingTime/1000.0)
                vol = vol + self.__measureVoltage(cha)
            return vol / self.__average, self.__checkCompliance(cha), True

        def __measureCurVol(self, cha):
            optns = []
            optns.append('smu%s.measure.count = 1' % cha)
            optns.append('print(smu%s.measure.iv())' % cha)
            self.__send(optns)
            return self.__device.read_values()[0:2]

        def getCurVol(self, cha):
            res = self.__measureCurVol(cha)
            return res[0], res[1], True
            
        def setMaxPower(self, pwr):
            '''define the maximum power through the device'''
            self.__maxPower = pwr
        
        def setIntegrationTime(self, time):
            '''time in seconds; for 50Hz 1 plc = 20ms --> range time from 20µs to 500ms'''
            self.__intTime = time / 0.02
            
        def setNumberOfAverages(self, n):
            '''defines over how many measurements per point should be averaged'''
            self.__average = n
            
        def outputOn(self, cha): # cha = channel A/B
            '''turns the output on'''
            self.__send(['smu%s.source.output = smu%s.OUTPUT_ON' % (cha, cha)])
            
        def outputOff(self, cha): # cha = channel A/B
            '''turns the output off'''
            self.__send(['smu%s.source.output = smu%s.OUTPUT_OFF' % (cha, cha)])
            
        def __checkCompliance(self, cha):
            '''checks wheter the source is in compliance or not'''
            self.__send(['print(smu%s.source.compliance)' % cha])
            tmp = self.__device.read()
            if tmp == 'false':
                return False
            else:
                return True
            
    def test():
        tst = Keithley2636A()
        fileName = raw_input('file name: ')
        fl = os.listdir('./')
        n = 0
        Ival = []
        Vval = []
        while '%02.i_%s.dat' % (n, fileName) in fl:
            n = n+1
        f = open('%02.i_%s.dat' % (n, fileName), mode='w')
        f.write('V_setpoint/V\tI_measured/A\tV_measured/V\n')
        tst.init4pt()
        minI = input('Minimum Voltage in V: ')
        maxI = input('Maximum Voltage in V: ')
        stepI = input('Voltage steps in V: ')
        tst.outputOn('a')
        tst.setCurrent(0.0, 'b')
        tst.outputOn('b')
        print 'V_setpoint/V\tI_measured/A\tV_measured/V'
        r1 = np.arange(0.0, maxI, stepI)
        r2 = np.arange(maxI, minI, -stepI)
        r3 = np.arange(minI, 0.0+stepI, stepI)
        vLoop = np.append(r1, r2)
        vLoop = np.append(vLoop, r3)
        for v in vLoop:
            tst.setVoltage(v, 'a')
            time.sleep(1.0)
            resCur = tst.getCurrent('a')
            resVolt = tst.getVoltage('b')
            print '%g\t%g\t%g' % (v, resCur[0], resVolt[0])
            f.write('%g\t%g\t%g\n' % (v, resCur[0], resVolt[0]))
            Ival.append(resCur[0])
            Vval.append(resVolt[0])
        print 'end'
        tst.outputOff('a')
        tst.outputOff('b')
        f.close()
        plt.plot(Vval, Ival, 'ro')
        plt.show()
        
    if __name__ == '__main__':
        test()



    --------------------------------------------------------------------------------------------
    Python 3.8 Transferred file :

    import pyvisa
    import time
    import numpy as np
    import os
    import matplotlib.pyplot as plt
    from queue import Queue

    class Keithley2636A:
        def __init__(self, visa_address):
            self.rm = pyvisa.ResourceManager()
            self.instrument = self.rm.open_resource(visa_address)
            self.queue = Queue(maxsize=100)  # Set a larger value for the queue size
            
        def setup_measurement(self):
            # Configure the instrument for the 4-point probe measurement
            self.instrument.write("reset()")
            self.instrument.write("display.screen = pyvisa.constants.SMUA_SMUB")
            self.instrument.write("smua.source.func = smua.OUTPUT_DCVOLTS")
            self.instrument.write("smub.source.func = smub.OUTPUT_DCAMPS")
            self.instrument.write("smua.source.autorangev = smua.AUTORANGE_ON")
            self.instrument.write("smub.source.autorangei = smua.AUTORANGE_ON")
            self.instrument.write('display.smua.measure.func =  display.MEASURE_DCAMPS')
            self.instrument.write('display.smub.measure.func =  display.MEASURE_DCVOLTS')
            self.instrument.write("smua.sense = smua.SENSE_REMOTE")
            self.instrument.write("smub.sense = smub.SENSE_REMOTE")
            self.instrument.write('smua.sense = smub.SENSE_LOCAL')  # 2 wire measurement
            self.instrument.write('smub.sense = smub.SENSE_LOCAL')  # 2 wire measurement
            self.instrument.write('smua.measure.autorangei = smua.AUTORANGE_ON')  # voltage measurement AutoRange
            self.instrument.write('smub.measure.autorangev = smua.AUTORANGE_ON')  # voltage measurement AutoRange
            self.instrument.write("smua.source.output = smua.OUTPUT_OFF")
            self.instrument.write("smub.source.output = smub.OUTPUT_OFF")
            self.instrument.write("smua.measure.nplc = 1")  # Set NPLC value as needed
            self.instrument.write("smub.measure.nplc = 1")  # Set NPLC value as needed


        def __getVoltageLimit(self, cur):
            '''calculates the voltage limit for current source to avoid too high powers in the DUT'''
            if cur == 0.0:
                #lim = 200.0 #only in interlock mode
                lim = 20.0
            else:
                lim = 1.0 / cur
                if np.abs(cur) < 0.1:
                    #lim = np.clip(np.abs(lim), 0.02, 200.0) #only in interlock mode
                    lim = np.clip(np.abs(lim), 0.02, 20.0)
                else:
                    lim = np.clip(np.abs(lim), 0.02, 20.0)
            return lim
        
        def __getCurrentLimit(self, vol):
            '''calculates the current limit for voltage source to avoid too high powers in the DUT'''
            if vol == 0.0:
                lim = 1.5
            else:
                lim = 1.0 / vol
                if np.abs(vol) < 20.0:
                    lim = np.clip(np.abs(lim), 100e-12, 1.5)
                else:
                    lim = np.clip(np.abs(lim), 100e-12, 0.1)
            return lim
        
        def set_voltage(self, voltage, cha):
            #self.instrument.write(f"smua.source.levelv = {voltage}")
            self.instrument.write('smu%s.source.limiti = %f' % (cha, self.__getCurrentLimit(voltage)))
            self.instrument.write('smu%s.source.levelv = %f' % (cha, voltage))
            time.sleep(0.1)
            # Put the measured value into the queue
            self.queue.put({'voltage': voltage, 'current': self.measure_current(cha), 'voltage_measurement': self.measure_voltage(cha)})
        
        def set_current(self, current, cha):
            #self.instrument.write(f"smub.source.leveli = {current}")
            self.instrument.write('smu%s.source.limitv = %f' % (cha, self.__getVoltageLimit(current)))
            self.instrument.write('smu%s.source.leveli = %f' % (cha, current))
            time.sleep(0.1)
        
        def turn_on_channels(self):
            self.instrument.write("smua.source.output = smua.OUTPUT_ON")
            self.instrument.write("smub.source.output = smub.OUTPUT_ON")
        
        def turn_off_channels(self):
            self.instrument.write("smua.source.output = smua.OUTPUT_OFF")
            self.set_current(0.0, 'B')
            self.instrument.write("smub.source.output = smub.OUTPUT_OFF")
            self.queue.queue.clear()  # Clear the queue when turning off channels
        
        def measure_current(self, cha):
            return float(self.instrument.query(f'print(smub.measure.i())'))
        
        def measure_voltage(self, cha):
            return float(self.instrument.query(f'print(smub.measure.v())'))
        
        def close(self):
            self.instrument.close()
            self.rm.close()

    if __name__ == "__main__":
        # Configure the GPIB address for your Keithley 2636A
        visa_address = "GPIB0::18::INSTR"  # Adjust this address as needed

        keithley = Keithley2636A(visa_address)

        try:
            keithley.setup_measurement()
            measurement_name = input("Enter the measurement name:")

            minI = float(input('Minimum Voltage in V: '))
            maxI = float(input('Maximum Voltage in V: '))
            stepI = float(input('Voltage steps in V: '))
            cha = 'A'  # Define cha before using it
            
            r1 = np.arange(0.0, maxI, stepI)
            r2 = np.arange(maxI, minI, -stepI)
            r3 = np.arange(minI, 0.0 + stepI, stepI)
            vLoop = np.append(r1, r2)
            vLoop = np.append(vLoop, r3)
            voltage_list = np.arange(minI, maxI, stepI)  # Set your desired voltage range

            current_list = []
            v_list = []

            keithley.turn_on_channels()
            print(f"Step Voltage/V \t Measured Current/A \t  Measured Voltage/V")

            for voltage in vLoop:
                keithley.set_voltage(voltage, cha)
                time.sleep(1.0)
                # Add the measured values to the queue
                keithley.queue.put({'voltage': voltage, 'current': keithley.measure_current(cha), 'voltage_measurement': keithley.measure_voltage(cha)})
                current_list.append(keithley.queue.get()['current'])
                v_list.append(keithley.queue.get()['voltage_measurement'])
                current = keithley.measure_current(cha)
                current_list.append(current)
                v = keithley.measure_voltage(cha)
                v_list.append(v)

                print(f"{round(voltage, 1)} V  {current} A \t  {v} V")
        
            keithley.turn_off_channels()
        finally:
            keithley.close()

    Thank you in advance.