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.