Page 1 of 1

Can 2450 (Non EC Model) Output a low frequency Square-wave while Measuring Current

Posted: March 7th, 2020, 12:56 pm
by Faraday303
Hello All,

I have a 2450 and we are trying to use it to output a low frequency (1-5Hz) square wave while measuring current on our FAPI sample while taking XPS measurements. I was wondering if this is even possible using TPS or Lua, I know there are no default AC functions on the machines GUI. I have found things here and there about the 2450 EC model, but not the regular 2450.

Any kind of help is much appreciated

Re: Can 2450 (Non EC Model) Output a low frequency Square-wave while Measuring Current

Posted: March 8th, 2020, 11:11 am
by Andrea C
Yes, it can.
Before you embark, check your firmware level and consider updating. I used 1.7.1e

Here is some code run from JupyterLab. It uses pyVISA to an NI-VISA backend on Windows 10.
I used a LAN connection, but you can use USB or GPIB too. Just update the resource descriptor.

To have good timing control, use of trigger blocks is best.
Trigger Model also gives you timers; program one of those to raise an event at twice your desired square wave freq; use those events to toggle between two voltage levels.
Generally range changes interfere with good timing control. However your slow waveform freq goals could allow for range changes.

Code: Select all

import visa
import time

resource_mgr = visa.ResourceManager()
#optional print available VISA resources on this computer
print (resource_mgr.list_resources())

#get a session/handle for one resource
instrument_resource_string = "TCPIP0::"
my_instr = resource_mgr.open_resource(instrument_resource_string)


src_cmd_list = ["smu.source.configlist.create('"'MY_SOURCE_LIST'"')" ,
                "smu.source.func = smu.FUNC_DC_VOLTAGE",
                "smu.source.range = 2",
                "smu.source.ilimit.level = 0.1",
                "smu.source.readback = smu.OFF",
                "smu.source.level = 0",
                "smu.source.level = 0.8",

for cmd in src_cmd_list:

#meas config list of one value - using same measure settings for all source levels
meas_cmd_list = ["smu.measure.configlist.create('"'MY_MEAS_LIST'"')",
                "smu.measure.func = smu.FUNC_DC_CURRENT",
                "smu.measure.range = 0.1",
                "smu.measure.nplc = 1",
#consider also auto zero, use of limited auto ranginging, 4W Remote Sense, Front/Rear Terminals, etc.

for cmd in meas_cmd_list:

#config a timer object for our square wave freq;  timer event_id will be used to control timing of sourcing
my_instr.write("trigger.timer[1].enable = 0")
my_instr.write("trigger.timer[1].delay = 0.5")  #squarewave freq = 2 * this delay
my_instr.write("trigger.timer[1].count = 20")  #squarewave cycles = 0.5 * this count
my_instr.write("trigger.timer[1].start.stimulus = trigger.EVENT_NOTIFY1")
my_instr.write("trigger.timer[1].start.generate = trigger.OFF")
my_instr.write("trigger.timer[1].enable = 1")

#setup trigger blocks
my_instr.write("trigger.model.setblock(1, trigger.BLOCK_BUFFER_CLEAR, defbuffer1)")
my_instr.write("trigger.model.setblock(2, trigger.BLOCK_SOURCE_OUTPUT, smu.ON)")
my_instr.write("trigger.model.setblock(3, trigger.BLOCK_CONFIG_RECALL, '"'MY_SOURCE_LIST'"', 1, '"'MY_MEAS_LIST'"', 1)")
my_instr.write("trigger.model.setblock(4, trigger.BLOCK_NOTIFY, trigger.EVENT_NOTIFY1)")  #start timer
my_instr.write("trigger.model.setblock(5, trigger.BLOCK_WAIT, trigger.EVENT_TIMER1)")
my_instr.write("trigger.model.setblock(6, trigger.BLOCK_CONFIG_NEXT, '"'MY_SOURCE_LIST'"')")
my_instr.write("trigger.model.setblock(7, trigger.BLOCK_MEASURE, defbuffer1, 10)")  #reading count and measure times needs to be managed
my_instr.write("trigger.model.setblock(8, trigger.BLOCK_BRANCH_COUNTER, 20, 5)")  #branch back to block_wait N times
my_instr.write("trigger.model.setblock(9, trigger.BLOCK_SOURCE_OUTPUT, smu.OFF)")

print("TSP commands Loaded")

When ready to run it, do this:

Code: Select all

#run the trigger blocks code

time.sleep(10)   #TODO:  interrogate instrument for done state
print("done sleeping")
To retrieve the data and plot it:

Code: Select all

import matplotlib.pyplot as plt #
import numpy as np #

#retrieve data from the buffer into arrays of floats

current_values = my_instr.query_ascii_values("printbuffer(1, defbuffer1.n, defbuffer1.readings)", container=np.array, separator=',', converter='f')

src_values = my_instr.query_ascii_values("printbuffer(1, defbuffer1.n, defbuffer1.sourcevalues)", container=np.array, separator=',', converter='f')

time_values = my_instr.query_ascii_values("printbuffer(1, defbuffer1.n, defbuffer1.relativetimestamps)", container=np.array, separator=',', converter='f')

debug = 0
if debug == 1:
   print("**** Time Stamps: *******")
   print("**** Current: *******")
   print("**** Source Values: *******")

#plot the data

fig, axs = plt.subplots(1, 2)   #one row, two columns
fig.suptitle('Slow Square Wave from 2450 SMU')

axs[0].plot(time_values, current_values, color='green', marker='o', linestyle='None', linewidth=1, markersize=3)

axs[0].set_title('SMU Current vs. Time')
plt.title('SMU Current vs. Time') # plot label
axs[0].set(xlabel='time (seconds)', ylabel='measured current (amps)')

plt.autoscale(True, True, True)

axs[1].plot(time_values, src_values, color='blue', marker='x', linestyle='None', linewidth=1, markersize=3)   #'rs')
axs[1].set_title('SMU Voltage vs. Time')
axs[1].set(xlabel='time (seconds)', ylabel='source voltage (volts)')
Here is the outcome for a 0v-0.8V squarewave into 100Ω DUT:
0.8V square wave into 100 ohms
2450_slow_squarewave_outcome.PNG (17.01 KiB) Viewed 441 times