Posted Fri, 23 Aug 2024 18:01:05 GMT by Cole, Shae
I have attempted to use PYVISA package with Python to communicate with SCIP commands with a Keithley 2602B instrument. I get error codes -285 where there seems to be syntax issues. 
When running the following code in python I get an error code -285 unexpected symbol near ':' : 
import pyvisa
# Initialize the VISA resource manager
    rm = pyvisa.ResourceManager()

# Connect to the Keithley 2600
    instrument = rm.open_resource('USB0::0x05E6::0x2602::4422867::INSTR')

# Initialize the instrument
        instrument.write('*RST')  # Reset the instrument to default settings
        
# Select channel A
        instrument.write(':INST:NSEL 1')  # Selects the source meter channel (channel A)
After this issue I noticed that for my Keithley instrument 2602B there are no SCPI commands for this instrument in the manual or at least the one I have. 

I have sense then installed Keithley Test Script Builder and I have connected the instrument but when I run this pre-made script I get a -286 error code -286 with a run time error attempting to index global 'debuffer1' (a nil value): 
--[[
This example demonstrates how to generate an I-V sweep on a solar panel.  
In this particular example the voltage is swept from 0V to 20V and the resulting current
is measured.  The maximum power, maximum current, maximum voltage, short circuit current,
and open circuit voltage are calculated and displayed in the Instrument Console along with
all the I-V sweep data. More information about this tsp code can be found in the 
View This First document.
--]]

--Define the number of points in the sweep.
num = 115

--Reset the Model 2460 and clear the buffer.
reset()
defbuffer1.clear()

--Set the source and measure functions.
smu.measure.func = smu.FUNC_DC_CURRENT
smu.source.func = smu.FUNC_DC_VOLTAGE

--Configure the measurement settings.
smu.measure.terminals = smu.TERMINALS_FRONT
smu.measure.sense = smu.SENSE_4WIRE
smu.measure.autorange = smu.ON
smu.measure.nplc = 1

--Configure the source settings.
smu.source.highc = smu.OFF
smu.source.range = 20
smu.source.readback = smu.ON
smu.source.highc = smu.OFF
smu.source.ilimit.level = 4
smu.source.sweeplinear("SolarCell", 0, 20, num, 0.05)

--Start the trigger model and wait for it to complete.
trigger.model.initiate()
waitcomplete()

--Define initial values.
voltage = defbuffer1.sourcevalues
current = defbuffer1
isc = current[1]
mincurr = current[1]
imax = current[1]
voc = voltage[1]
vmax = voltage[1]
pmax = voltage[1]*current[1]

--Calculate values.
for i = 1, num do
print(voltage[i],current[i],voltage[i]*current[i])
 if (voltage[i]*current[i] < pmax) then
pmax = voltage[i]*current[i]
imax = current[i]
vmax = voltage[i]
 end
 if math.abs(current[i]) < math.abs(mincurr) then
voc = voltage[i]
 end
end
pmax = math.abs(pmax)
imax = math.abs(imax)
print("Pmax = ", pmax, ", Imax = ", imax, ", Vmax = ", vmax, ", Isc = ", isc, ",Voc = ", voc)

--Display values on the Model 2460 front panel.
display.changescreen(display.SCREEN_USER_SWIPE)
display.settext(display.TEXT1, string.format("Pmax = %.4fW", pmax))
display.settext(display.TEXT2, string.format("Isc = %.4fA, Voc = %.2fV", isc, voc))

Any help would be greatly appreciated! 
Posted Sat, 24 Aug 2024 13:20:16 GMT by C, Andrea
In Test Script Builder, look for the samples in folders labeled with 2600 such as KE26XXB_Example_Scripts.

In your post, you are attempting to use commands related to different products/different model numbers which have different command set from what the 2602B understands.

Here is some Python code for use with 2600B to carry out a voltage sweep and measure current.
import pyvisa as visa
import time
import sys
import numpy as np
import matplotlib.pyplot as plt

resource_mgr = visa.ResourceManager()

try:
     #get a session/handle for one resource
     #change the instrument_resource_string for YOUR INSTRUMENT  
     #instrument_resource_string = "USB0::0x05E6::0x2602::4566591::INSTR"
     instrument_resource_string = "USB0::0x05E6::0x2636::4597212::INSTR"
     #instrument_resource_string = "TCPIP0::192.168.1.208::INSTR"
     my_instr = resource_mgr.open_resource(instrument_resource_string)
except visa.VisaIOError as e:
     #did not connect.....
     print("Whoops, something went wrong")
     #print(e.args)
     #print(resource_mgr.last_status)
     print(resource_mgr.visalib.last_status)
     sys.exit(1)


# set some parameters for our session
my_instr.timeout = 25000   #timeout in msec
#my_instr.write_termination = '\n'
my_instr.VI_ATTR_TCPIP_KEEPALIVE = True
    
my_instr.write("*IDN?\n")
print("*****")
print(my_instr.read())

# set commands to setup a trigger model linear sweep
num_sweep_pts = 151
cmd_list = ["reset()",
            "errorqueue.clear()",
            "smua.source.func = smua.OUTPUT_DCVOLTS",
            "smua.source.limiti = 100e-3",
            "smua.source.rangev = 2",
            "smua.measure.nplc = 1",
            "smua.measure.delay = smua.DELAY_AUTO",
            "smua.measure.delayfactor = 1.0",
            "smua.measure.lowrangei = 100e-9",
            "smua.nvbuffer1.clear()",
            "smua.nvbuffer1.collecttimestamps = 1",
            "smua.nvbuffer2.clear()",
            "smua.nvbuffer2.collecttimestamps = 1",
            "smua.trigger.source.linearv(-1.0, 1.0, " + str(num_sweep_pts) + ")",
            "smua.trigger.source.limiti = 0.1",
            "smua.trigger.measure.action = smua.ENABLE",
            "smua.trigger.measure.iv(smua.nvbuffer1, smua.nvbuffer2)",
            "smua.trigger.endpulse.action = smua.SOURCE_HOLD",
            "smua.trigger.endsweep.action = smua.SOURCE_IDLE",
            "smua.trigger.count = " + str(num_sweep_pts),
            "smua.trigger.source.action = smua.ENABLE"]    

for cmd in cmd_list:
    my_instr.write(cmd)    
    

#commands to configure SRQ when SWEEPING bit goes 1 to 0 = sweep is finished
# see Chapter 12 in 2600B Reference Manual
cmd_list2 = ["status.reset()",
             "status.operation.enable = status.operation.SWEEPING",
             "status.operation.sweeping.enable = status.operation.sweeping.SMUA",
             "status.operation.sweeping.ptr = 0",
             "status.operation.sweeping.ntr = status.operation.sweeping.SMUA",
             "status.request_enable = status.OSB"]    

for cmd in cmd_list2:
    my_instr.write(cmd)


#turn output on and run the sweep
my_instr.write("smua.source.output = smua.OUTPUT_ON")

t1 = time.perf_counter()

# important to read stb once before starting trigger model
print("First status byte polling value: " + str(int(my_instr.read_stb())))   

#start the trigger model operation
my_instr.write("smua.trigger.initiate()")  

# ********************************************
# setup a polling loop to detect Sweep is finished
#repeat until the MSS (SRQ) bit is set
still_running = True
status_byte = 0
debug = 1

# attempts to my_instr.query("print(status.condition)") will be blocked by active trigger model task
# instead use my_instr.read_stb() to obtain status.condition register

while still_running:
    status_byte = int(my_instr.read_stb())  #read status byte (status.condition register)
    if debug: print(str(status_byte) + ' - ' + str(bin(status_byte)))    
    if (status_byte & 64) == 64:
         still_running = False
    time.sleep(0.25)  #250msec pause before asking again


#turn output off
my_instr.write("smua.source.output = smua.OUTPUT_OFF")

t2 = time.perf_counter()
print('Test time: {}'.format(t2 - t1))
print("Number of actual smua buffer pts: " + str(my_instr.query('print(smua.nvbuffer1.n)')))   

print("Polling loop done, status byte: " + str(int(my_instr.read_stb())))     

print('Go get the data.')

# retrieve data and graph it

#ask for voltage and current; buffer2=voltage
my_instr.write("printbuffer(1, smua.nvbuffer1.n, smua.nvbuffer2.readings,smua.nvbuffer1.readings)")
raw_data = my_instr.read()            #one long comma delimited string

print("After data downloaded, status byte: " + str(int(my_instr.read_stb())))   
my_instr.write("status.reset()")
print("Post reset, status byte value: " + str(int(my_instr.read_stb())))  

# split yields an array of strings alternating voltage, current, voltage, current
raw_data_array = raw_data.split(",")  

volts = []
current = []
abs_current = []

# step through the array of strings, step size 2
# place the V and I into their own array of floats
for i in range(0, len(raw_data_array),2):
    volts.append(float(raw_data_array[i]))
    current.append(float(raw_data_array[i+1]))
    abs_current.append(abs(float(raw_data_array[i+1])))   #absolute value of currents for log scale
    
#plot the absolute value of current vs. voltage    
plt.plot(volts, abs_current, 'o-g')

x_min = min(volts) * 1.1
x_max = max(volts) * 1.1
y_min = abs(min(abs_current)) / 10
y_max = abs(max(abs_current)) * 10
plt.axis([x_min,x_max,y_min,y_max])
plt.yscale('log')
plt.xscale('linear')
plt.title('Sweep V, Measure I, 1MOhm')
plt.margins(x=0.1, y=0.1)
plt.grid(True)

plt.show()

save_image = 0
if save_image:
    plt.savefig('alc_plot.png')
Posted Sat, 24 Aug 2024 13:22:41 GMT by C, Andrea
When running the above code, the following output occurs:
*****
KEITHLEY INSTRUMENTS INC.,MODEL 2636B,4597212,4.0.4

First status byte polling value: 0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
0 - 0b0
192 - 0b11000000
Test time: 3.765706600010162
Number of actual smua buffer pts: 1.51000e+02

Polling loop done, status byte: 128
Go get the data.
After data downloaded, status byte: 128
Post reset, status byte value: 0


 

You must be signed in to post in this forum.