3. To Create a Hardware Diagram
The following Python script creates an example Hardware Diagram using a Keysight N7734A optical switch. The script uses the :CONFigure SCPI subsystem
to create the Hardware Diagram. Notice that the visa address uses hislip0
.
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()