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()