Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

#### [nidcpower] Unreleased
- Added
-`nidcpower_hardware_timed_single_point.py` example
- Changed
- Removed

Expand Down Expand Up @@ -796,6 +797,7 @@

#### [nidmm] Unreleased
- Added
-`nidmm_triggered_fetch_waveform.py` example
- Changed
- Removed

Expand Down Expand Up @@ -2494,6 +2496,7 @@

#### [niswitch] Unreleased
- Added
-`niswitch_software_scanning.py` example
- Changed
- Removed

Expand Down
9 changes: 9 additions & 0 deletions docs/nidcpower/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ nidcpower_constant_resistance_and_constant_power.py
:encoding: utf8
:caption: `(nidcpower_constant_resistance_and_constant_power.py) <https://github.com/ni/nimi-python/blob/master/src/nidcpower/examples/nidcpower_constant_resistance_and_constant_power.py>`_

nidcpower_hardware_timed_single_point.py
----------------------------------------

.. literalinclude:: ../../src/nidcpower/examples/nidcpower_hardware_timed_single_point.py
:language: python
:linenos:
:encoding: utf8
:caption: `(nidcpower_hardware_timed_single_point.py) <https://github.com/ni/nimi-python/blob/master/src/nidcpower/examples/nidcpower_hardware_timed_single_point.py>`_

nidcpower_lcr_source_ac_voltage.py
----------------------------------

Expand Down
9 changes: 9 additions & 0 deletions docs/nidmm/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,12 @@ nidmm_multi_point_measurement.py
:encoding: utf8
:caption: `(nidmm_multi_point_measurement.py) <https://github.com/ni/nimi-python/blob/master/src/nidmm/examples/nidmm_multi_point_measurement.py>`_

nidmm_triggered_fetch_waveform.py
---------------------------------

.. literalinclude:: ../../src/nidmm/examples/nidmm_triggered_fetch_waveform.py
:language: python
:linenos:
:encoding: utf8
:caption: `(nidmm_triggered_fetch_waveform.py) <https://github.com/ni/nimi-python/blob/master/src/nidmm/examples/nidmm_triggered_fetch_waveform.py>`_

9 changes: 9 additions & 0 deletions docs/niswitch/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,12 @@ niswitch_relay_control.py
:encoding: utf8
:caption: `(niswitch_relay_control.py) <https://github.com/ni/nimi-python/blob/master/src/niswitch/examples/niswitch_relay_control.py>`_

niswitch_software_scanning.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think it is wise to add scanning examples. This is a feature no longer supported by any of the switches developed in the last ~18 years.

-----------------------------

.. literalinclude:: ../../src/niswitch/examples/niswitch_software_scanning.py
:language: python
:linenos:
:encoding: utf8
:caption: `(niswitch_software_scanning.py) <https://github.com/ni/nimi-python/blob/master/src/niswitch/examples/niswitch_software_scanning.py>`_

135 changes: 135 additions & 0 deletions src/nidcpower/examples/nidcpower_hardware_timed_single_point.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""NI-DCPower Hardware-Timed Single Point.

This example demonstrates how to set up a hardware-timed Single Point operation.

The hardware is configured to source a voltage, wait for a specified delay and
then take a measurement.

The example uses the default resource name, channel, current level,
and voltage limit. Modify these values as needed for your measurement setup

HOW TO RUN:
-----------
i. From terminal (with default values):
python nidcpower_hardware_timed_single_point.py

ii. From terminal (with custom values):
python nidcpower_hardware_timed_single_point.py -n "PXI1Slot2" \
-vl1 3.0 -vl2 5.0 -sd 0.1

iii. To simulate without hardware:
PowerShell: python nidcpower_hardware_timed_single_point.py \

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Powershell and cmd instructions look the same to me. Do you need both? If you do, then you definitely need Linux.

But I don't think we need both.

-op 'Simulate=1, DriverSetup=Model:4162; BoardType:PXIe'
cmd.exe: python nidcpower_hardware_timed_single_point.py \
-op "Simulate=1, DriverSetup=Model:4162; BoardType:PXIe"

"""

# Module imports
import argparse # For parsing command-line arguments

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all these comments consistent with all other examples? If they are, ok.
If they aren't please remove. I don't think they add much value.

import sys # For accessing command-line arguments via sys.argv

import nidcpower # NI-DCPower instrument driver


def example(resource_name, options, voltage_level_1, voltage_level_2,
voltage_level_range, current_limit, current_limit_range,
source_delay):
"""Core measurement logic — sources two voltage levels sequentially and returns both measurements.

Args:
resource_name (str) : NI-MAX resource name, eg: "PXI1Slot2"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this consistent with all our other examples?
NI MAX is spelled with no dash, and is deprecated.

I would imagine the documentation when setting up argparse would suffice. DRY.

options (str or dict) : Driver options, eg: "" for real HW or simulate dict for simulation
voltage_level_1 (float) : First voltage level to source (V) — must be <= voltage_level_range
voltage_level_2 (float) : Second voltage level to source (V) — must be <= voltage_level_range
voltage_level_range (float) : Voltage range — must be >= both voltage levels (V)
current_limit (float) : Current limit (A) — must be <= current_limit_range
current_limit_range (float) : Current range — must be >= current_limit (A)
source_delay (float) : Delay before Source Complete Event fires(s)
"""
# 'with' block ensures session.abort() + session.close() are called automatically on exit.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this with block only ensures session.close() is called.

# channels=0 targets channel 0; reset=True clears any previous session state.
with nidcpower.Session(resource_name=resource_name, reset=True, channels=0, options=options) as session:

# Configure source mode and output function.
# SINGLE_POINT: sources one value and holds; voltage_level can be changed mid-session.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of mid-session you should say it can be "set while in the running state"

# measure_when = AUTOMATICALLY_AFTER_SOURCE_COMPLETE: required for fetch_multiple().
session.source_mode = nidcpower.SourceMode.SINGLE_POINT
session.output_function = nidcpower.OutputFunction.DC_VOLTAGE
session.voltage_level = voltage_level_1
session.voltage_level_range = voltage_level_range
session.current_limit = current_limit
session.current_limit_range = current_limit_range
session.source_delay = source_delay
session.measure_when = nidcpower.MeasureWhen.AUTOMATICALLY_AFTER_SOURCE_COMPLETE

# Commit sends all settings to hardware before initiate.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case, there is no point in explicitly calling commit

session.commit()

# Initiate output, fetch at voltage_level_1, change to voltage_level_2, fetch again.
# timeout=1.0 s — adjust if source_delay is longer than 1 s.
with session.initiate():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this context manager ensures abort() is closed

measurements1 = session.fetch_multiple(count=1, timeout=1.0)
session.voltage_level = voltage_level_2
measurements2 = session.fetch_multiple(count=1, timeout=1.0)

print(f'Measurements 1: \n- Voltage: {measurements1[0][0]:f} V'
f'\n- Current: {measurements1[0][1]:f} A'
f'\n- In Compliance: {measurements1[0][2]}')
print(f'Measurements 2: \n- Voltage: {measurements2[0][0]:f} V'
f'\n- Current: {measurements2[0][1]:f} A'
f'\n- In Compliance: {measurements2[0][2]}')

return measurements1, measurements2


def _main(argsv):
"""Parses command-line arguments and calls example() with the parsed values."""
parser = argparse.ArgumentParser(
description='Hardware-timed single point: source two voltage levels and measure.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument('-n', '--resource-name', default='PXI1Slot2/0', help='Resource name of NI SMU')
parser.add_argument('-vl1', '--voltage-level-1', default=2.0, type=float, help='First voltage level (V)')
parser.add_argument('-vl2', '--voltage-level-2', default=4.0, type=float, help='Second voltage level (V)')
parser.add_argument('-vr', '--voltage-level-range', default=10.0, type=float, help='Voltage level range — must be >= both voltage levels (V)')
parser.add_argument('-cl', '--current-limit', default=0.01, type=float, help='Current limit (A)')
parser.add_argument('-clr', '--current-limit-range', default=0.01, type=float, help='Current limit range — must be >= current-limit (A)')
parser.add_argument('-sd', '--source-delay', default=0.05, type=float, help='Source delay in seconds')
parser.add_argument('-op', '--option-string', default='', type=str, help='Driver option string, eg: "Simulate=1, DriverSetup=Model:4162; BoardType:PXIe"')
args = parser.parse_args(argsv)
example(
resource_name=args.resource_name,
options=args.option_string,
voltage_level_1=args.voltage_level_1,
voltage_level_2=args.voltage_level_2,
voltage_level_range=args.voltage_level_range,
current_limit=args.current_limit,
current_limit_range=args.current_limit_range,
source_delay=args.source_delay,
)


def main():
"""Entry point — passes real CLI args to _main()."""
_main(sys.argv[1:])


def test_example():
"""Simulated hardware test — runs example() with a virtual PXIe-4162 (no real HW needed)."""
options = {'simulate': True, 'driver_setup': {'Model': '4162', 'BoardType': 'PXIe'}}
example('PXI1Slot2/0', options, 2.0, 4.0, 10.0, 0.01, 0.01, 0.05)


def test_main():
"""Simulated CLI test — runs _main() with simulate option string."""
cmd_line = ['--option-string', 'Simulate=1, DriverSetup=Model:4162; BoardType:PXIe']
_main(cmd_line)


# ------------------------------------------------------------
# Script execution starts here
# ------------------------------------------------------------
if __name__ == '__main__':
main()
Loading
Loading