Hardware Bootup (N7734A)

The hardware-bootup-N7734A.py script demonstrates booting up FlexOTO the first time which involved building the Hardware Diagram and starting two Stations. The script opens a VISA connection to hislip0 which is FlexOTO Hardware Diagram's address. A bootup script never opens a VISA connection to a FlexOTO Station; opening a Station connection is the job for your Test Station script!

This example script has been tested and works with a Keysight N7734A switch. See also the example script for the Dicon 600 switch.

After this script completes, run the example Test Station script to build a test program and perform measurements.

The example Test Station script can be run after both the hardware-bootup-N7734A.py and hardware-bootup-Dicon.py scripts without modification. This demonstates how Test Programs are independent of the Hardware Diagram.

To run the hardware-bootup-N7734A.py as written, you will need the following hardware. Or, you can change the script to match your hardware.

  • One N1092A/B DCA-M (with options PLK, CDR, 30A/40A, and IRC). You'll find variables to enter the model numbers at the top of the script.
  • Keysight N7734A 1 x 13 optical switch.
  • Two four-lane DUT Fixtures (wavelength division mutliplexing is not used)

Edit the following constants are located at the top of the script to control the setup:

  • visa_address string on line 12. If you're running the script on your local PC, use localhost. Otherwise, use the name of the PC where FlexOTO is installed.
  • SWITCH. This is the optical switch's name as returned by the :CONFigure:SWITch:ALL? query. You can also use the Interactive SCPI Command Tree dialog to learn the name of your switch.
  • DCAM_MODULES. A list of model numbers for the DCA-Ms. In this case, only one DCA-M is used.
  • FIXTURES. Dictionary with Station number keys and values that are the name that you want to give your fixture blocks.
  • LANE_CNT. The number of lane in your fixtures.
  • STATION_CNT. The number of Stations to create. Normally, there would be one Station assigned to each test station.

The following picture shows the FlexOTO Hardware Diagram configuration that results from running the script.

This script performs the following tasks:

  1. Confirms the connected DCA-Ms
  2. Constructs the Hardware Diagram on FlexOTO's primary GUI.
  3. Defines and launches the number of FlexOTO's Station child processes.

Example Script

Copy
Hardware Diagram Program
#******************************************************************************
#    MIT License
#    Copyright(c) 2023 Keysight Technologies
#    Permission is hereby granted, free of charge, to any person obtaining a copy
#    of this software and associated documentation files (the "Software"), to deal
#    in the Software without restriction, including without limitation the rights
#    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#    copies of the Software, and to permit persons to whom the Software is
#    furnished to do so, subject to the following conditions:
#    The above copyright notice and this permission notice shall be included in all
#    copies or substantial portions of the Software.
#    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#    SOFTWARE.
#******************************************************************************

import pyvisa as visa  # import VISA library

visa_address = 'TCPIP0::localhost::hislip0,4880::INSTR'  # Edit as needed
# Switch module name required for :CONFigure:PORT:CONNect command arguments
SWITCHES = ['"N7734A"']  # switch name
DCAM_MODELS = ['N1092A']
# station number keys, DUT fixture name values
FIXTURES = {'1': '"Test Station 1"', '2': '"Test Station 2"'}  # station number keys, DUT fixture name values
LANE_CNT = 4
STATION_CNT = 2


class NoModuleException(Exception):
    """ Exception handler when a DCA-M module is not found. """
    pass


class NoSwitchException(Exception):
    """ Exception handler when a switch is not found. """
    pass


def open_connection(address):
    """ Opens visa connection FlexOTO. """
    print('Connecting to FlexOTO Hardware Diagram ...')
    try:
        rm = visa.ResourceManager()
        connection = rm.open_resource(address)
        connection.timeout = 5000  # Set connection timeout to s
        connection.read_termination = '\n'
        connection.write_termination = '\n'
        inst_id = connection.query('*IDN?')
        print('\nFlexOTO connection established to:\n\t' + inst_id, flush=True)
        connection.write(':SYSTem:DEFault')
        connection.query('*OPC?')
    except (visa.VisaIOError, visa.InvalidSession):
        print('\nVISA ERROR: Cannot open instrument address.\n', flush=True)
    except Exception as other:
        print('\nVISA ERROR: Cannot connect to instrument:', other, flush=True)
        print('\n')
    return connection


def place_switches_on_switch_diagram(hwdgm, switches):
    timeout = hwdgm.timeout
    hwdgm.timeout = 10000
    hwdgm.write(':SWITch:DMEThod SUPPorted')
    hwdgm.write(':SWITch:SCAN')
    detected_switches = hwdgm.query(':CONFigure:SWITch:ALL?')
    hwdgm.timeout = timeout
    for switch in switches:
        if switch in detected_switches:
            hwdgm.write(':CONFigure:SWITch:ACTive ' + switch + ',ON')
        else:
            raise NoSwitchException('A switch module was not found!')
    return


def place_dcams_on_switch_diagram(hwdgm, required_dcams):
    """ Confirms two N1092As found and places the N1092As on the Switch Diagram but does not connect ports. """
    found = hwdgm.query(':CONFigure:MODule:ALL?')
    dcams_found = found.split(',')
    found = list()
    for scope in required_dcams:
        for scope_name in dcams_found:
            if scope in scope_name:
                hwdgm.write(':CONFigure:MODule:ACTive ' + scope_name + ',ON')
                print(scope_name + ' placed on Switch Diagram.')
                found.append(scope_name)
                dcams_found.remove(scope_name)
                break
    if len(found) != len(required_dcams):
        raise NoModuleException('Required module was not found!')
    return found


def connect_dcams_to_switch(hwdgm, dcam_scope_names, switches):
    """ Connects switch Ports to Channel A on two N1092A. For example,
    ':CONFigure:PORT:CONNect "N7734A","A","N1092A-US92000001","A"'  """
    hwdgm.write(':CONFigure:PORT:CONNect ' + switches[0] + ',"A",' + dcam_scope_names[0] + ',"A"')


def place_fixtures_on_switch_diagram(hwdgm, dut_fixtures, lane_count):
    """ Places DUT Fixture 1 and DUT Fixture 2 on the Switch Diagram but does not connect ports. """
    hwdgm.write(':CONFigure:NLANes ' + str(lane_count))
    fixture_list = list(dut_fixtures.items())
    for station, fixture_name in fixture_list:
        hwdgm.write(':CONFigure:FIXTure:ACTive ' + fixture_name + ', ON')
        hwdgm.write(':CONFigure:FIXTure:TYPE ' + fixture_name + ', NORMal')
        print('Fixture ' + fixture_name + ' placed on Switch Diagram.')
    return


def connect_fixtures_to_switches(hwdgm, dut_fixtures, switches):
    """ Connects fixtures to switch ports. For example,
    ':CONFigure:PORT:CONNect "Test Station 1", "1", "N7731A (Switch 1)", "A"'
    """
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['1'] + ', "1", ' + switches[0] + ', "1"')
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['1'] + ', "2", ' + switches[0] + ', "2"')
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['1'] + ', "3", ' + switches[0] + ', "3"')
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['1'] + ', "4", ' + switches[0] + ', "4"')
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['2'] + ', "1", ' + switches[0] + ', "5"')
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['2'] + ', "2", ' + switches[0] + ', "6"')
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['2'] + ', "3", ' + switches[0] + ', "7"')
    hwdgm.write(':CONFigure:PORT:CONNect ' + dut_fixtures['2'] + ', "4", ' + switches[0] + ', "8"')


def switch_diagram_ok(hwdgm):
    """ Switch diagram must be correct before Sessions can be started. """
    if 'CORR' in hwdgm.query(':CONFigure:STATus?'):
        hwdgm.write('*CLS')
        print('The switch diagram is correct!')
        return True
    else:
        print(hwdgm.query(':CONFigure:STATus:REASon?'))
        return False


def launch_stations(hwdgm, assignments, number_of_sessions):
    """ Configures two stations, assigns DUT1 to Station 1, DUT2 to Station 2, and launches the
    station child process. One fixture per Session (Test Station) """
    hwdgm.timeout = 120000
    hwdgm.write(':CONFigure:AASessions OFF')  # Auto Session assignment off
    hwdgm.write(':CONFigure:NSTations ' + str(number_of_sessions))
    for i in range(1, number_of_sessions + 1):
        fixture_name = assignments[str(i)]
        hwdgm.write(':CONFigure:FIXTure:STATion ' + fixture_name + ', ' + str(i))


    print('Starting Sessions. This takes about a minute.', flush=True)
    hwdgm.write(':STARt')
    hwdgm.query('*OPC?')
    print('FlexOTO Sessions are ready.', flush=True)
    hwdgm.timeout = 20000

#  Main Loop
s = '\nDemo of bootup script with:\n\tKeysight N7734A, \
\n\t2 four-lane fixtures,\n\t1 N1092A, and\n\t2 Sessions (Test Stations).'
print(s)
hwdiagram = open_connection(visa_address)
place_switches_on_switch_diagram(hwdiagram, SWITCHES)
scope_names = place_dcams_on_switch_diagram(hwdiagram, DCAM_MODELS)
connect_dcams_to_switch(hwdiagram, scope_names, SWITCHES)
place_fixtures_on_switch_diagram(hwdiagram, FIXTURES, LANE_CNT)
connect_fixtures_to_switches(hwdiagram, FIXTURES, SWITCHES)
print('All port connections on Switch Diagram made.')
if switch_diagram_ok(hwdiagram):
    launch_stations(hwdiagram, FIXTURES, STATION_CNT)
    print('\nRun the "test-station.py" script to run Test Programs.')
else:
    print('\nProgram aborted. The Hardware Diagram is not properly configured.')
hwdiagram.write(':SYSTem:GTLocal')
hwdiagram.close()