• RE: How can I set "pulse mode" in keithley 2602B ?

    Needs an update:

    The code posted above will not take you into pulse region 4.
    These high watt pulse regions are in our Extended Operating Area and have firmware imposed max PW and Duty Cycle limits.

    To access the EOA regions, supply a higher voltage value for the trigger.source.limitv which will be applied only during the high watt pulse.
    When not sourcing the pulse level, the lower value set for the smuX.source.limitv applies.  The combo of smuX.source.leveli and smuX.source.limitv needs to be within the DC operating area of the SMU.

    These three lines in particular for accessing EOA region:

    smuX.measure.rangev = EOA_limit

    smuX.source.limitv = limitV

    smuX.trigger.source.limitv = EOA_limit

    I'll upload scope shot of 1.5A into 10Ω.

    Revised code:
    function Run_test(show_data, PulsePeriod, PulseWidth, MeasDelay)
    
    
       -- when passthrough is true, the timer will "tic" immediately,
       -- which for this application will start as soon as the
       -- trigger model is ARMED.  
       node[1].trigger.timer[1].delay = PulsePeriod
       node[1].trigger.timer[1].stimulus = node[1].smua.trigger.ARMED_EVENT_ID
       node[1].trigger.timer[1].count = 1  --PulseCount - 1
       node[1].trigger.timer[1].passthrough = true
       node[1].trigger.timer[1].clear()
       
       node[1].trigger.timer[2].delay = PulseWidth
       node[1].trigger.timer[2].stimulus = node[1].trigger.timer[1].EVENT_ID
       node[1].trigger.timer[2].count = 1        
       node[1].trigger.timer[2].passthrough = false
       node[1].trigger.timer[2].clear()
       
       node[1].trigger.timer[3].delay = MeasDelay
       node[1].trigger.timer[3].stimulus = node[1].trigger.timer[1].EVENT_ID
       node[1].trigger.timer[3].count = 1        
       node[1].trigger.timer[3].passthrough = false
       node[1].trigger.timer[3].clear()
    
    
        
        -- digital output trigger for external equipment
        -- configure digital IO line 1 to output a active LO/falling edge
        -- pulse at start of each current pulse
        digio.trigger[1].clear()
        digio.trigger[1].mode = digio.TRIG_FALLING  --digio.TRIG_RISINGM
        digio.trigger[1].pulsewidth = 100e-6
        digio.trigger[1].stimulus = node[1].trigger.timer[1].EVENT_ID  -- source stimulus too
        
            
       -- clear the reading buffers
       reset_buffers(node[1].smua)
         
     
    
        -- Turn the outputs on
        smua.source.output                    = smua.OUTPUT_ON
        
        -- after blue light state change, delay a little 
        delay(0.1)  
    
        -- Start the trigger model execution
        smua.trigger.initiate()   -- start this one last as all the other smus follow this leader
        
        -- Wait until the sweep has completed
        waitcomplete()
    
    --[[
    -- hot switch:
    -- to bleed off the trapped charge on PN junction capacitance and non-zero voltage
    -- briefly set the voltage compliance to small number
    restore_val = smua.source.limitv
    smua.source.limitv = 0.01
    delay(0.001)
    smua.source.limitv = restore_val
    ]]
    
        -- before blue light state change, delay a little 
        delay(0.1)
        -- Turn the output off
        smua.source.output                    = smua.OUTPUT_OFF
        
    
        -- IV data for the laser
        if show_data == true then
           -- Print the data back to the Console in tabular format
           print(" Voltage\tCurrent\tResistance")
           for x=1,smua.nvbuffer1.n do
              -- Voltage readings are in nvbuffer2.  Current readings are in nvbuffer1.
              print(smua.nvbuffer2[x], smua.nvbuffer1[x], smua.nvbuffer2[x]/smua.nvbuffer1[x] )
           end
        end
        
    
        
    end
    
    function reset_buffers(smu)
            -- Prepare the Reading Buffers
        smu.nvbuffer1.clear()
        smu.nvbuffer1.appendmode        = 1
        smu.nvbuffer1.collecttimestamps    = 1
        smu.nvbuffer2.clear()
        smu.nvbuffer2.appendmode        = 1
        smu.nvbuffer2.collecttimestamps    = 1
    
    end
    
    
    function config_smu_list_sweep(nodenum, smu, srcRange, srclist, limitV, EOA_limit, nplc, remoteSense)
        
        smu.source.func                    = smu.OUTPUT_DCAMPS
        if (remoteSense == true) then
            smu.sense                    = smu.SENSE_REMOTE
        else
            smu.sense                    = smu.SENSE_LOCAL
        end
        smu.source.autorangei            = smu.AUTORANGE_OFF
        smu.source.rangei                = srcRange
        smu.source.leveli                = 0
        smu.source.limitv                = limitV
    
        -- Disabling Auto-Ranging and Auto-Zero ensures accurate and consistent timing
        smu.measure.autozero            = smu.AUTOZERO_ONCE
        smu.measure.autorangev            = smu.AUTORANGE_OFF
        smu.measure.rangev                = EOA_limit
        smu.measure.nplc                = nplc
        -- A timer will be used to set the measure delay and synchronize the measurement
        -- between the SMUs so set the built in delay to 0.
        smu.measure.delay                = 0
        
        -- Configure SMU Trigger Model for Sweep
        --smu.trigger.source.lineari(start, stop, numPoints)
        smu.trigger.source.listi(srclist)
        smu.trigger.source.limitv        = EOA_limit
        smu.trigger.measure.action        = smu.ENABLE
        smu.trigger.measure.iv(smu.nvbuffer1, smu.nvbuffer2)
        smu.trigger.endpulse.action        = smu.SOURCE_IDLE
        smu.trigger.endsweep.action        = smu.SOURCE_IDLE
        smu.trigger.count                = table.getn(srclist)
        smu.trigger.arm.stimulus        = 0
        smu.trigger.source.stimulus        = trigger.timer[1].EVENT_ID
        smu.trigger.measure.stimulus    = trigger.timer[3].EVENT_ID
        smu.trigger.endpulse.stimulus    = trigger.timer[2].EVENT_ID
        smu.trigger.source.action        = smu.ENABLE
    end
    
    
    --  **************************************  MAIN PROGRAM BELOW *****************
    
    reset()
    errorqueue.clear()
    
    nodesFound = tsplink.reset(1)
    
    print("Nodes found = " .. nodesFound)
    
    --smua.interlock.enable = smua.DISABLE
    
    
    -- use of pulse region 4 of 2602B:  10A at up to 20V
    -- max 1.8msec pulse with 1% duty cycle
    local PulseWidth = 1.0e-3
    local PulsePeriod = PulseWidth / 0.01
    local MeasDelay = PulseWidth * 0.8
    local nplc = (PulseWidth - MeasDelay - 60e-6) * localnode.linefreq
    
    
    print("Computed NPLC value: "..tostring(nplc))
    
    if tostring(nplc) < "0.001" then
      nplc = 0.001   -- 16.7usec, minimum value allowed
      MeasDelay = 1e-6
    end -- if
    
    
    -- voltage ranges on 2602B:  100mV, 1V, 6V, 40V
    -- pick a limit value higher than expected I*DUT_R and
    -- puts you on appropriate range.
    local voltageLimit = 1
    local duringPulse_voltageLimit = 20
    
    -- ranges:  decades of 10.....100mA, 1A, 3A, 10A
    local mySrcRange = 3  
    mysrclist = { 1.5}  -- use this one for a single pulse
    --local numPulses = table.getn(mysrclist)
    
    
    
       
        --config_smu_list_sweep(nodenum, smu, srcRange, srclist, limitV, EOA_limit, nplc, remoteSense)
        config_smu_list_sweep(1, node[1].smua, mySrcRange, mysrclist, voltageLimit, duringPulse_voltageLimit, nplc, true)
    
    
    
       timer.reset()
       
       
       Run_test(true, PulsePeriod, PulseWidth, MeasDelay) -- pass true to print data back to console
       
       time = timer.measure.t()
       print("Time to run: "..time)
       print("****************************************")
       print("Current Source Range: "..node[1].smua.source.rangei)

    ​​​​​​​
  • RE: Driver to control Keithley 3706A with visual basic application using ethernet cable

    Attached is a form file from a VB sample using IVI driver and 3706A.
  • RE: Driver to control Keithley 3706A with visual basic application using ethernet cable

    The IVI driver is probably the way to go.
    The IVI driver "sits upon" NI VISA for the communication with instruments.
    Instead of GPIB0:: type resource name, pass info for your LAN connected instrument.
    Typically like this:  TCPIP0::192.168.1.50::inst0::INSTR
    Substitute your IP address in there.
  • RE: How can I set "pulse mode" in keithley 2602B ?

    See how this does for you.
    In the attachment is scope shot of the 1.5Amp, 1msec pulse into 50mΩ resistor (~75mV response).

    TSP code:
    ​​​​​​​
    
    function Run_test(show_data, PulsePeriod, PulseWidth, MeasDelay)
    
    
       -- when passthrough is true, the timer will "tic" immediately,
       -- which for this application will start as soon as the
       -- trigger model is ARMED.  
       node[1].trigger.timer[1].delay = PulsePeriod
       node[1].trigger.timer[1].stimulus = node[1].smua.trigger.ARMED_EVENT_ID
       node[1].trigger.timer[1].count = 1  --PulseCount - 1
       node[1].trigger.timer[1].passthrough = true
       node[1].trigger.timer[1].clear()
       
       node[1].trigger.timer[2].delay = PulseWidth
       node[1].trigger.timer[2].stimulus = node[1].trigger.timer[1].EVENT_ID
       node[1].trigger.timer[2].count = 1        
       node[1].trigger.timer[2].passthrough = false
       node[1].trigger.timer[2].clear()
       
       node[1].trigger.timer[3].delay = MeasDelay
       node[1].trigger.timer[3].stimulus = node[1].trigger.timer[1].EVENT_ID
       node[1].trigger.timer[3].count = 1        
       node[1].trigger.timer[3].passthrough = false
       node[1].trigger.timer[3].clear()
    
    
        
        -- digital output trigger for external equipment
        -- configure digital IO line 1 to output a active LO/falling edge
        -- pulse at start of each current pulse
        digio.trigger[1].clear()
        digio.trigger[1].mode = digio.TRIG_FALLING  --digio.TRIG_RISINGM
        digio.trigger[1].pulsewidth = 100e-6
        digio.trigger[1].stimulus = node[1].trigger.timer[1].EVENT_ID  -- source stimulus too
        
            
       -- clear the reading buffers
       reset_buffers(node[1].smua)
         
     
    
        -- Turn the outputs on
        smua.source.output                    = smua.OUTPUT_ON
        
        -- after blue light state change, delay a little 
        delay(0.1)  
    
        -- Start the trigger model execution
        smua.trigger.initiate()   -- start this one last as all the other smus follow this leader
        
        -- Wait until the sweep has completed
        waitcomplete()
    
    --[[
    -- hot switch:
    -- to bleed off the trapped charge on PN junction capacitance and non-zero voltage
    -- briefly set the voltage compliance to small number
    restore_val = smua.source.limitv
    smua.source.limitv = 0.01
    delay(0.001)
    smua.source.limitv = restore_val
    ]]
    
        -- before blue light state change, delay a little 
        delay(0.1)
        -- Turn the output off
        smua.source.output                    = smua.OUTPUT_OFF
        
    
        -- IV data for the laser
        if show_data == true then
           -- Print the data back to the Console in tabular format
           print(" Voltage\tCurrent\tResistance")
           for x=1,smua.nvbuffer1.n do
              -- Voltage readings are in nvbuffer2.  Current readings are in nvbuffer1.
              print(smua.nvbuffer2[x], smua.nvbuffer1[x], smua.nvbuffer2[x]/smua.nvbuffer1[x] )
           end
        end
        
    
        
    end
    
    function reset_buffers(smu)
            -- Prepare the Reading Buffers
        smu.nvbuffer1.clear()
        smu.nvbuffer1.appendmode        = 1
        smu.nvbuffer1.collecttimestamps    = 1
        smu.nvbuffer2.clear()
        smu.nvbuffer2.appendmode        = 1
        smu.nvbuffer2.collecttimestamps    = 1
    
    end
    
    
    function config_smu_list_sweep(nodenum, smu, srcRange, srclist, limitV, nplc, remoteSense)
        
        smu.source.func                    = smu.OUTPUT_DCAMPS
        if (remoteSense == true) then
            smu.sense                    = smu.SENSE_REMOTE
        else
            smu.sense                    = smu.SENSE_LOCAL
        end
        smu.source.autorangei            = smu.AUTORANGE_OFF
        smu.source.rangei                = srcRange
        smu.source.leveli                = 0
        smu.source.limitv                = limitV
    
        -- Disabling Auto-Ranging and Auto-Zero ensures accurate and consistent timing
        smu.measure.autozero            = smu.AUTOZERO_ONCE
        smu.measure.autorangev            = smu.AUTORANGE_OFF
        smu.measure.rangev                = limitV
        smu.measure.nplc                = nplc
        -- A timer will be used to set the measure delay and synchronize the measurement
        -- between the SMUs so set the built in delay to 0.
        smu.measure.delay                = 0
        
        -- Configure SMU Trigger Model for Sweep
        --smu.trigger.source.lineari(start, stop, numPoints)
        smu.trigger.source.listi(srclist)
        smu.trigger.source.limitv        = limitV
        smu.trigger.measure.action        = smu.ENABLE
        smu.trigger.measure.iv(smu.nvbuffer1, smu.nvbuffer2)
        smu.trigger.endpulse.action        = smu.SOURCE_IDLE
        smu.trigger.endsweep.action        = smu.SOURCE_IDLE
        smu.trigger.count                = table.getn(srclist)
        smu.trigger.arm.stimulus        = 0
        smu.trigger.source.stimulus        = trigger.timer[1].EVENT_ID
        smu.trigger.measure.stimulus    = trigger.timer[3].EVENT_ID
        smu.trigger.endpulse.stimulus    = trigger.timer[2].EVENT_ID
        smu.trigger.source.action        = smu.ENABLE
    end
    
    
    --  **************************************  MAIN PROGRAM BELOW *****************
    
    reset()
    errorqueue.clear()
    
    nodesFound = tsplink.reset(1)
    
    print("Nodes found = " .. nodesFound)
    
    --smua.interlock.enable = smua.DISABLE
    
    
    -- use of pulse region 4 of 2602B:  10A at up to 20V
    -- max 1.8msec pulse with 1% duty cycle
    local PulseWidth = 1.0e-3
    local PulsePeriod = PulseWidth / 0.01
    local MeasDelay = PulseWidth * 0.8
    local nplc = (PulseWidth - MeasDelay - 60e-6) * localnode.linefreq
    
    
    print("Computed NPLC value: "..tostring(nplc))
    
    if tostring(nplc) < "0.001" then
      nplc = 0.001   -- 16.7usec, minimum value allowed
      MeasDelay = 1e-6
    end -- if
    
    
    -- voltage ranges on 2602B:  100mV, 1V, 6V, 40V
    -- pick a limit value higher than expected I*DUT_R and
    -- puts you on appropriate range.
    local voltageLimit = 1
    
    -- ranges:  decades of 10.....100mA, 1A, 3A, 10A
    local mySrcRange = 3  
    mysrclist = { 1.5}  -- use this one for a single pulse
    --local numPulses = table.getn(mysrclist)
    
    
    
       
        --config_smu_list_sweep(nodenum, smu, srcRange, srclist, limitV, nplc, remoteSense)
        config_smu_list_sweep(1, node[1].smua, mySrcRange, mysrclist, voltageLimit, nplc, true)
    
    
    
       timer.reset()
       
       
       Run_test(true, PulsePeriod, PulseWidth, MeasDelay) -- pass true to print data back to console
       
       time = timer.measure.t()
       print("Time to run: "..time)
       print("****************************************")
       print("Current Source Range: "..node[1].smua.source.rangei)
    
    
  • RE: Triggering SMUs via tsplink

    See if this helps:
    --[[
    
         Purpose:  show how an event on one 2600B can be "echoed" to second 2600B
         
         Setup:  need two 2600B that have TSP-LINK connectors.
                 Assign node 1 and 2 and use the cross-over cable to link them.
                 On front panel, use the reset under TSPLINK to verify the link.
                 
         Method:  Use a timer as stimulus for digital IO active lo pulse.
                  Cause 10 pulses from DIO line 1 on rear DB25 connector.
                  Echo the timer event_id on tsp-link for digital IO on second node to also pulse.        
    
    
    ]]--
    
    
    function ConfigTSPLinkTriggers(nodenum)
        node[nodenum].tsplink.trigger[1].clear()
        node[nodenum].tsplink.trigger[1].mode        = tsplink.TRIG_FALLING
        node[nodenum].tsplink.trigger[2].clear()
        node[nodenum].tsplink.trigger[2].mode        = tsplink.TRIG_FALLING
        node[nodenum].tsplink.trigger[3].clear()
        node[nodenum].tsplink.trigger[3].mode        = tsplink.TRIG_FALLING
    end
    
    
    -- *********************
    --
    --  Main Program
    --
    -- *********************
    reset()
    errorqueue.clear()
    
    if tsplink.state == "offline" then
        nodesFound = tsplink.reset()
        if nodesFound ~= 2 then
            print(string.format("Error: Found %d Nodes. Expecting 2.", nodesFound))
            exit()
        end
    end
    
    -- for each tsplink node    
    ConfigTSPLinkTriggers(1)
    ConfigTSPLinkTriggers(2)
    
    
    -- configure a timer on node 1 to issue 10 events
    -- upon receipt of one tsplink event_id
    nodenum = 1
    node[nodenum].trigger.timer[1].delay = 1e-3
    node[nodenum].trigger.timer[1].stimulus = node[nodenum].tsplink.trigger[1].EVENT_ID
    node[nodenum].trigger.timer[1].count = 10
    node[nodenum].trigger.timer[1].passthrough = false
    node[nodenum].trigger.timer[1].clear()
    
    -- echo the timer event on tsplink two
    node[nodenum].tsplink.trigger[2].stimulus = node[nodenum].trigger.timer[1].EVENT_ID
    
    -- digital IO *could* use timer event directly on this same node
    -- but it can also make use of the locally available tsplink two   
    node[nodenum].digio.trigger[1].clear()
    node[nodenum].digio.trigger[1].mode = digio.TRIG_FALLING
    node[nodenum].digio.trigger[1].pulsewidth = 100e-6
    --node[nodenum].digio.trigger[1].stimulus = node[nodenum].trigger.timer[1].EVENT_ID
    node[nodenum].digio.trigger[1].stimulus = node[nodenum].tsplink.trigger[2].EVENT_ID  
    
    -- this remote node cannot "see" the timer events on other node
    -- this remote node must use the echoed event on tsplink two    
    nodenum = 2
    node[nodenum].digio.trigger[1].clear()
    node[nodenum].digio.trigger[1].mode = digio.TRIG_FALLING 
    node[nodenum].digio.trigger[1].pulsewidth = 100e-6
    node[nodenum].digio.trigger[1].stimulus = node[nodenum].tsplink.trigger[2].EVENT_ID    
    
    
    -- issue an assert to get the party started
    node[1].tsplink.trigger[1].assert()       
        

    Scope shot of the digital IO pulses in attached document.
     
  • Use Digitize V to compute the RMS or Frequency of a Waveform

    <p>&lt;p&gt;&lt;a href=&quot;https://fortive.box.com/s/t3008ugydzhvlqzvcm6zjvixobm27bh8&quot;&gt;&lt;img alt=&quot;Digitize Voltage&quot; src=&quot;https://fortive.box.com/s/t3008ugydzhvlqzvcm6zjvixobm27bh8&quot; style=&quot;float:left;&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt;</p> <p></p> <p></p> <p><a href="https://fortive.box.com/s/t3008ugydzhvlqzvcm6zjvixobm27bh8"><img alt="Digitize V trial 2" src="https://fortive.box.com/s/t3008ugydzhvlqzvcm6zjvixobm27bh8" style="float:left;"></a></p>

    Digitize V trial 3

  • RE: DAQ6510 OverflowHz/V Issue

    Here is a little more general info on using the Digitize Voltage and the TSP scripting to extract frequency information from a measured voltage waveform.

    For your waveform frequency and amplitude, configure the digitizer to obtain enough data to capture at least two peaks.
    waveform view of digitized voltage

    In attached document, is more info and a sample TSP script.
  • RE: Using 2450 SMU in 4200 UTM

    For others who might follow along:
    2450 has USB, LAN and GPIB for remote command control.
    Newer 4200A-SCS have VISA library available from KULT, so could use any of those command interfaces if we code at VISA  API.  Newer 4200A also have the GPIB interface API.

    Older 4200-SCS do not have the VISA library.  They have GPIB API for external instruments accessible from KULT and UTMs.

    This sample code is written using GPIB API to do a voltage sweep on a model 2450 from a UTM in KITE or Clarius.
    The 2450 requires the TSP command set and connected on GPIB to the 4200x.

    In the attached files:
    the *.c file is contain in a zip so that this forum tool permits it.
    The PDF has instructions for installing it.
  • RE: DAQ6510 OverflowHz/V Issue

    Thank you for posting the screenshots.

    So clearly there are some crest factor issues as you have a significant leading edge spike in the waveform.

    In the digitizer mode, if you up range the voltage, what is the max voltage of the spike?  On the full screen graph, you can zoom in and place cursors too.

    I suspect that when using the Freq or VAC modes and low ranges, the spike is saturating the range.

    But higher ranges that tolerate the spike, don’t have sensitivity for the much lower amplitude remaining signal.

    Not sure the origin of the spike.  Calm it down if you can (reduce inductance if the spike corresponds to current load changes).

    With TSP and Digitize, you could extract the freq info from timestamps between two peaks for example.

    Can your use case support idea of not scanning conventionally, but closing a channel and then calling a TSP function?

  • RE: DAQ6510 OverflowHz/V Issue

    My question about using DCV was to get some confidence of the relay function and the wiring to it.

    To make it simpler, do select front terminals and directly feed your signal to dmm.

    For the digitize V, same place you select ACV or DCV, pick Digitize V.

    Swipe screen to see the digitize settings for sample rate and number of samples.

    For your ~20Hz signal, I’d say slow down the sampling rate and set buffer size.

    1KHz and 1000 samples = 1 second of data

    Swipe to graph.

    What range do you have to use to reliably see the waveform?

    What does waveform look like?  Hoping it gives some insight into why VAC is having trouble.

    For freq measurements, what aperture setting did you use?  A 2msec aperture is not long enough to measure freq or period of a 20Hz signal.