Skip to content

Commit

Permalink
Correct setting of voltage limits when forcing PPMU current (#142)
Browse files Browse the repository at this point in the history
* Correct the setting of voltage limit low for digital.

* Add auto tests.

* Add more tests.

* Add new dependency.

* Referece A as a dependency.

* Add more auto tests.

* Adjust implementation and auto tests.

* Update summary documentation for ForceCurrentMeasureVoltage and ForceDcCurrent methods, and add all changes for these method to the CHANGELOG.md

---------

Co-authored-by: mattjet27 <[email protected]>
  • Loading branch information
lornazh and Mattjet27 authored Oct 16, 2024
1 parent 45f17ee commit e945645
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 10 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

- ### Changed

- `LeakageTest` TestStand step now forces 0V on all pins at start of test and after measuring. It also now ensures all pins are forced to the specified voltage before measuring current. Finally, it will now disable the output of all pins at the end of the test.
- DMM Mulipoint extension methods now return `PinSiteData<double[]>` instead of a 2D per-instrument, per-sample array `double[][]`
- `PinSiteData<double[]> ReadMultiPoint(this DMMSessionsBundle sessionsBundle, int numberOfPoints, double maximumTimeInMilliseconds)`
- `PinSiteData<double[]> FetchMultiPoint(this DMMSessionsBundle sessionsBundle, int numberOfPoints, double maximumTimeInMilliseconds)`
Expand All @@ -175,6 +174,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- For `SiteData<T>` objects, the scalar value will be applied to all elements in the array, across each site.
- `Utilities.TryDeterminePowerLineFrequency` updated to now support OfflineMode.
- `TestStandSteps.ContinuityTest` modified to correctly accept negative current level values.
- `TestStandSteps.LeakageTest` now forces 0V on all pins at start of test and after measuring. It also now ensures all pins are forced to the specified voltage level before measuring current. Finally, it will now disable the output of all pins at the end of the test. The method summary documentation has also been updated to reflect this change.
- `TestStandSteps.ForceDcCurrent` now correctly applies the specified voltage limit symmetrically for PPMU pins and has updated method summary documentation to reflect this change.
- `TestStandSteps.ForceCurrentMeasureVoltage` now correctly applies symmetric voltage limits for PPMU pins and has updated method summary documentation to reflect this change.
- CSProject files for TestStandSteps and Extensions now exclude net48 path from being included as a folder within the project, which could cause build issues for contributors in certain situations.
- Improved documentation for the following DCPower extension methods: `ConfigureOutputEnabled`, `ConfigureOutputConnected`, `PowerDown`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ public static partial class CommonSteps
{
/// <summary>
/// Forces the specified DC current on all pins and/or pin groups specified, waits the specified amount of settling time,
/// and then measures the voltage on those pins and publishes the results to TestStand. Both DCPower and Digital PPMU pins are supported.
/// Both the <paramref name="settlingTime"/> and <paramref name="apertureTime"/> inputs are expected to be provided in Seconds.
/// By default the <paramref name="apertureTime"/> input is set to -1, which will cause this input to be ignored
/// and then measures the voltage on those pins and publishes the results to TestStand.
/// Note that the voltage measurements are published separately for each pin, regardless of if a pin group is provided, using the following Published Data Id: Voltage.
/// Both DCPower and Digital PPMU pins are supported.
/// Both the settlingTime and apertureTime inputs are expected to be provided in Seconds.
/// By default the apertureTime input is set to -1, which will cause this input to be ignored
/// and the device will use any pre-configured aperture time set by a proceeding set, such as the Setup NI-DCPower Instrumentation step.
/// The absolute value of voltage limit will be applied symmetrically (i.e if voltageLimit = 1, the output voltage will be limited between -1V and +1V).
/// An exception will be thrown if the specified limit value is outside the high-end of the voltage limit range for any of the mapped instruments.
/// For Digital PPMU pins, since the voltage range of the digital pattern instruments is typically not symmetrically (i.e. -2V to 6V),
/// the low-end of the applied voltage limit will be coerced to within range (i.e if voltageLimit = 3, the output voltage will be limited between -2V and +3V).
/// </summary>
/// <param name="tsmContext">The <see cref="ISemiconductorModuleContext"/> object.</param>
/// <param name="pinsOrPinGroups">The pins or pin groups to force DC voltage on.</param>
Expand All @@ -35,6 +41,7 @@ public static void ForceCurrentMeasureVoltage(
try
{
var sessionManager = new TSMSessionManager(tsmContext);
var absoluteValueOfVoltageLimit = Math.Abs(voltageLimit);
InvokeInParallel(
() =>
{
Expand All @@ -48,7 +55,7 @@ public static void ForceCurrentMeasureVoltage(
{
dcPower.ConfigureMeasureSettings(new DCPowerMeasureSettings { ApertureTime = apertureTime });
}
dcPower.ForceCurrent(currentLevel, voltageLimit, waitForSourceCompletion: true);
dcPower.ForceCurrent(currentLevel, absoluteValueOfVoltageLimit, waitForSourceCompletion: true);
dcPower.MeasureAndPublishVoltage("Voltage", out _);
dcPower.ConfigureSourceDelay(originalSourceDelays);
}
Expand All @@ -63,7 +70,7 @@ public static void ForceCurrentMeasureVoltage(
{
digital.ConfigureApertureTime(apertureTime);
}
digital.ForceCurrent(currentLevel, voltageLimitLow: voltageLimit, voltageLimitHigh: voltageLimit);
digital.ForceCurrent(currentLevel, voltageLimitLow: Math.Max(-2, -absoluteValueOfVoltageLimit), voltageLimitHigh: absoluteValueOfVoltageLimit);
PreciseWait(settlingTime);
digital.MeasureAndPublishVoltage("Voltage", out _);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public static partial class CommonSteps
/// <summary>
/// Forces the specified DC current on all pins and/or pin groups specified. Both DCPower and Digital PPMU pins are supported.
/// If a value is provided to the settlingTimeInSeconds input, the method will wait the specified amount of settling time before continuing.
/// The absolute value of voltage limit will be applied symmetrically (i.e if voltageLimit = 1, the output voltage will be limited between -1V and +1V).
/// An exception will be thrown if the specified limit value is outside the high-end of the voltage limit range for any of the mapped instruments.
/// For Digital PPMU pins, since the voltage range of the digital pattern instruments is typically not symmetrically (i.e. -2V to 6V),
/// the low-end of the applied voltage limit will be coerced to within range (i.e if voltageLimit = 3, the output voltage will be limited between -2V and +3V).
/// </summary>
/// <param name="tsmContext">The <see cref="ISemiconductorModuleContext"/> object.</param>
/// <param name="pinsOrPinGroups">The pins or pin groups to force DC voltage on.</param>
Expand All @@ -30,6 +34,7 @@ public static void ForceDcCurrent(
try
{
var sessionManager = new TSMSessionManager(tsmContext);
var absoluteValueOfVoltageLimit = Math.Abs(voltageLimit);
InvokeInParallel(
() =>
{
Expand All @@ -39,7 +44,7 @@ public static void ForceDcCurrent(
var dcPower = sessionManager.DCPower(dcPowerPins);
var originalSourceDelays = dcPower.GetSourceDelayInSeconds();
dcPower.ConfigureSourceDelay(settlingTime);
dcPower.ForceCurrent(currentLevel, voltageLimit);
dcPower.ForceCurrent(currentLevel, absoluteValueOfVoltageLimit);
dcPower.ConfigureSourceDelay(originalSourceDelays);
}
},
Expand All @@ -49,7 +54,7 @@ public static void ForceDcCurrent(
if (digitalPins.Any())
{
var digital = sessionManager.Digital(digitalPins);
digital.ForceCurrent(currentLevel, voltageLimitLow: voltageLimit, voltageLimitHigh: voltageLimit);
digital.ForceCurrent(currentLevel, voltageLimitLow: Math.Max(-2, -absoluteValueOfVoltageLimit), voltageLimitHigh: absoluteValueOfVoltageLimit);
PreciseWait(settlingTime);
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
using NationalInstruments.ModularInstruments.NIDCPower;
using NationalInstruments.SemiconductorTestLibrary.Common;
using NationalInstruments.SemiconductorTestLibrary.InstrumentAbstraction;
using Xunit;
using static NationalInstruments.SemiconductorTestLibrary.Common.ParallelExecution;
using static NationalInstruments.SemiconductorTestLibrary.TestStandSteps.CommonSteps;
using static NationalInstruments.SemiconductorTestLibrary.TestStandSteps.SetupAndCleanupSteps;
using static NationalInstruments.Tests.SemiconductorTestLibrary.Utilities.TSMContext;

namespace NationalInstruments.Tests.SemiconductorTestLibrary.Integration
{
[Collection("NonParallelizable")]
public class ForceCurrentMeasureVoltageTests
{
[Fact]
public void Initialize_RunForceCurrentMeasureVoltageWithPositiveInRangeVoltageLimit_VoltageLimitsCorrectlySet()
{
var tsmContext = CreateTSMContext("Mixed Signal Tests.pinmap", "Mixed Signal Tests.digiproj");
SetupNIDCPowerInstrumentation(tsmContext, measurementSense: DCPowerMeasurementSense.Local);
SetupNIDigitalPatternInstrumentation(tsmContext);

ForceCurrentMeasureVoltage(
tsmContext,
pinsOrPinGroups: new[] { "VCC1", "DigitalPins" },
currentLevel: 0.005,
voltageLimit: 3.3,
apertureTime: 5e-5,
settlingTime: 5e-5);

var dcPower = new TSMSessionManager(tsmContext).DCPower("VCC1");
dcPower.Do(sessionInfo =>
{
Assert.Equal(3.3, sessionInfo.AllChannelsOutput.Source.Current.VoltageLimit, 1);
});
var digital = new TSMSessionManager(tsmContext).Digital("DigitalPins");
digital.Do(sessionInfo =>
{
Assert.Equal(-2, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitLow);
Assert.Equal(3.3, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitHigh, 1);
});
CleanupInstrumentation(tsmContext);
}

[Fact]
public void Initialize_RunForceCurrentMeasureVoltageWithPositiveOutRangeVoltageLimit_VoltageLimitsCorrectlySet()
{
var tsmContext = CreateTSMContext("Mixed Signal Tests.pinmap", "Mixed Signal Tests.digiproj");
SetupNIDCPowerInstrumentation(tsmContext, measurementSense: DCPowerMeasurementSense.Local);
SetupNIDigitalPatternInstrumentation(tsmContext);

ForceCurrentMeasureVoltage(
tsmContext,
pinsOrPinGroups: new[] { "VCC1", "DigitalPins" },
currentLevel: 0.005,
voltageLimit: 1.3,
apertureTime: 5e-5,
settlingTime: 5e-5);

var dcPower = new TSMSessionManager(tsmContext).DCPower("VCC1");
dcPower.Do(sessionInfo =>
{
Assert.Equal(1.3, sessionInfo.AllChannelsOutput.Source.Current.VoltageLimit, 1);
});
var digital = new TSMSessionManager(tsmContext).Digital("DigitalPins");
digital.Do(sessionInfo =>
{
Assert.Equal(-1.3, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitLow, 1);
Assert.Equal(1.3, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitHigh, 1);
});
CleanupInstrumentation(tsmContext);
}

[Fact]
public void Initialize_RunForceCurrentMeasureVoltageWithNegativeInRangeVoltageLimit_VoltageLimitsCorrectlySet()
{
var tsmContext = CreateTSMContext("Mixed Signal Tests.pinmap", "Mixed Signal Tests.digiproj");
SetupNIDCPowerInstrumentation(tsmContext, measurementSense: DCPowerMeasurementSense.Local);
SetupNIDigitalPatternInstrumentation(tsmContext);

ForceCurrentMeasureVoltage(
tsmContext,
pinsOrPinGroups: new[] { "VCC1", "DigitalPins" },
currentLevel: 0.005,
voltageLimit: -1.3,
apertureTime: 5e-5,
settlingTime: 5e-5);

var dcPower = new TSMSessionManager(tsmContext).DCPower("VCC1");
dcPower.Do(sessionInfo =>
{
Assert.Equal(1.3, sessionInfo.AllChannelsOutput.Source.Current.VoltageLimit, 1);
});
var digital = new TSMSessionManager(tsmContext).Digital("DigitalPins");
digital.Do(sessionInfo =>
{
Assert.Equal(-1.3, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitLow, 1);
Assert.Equal(1.3, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitHigh, 1);
});
CleanupInstrumentation(tsmContext);
}

[Fact]
public void Initialize_RunForceCurrentMeasureVoltageWithNegativeOutRangeVoltageLimit_VoltageLimitsCorrectlySet()
{
var tsmContext = CreateTSMContext("Mixed Signal Tests.pinmap", "Mixed Signal Tests.digiproj");
SetupNIDCPowerInstrumentation(tsmContext, measurementSense: DCPowerMeasurementSense.Local);
SetupNIDigitalPatternInstrumentation(tsmContext);

ForceCurrentMeasureVoltage(
tsmContext,
pinsOrPinGroups: new[] { "VCC1", "DigitalPins" },
currentLevel: 0.005,
voltageLimit: -3.3,
apertureTime: 5e-5,
settlingTime: 5e-5);

var dcPower = new TSMSessionManager(tsmContext).DCPower("VCC1");
dcPower.Do(sessionInfo =>
{
Assert.Equal(3.3, sessionInfo.AllChannelsOutput.Source.Current.VoltageLimit, 1);
});
var digital = new TSMSessionManager(tsmContext).Digital("DigitalPins");
digital.Do(sessionInfo =>
{
Assert.Equal(-2, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitLow);
Assert.Equal(3.3, sessionInfo.PinSet.Ppmu.DCCurrent.VoltageLimitHigh, 1);
});
CleanupInstrumentation(tsmContext);
}

[Fact]
public void Initialize_RunForceCurrentMeasureVoltageWithOutHighRangeVoltageLimit_ThrowsException()
{
var tsmContext = CreateTSMContext("Mixed Signal Tests.pinmap", "Mixed Signal Tests.digiproj");
SetupNIDigitalPatternInstrumentation(tsmContext);

void ForceCurrentMeasureVoltageMethod() => ForceCurrentMeasureVoltage(
tsmContext,
pinsOrPinGroups: new[] { "VCC1", "DigitalPins" },
currentLevel: 0.005,
voltageLimit: 8,
apertureTime: 5e-5,
settlingTime: 5e-5);

var exception = Assert.Throws<NISemiconductorTestException>(ForceCurrentMeasureVoltageMethod);
Assert.Contains("Maximum Value: 6", exception.Message);
CleanupInstrumentation(tsmContext);
}
}
}
Loading

0 comments on commit e945645

Please sign in to comment.