Flex-on-AWG Configuration

This Python script demonstrates using an N8195/6A Arbitrary Waveform Generator (AWG) with a DCA-X. As shown in the following picture, the script runs on a PC and all SCPI commands are sent to N1010A FlexDCA on the PC. The script creates extended module connections from FlexDCA N1010A to the DCA-X and to the AWG via the LAN. The AWG's AXIe chassis must have an embedded controller module which has the AWG Soft Front Panel application running. N1010A FlexDCA connects to the Soft Front Panel.

In the test setup, install an electrical module into the DCA-X making channel 2 available. The script configures AWG channel 1 as a CLOCK and AWG channel 4 as a DATA signal. In the setup, connect the CLOCK to the 86100D's clock input. Connect this DATA signal to the 86100D's channel 2 input.

Example Script

Copy

flex-on-AWG.py

# -*- coding: utf-8 -*-
""" Demonstrates using an N8195/6A Arbitrary Waveform Generator with a
DCA-X. AWG's AXIe chassis has an embedded controller module which has
AWG's Soft Front Panel application running. N1010A FlexDCA connects to
the Soft Front Panel.
Script on PC controls N1010A FlexDCA. Script makes extended
module connections from FlexDCA N1010A to the 86100D and to the AWG
via the LAN. AWG channel 1 CLOCK signal is used as DCA-X clock input.
AWG channel 4 is used as DATA input signal to DCA-X channel 2.
"""

import pyvisa as visa  # import VISA library
import time

N1010AADDRESS = 'TCPIP0::localhost::hislip0::INSTR'
HOSTNAME86100D = 'KEYSIGH-3T98UQG'
AWGADDRESS = 'TCPIP0::WINDOWS-0ISM873::hislip0::INSTR'
MEAS_CHAN = 'CHAN2A'


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 connect_to_N1010A():
    """ Connects to FlexDCA running on PC. """
    flex = open_flexdca_connection(N1010AADDRESS)
    return flex


def connect_flex_on_flex():
    """ Connects FlexDCA on PC to DCA-X via LAN. """
    flex.write(':EMODules:SLOT1:SELection DCA')
    flex.write(':RDCA:CONNect:HOST "' + HOSTNAME86100D + '"')
    flex.query(':RDCA:CONNect;*OPC?')
    if 'CONN' in flex.query(':EMOD:SLOT1:STATe?'):
        print('Connected to DCA-X.')
        flex.query(':SYST:DEFault;*OPC?')  # Defaults FlexDCA and AWG settings
    else:
        print('DCA-X connection failed!')


def connect_flex_on_awg_sfp():
    """ Connects FlexDCA on PC to AWG's Soft Front Panel via LAN. Defaults
    N1010A FlexDCA which also defaults AWG settings including turning any
    AWG channels off. """
    flex.write(':EMODules:SLOT5:SELection AWGenerator')
    flex.write(':EMODules:SLOT5:ADDRess VISA')
    flex.write(':EMODules:AWGenerator5:VADDress "' + AWGADDRESS + '"')
    flex.query(':EMODules:SLOT5:CONNect;*OPC?')
    if 'CONN' in flex.query(':EMOD:SLOT5:STATe?'):
        print('Connected to AWG.')
        flex.query(':SYST:DEFault;*OPC?')  # Defaults FlexDCA and AWG settings
    else:
        print('AWG connection failed!')


def configure_awg_sfp():
    """ Uses N1010A FlexDCA commands to configure AWG's clock and data
    signals. AWG is 'installed' in N1010A's slot 5 which is specified
    in the 'AWGenerator5' and 'SOUR5A' SCPI node strings. """
    flex.write(':EMODules:AWGenerator5:AUPDate ON')
    flex.write(':EMODules:AWGenerator5:CDIVide SUB2')
    flex.write(':EMODules:AWGenerator5:WTYPe DATA')
    flex.write(':EMODules:AWGenerator5:FORMat NRZ')
    flex.write(':EMODules:AWGenerator5:SRATe 9.953280000E+9')
    flex.write(':EMODules:AWGenerator5:PATTern PRBS9')
    flex.write(':EMODules:AWGenerator5:CDIVide SUB2')
    flex.write(':SOUR5A:WTYPe CLOCk')
    flex.write(':SOUR5A:OENable ON')  # AWG's channel 1
    flex.write(':SOUR5D:OENable ON')  # AWG's channel 4
    flex.write(':SOUR5D:AMPLitude 1.40000E-1')
    flex.write(':SOUR5D:FILTer:TYPE BUTTerworth2')
    flex.write(':SOUR5D:FILTer:CUToff 2.000E+10')


def all_channels_off(FlexDCA):
    """ Turns all available channels off. """
    for slot in '12345678':
        for letter in 'ABCD':
            channel = slot + letter
            FlexDCA.write(':CHANnel' + channel + ':DISPlay OFF')


def configure_N1010A():
    """ Basic configuration of N1010A FlexDCA. """
    all_channels_off(flex)
    flex.write(':' + MEAS_CHAN + ':DISPlay ON')
    flex.write(':SYST:MODE EYE')
    flex.query(':SYSTem:AUToscale;*OPC?')


def return_scalar(FlexDCA, query):
    """ Returns a FlexDCA scalar measurement result. Uses a loop that checks
    the status of the measurement every 200 ms until the measurement
    result is ready. If the status is invalid 'INV', the loop
    continues waiting for the measurement to be ready.
    If status is questionable 'QUES', an exception is thrown.
    If a valid measurement cannot be returned within the Visa
    timeout setting an exception is thrown.
    """
    class ScalarMeasQuestionableException(Exception):
        """ A scalar measurement result is questionable. """
        pass

    class ScalarMeasTimeOutException(Exception):
        """ A scalar measurement has timed out. """
        pass

    timeout = FlexDCA.timeout / 1000  # convert ms to s
    query = query.strip('?')
    start_time = time.time()  # time in seconds
    while(True):
        time.sleep(0.2)
        status = FlexDCA.query(query + ':STATus?')
        if 'CORR' in status:  # valid measurement result
            return FlexDCA.query(query + '?')  # get measurement
        elif 'QUES' in status:  # questionable results
            s = query + '\nReason: ' + FlexDCA.query(query + ':STATus:REASon?')
            raise ScalarMeasQuestionableException(s)
        elif (int(time.time() - start_time)) > timeout:  # IO timout
            s = query + '\nReason: ' + FlexDCA.query(query + ':STATus:REASon?')
            raise ScalarMeasTimeOutException(s)


def return_measurements():
    """ Displays measurement table on FlexDCA and returns eye height and
    eye width measurements. """
    flex.write(':MEASure:EYE:EHEight:SOURCe ' + MEAS_CHAN)
    flex.write(':MEASure:EYE:EWIDth:SOURCe ' + MEAS_CHAN)
    flex.write(':MEASure:EYE:EHEight')
    flex.write(':MEASure:EYE:EWIDth')
    s = return_scalar(flex, ':MEASure:EYE:EHEight?')
    print('Eye Height: ', s)
    s = return_scalar(flex, ':MEASure:EYE:EWIDth?')
    print('Eye Width: ', s)
    flex.write(':ACQuire:STOP')


flex = connect_to_N1010A()
connect_flex_on_flex()
awg = connect_flex_on_awg_sfp()
configure_awg_sfp()
configure_N1010A()
return_measurements()
flex.write(':SYSTem:GTLocal')
flex.close()