Tektronix Technical Forums are maintained by community involvement. Feel free to post questions or respond to questions by other members. Should you require a time-sensitive answer, please contact your local Tektronix support center here.

pulsed IV works in TSB, but not in Visual Studio

Use this forum for questions about Keithley Test Script Builder software.
Post Reply
Posts: 16
Joined: April 2nd, 2014, 8:07 am
Country: Netherlands

pulsed IV works in TSB, but not in Visual Studio

Post by bscrooks » October 2nd, 2015, 3:07 am

Dear Keithley team,

I coded a TSP script to measure the IV curve of a solar cell with my Keithley 2601B (I will attach it in case is useful for someone else). The cell may deliver a current higher than 3A, therefore I need to use the pulsed method to be in the safe range of the instrument. It works perfectly fine, even when measuring high currents (around 9A). I never measure voltages beyond 20V.

Code: Select all

function IV(irradiance) 
 smua.source.func     = smua.OUTPUT_DCVOLTS 
 if remoteSense == true then 
  smua.sense      = smua.SENSE_REMOTE 
  smua.sense      = smua.SENSE_LOCAL 
 smua.source.autorangev   = smua.AUTORANGE_OFF 
 smua.source.rangev    = math.max(math.abs(start), math.abs(stop)) 
 smua.source.levelv    = 0 
 -- Set the DC bias limit.  This is not the limit used during the pulses. 
 smua.source.limiti    = 0.1  
 -- Disabling Auto-Ranging and Auto-Zero ensures accurate and consistent timing 
 smua.measure.autozero   = smua.AUTOZERO_ONCE 
 smua.measure.autorangei   = smua.AUTORANGE_OFF 
 smua.measure.rangei    = limitI 
 measDelay = 300e-6
 smua.measure.nplc    = nplc 
 -- A timer will be used to control the measure delay so set the built-in delay to 0 
 smua.measure.delay    = 0 
 -- Prepare the Reading Buffers 
 smua.nvbuffer1.collecttimestamps= 1 
 smua.nvbuffer2.collecttimestamps= 1  
 -- Configure the Trigger Model 
 -- Pressing the TRIG button on the front panel will trigger the sweep to start 
 -- Timer 1 controls the pulse period 
 trigger.timer[1].count   = numPoints > 1 and numPoints - 1 or 1 
 trigger.timer[1].delay   = pulsePeriod 
 trigger.timer[1].passthrough = true 
 trigger.timer[1].stimulus  = display.trigger.EVENT_ID  
 -- Timer 2 controls the measure delay 
 trigger.timer[2].count   = 1 
 -- Set the measure delay long enough so that measurements start after the pulse 
 -- has settled, but short enough that it fits within the width of the pulse. 
 trigger.timer[2].delay   = measDelay 
 trigger.timer[2].passthrough = false 
 trigger.timer[2].stimulus  = trigger.timer[1].EVENT_ID 
 -- Timer 3 controls the pulse width 
 trigger.timer[3].count   = 1 
 trigger.timer[3].delay   = pulseWidth 
 trigger.timer[3].passthrough = false 
 trigger.timer[3].stimulus  = trigger.timer[1].EVENT_ID  
 -- Configure SMU Trigger Model for Sweep 
 if linear == true then
 smua.trigger.source.linearv(start, stop, numPoints)
 smua.trigger.source.logv(start, stop, numPoints,stop+0.01)
 smua.trigger.source.limiti  = limitI 
 smua.trigger.measure.action  = smua.ENABLE 
 smua.trigger.measure.iv(smua.nvbuffer1, smua.nvbuffer2) 
 smua.trigger.endpulse.action = smua.SOURCE_IDLE 
 smua.trigger.endsweep.action = smua.SOURCE_IDLE 
 smua.trigger.count    = numPoints 
 smua.trigger.arm.stimulus  = 0 
 smua.trigger.source.stimulus = trigger.timer[1].EVENT_ID 
 smua.trigger.measure.stimulus = trigger.timer[2].EVENT_ID 
 smua.trigger.endpulse.stimulus = trigger.timer[3].EVENT_ID 
 smua.trigger.source.action  = smua.ENABLE 
 -- End Trigger Model Configuration  
 smua.source.output    = smua.OUTPUT_ON  
 -- Start the trigger model execution 
 -- Sweep will not start TRIG button is pressed  
 -- Wait until the sweep has completed 
 smua.source.output    = smua.OUTPUT_OFF
 -- Print the data back to the Console in tabular format 
 for x=1,smua.nvbuffer1.n do 

 for x=1,smua.nvbuffer1.n do 
  if x>1 then 
   if smua.nvbuffer2[x]>0 and smua.nvbuffer2[x-1]<0 then 
    Isc=smua.nvbuffer1[x-1]-(smua.nvbuffer1[x]-smua.nvbuffer1[x- 1])*smua.nvbuffer2[x-1]/(smua.nvbuffer2[x]-smua.nvbuffer2[x-1]) 
    if smua.nvbuffer1[x]>0 and smua.nvbuffer1[x-1]<0 then 
    Voc=smua.nvbuffer2[x-1]-smua.nvbuffer1[x-1]*(smua.nvbuffer2[x]- smua.nvbuffer2[x-1])/(smua.nvbuffer1[x]-smua.nvbuffer1[x-1]) 
  if smua.nvbuffer2[x]>0 and smua.nvbuffer1[x]<0 and math.abs(power[x])>pmax then 
 print("Voc(V)", "Isc(A)","FF(%)","Vmpp(V)","Impp(A)","efficiency(%)","area(cm2)","irradiance(W/m2)","pulse width(s)","pulse period(s)","NPLC(s)","meas. delay (us)","limitI (A)","Pmpp(W)","Isc1sun(A)","Jsc1sun (mA/cm2") 

 for x=1,smua.nvbuffer1.n do 
  print(smua.nvbuffer1.timestamps[x], smua.nvbuffer2[x], -smua.nvbuffer1[x],-power[x]) 
I got tired of copy-pasting each IV from the instrument console, so I decided to build a user interface with Visual Studio in order to make the process a bit more automatic. I downloaded the Keithley Ke26XXA driver and wrote the whole code into C#, exactly line by line, using the driver's help library.

The problem: The interface works great as long as I set a limitI below 3A (I can initialize the instrument, measure, plot, save, etc..). However, once I set a limitI above 3A, it tells me "Operation would exceed safe operating area of the instrument" and I cannot measure.

It is weird, because the exactly same code written in the TSB gives no "out of safe operating area" error (I am pulsing the IV exactly for this reason). For me it seems as if when initializing the instrument in C#, something is going wrong and it may not get that my 2601B can go beyond 3A when pulsing (always below 20V). The way I initialize in C# is:

Code: Select all

private void initializeButton_Click(object sender, System.EventArgs e)
				// Disable the Initialize button to provide visual feedback
				initializeButton.Enabled = false;

				// Close the driver if it's already been initialized
				if (_driver.Initialized)
                    statusBar.Text = "Instrument not initialized.";

				statusBar.Text = "Initializing...";

                		_driver.Initialize(IPaddress.Text, true, true, "QueryInstrStatus=True");

				statusBar.Text = "Instrument initialized.";
			catch (Exception ex)
				MessageBox.Show("Error:  " + ex.Message, "Ke26XX Simple Source Measure", MessageBoxButtons.OK, MessageBoxIcon.Error);

				statusBar.Text = "Initialize failed.";
				// Re-enable the Initialize button
				initializeButton.Enabled = true;
I have also tried to stress the instrument model with
_driver.Initialize(IPaddress.Text, true, true, "QueryInstrStatus=True, Simulate=True, DriverSetup= Model=Model 2601B");
but does not work either.

Any ideas?

Thank you very much in advance!


Norbert W
Keithley Applications
Keithley Applications
Posts: 227
Joined: October 21st, 2010, 7:18 am
Country: Germany

Re: pulsed IV works in TSB, but not in Visual Studio

Post by Norbert W » October 5th, 2015, 6:41 am

having all the programming done in TSB a simple idea would be to take the complete code,
add loadandrunscript / endscript and send it directly in another language (like C#) without spending much work using driver
This said I don't see a hint in your initialization but would believe the problem lying somewhere deep in your code.

Posts: 16
Joined: April 2nd, 2014, 8:07 am
Country: Netherlands

Re: pulsed IV works in TSB, but not in Visual Studio

Post by bscrooks » October 6th, 2015, 6:15 am

Hi Norbert,

Thanks for your response.
I have read all the parts of the Reference manual where the loadandrunscript,loadscript,endscript,etc are described. However, I am not quite sure if I understood you.
What do you mean by "send it directly in another language"?. This is exactly my objective (namely in C# with visual studio) and the only way i found is to re-write the script with this driver I mentioned you.
Do you mean that I can just copy the script as it is written in TSB (Lua language) and somehow paste it in C#, with a couple of extra commands, and directly send it? Could you please explain a bit more how to do that? It would be of great help.
Thanks again!

Andrea C
Keithley Applications
Keithley Applications
Posts: 1436
Joined: October 15th, 2010, 10:35 am
Country: United States

Re: pulsed IV works in TSB, but not in Visual Studio

Post by Andrea C » October 7th, 2015, 6:41 am


For customized pulsing with the 2600, I agree with Norbert about using the TSP native commands rather than the IVI driver.
With this in mind, it may be better to just use VISA to do write and read operations to the 2600 from C#.
As you have done, first use the Test Script Builder application to first write, debug and test your script. Then close TSB connection to instrument and use C#.

I'll upload a simple C# example for using VISA COM object that demonstrates the concepts of loadrunscript/endscript. It was written in Visual Studio 2012.
VS.NET 2012 C# example using VISA COM 5.2 Type Lib
(61.11 KiB) Downloaded 1490 times

Posts: 16
Joined: April 2nd, 2014, 8:07 am
Country: Netherlands

Re: pulsed IV works in TSB, but not in Visual Studio

Post by bscrooks » November 4th, 2015, 3:42 am

Thanks a lot Andrea

Right now I dont have time to test it, but will do it soon and will come back to you.


Posts: 16
Joined: April 2nd, 2014, 8:07 am
Country: Netherlands

Re: pulsed IV works in TSB, but not in Visual Studio

Post by bscrooks » February 3rd, 2016, 3:52 am

Hi again,

Thank you so much for the C# example, it really helped to understand how it works. Now I have successfully sent line by line all the TSP code of my IV() function.

I have a final doubt. The results that my TSP script generates are written in the TSP console.
How can I read the TSP console from C#?

If i could do that, I could further process all the data from C#, much more comfortable!

Thanks a lot for the support,

Andrea C
Keithley Applications
Keithley Applications
Posts: 1436
Joined: October 15th, 2010, 10:35 am
Country: United States

Re: pulsed IV works in TSB, but not in Visual Studio

Post by Andrea C » February 4th, 2016, 4:42 am

Hi Jorge,

Key concept is to send a print command to the 2600B and then read back the response.
For example, use VISA write send print(smua.nvbuffer1[index]) and then use VISA read to get the response.

There are also printbuffer() TSP commands that you could send in case you want to have it send multiple values back.

Last, you can also define a custom data printing function in case you want to control the order, format, etc.

Code: Select all

-- define a simple function to display data
--Prints the results from the reading buffers.
function printData(whichsmu)
   if whichsmu.nvbuffer1.n == 0 then
      print("No readings in buffer")
       for i = 1, whichsmu.nvbuffer1.n do
         print(string.format("%g\t%g\t%g", whichsmu.nvbuffer1.timestamps[i], 
       end  -- for loop
   end  -- if
end  -- function printData definition

Post Reply

Return to “Test Script Builder”

Who is online

Users browsing this forum: No registered users and 0 guests