Posted Mon, 07 Apr 2025 23:19:29 GMT by EM, Dalin
 Any idea, How to generate arbitrary current pulses using a 2450 Source Meter? Specifically, is it possible to import waveform shapes from a CSV file using TSP? 
Thanks
Posted Wed, 09 Apr 2025 19:53:53 GMT by C, Andrea

The source meter can be configured to output a list of values from a source configuration list.
By controlling the speed of outputting each value from the list, the waveform can be generated.
Keep in mind, the max speed of 2450 for source + measure operations is about 1700 operations per second.

Github Sample Code for Current Sine Wave with 2450

What sort of timing in your arbitrary current were you hoping for?

Our model 6221 has an ARB mode with faster current sourcing than 2450.

Posted Wed, 09 Apr 2025 22:45:42 GMT by EM, Dalin

I’ve attached an image of the simulated current pulses I want to generate using 2450. I'm using PyVISA to configure and automate the testing process. However, I'm currently encountering an issue when trying to set the protection limit.

Specifically, I'm receiving the following error:

Sending: :SENS:VOLT:PROT 5
Error state: -113,"Undefined header;1;2025/04/10 12:31:32.785"

Below is the Python code I'm using:

import pyvisa
import time

rm = pyvisa.ResourceManager()
resource_name = 'TCPIP0::10.0.0.38::5025::SOCKET'

try:
    print("Connecting to Keithley 2450...")
    instrument = rm.open_resource(resource_name)
    instrument.timeout = 10000
    instrument.read_termination = '\n'
    instrument.write_termination = '\n'

    print("Sending: *IDN?")
    idn = instrument.query('*IDN?')
    print(f"Instrument ID: {idn}")
    print(f"Error state: {instrument.query(':SYST:ERR?')}")

    print("Sending: :SYST:CLE")
    instrument.write(':SYST:CLE')
    time.sleep(0.5)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")

    print("Sending: *RST")
    instrument.write('*RST')
    time.sleep(2)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")

    print("Sending: :SOUR:FUNC CURR")
    instrument.write(':SOUR:FUNC CURR')
    time.sleep(0.5)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")

    print("Sending: :SOUR:CURR:RANG 0.001")
    instrument.write(':SOUR:CURR:RANG 0.001')
    time.sleep(0.5)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")
    
    print("Sending: :SOUR:CURR:LEV 0.0002")
    instrument.write(':SOUR:CURR:LEV 0.0002')
    time.sleep(0.5)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")

    print("Sending: :SENS:VOLT:PROT 5")
    instrument.write(':SENS:VOLT:PROT 5')
    time.sleep(1)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")
    
    print("Sending: :SENS:FUNC VOLT")
    instrument.write(':SENS:FUNC "VOLT"')
    time.sleep(1)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")
    
    print("Sending: :SENS:VOLT:RANG 5")
    instrument.write(':SENS:VOLT:RANG 5')
    time.sleep(1)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")
    
    print("Sending: :OUTP ON")
    instrument.write(':OUTP ON')
    
    print("Sending: :Trigger ON")
    instrument.write(':READ?')
    
    time.sleep(20)
    
    print("Sending: :OUTP OFF")
    instrument.write(':OUTP OFF')
    
    print("Sending: *RST")
    instrument.write('*RST')
    time.sleep(2)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")
    
   
except pyvisa.VisaIOError as e:
    print("VI_ERROR_IO Details:", e)
except Exception as e:
    print("Unexpected Error:", e)
finally:
    try:
        instrument.close()
    except:
        pass

runfile('C:/Users/Dalin EM/.spyder-py3/test4.py', wdir='C:/Users/Dalin EM/.spyder-py3')
Connecting to Keithley 2450...
Sending: *IDN?
Instrument ID: KEITHLEY INSTRUMENTS,MODEL 2450,04434429,1.6.7c
Error state: 0,"No error;0;0 0"
Sending: :SYST:CLE
Error state: 0,"No error;0;0 0"
Sending: *RST
Error state: 0,"No error;0;0 0"
Sending: :SOUR:FUNC CURR
Error state: 0,"No error;0;0 0"
Sending: :SOUR:CURR:RANG 0.001
Error state: 0,"No error;0;0 0"
Sending: :SOUR:CURR:LEV 0.0002
Error state: 0,"No error;0;0 0"
Sending: :SENS:VOLT:PROT 5
Error state: -113,"Undefined header;1;2025/04/10 12:31:32.785"
Sending: :SENS:FUNC VOLT
Error state: 0,"No error;0;0 0"
Sending: :SENS:VOLT:RANG 5
Error state: 0,"No error;0;0 0"
Sending: :OUTP ON
Sending: :Trigger ON
Sending: :OUTP OFF
Sending: *RST
Error state: 2.189537E+00

Posted Wed, 09 Apr 2025 22:54:42 GMT by EM, Dalin
Is it possible to load a .csv to 2450 using pyVISA to generate the current pulses?
Posted Fri, 11 Apr 2025 20:07:14 GMT by C, Andrea
Since your source function is current, the voltage compliance limit command would look like this:
:SOUR:CURR:VLIM 5

Separate from this is a protection level.  The instrument is capable of up to 200V.  The protection level lets you set an upper limit on this.
Suppose you meant to set the VLIM to 5.0 but passed 50 by mistake.  Having a PROTection level at 10 would restrict the output to 10V.

SOUR:VOLT:PROT PROT10

NOTE the enumerated values for protection level,  12 discrete values supported.
Posted Fri, 11 Apr 2025 20:14:27 GMT by C, Andrea
Q:  Is it possible to load a .csv to 2450 using pyVISA to generate the current pulses?

A:  Yes but will require some coding to pass the values of the csv to a source configuration list.
And building a trigger model to step through the list at a desired rate to achieve the waveform timing.

In your uploaded image of the pulse, they are about 2 seconds in duration.  Agree?
How many points would you want to use to approximate that pulse?

Is SMU sourcing only?  No measure?
Posted Sun, 13 Apr 2025 22:05:49 GMT by EM, Dalin
Yeah, the duration is about 2sec to 4 sec.  I am planning to use a step size of 50ms or 40 points. I want source current and measure it. Can you please provide pyvisa code or coding manual to accurately use the trigger or timer to program 2450.
Posted Mon, 14 Apr 2025 04:17:19 GMT by EM, Dalin
I have implemented the code below to generate the pulses. However, it is not accurate. I am exploring more accurate methods of generating the current pulses. Is it possible to write the data ( data in the .csv) into the internal memory of 2450 and use the internal timer to generate accurate pulse waveforms? 
import pyvisa
import pandas as pd
import time

# Load CSV file
csv_file = 'C:/Users/Dalin EM/.spyder-py3/test1.csv'
df = pd.read_csv(csv_file)

# Extract current values
if 'Current' in df.columns:
    currents = df['Current'].tolist()  # List of currents in amperes
else:
    currents = df.iloc[:, 0].tolist()  # Assume single column if no header

# Connect to Keithley 2450
rm = pyvisa.ResourceManager()
resource_name = 'TCPIP0::10.0.0.38::5025::SOCKET'
instrument = rm.open_resource(resource_name)
instrument.timeout = 10000
instrument.read_termination = '\n'
instrument.write_termination = '\n'

try:
    # Initialize instrument
    instrument.write('*IDN?')
    time.sleep(1)
    print(f"Instrument ID: {instrument.read()}")
    instrument.write(':SYST:CLE')
    time.sleep(1)
    instrument.write('*RST')
    time.sleep(1)
    instrument.write(':SOUR:FUNC CURR')
    time.sleep(1)
    instrument.write(':SOUR:CURR:RANG 0.001')  # 1 mA range
    time.sleep(1)
    instrument.write(':SENS:FUNC "CURR"')
    time.sleep(1)
    instrument.write(':SOUR:CURR:VLIM 3')
    time.sleep(1)
    instrument.write(':SENS:CURR:RANG 0.001')     # sense current range
    time.sleep(1)
    instrument.write(':OUTP ON')
    time.sleep(1)
    print(f"Error state: {instrument.query(':SYST:ERR?')}")

    
    interval = 0.02 
    start_time = time.time()
    for current in currents:
        current_time = time.time()
        elapsed_since_start = current_time - start_time
        target_time = start_time + (interval * currents.index(current))
        sleep_time = max(0, target_time - current_time)
        
        if sleep_time > 0:
            time.sleep(sleep_time)
        
        print(f"Setting current to {current*1e6:.1f} µA")
        instrument.write(f':SOUR:CURR:LEV {current}')
        measurement = instrument.query(':READ?')
        print(f"Measurement: {measurement}")

    # Cleanup
    instrument.write(':OUTP OFF')
    instrument.write('*RST')
    print(f"Final error state: {instrument.query(':SYST:ERR?')}")

except pyvisa.VisaIOError as e:
    print("VI_ERROR_IO Details:", e)
except Exception as e:
    print("Unexpected Error:", e)
finally:
    try:
        instrument.write(':OUTP OFF')
        instrument.close()
    except:
        print("Failed to close connection cleanly")

You must be signed in to post in this forum.