TDR mode DUT setup with fixture de-embedding

This Python example, tdr_dut_setup.py, creates a 2-port single-ended DUT setup and applies fixture de-embedding. No TDR waveforms are captured or measured, as this script simply shows how to successfuly setup a DUT with de-embedding. Before running the script, you must install a TDR module in the 86100D's slot 1. Calibrate the module.

TDR/TDT instrument mode requires a instrument as there are no simulated TDR/TDT modules. Perform a TDR step calibration on the TDR module before running the script.

Editable Constants

At the top of the script, edit the following three global constants with your values. Each constant must have a value and all three are passed to the basic_setup() function. Refer to locating the VISA address.

ADDRESS
Edit this constant to be the VISA HiSLIP address for FlexDCA on the PC or an DCA-X.
SPARAMETER_FILE
The file name including path for the s2p file that is loaded into the new deembed fixtures. This happens in the create_deembed_fixture() function. The file is imported from FlexDCA's Demo folder, which is sure to be available for the script. Any s2p that you want can be substituted. The demo folder is indicated by the path substitution variable (%DEMO_DIR%). Path subsitution variables make saving files in the default user folders easier and more reliable because they automatically point to different paths depending if FlexDCA is running on a PC or 86100D.

Script Notes

The find_available_dut() function, locates the first available DUT definition. Up to 16 DUTs can be defined. Determines the next available DUT number and returns that DUT. So, if 3 DUTs exist, it returns "DUT4".

The find_available_fixtures() function, locates the first available deembed definition. Up to 16 fixture components can be defined for the Fixture De-Embedding setup. Returns a list of the requested fixture names. So, if 3 fixtures exist (a,b, and c), it returns "FCOMD" and "FCOME'. Up to 16 fixtures can exist with the last one identified with the letter "P". If there are not enough available fixtures and empty list is returned.

The create_deembed_fixture() function creates a new fixture component. The 5th character in the fixture argument (index number 4) identifies the new fixture. For example, "E" in "FCOME". Letters can range from "A" to "P". The filename argument is the s2p file.

The create_TDR_setup() function, creates a new TDR DUT setup (2-port SE) using the dut argument. The dut argument is a string. For example, "DUT4".

Algorithm

  1. Connects to FlexDCA.
  2. Changes to TDR/TDT mode. Assumes that an TDR module is installed in slot 1.
  3. Determine if a DUT definition is available in TDR Setup. A maximum of 16 DUTs defined.
  4. Determine if two fixture de-embedding component definitions are available in TDR De-Embedding Setup. A maximum of 16 fixture components defined.
  5. Creates two fixture components if available otherwise aborts program. The fixture components are created from an s2p S-parameter file that is located in the FlexDCA's Demo folder.
  6. Creates a new single-ended DUT setup with fixture deembeding.
  7. Turns on the channel 1A step. Turns on channel 1B. Turns off channels 1C and 1D.
  8. Save an instrument state. For example, DUT3.setx. This ensures that the DUT setup and fixture de-embedding compontents are saved.
  9. Closes the FlexDCA session.

Example Script

Copy

tdr-dut-setup.py

# -*- coding: utf-8 -*-
""" In TDR mode, creates a 2-port single-ended DUT and creates a fixture
deembedding setup with two fixture components.
Finds if capacity exists to add a new TDR DUT setup. There
can be up to 16. If available, creates a 2-port single-ended
DUT in TDR setup.
Finds if capacity exists to add 2 fixture deembedding
components. There can be up to 16. If available, creates
components from s2p file in DEMO folder.
Creates DUT setup with fixture deembedded fixtures connected.
Requires N1055A  or 54754A TDR module. """

import pyvisa as visa  # import VISA library

ADDRESS = 'TCPIP0::K-86100D-00003::hislip0,4880::INSTR'  # DCA-X
CHA = '2A'  # TDR module channel
CHB = '2B'  # TDR module channel
SPARAMETER_FILE = '"%DEMO_DIR%\\S-Parameter Data\Demo\\TDRDemoBoard_ET55780\
\\ET55780_Impedance_Profile.s2p"'


def open_flexdca_connection(address):
    """ Opens visa connection to FlexFlexDCA. """
    print('Connecting to Flexdca ...')
    try:
        rm = visa.ResourceManager()
        connection = rm.open_resource(address)
        connection.timeout = 20000  # Set connection timeout to 20s
        connection.read_termination = '\n'
        connection.write_termination = '\n'
        inst_id = connection.query('*IDN?')
        print('\nFlexDCA connection established to:\n' + inst_id, flush=True)
    except (visa.VisaIOError, visa.InvalidSession):
        print('\nVISA ERROR: Cannot open instrument address.\n', flush=True)
        return None
    except Exception as other:
        print('\nVISA ERROR: Cannot connect to instrument:', other, flush=True)
        print('\n')
        return None
    return connection


def find_available_dut():
    """ Up to 16 DUTs can be defined. Determines the next available DUT
    number and returns that DUT. So, if 3 DUTs exist, it returns "DUT4".
    """
    global FlexDCA
    for number in range(1, 17):
        dut = 'DUT' + str(number)
        if FlexDCA.query(':TDR:' + dut + ':ENABle?') == '1':
            if number == 16:  # all potential DUTs exist
                return ''
            continue
        else:
            return dut  # found available DUT


def find_available_fixtures(*args):
    """ Up to 16 fixture components can be defined for the Fixture
    De-Embedding setup. Returns the number of requested fixture
    names and returns the names. For example, if 3 fixtures
    exist (a,b, and c), it might return "FCOMD" and "FCOME'.
    If there are not enough available fixtures and empty tupple is returned.
    """
    global FlexDCA
    letters = 'ABCDEFGHIJKLMNOP'
    fixture_count = len(args)  # args is tupple of requestd fixtures
    fixture = ''
    available = []
    fixture_list = []
    for i in range(0, 16):  # find available fixtures
        fixture = 'FCOM' + letters[i]
        if FlexDCA.query(':TDR:DEEMbed:' + fixture + ':STATus?') == 'INV':
            available.append(fixture)  # make a list of available fixtures
    if len(available) < fixture_count:
        fixture_list = ['' for item in range(0, fixture_count)]
        return fixture_list  # Fixtures not available, return empty list.
    i = 0
    while i < fixture_count:
        fixture_list.append(available[i])
        i += 1
    return fixture_list


def create_deembed_fixture(fixture, filename):
    """ Creates a new fixture component.
    The 5th character in the fixture argument (index number 4) identifies
    the new fixture. For example, "E" in "FCOME". Letters can range from
    "A" to "P". The filename argument is the s2p file.
    """
    global FlexDCA
    FlexDCA.write(':TDR:DEEMbed:' + fixture + ':LOAD:FNAMe ' + filename)
    FlexDCA.write(':TDR:DEEMbed:' + fixture + ':LOAD')
    print('Created fixture: ' + fixture[4])


def create_TDR_setup(dut, fixture1, fixture2):
    """ Creates a new TDR DUT setup (2-port SE) using the dut argument. The
    dut argument is a string. For example, "DUT4".
    """
    global FlexDCA
    FlexDCA.write(':TDR:AMODe SENDed')  # single-ended DUT
    FlexDCA.write(':TDR:' + dut + ':ENABle ON')
    FlexDCA.write(':TDR:' + dut + ':DTYPe SEPorts2')
    print('Created ' + dut)
    FlexDCA.write(':TDR:CHANnel' + CHA + ':DUT ' + dut)
    FlexDCA.write(':TDR:CHANnel' + CHA + ':PORT PORT1')
    FlexDCA.write(':TDR:STIMulus:CHANnel' + CHA + ':STEP ON')
    FlexDCA.write(':TDR:CHANnel' + CHB + ':DUT ' + dut)
    FlexDCA.write(':TDR:CHANnel' + CHB + ':PORT PORT2')
    FlexDCA.write(':TDR:DEEMbed:' + dut + ':PORT1:FIXTure ' + fixture1)
    FlexDCA.write(':TDR:DEEMbed:' + dut + ':PORT1:TPORt PORT1')
    FlexDCA.write(':TDR:DEEMbed:' + dut + ':PORT1:DPORt PORT2')
    FlexDCA.write(':TDR:DEEMbed:' + dut + ':PORT2:FIXTure ' + fixture2)
    FlexDCA.write(':TDR:DEEMbed:' + dut + ':PORT2:TPORt PORT2')
    FlexDCA.write(':TDR:DEEMbed:' + dut + ':PORT2:DPORt PORT1')
    FlexDCA.write(':TDR:STIMulus:CHANnel' + CHA + ':STEP ON')
    print('Created TDR setup with deembedding.', flush=True)


def save_instrument_state(dut):
    """ Save DUT and fixture deembeding settings in instrument state file. """
    global FlexDCA
    print('Saving the instrument state....')
    FlexDCA.write(':DISK:SETup:SAVe "%USER_DATA_DIR%\\Setups\\' +
                  dut + '.setx"')


FlexDCA = open_flexdca_connection(ADDRESS)
FlexDCA.query(':SYSTem:MODE TDR;*OPC?')
dut = find_available_dut()
fixture1 = ''
fixture2 = ''
fixture1, fixture2 = find_available_fixtures(fixture1, fixture2)
if not (fixture1 and fixture2):
    print('\nERROR: fixtures not available.')
elif not dut:
    print('\nERROR: DUT not available.')
else:
    create_deembed_fixture(fixture1, SPARAMETER_FILE)
    create_deembed_fixture(fixture2, SPARAMETER_FILE)
    create_TDR_setup(dut, fixture1, fixture2)
    save_instrument_state(dut)
    print('Program has successfully completed.')
FlexDCA.write(':SYSTem:GTLocal')
FlexDCA.close()