Examples¶
You can download all nidigital examples here
nidigital_burst_with_start_trigger.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #!/usr/bin/python
import argparse
import nidigital
import os
import sys
def example(resource_name, options, trigger_source=None, trigger_edge=None):
with nidigital.Session(resource_name=resource_name, options=options) as session:
dir = os.path.join(os.path.dirname(__file__))
# Load the pin map (.pinmap) created using the Digital Pattern Editor
pin_map_filename = os.path.join(dir, 'PinMap.pinmap')
session.load_pin_map(pin_map_filename)
# Load the specifications (.specs), levels (.digilevels), and timing (.digitiming) sheets created using the Digital Pattern Editor
spec_filename = os.path.join(dir, 'Specifications.specs')
levels_filename = os.path.join(dir, 'PinLevels.digilevels')
timing_filename = os.path.join(dir, 'Timing.digitiming')
session.load_specifications_levels_and_timing(spec_filename, levels_filename, timing_filename)
# Apply the settings from the levels and timing sheets we just loaded to the session
session.apply_levels_and_timing(levels_filename, timing_filename)
# Loading the pattern file (.digipat) created using the Digital Pattern Editor
pattern_filename = os.path.join(dir, 'Pattern.digipat')
session.load_pattern(pattern_filename)
if trigger_source is None:
print('Start bursting pattern')
else:
# Specify a source and edge for the external start trigger
session.start_trigger_type = nidigital.TriggerType.DIGITAL_EDGE
session.digital_edge_start_trigger_source = trigger_source
session.digital_edge_start_trigger_edge = nidigital.DigitalEdge.RISING if trigger_edge == 'Rising' else nidigital.DigitalEdge.FALLING
print('Wait for start trigger and then start bursting pattern')
# If start trigger is configured, waiting for the trigger to start bursting and then blocks until the pattern is done bursting
# Else just start bursting and block until the pattern is done bursting
session.burst_pattern(start_label='new_pattern')
# Disconnect all channels using programmable onboard switching
session.selected_function = nidigital.SelectedFunction.DISCONNECT
print('Done bursting pattern')
def _main(argsv):
parser = argparse.ArgumentParser(description='Demonstrates how to create and configure a session that bursts a pattern on the digital pattern instrument using a start trigger', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='Resource name of a NI digital pattern instrument. Ensure the resource name matches the instrument name in the pinmap file.')
parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or real hardware')
subparser = parser.add_subparsers(dest='command', help='Sub-command help')
start_trigger = subparser.add_parser('start-trigger', help='Configure start trigger')
start_trigger.add_argument('-ts', '--trigger-source', default='/PXI1Slot2/PXI_Trig0', help='Source terminal for the start trigger')
start_trigger.add_argument('-te', '--trigger-edge', default='Rising', choices=['Rising', 'Falling'], help='Trigger on rising edge or falling edge of start trigger')
args = parser.parse_args(argsv)
example(args.resource_name,
'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '',
args.trigger_source if args.command == 'start-trigger' else None,
args.trigger_edge if args.command == 'start-trigger' else None)
def main():
_main(sys.argv[1:])
def test_main():
_main([])
_main(['start-trigger'])
def test_example():
resource_name = 'PXI1Slot2,PXI1Slot3'
options = {'simulate': True, 'driver_setup': {'Model': '6571'}, }
example(resource_name, options)
trigger_source = '/PXI1Slot2/PXI_Trig0'
trigger_edge = 'Rising'
example(resource_name, options, trigger_source, trigger_edge)
if __name__ == '__main__':
main()
|
nidigital_configure_time_set_and_voltage_levels.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #!/usr/bin/python
import argparse
import nidigital
import os
import sys
class VoltageLevelsAndTerminationConfig():
def __init__(self, vil, vih, vol, voh, vterm, termination_mode, iol, ioh, vcom):
self.vil = vil
self.vih = vih
self.vol = vol
self.voh = voh
self.vterm = vterm
self.termination_mode = termination_mode
self.iol = iol
self.ioh = ioh
self.vcom = vcom
class TimeSetConfig():
def __init__(self, time_set_name, period, drive_format, drive_on, drive_data, drive_return, drive_off, strobe_edge):
self.time_set_name = time_set_name
self.period = period
self.drive_format = drive_format
self.drive_on = drive_on
self.drive_data = drive_data
self.drive_return = drive_return
self.drive_off = drive_off
self.strobe_edge = strobe_edge
def convert_drive_format(drive_format):
converter = {'NR': nidigital.DriveFormat.NR,
'RL': nidigital.DriveFormat.RL,
'RH': nidigital.DriveFormat.RH,
'SBC': nidigital.DriveFormat.SBC}
return converter.get(drive_format, None)
def example(resource_name,
options,
channels,
voltage_config,
time_set_config):
with nidigital.Session(resource_name=resource_name, options=options) as session:
dir = os.path.dirname(__file__)
# Load pin map (.pinmap) created using Digital Pattern Editor
pin_map_filename = os.path.join(dir, 'PinMap.pinmap')
session.load_pin_map(pin_map_filename)
# Configure voltage levels and terminal voltage through driver API
session.channels[channels].configure_voltage_levels(voltage_config.vil, voltage_config.vih, voltage_config.vol, voltage_config.voh, voltage_config.vterm)
if voltage_config.termination_mode == 'High_Z':
session.channels[channels].termination_mode = nidigital.TerminationMode.HIGH_Z
elif voltage_config.termination_mode == 'Active_Load':
session.channels[channels].termination_mode = nidigital.TerminationMode.ACTIVE_LOAD
session.channels[channels].configure_active_load_levels(voltage_config.iol, voltage_config.ioh, voltage_config.vcom)
else:
session.channels[channels].termination_mode = nidigital.TerminationMode.VTERM
# Configure time set through driver API
session.create_time_set(time_set_config.time_set_name) # Must match time set name in pattern file
session.configure_time_set_period(time_set_config.time_set_name, time_set_config.period)
session.channels[channels].configure_time_set_drive_edges(time_set_config.time_set_name, convert_drive_format(time_set_config.drive_format),
time_set_config.drive_on, time_set_config.drive_data,
time_set_config.drive_return, time_set_config.drive_off)
session.channels[channels].configure_time_set_compare_edges_strobe(time_set_config.time_set_name, time_set_config.strobe_edge)
# Load the pattern file (.digipat) created using Digital Pattern Editor
pattern_filename = os.path.join(dir, 'Pattern.digipat')
session.load_pattern(pattern_filename)
# Burst pattern, blocks until the pattern is done bursting
session.burst_pattern(start_label='new_pattern')
print('Start bursting pattern')
# Disconnect all channels using programmable onboard switching
session.selected_function = nidigital.SelectedFunction.DISCONNECT
print('Done bursting pattern')
def _main(argsv):
parser = argparse.ArgumentParser(description='Demonstrates how to create an instrument session, configure time set and voltage levels, and burst a pattern on the digital pattern instrument.', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='Resource name of a NI digital pattern instrument, ensure the resource name matches the instrument name in the pinmap file.')
parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or on real hardware')
parser.add_argument('-c', '--channels', default='PinGroup1', help='Channel(s)/Pin(s) to configure')
# Parameters to configure voltage
parser.add_argument('--vil', default=0, type=float, help='The voltage that the instrument will apply to the input of the DUT when the pin driver drives a logic low (0)')
parser.add_argument('--vih', default=3.3, type=float, help='The voltage that the instrument will apply to the input of the DUT when the test instrument drives a logic high (1)')
parser.add_argument('--vol', default=1.6, type=float, help='The output voltage below which the comparator on the pin driver interprets a logic low (L)')
parser.add_argument('--voh', default=1.7, type=float, help='The output voltage above which the comparator on the pin driver interprets a logic high (H)')
parser.add_argument('--vterm', default=2, type=float, help='The termination voltage the instrument applies during non-drive cycles when the termination mode is set to Vterm')
parser.add_argument('-term-mode', '--termination-mode', default='High_Z', choices=['High_Z', 'Active_Load', 'Three_Level_Drive'])
parser.add_argument('--iol', default=0.002, type=float, help='The maximum current that the DUT sinks while outputting a voltage below VCOM')
parser.add_argument('--ioh', default=-0.002, type=float, help='The maximum current that the DUT sources while outputting a voltage above VCOM')
parser.add_argument('--vcom', default=0.0, type=float, help='The commutating voltage level at which the active load circuit switches between sourcing current and sinking current')
# Parameters to configure timeset
parser.add_argument('--period', default=0.00000002, type=float, help='Period in second')
parser.add_argument('-format', '--drive-format', default='NR', choices=['NR', 'RL', 'RH', 'SBC'], help='Non-return | Return to low | Return to high | Surround by complement')
parser.add_argument('--drive-on', default=0, type=float, help='The delay in seconds from the beginning of the vector period for turning on the pin driver')
parser.add_argument('--drive-data', default=0, type=float, help='The delay in seconds from the beginning of the vector period until the pattern data is driven to the pattern value')
parser.add_argument('--drive-return', default=0.000000015, type=float, help='The delay in seconds from the beginning of the vector period until the pin changes from the pattern data to the return value, as specified in the format.')
parser.add_argument('--drive-off', default=0.00000002, type=float, help='The delay in seconds from the beginning of the vector period to turn off the pin driver when the next vector period uses a non-drive symbol (L, H, X, V, M, E).')
parser.add_argument('--strobe-edge', default=0.00000001, type=float, help='The time in second when the comparison happens within a vector period')
args = parser.parse_args(argsv)
voltage_config = VoltageLevelsAndTerminationConfig(args.vil, args.vih, args.vol, args.voh, args.vterm, args.termination_mode, args.iol, args.ioh, args.vcom)
time_set_config = TimeSetConfig("tset0", args.period, args.drive_format, args.drive_on, args.drive_data, args.drive_return, args.drive_off, args.strobe_edge)
example(args.resource_name,
'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '',
args.channels,
voltage_config,
time_set_config)
def main():
_main(sys.argv[1:])
def test_main():
_main([])
def test_example():
resource_name = 'PXI1Slot2,PXI1Slot3'
options = {'simulate': True, 'driver_setup': {'Model': '6571'}, }
channels = 'PinGroup1'
voltage_config = VoltageLevelsAndTerminationConfig(vil=0, vih=3.3, vol=1.6, voh=1.7, vterm=2,
termination_mode='Active_Load', iol=0.002, ioh=-0.002, vcom=0)
time_set_config = TimeSetConfig(time_set_name="tset0",
period=0.00000002,
drive_format='NR',
drive_on=0, drive_data=0, drive_return=0.000000015, drive_off=0.00000002, strobe_edge=0.00000001)
example(resource_name, options, channels, voltage_config, time_set_config)
if __name__ == '__main__':
main()
|
nidigital_ppmu_source_and_measure.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | #!/usr/bin/python
import argparse
import nidigital
import os
import pytest
import sys
import time
def example(resource_name, options, channels, measure, aperture_time,
source=None, settling_time=None, current_level_range=None, current_level=None,
voltage_limit_high=None, voltage_limit_low=None, current_limit_range=None, voltage_level=None):
with nidigital.Session(resource_name=resource_name, options=options) as session:
dir = os.path.join(os.path.dirname(__file__))
# Load pin map (.pinmap) created using Digital Pattern Editor
pin_map_filename = os.path.join(dir, 'PinMap.pinmap')
session.load_pin_map(pin_map_filename)
# Configure the PPMU measurement aperture time
session.channels[channels].ppmu_aperture_time = aperture_time
session.channels[channels].ppmu_aperture_time_units = nidigital.PPMUApertureTimeUnits.SECONDS
# Configure and source
if source == 'source-current':
session.channels[channels].ppmu_output_function = nidigital.PPMUOutputFunction.CURRENT
session.channels[channels].ppmu_current_level_range = current_level_range
session.channels[channels].ppmu_current_level = current_level
session.channels[channels].ppmu_voltage_limit_high = voltage_limit_high
session.channels[channels].ppmu_voltage_limit_low = voltage_limit_low
session.channels[channels].ppmu_source()
# Settling time between sourcing and measuring
time.sleep(settling_time)
elif source == 'source-voltage':
session.channels[channels].ppmu_output_function = nidigital.PPMUOutputFunction.VOLTAGE
session.channels[channels].ppmu_current_limit_range = current_limit_range
session.channels[channels].ppmu_voltage_level = voltage_level
session.channels[channels].ppmu_source()
# Settling time between sourcing and measuring
time.sleep(settling_time)
pin_info = session.channels[channels].get_pin_results_pin_information()
# Measure
if measure == 'current':
current_measurements = session.channels[channels].ppmu_measure(nidigital.PPMUMeasurementType.CURRENT)
print('{:<6} {:<20} {:<10}'.format('Site', 'Pin Name', 'Current'))
for pin, current in zip(pin_info, current_measurements):
print('{:<6d} {:<20} {:<10f}'.format(pin.site_number, pin.pin_name, current))
else:
voltage_measurements = session.channels[channels].ppmu_measure(nidigital.PPMUMeasurementType.VOLTAGE)
print('{:<6} {:<20} {:<10}'.format('Site', 'Pin Name', 'Voltage'))
for pin, voltage in zip(pin_info, voltage_measurements):
print('{:<6d} {:<20} {:<10f}'.format(pin.site_number, pin.pin_name, voltage))
# Disconnect all channels using programmable onboard switching
session.channels[channels].selected_function = nidigital.SelectedFunction.DISCONNECT
def _main(argsv):
parser = argparse.ArgumentParser(description='Demonstrates how to source/measure voltage/current using the PPMU on selected channels/pins of the digital pattern instrument',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='Resource name of a NI digital pattern instrument, ensure the resource name matches the instrument name in the pinmap file.')
parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or on real hardware')
parser.add_argument('-c', '--channels', default='DUTPin1, SystemPin1', help='Channel(s)/Pin(s) to use')
parser.add_argument('-m', '--measure', default='voltage', choices=['voltage', 'current'], help='Measure voltage or measure current')
parser.add_argument('-at', '--aperture-time', default=0.000004, type=float, help='Aperture time in seconds')
subparser = parser.add_subparsers(dest='source', help='Sub-command help, by default it measures voltage and does not source')
source_current = subparser.add_parser('source-current', help='Source current')
source_current.add_argument('-clr', '--current-level-range', default=0.000002, type=float, help='Current level range in amps')
source_current.add_argument('-cl', '--current-level', default=0.000002, type=float, help='Current level in amps')
source_current.add_argument('-vlh', '--voltage-limit-high', default=3.3, type=float, help='Voltage limit high in volts')
source_current.add_argument('-vll', '--voltage-limit-low', default=0, type=float, help='Voltage limit low in volts')
source_current.add_argument('-st', '--settling-time', default=0.01, type=float, help='Settling time in seconds')
source_voltage = subparser.add_parser('source-voltage', help='Source voltage')
source_voltage.add_argument('-clr', '--current-limit-range', default=0.000002, type=float, help='Current limit range in amps')
source_voltage.add_argument('-vl', '--voltage-level', default=3.3, type=float, help='Voltage level in volts')
source_voltage.add_argument('-st', '--settling-time', default=0.01, type=float, help='Settling time in seconds')
args = parser.parse_args(argsv)
if args.source == 'source-current':
example(
args.resource_name,
'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '',
args.channels,
args.measure,
args.aperture_time,
args.source,
args.settling_time,
args.current_level_range,
args.current_level,
args.voltage_limit_high,
args.voltage_limit_low)
elif args.source == 'source-voltage':
example(
args.resource_name,
'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '',
args.channels,
args.measure,
args.aperture_time,
args.source,
args.settling_time,
current_limit_range=args.current_limit_range,
voltage_level=args.voltage_level)
else:
if args.measure == 'current':
raise ValueError('Cannot measure current on a channel that is not sourcing voltage or current')
example(
args.resource_name,
'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '',
args.channels,
args.measure,
args.aperture_time)
def main():
_main(sys.argv[1:])
def test_main():
_main([])
_main(['-m', 'voltage'])
with pytest.raises(Exception):
_main(['-m', 'current'])
_main(['-m', 'voltage', 'source-current'])
_main(['-m', 'current', 'source-current'])
_main(['-m', 'voltage', 'source-voltage'])
_main(['-m', 'current', 'source-voltage'])
def test_example():
resource_name = 'PXI1Slot2,PXI1Slot3'
options = {'simulate': True, 'driver_setup': {'Model': '6571'}, }
channels = 'DUTPin1, SystemPin1'
aperture_time = 0.000004
example(resource_name, options, channels, 'voltage',
aperture_time)
with pytest.raises(Exception):
example(resource_name, options, channels, 'current',
aperture_time)
settling_time = 0.01
current_level_range = 0.000002
current_level = 0.000002
voltage_limit_high = 3.3
voltage_limit_low = 0
example(resource_name, options, channels, 'voltage',
aperture_time, 'source-current', settling_time,
current_level_range, current_level,
voltage_limit_high, voltage_limit_low)
example(resource_name, options, channels, 'current',
aperture_time, 'source-current', settling_time,
current_level_range, current_level,
voltage_limit_high, voltage_limit_low)
current_limit_range = 0.000002
voltage_level = 3.3
example(resource_name, options, channels, 'voltage',
aperture_time, 'source-voltage', settling_time,
current_limit_range=current_limit_range,
voltage_level=voltage_level)
example(resource_name, options, channels, 'current',
aperture_time, 'source-voltage', settling_time,
current_limit_range=current_limit_range,
voltage_level=voltage_level)
if __name__ == '__main__':
main()
|