N109X-Series Oscilloscope with acquisition limit test
This Python example uses an N109X-series DCA-M oscilloscope to perform an eye measurement (bit rate) on channel 6A. The programs performs the following tasks:
- Places FlexDCA to its default settings. This places the FlexDCA triggering to front panel which is required to view a valid eye diagram, and then makes all the required setting to view an eye diagram.
- Queries the N109X to see if it supports pattern locking (option PLK) and then turns on pattern locking if available.
- Returns the measured trigger rate that is input to the N109X.
- Runs an acquisition limit test and then activates the bit-rate measurement on the data.
About the :TRIGger:MRATe? query
The :TRIGger:MRATe? query returns the baud rate of the N109X’s clock input signal. For this query to work, at least one of the N109X’s input channels must be turned on, but a signal does not need to be connected to the channel. Also, the N109X’s data acquisition must be in Run mode, or, if in single mode, a single acquisition must first be run to ensure valid data for the measurement.
To run this program
- Run this program on a PC that has FlexDCA running. In the following listing, FlexDCA is identified by the red text: localhost.
- Install an N109X-series oscilloscope to FlexDCA’s slot 6. Change the
DCAMSLT
constant if you want to use a different slot. - Data in is expected to be 10.3125 GBd, but you can change this to any acceptable rate for the oscilloscope.
- Connect valid signal to channel 6A on the N1090X.
- Connect a clock to the N1090X’s Clock In.
- Display an eye diagram on FlexDCA.
If you change localhost
to an N1000A, you can run the program on a PC to control FlexDCA on an N1000A. Connect the N109X to the N1000A.
Example Script
Copy
DCA-M-eye-meas.py
# -*- coding: utf-8 -*-
""" Demonstrates measurements on DCA-M oscilloscope.
- Requres a N109X-series DCA-M oscilloscope with valid eye diagram displayed.
- Change the CHANNEL constant to match your setup.
- ADDRESS constant is set for FlexDCA and DCA-M on PC.
- Change ADDRESS constant to DCA-X's address if DCA-M is connected
to the DCA-X.
Data in is expected to be 10.3125 Gb/s, but you can change this
to any acceptable rate for the oscilloscope.
The default setup command places the DCA-M triggering to front
panel which is required to view a valid eye diagram.
"""
import pyvisa as visa # import VISA library
ADDRESS = 'TCPIP0::localhost::hislip0,4880::INSTR'
#ADDRESS = 'TCPIP0::K-N1000A-00003::hislip0,4880::INSTR'
CHANNEL = '5A' # N109X's channel
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)
connection.write(':SYSTem:DEFault')
connection.query('*OPC?')
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 show_module_information(FlexDCA, channel):
""" Queries information from the DCA-M. Returns a string
of DCA-M's options. """
slot = channel[0]
print('\nDCA-M Device ID: ', FlexDCA.query(':EMODules:DCAM' + slot + ':DEVice?'))
print('DCA-M model: ', FlexDCA.query(':SYSTem:MODel? SLOT' + slot))
print('Options: ', FlexDCA.query(':SYSTem:OPTions? SLOT' + slot))
print('Trigger source: ', FlexDCA.query(':SLOT' + slot + ':TRIGger:SOURce?'))
clockrate = FlexDCA.query(':SLOT' + slot + ':TRIG:MRATe?')
if '-1.00' in clockrate or '0.00' in clockrate:
print('ERROR: DCA-M is not triggered. Check inputs.')
else:
print('Measured clock rate: ', clockrate)
def return_scalar(FlexDCA, query):
""" Returns a FlexDCA scalar measurement result. """
import time
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 make_measurements(FlexDCA, slot):
""" Displays four measurements in FlexDCA's results panel.
Returns the result of each measurement. """
FlexDCA.write(':MEASure:EYE:LIST:CLEar')
FlexDCA.write(':MEASure:EYE:BITRate')
FlexDCA.write(':MEASure:EYE:FALLtime')
FlexDCA.write(':MEASure:EYE:RISetime')
FlexDCA.write(':MEASure:EYE:AMPLitude')
print('-' * 20, '\nMeasured:')
meas = return_scalar(FlexDCA, ':MEASure:EYE:BITRate?')
print('Eye Bit Rate: ' + meas + ' b/s')
meas = return_scalar(FlexDCA, ':MEASure:EYE:FALLtime?')
print('Fall Time: ' + meas + 's')
meas = return_scalar(FlexDCA, ':MEASure:EYE:RISetime?')
print('Rise Time: ' + meas + 's')
meas = return_scalar(FlexDCA, ':MEASure:EYE:AMPLitude?')
print('Eye Amplitude: ' + meas)
FlexDCA = open_flexdca_connection(ADDRESS)
show_module_information(FlexDCA, CHANNEL)
print('Acquiring data...')
make_measurements(FlexDCA, CHANNEL[0])
FlexDCA.write(':SYSTem:GTLocal')
FlexDCA.close()