• RE: Simultaneous sine waves on SMU 2602 channels A & B

    Here is a lightly edited version of your code:
    1. local _startV -- Used by script to track the starting voltage
    2. local _srcRate = 4000 -- Source Update Rate used by the script Sets the source update rate (pts/sec) used by the script. 
    3.                       --Do not set higher than 8,000 if your waveform will have polarity changes 0V crossings)
    4.     
    5. function SetupAWG(startV, rangeV, limitI, wfrmTbl, remoteSense, trigLineIn)
    6.     -- Do some parameter checks
    7.     --=========================
    8.     if startV == nil then startV = 0 end
    9.     if remoteSense ~= true then remoteSense = false end
    10.     if type(trigLineIn) == "number" then
    11.         trigLineIn = math.floor(trigLineIn)
    12.         if trigLineIn < 0 or trigLineIn > 14 then
    13.             return true, "Error: Selected trigger line is not valid.  trigLineIn must be a number between 0 and 14 or nil."
    14.         end
    15.     elseif trigLineIn ~= nil then
    16.         return true,"Error: Invalid parameter trigLineIn.  trigLineIn must be a number between 0 and 14 or nil."
    17.     end
    18.     _startV = startV
    19.     
    20.     --wfrmTbl = {0.078459,0.156434,0.233445,0.309017,0.382683,0.45399,0.522499,0.587785,0.649448,0.707107,0.760406,0.809017,0.85264,0.891007,0.92388,0.951057,0.97237,0.987688,0.996917,1,0.996917,0.987688,0.97237,0.951057,0.92388,0.891007,0.85264,0.809017,0.760406,0.707107,0.649448,0.587785,0.522499,0.45399,0.382683,0.309017,0.233445,0.156434,0.078459,0,-0.078459,-0.156434,-0.233445,-0.309017,-0.382683,-0.45399,-0.522499,-0.587785,-0.649448,-0.707107,-0.760406,-0.809017,-0.85264,-0.891007,-0.92388,-0.951057,-0.97237,-0.987688,-0.996917,-1,-0.996917,-0.987688,-0.97237,-0.951057,-0.92388,-0.891007,-0.85264,-0.809017,-0.760406,-0.707107,-0.649448,-0.587785,-0.522499,-0.45399,-0.382683,-0.309017,-0.233445,-0.156434,-0.078459,0}      
    21.    
    22.    -- compute the sine wave
    23.     pts_per_cycle = 72
    24.     wfrmTbl = {}
    25.     for i=1, pts_per_cycle do
    26.         wfrmTbl[i] = 1 * math.sin(i * 2 * math.pi/pts_per_cycle)
    27.     end
    28.     
    29.     -- use some phase shift for smub sine wave
    30.     wfrmTbl_smub = {}
    31.     for i=1, pts_per_cycle do
    32.         wfrmTbl_smub[i] = 1 * math.sin(i * 2 * math.pi/pts_per_cycle + math.rad(90))
    33.     end
    34.     
    35.     
    36.     
    37.         
    38.     -- Setup the SMU for arb waveform output
    39.     --======================================
    40.     reset()
    41.     smua.reset()
    42.     smub.reset()
    43.     
    44.     -- digital output trigger for external equipment
    45.     -- configure digital IO line 1 to output a active LO/falling edge
    46.     -- pulse at start of each current pulse
    47.     digio.trigger[1].clear()
    48.     digio.trigger[1].mode = digio.TRIG_FALLING  
    49.     digio.trigger[1].pulsewidth = 10e-6
    50.     digio.trigger[1].stimulus = trigger.timer[1].EVENT_ID
    51.     
    52.     smua.source.func                    = smua.OUTPUT_DCVOLTS
    53.     smub.source.func                    = smub.OUTPUT_DCVOLTS
    54.     if remoteSense == true then
    55.         smua.sense                        = smua.SENSE_REMOTE
    56.         smub.sense                        = smub.SENSE_REMOTE
    57.     else
    58.         smua.sense                        = smua.SENSE_LOCAL
    59.         smub.sense                        = smub.SENSE_LOCAL
    60.     end
    61.     smua.source.autorangev            = smua.AUTORANGE_OFF
    62.     smua.source.autorangei            = smua.AUTORANGE_OFF
    63.     smua.source.rangev                = rangeV
    64.     smua.source.levelv                = startV
    65.     smua.source.limiti                = limitI
    66.     smua.source.delay                = 0
    67.     smua.source.settling            = smua.SETTLE_FAST_POLARITY
    68.     
    69.        
    70.     smub.source.autorangev            = smub.AUTORANGE_OFF
    71.     smub.source.autorangei            = smub.AUTORANGE_OFF
    72.     smub.source.rangev                = rangeV
    73.     smub.source.levelv                = startV
    74.     smub.source.limiti                = limitI
    75.     smub.source.delay                = 0
    76.     smub.source.settling            = smub.SETTLE_FAST_POLARITY
    77.     
    78.     
    79.     -- Configure the Trigger Model
    80.     --============================
    81.     -- Timer 1 controls the time per point table phase A
    82.     trigger.timer[1].delay            = 1 / _srcRate
    83.     trigger.timer[1].count            = table.getn(wfrmTbl) > 1 and table.getn(wfrmTbl) - 1 or 1
    84.     if trigLineIn == nil then
    85.         -- Immediate
    86.         trigger.timer[1].stimulus    = smua.trigger.ARMED_EVENT_ID
    87.         
    88.     elseif trigLineIn == 0 then
    89.         -- Front panel TRIG button
    90.         display.trigger.clear()
    91.         trigger.timer[1].stimulus    = display.trigger.EVENT_ID
    92.     else
    93.         -- Digio Trigger
    94.         digio.trigger[trigLineIn].clear()
    95.         digio.trigger[trigLineIn].mode = digio.TRIG_EITHER
    96.         trigger.timer[1].stimulus    = digio.trigger[trigLineIn].EVENT_ID
    97.     end
    98.     trigger.timer[1].passthrough    = true
    99.     
    100.     
    101.     
    102.  
    103.     -- Configure SMU Trigger Model for arb waveform output
    104.     smua.trigger.source.listv(wfrmTbl)
    105.     smua.trigger.source.limiti        = limitI
    106.     smua.trigger.measure.action        = smua.DISABLE
    107.     smua.trigger.endpulse.action    = smua.SOURCE_HOLD
    108.     smua.trigger.endsweep.action    = smua.SOURCE_HOLD  
    109.     smua.trigger.count                = table.getn(wfrmTbl)
    110.     smua.trigger.arm.count            = 1
    111.     smua.trigger.arm.stimulus        = 0
    112.     smua.trigger.source.stimulus    = trigger.timer[1].EVENT_ID
    113.     smua.trigger.measure.stimulus    = 0
    114.     smua.trigger.endpulse.stimulus    = 0
    115.     smua.trigger.source.action        = smua.ENABLE
    116.     
    117.         
    118.     smub.trigger.source.listv(wfrmTbl_smub)
    119.     smub.trigger.source.limiti        = limitI
    120.     smub.trigger.measure.action        = smub.DISABLE
    121.     smub.trigger.endpulse.action    = smub.SOURCE_HOLD
    122.     smub.trigger.endsweep.action    = smub.SOURCE_HOLD
    123.     smub.trigger.count                = table.getn(wfrmTbl)
    124.     smub.trigger.arm.count            = 1
    125.     smub.trigger.arm.stimulus        = 0
    126.     smub.trigger.source.stimulus    = trigger.timer[1].EVENT_ID  -- ALC
    127.     smub.trigger.measure.stimulus    = 0
    128.     smub.trigger.endpulse.stimulus    = 0
    129.     smub.trigger.source.action        = smub.ENABLE
    130.     
    131.     --==============================
    132.     -- End Trigger Model Configuration
    133.     
    134.     if errorqueue.count > 0 then
    135.         return true,"Error occured during setup.  Please check that your parameters are valid."
    136.     else
    137.         return false,"No error."
    138.     end
    139. end
    140.  
    141.  
    142. function RunAWG(numCycles)
    143.     if numCycles == nil or numCycles < 0 then
    144.         numCycles = 1
    145.     end
    146.     
    147.     -- Set the number of cycles to output
    148.     smua.trigger.arm.count = numCycles
    149.     smub.trigger.arm.count = numCycles
    150.     -- Turn output on
    151.     smua.source.output = smua.OUTPUT_ON
    152.     smub.source.output = smub.OUTPUT_ON
    153.     -- Start the trigger model execution
    154.     smub.trigger.initiate()  -- start this first
    155.     smua.trigger.initiate()
    156.     
    157.     if errorqueue.count > 0 then
    158.         return true,"Error occurred.  See error queue for details."
    159.     else
    160.         return false,"No error."
    161.     end
    162. end
    163.  
    164.  
    165. --[[ Name: StopAWG()
    166.  
    167.     Usage: err,msg = StopAWG()
    168.  
    169.     Description:
    170.         This function stops the waveform output and turns the SMU
    171.         output off.
    172. --]]
    173. function StopAWG()
    174.     smua.abort()
    175.     smua.source.output = 0
    176.     smua.source.levelv = _startV
    177.     
    178.     smub.abort()
    179.     smub.source.output = 0
    180.     smub.source.levelv = _startV
    181.     
    182.     if errorqueue.count > 0 then
    183.         return true,"Error occured.  See error queue for details."
    184.     else
    185.         return false,"No error."
    186.     end
    187. end

    To run it:
    1. --SetupAWG(startV, rangeV, limitI, wfrmTbl, remoteSense, trigLineIn)
    2. SetupAWG(0, 20, 0.1, wfrmC, false, nil)
    3.  
    4. --RunAWG(numCycles)
    5. RunAWG(8)

    See scope shot attached.
  • RE: Simultaneous sine waves on SMU 2602 channels A & B

    Hello,

    You are almost there.

    To accomplish the phase shift, were you thinking to use a different timer for each SMU?
    Instead, I would use a single timer to provide the smuX.trigger.source.stimulus to each SMU channel.

    Rather than providing a list of source levels, I recommend computing them. in the TSP or Lua code.
    You can account for the phase shift in the computed source levels.
    1.    
    2.    -- compute the sine wave
    3.     pts_per_cycle = 72
    4.     wfrmTbl = {}
    5.     for i=1, pts_per_cycle do
    6.         wfrmTbl[i] = 1 * math.sin(i * 2 * math.pi/pts_per_cycle)
    7.     end
    8.     
    9.     -- use some phase shift for smub sine wave
    10.     wfrmTbl_smub = {}
    11.     for i=1, pts_per_cycle do
    12.         wfrmTbl_smub[i] = 1 * math.sin(i * 2 * math.pi/pts_per_cycle + math.rad(90))
    13.     end
  • RE: 2636B: V pulse and transient current measurement

    You second task can be implemented with the asynchronous trigger model.

    Old forum showing the feature:
    asynchronous sampling from the source timing - capture transients

    I will upload a simple LabVIEW sample for loading scripts/functions and then making use of the functions from VIs.
     
  • RE: picoammeter 6485 firmware update problem

    Hello.
    I asked the factory AE to take a look at this.
    We suspect you have a serial number that has C01 firmware.
    If that is true, the unit cannot be down rev to Bxx firmware.

    Please provide screen shot of the *idn? response.
  • RE: IV measurements using arb waveform

    For PMU, there are three modes:
    two level pulsing (base and amplitude)
    SegArb
    FullArb

    The FullArb has no measurements;  it is sourcing only.
    The KPULSE utility is accessing the FullArb to play sine waves, etc.

    If you want IV measurements AND doing sine wave, you'd have to build it up from a piece wise segments in a SegArb sequence/waveform.

    Check out the pmu-dut-examples project and the pmu-segarb-complete test.
    It is using the PMU_SegArb_ExampleFull user module of PMU_examples_ulib.
    So long as you observe the rules for sequence defining, you can enter any SegArb that you desire on this.

    I suggest you contact your sales office/local applications engineer to get some detail on PMU.

     
  • RE: Simultaneous sine waves on SMU 2602 channels A & B

    Hello Fabrizio,

    Yes, this is very much possible with the 2600B SourceMeter.

    Sounds like you have our application note on ARB features of the 2600B SMUs
    Github code
    ARB Features for testing Ford EMC

    Either approach could work for generating sine wave from the SMUs.

    Suppose you use a list of 100 points to describe one cycle of the waveform.
    If you source those values at 10KHz rate, you’ll have the 100 Hz waveform.

    The max source rate is about 12K, so you’re approaching the limits of the speed.

    Keeping with the idea of 100 point list sweep:
    if trigger count is 100, then one cycle is sourced.
    if more than 100, the list is recycled.
    If trigger count is 0, then plays until you send abort command.

    If you don’t already, download the Test Script Builder application for running TSP code with the instrument.
    Then port it out to C# or Python, etc.

    Test Script Builder
     
  • RE: License File Not Working for KickStart

    Try this:
    - if open, close KickStart application.
    - use file explorer to navigate to the C:\ProgramData\Keithley directory
    - delete the Keithley directory
    - restart KickStart and again navigate to the manage license.
    Any host id info now?

    If still not, please contact your local sales/support office for assistance.
  • RE: Python VISA control of DAQ6510 with 7700 MUX card

    There are many, but I typically use the status byte and opc() for operation complete.

    Here I setup for 10 scans of 4 thermocouple channels:
    1. my_instr.write("status.clear()")
    2. my_instr.write("status.request_enable = 32")
    3. my_instr.write("status.standard.enable = 1")
    4. my_instr.write("myScanList = \"101,110, 115, 120\"")
    5. my_instr.write("channel.setdmm(myScanList, dmm.ATTR_MEAS_FUNCTION, dmm.FUNC_TEMPERATURE)")
    6. my_instr.write("channel.setdmm(myScanList, dmm.ATTR_MEAS_THERMOCOUPLE, dmm.THERMOCOUPLE_K)")
    7. my_instr.write("channel.setdmm(myScanList, dmm.ATTR_MEAS_REF_JUNCTION, dmm.REFJUNCT_INTERNAL)")
    8. my_instr.write("channel.setdmm(myScanList, dmm.ATTR_MEAS_OPEN_DETECTOR, dmm.ON)")
    9. my_instr.write("channel.setdmm(myScanList, dmm.ATTR_MEAS_NPLC, 1)")
    10. my_instr.write("display.watchchannels = myScanList")
    11. my_instr.write("scan.scancount = 10")
    12. my_instr.write("scan.scaninterval = 1")
    13. my_instr.write("scan.create(\"101,110, 115, 120\")")

    Then when ready to run the scan:
    1. #status poll for opc()
    2. my_instr.write("status.clear()")
    3. #attach our session to read_stb channel
    4. print("First status byte value: " + str(my_instr.read_stb()))
    5. #my_instr.read_stb()  
    6. my_instr.write("trigger.model.initiate()")
    7. my_instr.write("opc()")  #this signals operation complete
    8. #repeat until the SRQ bit is set
    9. still_running = True
    10. status_byte = 0
    11. debug = 1
    12. while still_running:
    13.         status_byte = int(my_instr.read_stb())
    14.         #if debug: print(status_byte)
    15.         if debug: print(str(status_byte) + ' - ' + str(bin(status_byte)) + ' - ' + str(hex(status_byte)))
    16.         if (status_byte and 64) == 64:
    17.              still_running = False
    18.         time.sleep(0.5)  #500msec pause before asking again
    19.          
    20. print("Last status byte value: " + str(status_byte))
    21. print("Scan is done - go get the data")

    Typical output from the Python code:
    1. First status byte value: 0 0 - 0b0 - 0x0
    2. 0 - 0b0 - 0x0
    3. 0 - 0b0 - 0x0
    4. 0 - 0b0 - 0x0
    5. 0 - 0b0 - 0x0
    6. 0 - 0b0 - 0x0
    7. 0 - 0b0 - 0x0
    8. 0 - 0b0 - 0x0
    9. 0 - 0b0 - 0x0
    10. 0 - 0b0 - 0x0
    11. 0 - 0b0 - 0x0
    12. 0 - 0b0 - 0x0
    13. 0 - 0b0 - 0x0
    14. 0 - 0b0 - 0x0
    15. 0 - 0b0 - 0x0
    16. 0 - 0b0 - 0x0
    17. 0 - 0b0 - 0x0
    18. 0 - 0b0 - 0x0
    19. 96 - 0b1100000 - 0x60
    20. Last status byte value: 96
    21. Scan is done - go get the data


    The attached PDF has a second example for when using TSP functions.
  • RE: DMM 2750 Auto recording & export of measured values

    Are you using any scan cards with the 2750?  Or using it as a DMM to measure Ohms of a single devices at a time.

    The 2750 can be controlled by sending the SCPI commands that it understands over GPIB or RS-232.
    The SCPI commands are documented in the 2750 manual.

    The KickStart software can interface with 2750 over GPIB interface.
    The Windows computer will need a GPIB interface from National Instruments or Keithley (KUSB-488B).

    If using scan cards, use the datalogger application of KickStart (KICKSTARTFL-DL).
    If not using scan cards, use the DMM application of KickStart (KICKSTARTFL-DMM)

    More info:KickStart
  • RE: Python VISA control of DAQ6510 with 7700 MUX card

    Assuming the scan is complete, then from Python you could send something like this:
    1. my_instr.write("printbuffer(1, defbuffer1.n, defbuffer1.readings)")
    2. raw_data = my_instr.read()
    3. raw_data_array = raw_data.split(",")
    4. my_instr.write("printbuffer(1, defbuffer1.n, defbuffer1.relativetimestamps)")
    5. raw_time = my_instr.read()
    6. scaled_time = raw_time.split(",")

    The data from the readings will be from the various channels.
    So here is simple code for putting that into arrays for each channel
    1. #for the number of channels in the scan, need to decimate the data
    2. number_channels_in_scan = 4
    3. number_data_elements_per_chan = 1
    4. ch101_time = []
    5. ch101 = []
    6. ch102 = []
    7. ch103 = []
    8. ch104 = []
    9. for i in range(0, len(raw_data_array), number_data_elements_per_chan*number_channels_in_scan):
    10.     if len(raw_data_array[i]) > 0:
    11.         ch101_time.append(float(scaled_time[i]))
    12.         ch101.append(float(raw_data_array[i]))
    13.         ch102.append(float(raw_data_array[i+1]))
    14.         ch103.append(float(raw_data_array[i+2]))
    15.         ch104.append(float(raw_data_array[i+3]))