Posted Fri, 08 Dec 2023 09:56:13 GMT by Hartmann, Michael
Hello,

I am struggeling to trigger another SMU using a tsplink trigger over tsplink.

I am using two Keithley 2612B System Source Meters. Setting up the tsplink network works and I am able to send commands using node[2].execute(cmd) to the second SMU.

My goal is to output synchronized sweeps on both SMUs. On smua of SMU1 and SMU2 a pulsed sweep should be outputted, on smub of SMU1 and SMU2 also a pulsed sweep with constant voltage should be outputted. In addition, the currents should be measured.

The main idea is to use two timers to control the pulse width and the pulse period. The timer 1 (period time) is stimulated by a tsplink trigger (tsplink.trigger[2].EVENT_ID). If I look at the scope, this works fine for SMU1 (the master SMU) on which I execute the script. However, SMU2 seems never to receive the trigger.

Here is the source code of the script that I am using:

function pm_configure(pulse_levels_v, constant_v, bias_level_v, limit_i, pulse_period_s, pulse_width_s, measure_time_s, measure_delay_s) 
    -- checks 
    assert(pulse_width_s > (measure_time_s + measure_delay_s), "pulse width must be longer than measure time + measure delay") 
    assert(pulse_period_s > pulse_width_s, "pulse period must be longer than pulse width") 
 
    -- measure time in number of power line cycles 
    local measure_nplc = measure_time_s * localnode.linefreq 
 
    -- number of pulses
    local npulses = table.getn(pulse_levels_v) 
 
    -- Use trigger timer 1 to control the period and trigger timer 2 to control the 
    -- pulse width. 
    -- period_timer:     trigger.timer[1] 
    -- pulsewidth_timer: trigger.timer[2] 
 
    -- Configure the period timer to output. 
    trigger.timer[1].delay = pulse_period_s 
    -- The effective count is npulses-1 because the passthrough setting is true. 
    trigger.timer[1].count = npulses-1 
    -- Configure the timer to immediately output a trigger event when it is started. 
    trigger.timer[1].passthrough = true 
    -- Start the timer with a trigger from tsplink
    trigger.timer[1].stimulus = tsplink.trigger[2].EVENT_ID 
 
    -- Configure the pulse width timer to output one trigger event for each period. 
    trigger.timer[2].delay = pulse_width_s 
    trigger.timer[2].count = 1 
    -- Do not immediately output a trigger event when pulse width timer is started. 
    trigger.timer[2].passthrough = false 
    -- Start the pulse width timer with the period timer output trigger event. 
    trigger.timer[2].stimulus = trigger.timer[1].EVENT_ID 
 
    for _,smu in ipairs({smua, smub} ) do 
        -- reset SMU such that we are in a defined state
        smu.reset()
 
        smu.sense = smu.SENSE_LOCAL -- 2-wire 
 
        -- perform calibration measurements 
        smu.measure.autozero = smu.AUTOZERO_ONCE 
 
        -- clear buffers 
        smu.nvbuffer1.clear() 
 
        -- set measurement delay 
        smu.measure.delay = measure_delay_s 
 
        smu.measure.autorangei = smu.AUTORANGE_OFF
 
        -- Configure the source function. 
        smu.source.func = smu.OUTPUT_DCVOLTS 
        smu.source.levelv = bias_level_v 
        smu.source.limiti = limit_i 
 
        -- Configure the trigger model to execute a 10-point fixed-level voltage pulse 
        -- train. No measurements are made. 
        smu.trigger.source.action = smu.ENABLE 
 
        smu.measure.nplc = measure_nplc 
        smu.trigger.measure.i(smu.nvbuffer1) 
        smu.trigger.measure.action = smu.ENABLE 
 
        -- Set the trigger source limit, which can be different than the bias limit. 
        -- This is an important setting for pulsing in the extended operating area. 
        smu.trigger.source.limiti = limit_i 
        smu.measure.rangei = limit_i 
        -- Trigger SMU source action with the period timer event. 
        smu.trigger.source.stimulus = trigger.timer[1].EVENT_ID 
        -- Configure the endpulse action to achieve a pulse. 
        smu.trigger.endpulse.action = smu.SOURCE_IDLE 
        -- Trigger the SMU end pulse action with a pulse width timer event. 
        smu.trigger.endpulse.stimulus = trigger.timer[2].EVENT_ID 
        -- Set the trigger model count to generate one npulses pulse train. 
        smu.trigger.arm.count = 1 
        smu.trigger.count = npulses 
    end 
 
    smua.trigger.source.listv(pulse_levels_v) 
    smub.trigger.source.listv({constant_v}) 
    for _,smu in ipairs({smua, smub}) do 
        smu.source.output = smu.OUTPUT_ON 
        smu.trigger.initiate() 
    end 
end 
 
function pm_trigger() 
    tsplink.trigger[2].mode = tsplink.TRIG_SYNCHRONOUS 
    tsplink.trigger[2].assert() 
 
    -- Wait for the sweep to complete. 
    waitcomplete() 
end 
 
function main() 
  -- empty error queue 
  errorqueue.clear() 
 
  -- tsplink.reset() 
  tsplink.reset() 
  assert(tsplink.state == "online", "resetting tsplink was not successful") 
  node[2].tsplink.group = 2 
 
  -- copy script to node 2 
  node[2].dataqueue.clear()
  node[2].dataqueue.add(sweeps.source) 
  node[2].execute("script.newautorun(dataqueue.next())") 
 
  -- perform a reset
  reset() 
  node[2].execute("pm_configure({1,2,3,4,5,6,7,8}, 2.5, 0, 0.1, 50e-3, 25e-3, 5e-3, 1e-3)") 
  pm_configure({1,2,3,4,5,6,7,8}, 2.5, 0, 0.1, 50e-3, 25e-3, 5e-3, 1e-3) 
 
  -- send trigger 
  pm_trigger() 
   
  -- check if errors occured 
  print(errorqueue.count)
end


The script sets up the network, copies the script from SMU1 to SMU2, sets up the sweeps on both SMUs by calling the function pm_configure and finally sends the trigger. The output of the 1st SMU (master SMU) is as expected. However, the output of SMU2 is not as expected and it seems that the trigger event is never noticed (see attached waveform).

I am confident that the trigger event is the problem, because if I change the trigger event from tsplink (tsplink.trigger[2].EVENT_ID) to display.trigger.EVENT_ID, then I see the sweep at SMU1 if I press the TRIG key of SMU1, and I see the sweep at SMU2 if I press the TRIG key of SMU2.

Why is the trigger event over tspnet not noticed by the 2nd SMU?
Posted Fri, 08 Dec 2023 15:52:12 GMT by Hartmann, Michael
After a bit more of research, I am able to simplify my question. I want to use the event smua.trigger.ARMED_EVENT_ID of the node 1 to be the stimulus for timers on node 1 and node 2. But it seemed that the tsplink trigger is not correctly echoed (I am referring to page 9 of this document: https://download.tek.com/document/1KW-61291-1_Trigger_Sync_High_ProductinTest_VCSELs_083018.pdf).

In particular, this triggers the timers (even though the timers are not triggered synchronously):
node[node_number].trigger.timer[1].stimulus = node[1].smua.trigger.ARMED_EVENT_ID
What I want, however, is that the event node[1].smua.trigger.ARMED_EVENT_ID is echoed on the tsplink. This code, however, does not trigger any timer:
node[node_number].tsplink.trigger[2].stimulus = node[1].smua.trigger.ARMED_EVENT_ID
node[node_number].trigger.timer[1].stimulus = node[node_number].tsplink.trigger[2].EVENT_ID

Why does this not work? I had expected that the event ARMED_EVENT of smua of node 1 is echoed and available on all nodes (node 1 and 2 in my example) as node[node_number].tsplink.trigger[2].EVENT_ID. What am I getting wrong?

Posted Mon, 18 Dec 2023 22:04:36 GMT by C, Andrea
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.
 
Posted Wed, 20 Dec 2023 07:58:18 GMT by Hartmann, Michael
That seems to work for me, thank you!

You must be signed in to post in this forum.