From ac60861b3fa7f9a450c0965282c60404a832c363 Mon Sep 17 00:00:00 2001 From: Rolf Madsen Date: Fri, 7 Nov 2025 12:47:11 +0100 Subject: [PATCH 1/2] Update SourceUrl to point to GitHub repository --- ResultsAndTiming/package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ResultsAndTiming/package.xml b/ResultsAndTiming/package.xml index 7ab749b..aa3f9eb 100644 --- a/ResultsAndTiming/package.xml +++ b/ResultsAndTiming/package.xml @@ -11,7 +11,7 @@ Keysight Technologies, Inc. - https://gitlab.com/OpenTAP/Plugins/demonstration + https://github.com/opentap/Demonstration From 28e982c1ce2a8ac8d0cff8157a08cddaeac6aa00 Mon Sep 17 00:00:00 2001 From: Rolf Madsen Date: Mon, 24 Nov 2025 14:07:35 +0100 Subject: [PATCH 2/2] Demo panel (#7) * Added battery Demo Panel and improved demo - Added panel that gives an easy introduction to the demonstration. - Made the demo a bit more interesting wrt temperature. * Bump to git version 9.1.0 * Minor adjustments to battery demo panel. * More realistic battery model bette presets. * Minor adjustments based on feedback. * Refined the demo and using the latest KS8400 RC. * setup dotnet 9 * EnableWindowsTargeting * Tried to fix build * Try building on windows. * test using public runners, * dont force install packages uring build * Fixed test test plan * Added dut to test * Scaled the picture in the demonstration UI a bit. --- .github/workflows/ci.yml | 53 +- .gitversion | 2 +- Battery/BatteryDut.cs | 42 ++ Battery/BatteryModel.cs | 109 +++ Battery/ChargeStep.cs | 38 +- Battery/DischargeStep.cs | 15 +- Battery/OpenTap.Plugins.Demo.Battery.csproj | 3 +- Battery/PowerAnalyzer.cs | 73 +- Battery/RatingStep.cs | 1 - Battery/SamplingStepBase.cs | 30 +- Battery/SetTemperatureStep.cs | 23 +- Battery/TemperatureChamber.cs | 48 +- Demos.sln | 6 + Directory.Build.props | 2 +- .../BatteryDemoPanel.cs | 17 + .../DemonstrationPanelTest.xaml | 46 ++ .../DemonstrationPanelTest.xaml.cs | 167 +++++ .../OpenTap.Plugins.Demo.Battery.UI.csproj | 37 + .../Resources/battery_demo.TapReport | 169 +++++ .../Resources/battery_demo_preset.xml | 631 ++++++++++++++++++ .../Resources/batterydemo.png | Bin 0 -> 21432 bytes ResultsAndTiming/DemoBaseStep.cs | 1 - .../LimitCheckAndNoiseBaseStep.cs | 1 - ...enTap.Plugins.Demo.ResultsAndTiming.csproj | 2 +- ResultsAndTiming/Properties/AssemblyInfo.cs | 1 - ResultsAndTiming/RampResultsStep.cs | 1 - ResultsAndTiming/SineResultsStep.cs | 1 - .../Tests/DemonstrationAllSteps.TapPlan | 6 - .../Tests/Test Bench Profile/DUTs.xml | 9 + ResultsAndTiming/TimeActivityStep.cs | 1 - ResultsAndTiming/TimeDut.cs | 1 - ResultsAndTiming/TimeInst.cs | 1 - ResultsAndTiming/TimeResourceActivityStep.cs | 1 - ResultsAndTiming/package.xml => package.xml | 6 +- 34 files changed, 1409 insertions(+), 135 deletions(-) create mode 100644 Battery/BatteryDut.cs create mode 100644 Battery/BatteryModel.cs create mode 100644 OpenTap.Plugins.Demo.Battery.UI/BatteryDemoPanel.cs create mode 100644 OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml create mode 100644 OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml.cs create mode 100644 OpenTap.Plugins.Demo.Battery.UI/OpenTap.Plugins.Demo.Battery.UI.csproj create mode 100644 OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo.TapReport create mode 100644 OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo_preset.xml create mode 100644 OpenTap.Plugins.Demo.Battery.UI/Resources/batterydemo.png rename ResultsAndTiming/package.xml => package.xml (95%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54ec401..7918262 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,51 +28,43 @@ jobs: retention-days: 7 path: "ResultsAndTiming/*.chm" Build: - runs-on: - group: OpenTAP-SpokeVPC - labels: [Linux, X64] - container: ghcr.io/opentap/oci-images/build-dotnet:latest + runs-on: windows-latest env: KS8500_USER_TOKEN: ${{ secrets.KS8500_USER_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 with: - fetch-depth: 0 - + fetch-depth: 0 + - name: Fix tags if: startsWith(github.ref, 'refs/tags/v') run: git fetch -f origin ${{ github.ref }}:${{ github.ref }} # Fixes an issue with actions/checkout@v4. See https://github.com/actions/checkout/issues/290 - - - name: Setup OpenTAP - uses: opentap/setup-opentap@main - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.x - + - name: Build + run: dotnet build -c Release + + - name: Create Package run: | - dotnet restore - dotnet publish -c Release - mv bin/Release/*.TapPackage . - + cd bin/Release + ./tap package create ../../package.xml -v + - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: tap_package retention-days: 7 - path: "*.TapPackage" + path: "bin/Release/*.TapPackage" Package-Test: - runs-on: - group: OpenTAP-SpokeVPC - labels: [Linux, X64] - container: ghcr.io/opentap/oci-images/build-dotnet:latest + runs-on: ubuntu-latest needs: - Build steps: + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Setup OpenTAP uses: opentap/setup-opentap@main @@ -85,17 +77,18 @@ jobs: - name: Package run: | cp Demonstration.*.TapPackage DemonstrationTest.TapPackage - tap package install DemonstrationTest.TapPackage --force + tap package install DemonstrationTest.TapPackage tap package test Demonstration -v TestPlan-Test: - runs-on: - group: OpenTAP-SpokeVPC - labels: [Linux, X64] - container: ghcr.io/opentap/oci-images/build-dotnet:latest + runs-on: ubuntu-latest needs: - Build steps: + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Setup OpenTAP uses: opentap/setup-opentap@main @@ -108,7 +101,7 @@ jobs: - name: Package run: | cp Demonstration.*.TapPackage DemonstrationTest.TapPackage - tap package install DemonstrationTest.TapPackage --force + tap package install DemonstrationTest.TapPackage cd /opt/tap tap run Packages/Demonstration/DataGenForResultsViewer.TapPlan tap run Packages/Demonstration/DataGenForTimingAnalysis.TapPlan --settings "../../Packages/Demonstration/Tests/Test Bench Profile" diff --git a/.gitversion b/.gitversion index 787a5ff..c0aee99 100644 --- a/.gitversion +++ b/.gitversion @@ -3,7 +3,7 @@ # This is the version number that will be used. Prerelease numbers are calculated by # counting git commits since the last change in this value. -version = 9.0.7 +version = 9.1.0 # A version is determined to be a "beta" prerelease if it originates from the default branch # The default branch is the first branch that matches the following regular expession. diff --git a/Battery/BatteryDut.cs b/Battery/BatteryDut.cs new file mode 100644 index 0000000..2796124 --- /dev/null +++ b/Battery/BatteryDut.cs @@ -0,0 +1,42 @@ +namespace OpenTap.Plugins.Demo.Battery +{ + [Display("Battery", "This DUT represents the battery itself.")] + public class BatteryDut : Dut + { + #region Settings + + [Display("Capacity", "A larger cell size will result in faster charging and discharging.")] + [Unit("Ah")] + public double Capacity { get; set; } = 0.3; + + [Display("Base Voltage", "The battery voltage when discharged.")] + [Unit("V")] + public double BaseVoltage { get; set; } = 3.0; + + [Display("Charged Voltage", "The battery voltage when charged.")] + [Unit("V")] + public double ChargedVoltage { get; set; } = 4.2; + + [Display("Initial Charge")] + [Unit("Ah")] + public double InitialCharge { get; set; } = 0.01; + + #endregion + + internal BatteryModel Model { get; private set; } + public BatteryDut() + { + Name = "Bat"; + Rules.Add(() => Capacity >= 0, "Capacity must be greater than 0", nameof(Capacity)); + Rules.Add(() => BaseVoltage >= 0, "Base Voltage must be greater than 0", nameof(BaseVoltage)); + Rules.Add(() => ChargedVoltage >= BaseVoltage, "Charted Voltage must be greater than 0", nameof(ChargedVoltage)); + Model = new BatteryModel(); + } + + public override void Open() + { + Model = new BatteryModel(initialCharge_Ah: InitialCharge, capacity_Ah: Capacity, chargedVoltage: ChargedVoltage, baseVoltage: BaseVoltage); + base.Open(); + } + } +} \ No newline at end of file diff --git a/Battery/BatteryModel.cs b/Battery/BatteryModel.cs new file mode 100644 index 0000000..c6577ee --- /dev/null +++ b/Battery/BatteryModel.cs @@ -0,0 +1,109 @@ +using System; + +namespace OpenTap.Plugins.Demo.Battery +{ + /// + /// This is a relatively inaccurate physical model of a Lithium-ion-like battery. + /// + class BatteryModel + { + // --- Physical constants --- + private const double Rgas = 8.314; // J/mol·K + private const double Tref = 298.15; // 25°C in Kelvin + + // --- Simulation + private double baseVoltage = 3.0; + private double chargedVoltage = 4.2; + + // --- Nominal parameters --- + private readonly double nominalCapacity; // Ah + private readonly double R25; // Internal resistance (Ohm) at 25°C + private readonly double beta; // Temperature coefficient for resistance + private readonly double Ea; // Activation energy (J/mol) + private readonly double selfDischarge25; // Self-discharge rate at 25°C (fraction/min) + + // --- State variables --- + public double Charge_Ah { get; private set; } // Current stored charge + public double Voltage_V { get; private set; } // Terminal voltage + public double Current_A { get; private set; } // Charging (+) or discharging (-) + public double Voc { get; private set; } // Voltage open-circuit + public double SOC { get; private set; } // State of Charge (0–1) + public double CoulombicEfficiency { get; private set; } + + public BatteryModel( + double capacity_Ah = 3.0, + double initialCharge_Ah = 1.5, + double internalResistance25 = 0.05, + double temperatureCoeff = 0.04, + double activationEnergy = 35000.0, + double selfDischargeRate25 = 0.0001, + double baseVoltage = 3.0, + double chargedVoltage = 4.2) + { + nominalCapacity = capacity_Ah; + Charge_Ah = initialCharge_Ah; + R25 = internalResistance25; + beta = temperatureCoeff; + Ea = activationEnergy; + selfDischarge25 = selfDischargeRate25; + this.baseVoltage = baseVoltage; + this.chargedVoltage = chargedVoltage; + + double capacity = nominalCapacity * 1; + SOC = Charge_Ah / capacity; + SOC = Math.Min(Math.Max(SOC, 0.0), 1.0); + Voc = baseVoltage + (chargedVoltage - baseVoltage) * SOC + 0.05 * Math.Sin(5 * SOC); + } + + /// + /// Update the battery state given an applied terminal voltage, temperature, and timestep. + /// + /// Applied terminal voltage (V) + /// Timestep (minutes) + /// Cell temperature (°C) + /// Current limited by the generator. + public void Update(double appliedVoltage, double dt_min, double temperature_C, double current_limit) + { + double T_K = temperature_C + 273.15; + + // external resistance + double R_external = 0.02; + + // --- Temperature-dependent parameters --- + double R_internal = R25 * Math.Exp(beta * (25 - temperature_C)); + double capacity = nominalCapacity * (1 - 0.002 * Math.Abs(temperature_C - 25)); + double k_self = selfDischarge25 * Math.Exp(0.05 * (temperature_C - 25)); + + // --- Compute open-circuit voltage based on SOC --- + SOC = Charge_Ah / capacity; + SOC = Math.Min(Math.Max(SOC, 0.0), 1.0); + Voc = baseVoltage + (chargedVoltage - baseVoltage) * SOC + 0.05 * Math.Sin(5 * SOC); + + // --- Solve current from voltage equation --- + // I is clamped by +/- current_limit. + // appliedVoltage = Voc - I * R_internal + Current_A = Math.Max(Math.Min((Voc- appliedVoltage) / (R_internal + R_external), current_limit), -current_limit); + + // --- Temperature-dependent efficiency (Arrhenius relation) --- + CoulombicEfficiency = Math.Exp(-Ea / Rgas * (1.0 / T_K - 1.0 / Tref)); + CoulombicEfficiency = Math.Min(Math.Max(CoulombicEfficiency, 0.7), 1.0); + + // --- Effective current (charging losses) --- + double effectiveCurrent = Current_A; + if (Current_A > 0) // Charging + effectiveCurrent *= CoulombicEfficiency; + + // --- Update charge (Ah) --- + Charge_Ah += -effectiveCurrent * dt_min / 60.0; + + // --- Apply self-discharge --- + Charge_Ah -= Charge_Ah * k_self * dt_min; + + // --- Clamp charge --- + Charge_Ah = Math.Min(Math.Max(Charge_Ah, 0.0), capacity); + + // --- Update terminal voltage --- + Voltage_V = appliedVoltage; + } + } +} \ No newline at end of file diff --git a/Battery/ChargeStep.cs b/Battery/ChargeStep.cs index b02dcbe..7700ae9 100644 --- a/Battery/ChargeStep.cs +++ b/Battery/ChargeStep.cs @@ -4,8 +4,6 @@ // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. using System; -using OpenTap; - using System.Diagnostics; // Use Platform infrastructure/core components (log,TestStep definition, etc) namespace OpenTap.Plugins.Demo.Battery @@ -21,28 +19,33 @@ public class ChargeStep : SamplingStepBase [Unit("V")] public double Voltage { get; set; } - [Display("Target Voltage Margin", Group: "Cell", Order: -1)] + [Display("Target Voltage", Group: "Power Supply", Order: -1)] [Unit("V")] - public double TargetCellVoltageMargin { get; set; } + public double TargetVoltage { get; set; } [Display("Charge Time", Group: "Output", Order: 0)] [Unit("s")] [Output] public double ChargeTime { get; private set; } + + #endregion public ChargeStep() { Voltage = 4.2; Current = 10; - TargetCellVoltageMargin = 0.1; - Rules.Add(() => (Voltage >= 0) && (Voltage <= 10), "Voltage must be >= 0 and <= 10", "Voltage"); - Rules.Add(() => (Current >= 0) && (Current <= 20), "Current must be >= 0 and <= 20", "Current"); - Rules.Add(() => (TargetCellVoltageMargin >= 0) && (TargetCellVoltageMargin <= 1), "TargetCellVoltageMargin must be >= 0 and <= 1", "TargetCellVoltageMargin"); + TargetVoltage = 4.1; + Rules.Add(() => (Voltage >= 0) && (Voltage <= 10), "Voltage must be >= 0 and <= 10", nameof(Voltage)); + Rules.Add(() => (Current >= 0) && (Current <= 20), "Current must be >= 0 and <= 20", nameof(Current)); + Rules.Add(() => TargetVoltage < Voltage, "Target voltage must be less than the voltage", nameof(TargetVoltage)); + } + public double accumulatedCharge; public override void Run() { + accumulatedCharge = 0; var sw = Stopwatch.StartNew(); PowerAnalyzer.Setup(Voltage, Current); PowerAnalyzer.EnableOutput(); @@ -50,11 +53,12 @@ public override void Run() base.Run(); // Most of the work is being done here, with callbacks to this class. PowerAnalyzer.DisableOutput(); ChargeTime = sw.Elapsed.TotalSeconds; + UpgradeVerdict(Verdict.Pass); } protected override void WhileSampling() { - while(Math.Abs(PowerAnalyzer.MeasureVoltage() - Voltage) > TargetCellVoltageMargin) + while(Dut.Model.Voc < TargetVoltage) { TapThread.Sleep(50); } @@ -66,9 +70,21 @@ public class ChargeResult [Display("Sample Number")] public int SampleNo { get; set; } [Display("Voltage")] + + [Unit("V")] public double Voltage { get; set; } + [Display("Current")] + [Unit("A")] public double Current { get; set; } + + [Display("Power")] + [Unit("W")] + public double Power { get; set; } + + [Display("Acc. Charge")] + [Unit("J")] + public double AccumulatedCharge { get; set; } } protected override void OnSample(double voltage, double current, int sampleNo) @@ -78,8 +94,8 @@ protected override void OnSample(double voltage, double current, int sampleNo) barVoltage.LowerLimit = 2; //Cell voltage defined in PowerAnalyzer barVoltage.UpperLimit = 4.7; Log.Info("Voltage: " + barVoltage.GetBar(voltage)); - - Results.Publish(new ChargeResult { SampleNo = sampleNo, Voltage = Math.Truncate(voltage * 100) / 100, Current = Math.Truncate(current * 100) / 100}); + accumulatedCharge += voltage * current * MeasurementInterval; + Results.Publish(new ChargeResult { SampleNo = sampleNo, Voltage = Math.Round(voltage, 2), Current = Math.Round(current,2), Power = voltage * current, AccumulatedCharge = accumulatedCharge}); } } diff --git a/Battery/DischargeStep.cs b/Battery/DischargeStep.cs index 112447a..a40a9c3 100644 --- a/Battery/DischargeStep.cs +++ b/Battery/DischargeStep.cs @@ -5,7 +5,6 @@ // warranty, obligations or liability for any sample application files. using System; using System.Diagnostics; // Use Platform infrastructure/core components (log,TestStep definition, etc) -using OpenTap; namespace OpenTap.Plugins.Demo.Battery { @@ -19,10 +18,11 @@ public class DischargeStep : SamplingStepBase [Display("Voltage", Group: "Power Supply", Order: -1)] [Unit("V")] public double Voltage { get; set; } - - [Display("Target Voltage Margin", Group: "Cell", Order: -1)] + + [Display("Target Voltage", Group: "Power Supply", Order: -1)] [Unit("V")] - public double TargetCellVoltageMargin { get; set; } + public double TargetVoltage { get; set; } + [Display("Discharge Time", Group: "Output", Order: 0)] [Unit("s")] @@ -35,10 +35,10 @@ public DischargeStep() { Voltage = 2.2; Current = 5; - TargetCellVoltageMargin = 0.8; + TargetVoltage = 3.1; Rules.Add(() => (Voltage >= 0) && (Voltage <= 10), "Voltage must be >= 0 and <= 10", "Voltage"); Rules.Add(() => (Current >= 0) && (Current <= 20), "Current must be >= 0 and <= 20", "Current"); - Rules.Add(() => (TargetCellVoltageMargin >= 0) && (TargetCellVoltageMargin <= 1), "TargetCellVoltageMargin must be >= 0 and <= 1", "TargetCellVoltageMargin"); + Rules.Add(() => (TargetVoltage > Voltage), "Target Voltage must be greater than the voltage.", "TargetCellVoltageMargin"); } public override void Run() @@ -50,11 +50,12 @@ public override void Run() base.Run(); PowerAnalyzer.DisableOutput(); DischargeTime = sw.Elapsed.TotalSeconds; + UpgradeVerdict(Verdict.Pass); } protected override void WhileSampling() { - while(Math.Abs(PowerAnalyzer.MeasureVoltage() - Voltage) > TargetCellVoltageMargin) + while(Dut.Model.Voc > TargetVoltage) { TapThread.Sleep(50); } diff --git a/Battery/OpenTap.Plugins.Demo.Battery.csproj b/Battery/OpenTap.Plugins.Demo.Battery.csproj index de127bb..9b1c3a7 100644 --- a/Battery/OpenTap.Plugins.Demo.Battery.csproj +++ b/Battery/OpenTap.Plugins.Demo.Battery.csproj @@ -15,7 +15,8 @@ - + + diff --git a/Battery/PowerAnalyzer.cs b/Battery/PowerAnalyzer.cs index 263859e..0d14f21 100644 --- a/Battery/PowerAnalyzer.cs +++ b/Battery/PowerAnalyzer.cs @@ -4,25 +4,24 @@ // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. +using System; using System.Diagnostics; -using OpenTap; +using OpenTap.Metrics; namespace OpenTap.Plugins.Demo.Battery { - [Display("Power Analyzer", "Simulated power analyzer instrument used for charge/discharge demo steps.", Groups: new[] { "Demo", "Battery Test" })] + [Display("Power Analyzer", "Simulated power analyzer instrument used for charge/discharge demo steps.", + Groups: new[] { "Demo", "Battery Test" })] public class PowerAnalyzer : Instrument { - #region Settings - [Display("Cell Size Factor", "A larger cell size will result in faster charging and discharging.")] - public double CellSizeFactor { get; set; } - #endregion - + private double idleVoltage = 0.0; + + [Metric] [Unit("V")] + [Display("Idle Voltage")] + public double? IdleVoltage => Math.Round( lastBattery?.Model?.Voc ?? idleVoltage, 2); public PowerAnalyzer() { - Name = "PSU"; - - CellSizeFactor = 0.005; - Rules.Add(() => (CellSizeFactor >= 0) && (CellSizeFactor <= .1), "CellSizeFactor must be >= 0 and <= .1", "Voltage"); + Name = "PSU"; } /// @@ -32,8 +31,10 @@ public override void Open() { base.Open(); _voltage = 0; - _cellVoltage = 2.7; Log.Info("Device PSU opened"); + _sw = new Stopwatch(); + + } /// @@ -49,23 +50,27 @@ public override void Close() base.Close(); } - public double MeasureCurrent() - { - UpdateCurrentAndVoltage(); - return _current; - } - - public double MeasureVoltage() + private BatteryDut lastBattery; + public (double voltage, double current) Measure(BatteryDut dut) { - UpdateCurrentAndVoltage(); - return _cellVoltage; + if (_sw.IsRunning == false) + { + dut.Model.Update(_voltage, 0.0, TemperatureChamber.Temperature, _currentLimit); + _sw.Start(); + } + lastBattery = dut; + if(_sw.ElapsedMilliseconds > 1) + { + dut.Model.Update(_voltage, _sw.Elapsed.TotalSeconds, TemperatureChamber.Temperature, _currentLimit); + _sw.Restart(); + } + return (dut.Model.Voc, dut.Model.Current_A); } internal void Setup(double voltage, double current) { _voltage = voltage; _currentLimit = current; - _current = current; } internal void EnableOutput() @@ -81,29 +86,7 @@ internal void DisableOutput() } private double _voltage; - private double _cellVoltage = 2.7; - private double _current = 10; - private double _currentLimit; Stopwatch _sw; - private void UpdateCurrentAndVoltage() - { - if (_sw == null || !_sw.IsRunning) // Only update if output is enabled - return; - - // Generates a somewhat random curve that gradually approaches the limit. - _current = (_currentLimit * (_voltage - _cellVoltage)*2 + RandomNumber.Generate()*_currentLimit/50); - - if (_current >= _currentLimit) - { - _current = _currentLimit; - } - else if (_current < 0-_currentLimit) - { - _current = 0- _currentLimit; - } - - _cellVoltage += CellSizeFactor * _current * _sw.Elapsed.TotalSeconds * 10; - _sw.Restart(); - } + private double _currentLimit; } } diff --git a/Battery/RatingStep.cs b/Battery/RatingStep.cs index ed767ef..d162082 100644 --- a/Battery/RatingStep.cs +++ b/Battery/RatingStep.cs @@ -5,7 +5,6 @@ // warranty, obligations or liability for any sample application files. using System.ComponentModel; using System.Xml.Serialization; -using OpenTap; namespace OpenTap.Plugins.Demo.Battery { diff --git a/Battery/SamplingStepBase.cs b/Battery/SamplingStepBase.cs index 787e238..4b0417a 100644 --- a/Battery/SamplingStepBase.cs +++ b/Battery/SamplingStepBase.cs @@ -3,8 +3,6 @@ // the sample application files (and/or any modified version) in any way // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. -using System.Timers; -using OpenTap; namespace OpenTap.Plugins.Demo.Battery { @@ -19,6 +17,9 @@ public abstract class SamplingStepBase : TestStep [Display("Power Analyzer", Group: "Resources", Order: -100)] public PowerAnalyzer PowerAnalyzer { get; set; } + [Display("DUT")] + public BatteryDut Dut { get; set; } + public SamplingStepBase() { MeasurementInterval = .2; @@ -27,9 +28,19 @@ public SamplingStepBase() public override void Run() { _sampleNo = 0; - Timer timer = new Timer((int)(MeasurementInterval * 1000)); - timer.Elapsed += timer_Elapsed; - timer.Start(); + bool measuring = true; + var trd = TapThread.Start(() => + { + PowerAnalyzer.Measure(Dut); + TapThread.Sleep(10); + while (measuring) + { + var (voltage, current) = PowerAnalyzer.Measure(Dut); + OnSample(voltage, current, _sampleNo++); + TapThread.Sleep((int)(1000.0 * MeasurementInterval)); + } + + }); try { // Sleep, while the timer thread generates data. @@ -39,17 +50,10 @@ public override void Run() } finally { - timer.Stop(); + measuring = false; } } - private void timer_Elapsed(object sender, ElapsedEventArgs e) - { - double voltage = PowerAnalyzer.MeasureVoltage(); - double current = PowerAnalyzer.MeasureCurrent(); - OnSample(voltage, current, _sampleNo++); - } - protected abstract void WhileSampling(); protected abstract void OnSample(double voltage, double current, int sampleNo); diff --git a/Battery/SetTemperatureStep.cs b/Battery/SetTemperatureStep.cs index 3a7b6a3..d38e3e6 100644 --- a/Battery/SetTemperatureStep.cs +++ b/Battery/SetTemperatureStep.cs @@ -4,8 +4,7 @@ // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. -using OpenTap; - +using System.Diagnostics; namespace OpenTap.Plugins.Demo.Battery { [Display("Set Temperature", "Configure the temperature chamber.", Groups: new[] {"Demo", "Battery Test" })] @@ -36,9 +35,23 @@ public SetTemperatureStep() public override void Run() { Log.Info("Temperature set to: " + Temperature + " °C"); - TapThread.Sleep(3000); - Log.Info("Temperature reached: " + Temperature + " °C [3000 ms]"); - RunChildSteps(); //If step has child steps. + bool waiting = true; + TapThread.Start(() => + { + while (waiting) + { + Log.Info($"Current temperature: {TemperatureChamber.Temperature:F1} °C"); + TapThread.Sleep(1000); + } + + }); + Chamber.SetTarget(Temperature, Humidity); + var sw = Stopwatch.StartNew(); + + Chamber.WaitForConditions(); + waiting = false; + + Log.Info(sw, "Temperature reached: " + Temperature + " °C"); } } } diff --git a/Battery/TemperatureChamber.cs b/Battery/TemperatureChamber.cs index 8d6ad6a..7478e34 100644 --- a/Battery/TemperatureChamber.cs +++ b/Battery/TemperatureChamber.cs @@ -3,13 +3,24 @@ // the sample application files (and/or any modified version) in any way // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. -using OpenTap; + +using System; +using OpenTap.Metrics; namespace OpenTap.Plugins.Demo.Battery { [Display("Temperature Chamber", "Simulated temperature chamber instrument used for SetTemperature demo step.", Groups: new[] { "Demo", "Battery Test" })] public class TemperatureChamber : Instrument { + private double humidityTarget = 50; + private double temperatureTarget = 50; + public static double Temperature = 25; + public static double Humidity = 25; + [Metric] + [Unit("°C")] + [Display("Temperature")] + public double TemperatureMetric => Math.Round(Temperature, 2); + public TemperatureChamber() { Name = "TEMP"; @@ -32,5 +43,40 @@ public override void Close() Log.Info("Device TEMP closed"); base.Close(); } + + public void SetTarget(double temperature, double humidity) + { + this.temperatureTarget = temperature; + this.humidityTarget = humidity; + } + + public void WaitForConditions() + { + var rnd = new Random(); + if (temperatureTarget > Temperature) + { + Log.Debug("Heating..."); + while (temperatureTarget > Temperature) + { + // heating up. + Temperature += rnd.NextDouble() * 0.02 + 0.05; + TapThread.Sleep(10); + OnActivity(); + } + }else if (temperatureTarget < Temperature) + { + Log.Debug("Cooling..."); + while (temperatureTarget < Temperature) + { + + Temperature -= (rnd.NextDouble() * 0.02 + 0.05); + TapThread.Sleep(10); + OnActivity(); + } + + } + + Temperature = temperatureTarget; + } } } diff --git a/Demos.sln b/Demos.sln index d883716..eb62656 100644 --- a/Demos.sln +++ b/Demos.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTap.Plugins.Demo.Batter EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTap.Plugins.Demo.ResultsAndTiming", "ResultsAndTiming\OpenTap.Plugins.Demo.ResultsAndTiming.csproj", "{400E13F0-E63E-496B-9E3F-955BECC22444}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTap.Plugins.Demo.Battery.UI", "OpenTap.Plugins.Demo.Battery.UI\OpenTap.Plugins.Demo.Battery.UI.csproj", "{E7549526-BA5E-4F56-8E03-ADF310FBD6B4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -22,6 +24,10 @@ Global {400E13F0-E63E-496B-9E3F-955BECC22444}.Debug|Any CPU.Build.0 = Debug|Any CPU {400E13F0-E63E-496B-9E3F-955BECC22444}.Release|Any CPU.ActiveCfg = Release|Any CPU {400E13F0-E63E-496B-9E3F-955BECC22444}.Release|Any CPU.Build.0 = Release|Any CPU + {E7549526-BA5E-4F56-8E03-ADF310FBD6B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7549526-BA5E-4F56-8E03-ADF310FBD6B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7549526-BA5E-4F56-8E03-ADF310FBD6B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7549526-BA5E-4F56-8E03-ADF310FBD6B4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Directory.Build.props b/Directory.Build.props index 553d82e..f6c255c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ netstandard2.0 false false - 9.25.1 + 9.31.1-rc.4+d1f598be $(MSBuildThisFileDirectory)/bin/$(Configuration) diff --git a/OpenTap.Plugins.Demo.Battery.UI/BatteryDemoPanel.cs b/OpenTap.Plugins.Demo.Battery.UI/BatteryDemoPanel.cs new file mode 100644 index 0000000..df2f840 --- /dev/null +++ b/OpenTap.Plugins.Demo.Battery.UI/BatteryDemoPanel.cs @@ -0,0 +1,17 @@ +using System.Windows; +using Keysight.OpenTap.Wpf; + +namespace OpenTap.Plugins.Demo.Battery.UI; + +[Display("Battery Demonstration", Group:"Getting Started", Description: "This is a demonstration panel for the battery test.")] +public class BatteryDemoPanel : IGettingStartedPanel +{ + + public FrameworkElement CreateElement(ITapDockContext context) + { + return new DemonstrationPanelTest(context); + } + + public double? DesiredWidth => 600; + public double? DesiredHeight => 800; +} diff --git a/OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml b/OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml new file mode 100644 index 0000000..e10f378 --- /dev/null +++ b/OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml @@ -0,0 +1,46 @@ + + + + + + Battery Test Demonstration + + In this demonstration, we will show how a basic battery test can be set up. + Here we are testing how different temperatures affect charging and discharging the battery. + It consists of the following simulated instruments: + + + + • A battery device under test (DUT). + + + • A power supply / analyzer + + + • A temperature chamber + + + + + • Load the demonstration. + + + • Run the test plan. + + + • Show Results Viewer. + + + + + + + + diff --git a/OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml.cs b/OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml.cs new file mode 100644 index 0000000..0febe92 --- /dev/null +++ b/OpenTap.Plugins.Demo.Battery.UI/DemonstrationPanelTest.xaml.cs @@ -0,0 +1,167 @@ +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using Keysight.OpenTap.Gui; +using Keysight.OpenTap.Plugins.Csv; +using Keysight.OpenTap.Plugins.ResultListeners; +using Keysight.OpenTap.Wpf; + +namespace OpenTap.Plugins.Demo.Battery.UI; + +public partial class DemonstrationPanelTest : UserControl +{ + private readonly ITapDockContext _context; + + public DemonstrationPanelTest(ITapDockContext context) + { + _context = context; + InitializeComponent(); + } + + private void LoadResources() + { + ComponentSettings.SetSettingsProfile("Bench", Path.GetFullPath(Path.Combine("Settings","Bench","Battery Demo"))); + InstrumentSettings.Current.Clear(); + InstrumentSettings.Current.Add(new PowerAnalyzer()); + InstrumentSettings.Current.Add(new TemperatureChamber()); + InstrumentSettings.Current.Save(); + DutSettings.Current.Clear(); + DutSettings.Current.Add(new BatteryDut()); + + DutSettings.Current.Save(); + if (!ResultSettings.Current.OfType().Any()) + ResultSettings.Current.Add(new CsvResultListener()); + + if (!ResultSettings.Current.OfType().Any()) + { + ResultSettings.Current.Add(new SQLiteDatabase()); + ResultSettings.Current.Save(); + } + + InstrumentSettings.Current.Invalidate(); + DutSettings.Current.Invalidate(); + + } + + private void LoadTestPlan() + { + var plan = new TestPlan(); + _context.Plan = plan; + + var tempSweep = new BasicSteps.SweepParameterStep(); + var temp = new SetTemperatureStep(); + var charge = new ChargeStep(); + var discharge = new DischargeStep(); + tempSweep.ChildTestSteps.Add(temp); + tempSweep.ChildTestSteps.Add(charge); + tempSweep.ChildTestSteps.Add(discharge);// set the sweep loop to being expanded. + ChildItemVisibility.SetVisibility(tempSweep, ChildItemVisibility.Visibility.Visible); + + plan.ChildTestSteps.Add(tempSweep); + + TypeData.GetTypeData(temp) + .GetMember(nameof(temp.Temperature)) + .Parameterize(tempSweep, temp, "Temperature"); + + tempSweep.SweepValues.Add(new BasicSteps.SweepRow(){Values = {["Temperature"] = -10.0}}); + tempSweep.SweepValues.Add(new BasicSteps.SweepRow(){Values = {["Temperature"] = 0.0}}); + tempSweep.SweepValues.Add(new BasicSteps.SweepRow(){Values = {["Temperature"] = 10.0}}); + tempSweep.SweepValues.Add(new BasicSteps.SweepRow(){Values = {["Temperature"] = 24.0}}); + tempSweep.SweepValues.Add(new BasicSteps.SweepRow(){Values = {["Temperature"] = 30.0}}); + tempSweep.SweepValues.Add(new BasicSteps.SweepRow(){Values = {["Temperature"] = 45.0}}); + + plan.Save("Battery Demo.TapPlan"); + + var testPlanGridType = TypeData.GetTypeData("Keysight.OpenTap.Gui.TestPlanPlugin"); + TapPanel.Focus(testPlanGridType); + + + } + + private void OnRunTestPlan(object sender, RoutedEventArgs e) + { + _context.Run(); + var testPlanGridType = TypeData.GetTypeData("Keysight.OpenTap.Gui.TestPlanPlugin"); + TapPanel.Focus(testPlanGridType); + } + + private void LoadViewPreset() + { + var destPath = Path.Combine(ViewPreset.PresetDir, "batterydemo.xml"); + var srcPath = Path.Combine("Packages", "Demonstration", "battery_demo_preset.xml"); + File.Delete(destPath); + File.Copy(srcPath, destPath); + + ViewPreset.SelectPreset(Path.GetFileNameWithoutExtension(destPath), raiseEvent: true); + + } + private void OnShowResultsViewer(object sender, RoutedEventArgs e) + { + var templatePath = Path.Combine("Packages", "Demonstration", "battery_demo.TapReport"); + var store = ResultSettings.Current.OfType().FirstOrDefault(); + ResultsViewer.Open(store, Application.Current.MainWindow, templatePath, 1); + } + + private void OnLoadDemo(object sender, RoutedEventArgs e) + { + var response = ShowMessage("Load Demonstration?", + " Loading the battery test demonstration will cause the following changes:\n" + + " - New bench profile: a DUT, a power analyzer and a temperature chamber.\n" + + " - Added result listeners: Adding CSV and SQLite database result storage.\n"+ + " - New view preset: A view preset will be applied providing an optimized view.\n" + + " - New test plan: A demonstration test plan will be loaded.\n\n" + + + "This can be undone by selecting the previous bench profile and view preset.", + ["OK", "Cancel"]); + if (response == "Cancel") + return; + LoadResources(); + LoadTestPlan(); + LoadViewPreset(); + } + + public class MessageBox : IDisplayAnnotation + { + string IDisplayAnnotation.Description => null; + string[] IDisplayAnnotation.Group => null; + + double IDisplayAnnotation.Order => 0.0; + bool IDisplayAnnotation.Collapsed => false; + + + public string Name { get; internal set; } + + [Layout(LayoutMode.FullRow)] + [Browsable(true)] + public string Message { get; internal set; } + + public bool ShowFilePath { get; internal set; } + + [EnabledIf(nameof(ShowFilePath), true, HideIfDisabled = true)] + [FilePath(FilePathAttribute.BehaviorChoice.Open)] + [Display ("File Path")] + public string FilePath { get; set; } + + + public string[] Options { get; internal set; } = ["OK"]; + + [Layout(LayoutMode.FloatBottom|LayoutMode.FullRow)] + [Submit] + [AvailableValues(nameof(Options))] + public string SelectedOption { get; set; } + } + + string ShowMessage(string title, string message, string[] options = null) + { + var box = new MessageBox + { + Name = title, Message = message, + Options = options ?? ["OK"], + SelectedOption = options?.FirstOrDefault() ?? "OK" + }; + UserInput.Request(box); + return box.SelectedOption; + } +} \ No newline at end of file diff --git a/OpenTap.Plugins.Demo.Battery.UI/OpenTap.Plugins.Demo.Battery.UI.csproj b/OpenTap.Plugins.Demo.Battery.UI/OpenTap.Plugins.Demo.Battery.UI.csproj new file mode 100644 index 0000000..681a48f --- /dev/null +++ b/OpenTap.Plugins.Demo.Battery.UI/OpenTap.Plugins.Demo.Battery.UI.csproj @@ -0,0 +1,37 @@ + + + + net9.0-windows + True + True + + + + + + + + + + + + + + + + + + + + + + Always + Packages/Demonstration/battery_demo.TapReport + + + Always + Packages/Demonstration/battery_demo_preset.xml + + + + diff --git a/OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo.TapReport b/OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo.TapReport new file mode 100644 index 0000000..2376046 --- /dev/null +++ b/OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo.TapReport @@ -0,0 +1,169 @@ + + + + + + UseDarkTheme=True + LegendPlacement=0 + LegendPosition=2 + LegendAxisName=True + LegendVisible=True + DatetimeAxis=False + + + + + + + + Sample Number + + + + + Voltage + + + + + + + + + + ResultType=Charge + + + + + Column=Temperature + + + + true + + + + UseDarkTheme=True + LegendPlacement=0 + LegendPosition=2 + LegendAxisName=True + LegendVisible=True + DatetimeAxis=False + + + + + + + + Sample Number + + + + + Current + + + + + + + + + + ResultType=Charge + + + + + Column=Temperature + + + + true + + + + UseDarkTheme=True + LegendPlacement=0 + LegendPosition=2 + LegendAxisName=True + LegendVisible=True + DatetimeAxis=False + + + + + + + + Sample Number + + + + + Voltage + + + + + + + + + + ResultType=Discharge + + + + + Column=Temperature + + + + true + + + + UseDarkTheme=True + LegendPlacement=0 + LegendPosition=2 + LegendAxisName=True + LegendVisible=True + DatetimeAxis=False + + + + + + + + Sample Number + + + + + Current + + + + + + + + + + ResultType=Discharge + + + + + Column=Temperature + + + + true + + + \ No newline at end of file diff --git a/OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo_preset.xml b/OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo_preset.xml new file mode 100644 index 0000000..ab03ad9 --- /dev/null +++ b/OpenTap.Plugins.Demo.Battery.UI/Resources/battery_demo_preset.xml @@ -0,0 +1,631 @@ + + + + Keysight.OpenTap.Gui.PanelSettings + + + Layout + + PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxMYXlvdXRSb290Pg0KICA8Um9vdFBhbmVsIE9yaWVudGF0aW9uPSJIb3Jpem9udGFsIj4NCiAgICA8TGF5b3V0UGFuZWwgT3JpZW50YXRpb249IlZlcnRpY2FsIiBEb2NrV2lkdGg9IjEuNTY1NDAwODQzODgxODU2NSoiPg0KICAgICAgPExheW91dFBhbmVsIE9yaWVudGF0aW9uPSJIb3Jpem9udGFsIiBEb2NrSGVpZ2h0PSIxLjMxNzE5Mzk0NzczMDM5ODkqIiBEb2NrTWluV2lkdGg9IjEwMCIgRG9ja01pbkhlaWdodD0iMTAwIj4NCiAgICAgICAgPExheW91dEFuY2hvcmFibGVQYW5lIElkPSIzNTZiNzcyOS1kYThiLTQ0OTAtODJmOS0zYTU0MDVkYmIzYjIiIERvY2tXaWR0aD0iMS44MjU5MzcxNjMyMjEzMTg4KiIgRG9ja01pbldpZHRoPSIxMDAiIERvY2tNaW5IZWlnaHQ9IjEwMCI+DQogICAgICAgICAgPExheW91dEFuY2hvcmFibGUgQXV0b0hpZGVNaW5XaWR0aD0iMTAwIiBBdXRvSGlkZU1pbkhlaWdodD0iMTAwIiBUaXRsZT0iV2VsY29tZSIgQ29udGVudElkPSJLZXlzaWdodC5PcGVuVGFwLkd1aS5XZWxjb21lU2NyZWVuUGFuZWwiIExhc3RBY3RpdmF0aW9uVGltZVN0YW1wPSIxMS8xMC8yMDI1IDE0OjQ5OjAwIiAvPg0KICAgICAgICAgIDxMYXlvdXRBbmNob3JhYmxlIEF1dG9IaWRlTWluV2lkdGg9IjEwMCIgQXV0b0hpZGVNaW5IZWlnaHQ9IjEwMCIgVGl0bGU9IlRlc3QgUGxhbiIgSXNTZWxlY3RlZD0iVHJ1ZSIgQ29udGVudElkPSJLZXlzaWdodC5PcGVuVGFwLkd1aS5UZXN0UGxhblBsdWdpbiIgVG9vbFRpcD0iVGVzdCBQbGFuIFBhbmVsIiBMYXN0QWN0aXZhdGlvblRpbWVTdGFtcD0iMTEvMTEvMjAyNSAwODoyMzozMCIgLz4NCiAgICAgICAgPC9MYXlvdXRBbmNob3JhYmxlUGFuZT4NCiAgICAgICAgPExheW91dEFuY2hvcmFibGVQYW5lIElkPSIxNDRmYWE0MS02YmRkLTRmNzQtYWY5Yy0wZGZlMzY1MTZiMzUiIERvY2tXaWR0aD0iMS44NzQxMzE5NDQ0NDQ0NDM1KiIgRG9ja01pbldpZHRoPSIxMDAiIERvY2tNaW5IZWlnaHQ9IjEwMCI+DQogICAgICAgICAgPExheW91dEFuY2hvcmFibGUgQXV0b0hpZGVNaW5XaWR0aD0iMTAwIiBBdXRvSGlkZU1pbkhlaWdodD0iMTAwIiBUaXRsZT0iTG9nIiBJc1NlbGVjdGVkPSJUcnVlIiBDb250ZW50SWQ9IktleXNpZ2h0Lk9wZW5UYXAuR3VpLkxvZ1BhbmVsUGx1Z2luIiBUb29sVGlwPSJMb2cgUGFuZWwiIEZsb2F0aW5nTGVmdD0iMTEzOC42NjY2NjY2NjY2NjY1IiBGbG9hdGluZ1RvcD0iMzk3LjMzMzMzMzMzMzMzMzMiIEZsb2F0aW5nV2lkdGg9IjUwMiIgRmxvYXRpbmdIZWlnaHQ9IjQzMC42NjY2NjY2NjY2NjY2MyIgTGFzdEFjdGl2YXRpb25UaW1lU3RhbXA9IjExLzEwLzIwMjUgMTQ6NTc6MDgiIFByZXZpb3VzQ29udGFpbmVySWQ9ImY4N2UxNTNjLTQ5ZTAtNDdkMC1iMDFhLTVjY2U5NWIwODE4OCIgUHJldmlvdXNDb250YWluZXJJbmRleD0iMSIgLz4NCiAgICAgICAgICA8TGF5b3V0QW5jaG9yYWJsZSBBdXRvSGlkZU1pbldpZHRoPSIxMDAiIEF1dG9IaWRlTWluSGVpZ2h0PSIxMDAiIFRpdGxlPSJUZXN0IFN0ZXAgU2V0dGluZ3MiIENvbnRlbnRJZD0iS2V5c2lnaHQuT3BlblRhcC5HdWkuU3RlcFNldHRpbmdzUGx1Z2luIiBUb29sVGlwPSJTdGVwIFNldHRpbmdzIFBhbmVsIiBMYXN0QWN0aXZhdGlvblRpbWVTdGFtcD0iMTEvMTAvMjAyNSAxNDo1Njo0MCIgLz4NCiAgICAgICAgPC9MYXlvdXRBbmNob3JhYmxlUGFuZT4NCiAgICAgIDwvTGF5b3V0UGFuZWw+DQogICAgICA8TGF5b3V0QW5jaG9yYWJsZVBhbmVHcm91cCBPcmllbnRhdGlvbj0iSG9yaXpvbnRhbCIgRG9ja0hlaWdodD0iMi4wODI1MDgyNTA4MjUwODI3KiI+DQogICAgICAgIDxMYXlvdXRBbmNob3JhYmxlUGFuZUdyb3VwIE9yaWVudGF0aW9uPSJIb3Jpem9udGFsIiBGbG9hdGluZ1dpZHRoPSI3OTQiIEZsb2F0aW5nSGVpZ2h0PSI1MDAiIEZsb2F0aW5nTGVmdD0iNjMyLjY2NjY2NjY2NjY2NjYiIEZsb2F0aW5nVG9wPSI4MjYuNjY2NjY2NjY2NjY2NiI+DQogICAgICAgICAgPExheW91dEFuY2hvcmFibGVQYW5lIEZsb2F0aW5nV2lkdGg9Ijc5NCIgRmxvYXRpbmdIZWlnaHQ9IjUwMCIgRmxvYXRpbmdMZWZ0PSI2MzIuNjY2NjY2NjY2NjY2NiIgRmxvYXRpbmdUb3A9IjgyNi42NjY2NjY2NjY2NjY2Ij4NCiAgICAgICAgICAgIDxMYXlvdXRBbmNob3JhYmxlIEF1dG9IaWRlTWluV2lkdGg9IjEwMCIgQXV0b0hpZGVNaW5IZWlnaHQ9IjEwMCIgVGl0bGU9IkxpdmUgUmVzdWx0cyAgMSIgSXNTZWxlY3RlZD0iVHJ1ZSIgQ29udGVudElkPSJLZXlzaWdodC5PcGVuVGFwLkxpdmVSZXN1bHRzUGFuZWwuTGl2ZVJlc3VsdHMiIEZsb2F0aW5nTGVmdD0iNjMyLjY2NjY2NjY2NjY2NjYiIEZsb2F0aW5nVG9wPSI4MjYuNjY2NjY2NjY2NjY2NiIgRmxvYXRpbmdXaWR0aD0iNzk0IiBGbG9hdGluZ0hlaWdodD0iNTAwIiBMYXN0QWN0aXZhdGlvblRpbWVTdGFtcD0iMTEvMTAvMjAyNSAxNDo1ODo1NyIgLz4NCiAgICAgICAgICA8L0xheW91dEFuY2hvcmFibGVQYW5lPg0KICAgICAgICA8L0xheW91dEFuY2hvcmFibGVQYW5lR3JvdXA+DQogICAgICAgIDxMYXlvdXRBbmNob3JhYmxlUGFuZSBJZD0iZjg3ZTE1M2MtNDllMC00N2QwLWIwMWEtNWNjZTk1YjA4MTg4IiBEb2NrV2lkdGg9IjEuMDU5NDgzMTM2ODM1OTU1OSoiIERvY2tNaW5XaWR0aD0iMTAwIiBEb2NrTWluSGVpZ2h0PSIxMDAiPg0KICAgICAgICAgIDxMYXlvdXRBbmNob3JhYmxlIEF1dG9IaWRlTWluV2lkdGg9IjEwMCIgQXV0b0hpZGVNaW5IZWlnaHQ9IjEwMCIgVGl0bGU9IkxpdmUgUmVzdWx0cyAyIiBJc1NlbGVjdGVkPSJUcnVlIiBDb250ZW50SWQ9IktleXNpZ2h0Lk9wZW5UYXAuTGl2ZVJlc3VsdHNQYW5lbC5MaXZlUmVzdWx0czIiIEZsb2F0aW5nTGVmdD0iMTI5MCIgRmxvYXRpbmdUb3A9IjgzMiIgRmxvYXRpbmdXaWR0aD0iNjI4LjY2NjY2NjY2NjY2NjYiIEZsb2F0aW5nSGVpZ2h0PSI0OTQiIExhc3RBY3RpdmF0aW9uVGltZVN0YW1wPSIxMS8xMS8yMDI1IDEwOjU0OjExIiAvPg0KICAgICAgICA8L0xheW91dEFuY2hvcmFibGVQYW5lPg0KICAgICAgICA8TGF5b3V0QW5jaG9yYWJsZVBhbmUgRG9ja1dpZHRoPSIwLjkzOTg2MjU0Mjk1NTMyNjEqIiBGbG9hdGluZ1dpZHRoPSI1MDAiIEZsb2F0aW5nSGVpZ2h0PSI1MDAiIEZsb2F0aW5nTGVmdD0iMTE1MCIgRmxvYXRpbmdUb3A9IjcxOC42NjY2NjY2NjY2NjY2Ij4NCiAgICAgICAgICA8TGF5b3V0QW5jaG9yYWJsZSBBdXRvSGlkZU1pbldpZHRoPSIxMDAiIEF1dG9IaWRlTWluSGVpZ2h0PSIxMDAiIFRpdGxlPSJMaXZlIFJlc3VsdHMgMyIgSXNTZWxlY3RlZD0iVHJ1ZSIgQ29udGVudElkPSJLZXlzaWdodC5PcGVuVGFwLkxpdmVSZXN1bHRzUGFuZWwuTGl2ZVJlc3VsdHMzIiBGbG9hdGluZ0xlZnQ9IjExNTAiIEZsb2F0aW5nVG9wPSI3MTguNjY2NjY2NjY2NjY2NiIgRmxvYXRpbmdXaWR0aD0iNTAwIiBGbG9hdGluZ0hlaWdodD0iNTAwIiBMYXN0QWN0aXZhdGlvblRpbWVTdGFtcD0iMTEvMTEvMjAyNSAxMDo1NDoyMiIgLz4NCiAgICAgICAgPC9MYXlvdXRBbmNob3JhYmxlUGFuZT4NCiAgICAgIDwvTGF5b3V0QW5jaG9yYWJsZVBhbmVHcm91cD4NCiAgICA8L0xheW91dFBhbmVsPg0KICAgIDxMYXlvdXRBbmNob3JhYmxlUGFuZUdyb3VwIE9yaWVudGF0aW9uPSJIb3Jpem9udGFsIiBEb2NrV2lkdGg9IjAuNDM0NTk5MTU2MTE4MTQzNSoiIEZsb2F0aW5nV2lkdGg9IjQwOCIgRmxvYXRpbmdIZWlnaHQ9IjcyOC42NjY2NjY2NjY2NjY2IiBGbG9hdGluZ0xlZnQ9IjE1MjYuNjY2NjY2NjY2NjY2NSIgRmxvYXRpbmdUb3A9IjU5My4zMzMzMzMzMzMzMzMzIj4NCiAgICAgIDxMYXlvdXRBbmNob3JhYmxlUGFuZSBEb2NrV2lkdGg9IjIuNyoiIERvY2tNaW5XaWR0aD0iMTAwIiBEb2NrTWluSGVpZ2h0PSIxMDAiIEZsb2F0aW5nV2lkdGg9IjQwOCIgRmxvYXRpbmdIZWlnaHQ9IjcyOC42NjY2NjY2NjY2NjY2IiBGbG9hdGluZ0xlZnQ9IjE1MjYuNjY2NjY2NjY2NjY2NSIgRmxvYXRpbmdUb3A9IjU5My4zMzMzMzMzMzMzMzMzIj4NCiAgICAgICAgPExheW91dEFuY2hvcmFibGUgQXV0b0hpZGVNaW5XaWR0aD0iMTAwIiBBdXRvSGlkZU1pbkhlaWdodD0iMTAwIiBUaXRsZT0iQmF0dGVyeSBEZW1vIiBJc1NlbGVjdGVkPSJUcnVlIiBDb250ZW50SWQ9Ik9wZW5UYXAuUGx1Z2lucy5EZW1vLkJhdHRlcnkuVUkuQmF0dGVyeURlbW9QYW5lbCIgVG9vbFRpcD0iVGhpcyBpcyBhIGRlbW9uc3RyYXRpb24gcGFuZWwgZm9yIHRoZSBiYXR0ZXJ5IHRlc3QuIiBGbG9hdGluZ0xlZnQ9IjE1MjYuNjY2NjY2NjY2NjY2NSIgRmxvYXRpbmdUb3A9IjU5My4zMzMzMzMzMzMzMzMzIiBGbG9hdGluZ1dpZHRoPSI0MDgiIEZsb2F0aW5nSGVpZ2h0PSI3MjguNjY2NjY2NjY2NjY2NiIgTGFzdEFjdGl2YXRpb25UaW1lU3RhbXA9IjExLzExLzIwMjUgMTA6NTM6MDQiIFByZXZpb3VzQ29udGFpbmVySWQ9IjM1NmI3NzI5LWRhOGItNDQ5MC04MmY5LTNhNTQwNWRiYjNiMiIgUHJldmlvdXNDb250YWluZXJJbmRleD0iMCIgLz4NCiAgICAgIDwvTGF5b3V0QW5jaG9yYWJsZVBhbmU+DQogICAgPC9MYXlvdXRBbmNob3JhYmxlUGFuZUdyb3VwPg0KICA8L1Jvb3RQYW5lbD4NCiAgPFRvcFNpZGUgLz4NCiAgPFJpZ2h0U2lkZSAvPg0KICA8TGVmdFNpZGUgLz4NCiAgPEJvdHRvbVNpZGUgLz4NCiAgPEZsb2F0aW5nV2luZG93cyAvPg0KICA8SGlkZGVuIC8+DQo8L0xheW91dFJvb3Q+ + + + + + + Keysight.OpenTap.LiveResultsPanel.LiveResultPanelSettings + + + Charts + + + false + false + false + false + + 1000 + true + + + + + + + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYScatter + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + + + + + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYScatter + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + None + 0 + + + + None + 0 + + + + None + 0 + + + + None + 0 + + + + + + true + false + false + false + Charge + 1000 + true + + + + + + + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYScatter + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + + + Charge + + Sample Number + Voltage + + IA== + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYLine + + Split + 0 + Test Step \ Temperature + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + + + Sample Number + Voltage + + IA== + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYLine + + Split + 0 + Test Step \ Temperature + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + Split + 0 + Test Step \ Temperature + + + None + 0 + + + + None + 0 + + + + None + 0 + + + + + + true + false + false + false + Charge + 1000 + false + + + Discharge + + [Index] + Current + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYScatter + + Split + 0 + Test Step \ Temperature + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + + + Charge + + Sample Number + Current + + + 10 + false + + Test Plan \ Name + Test Plan \ Station + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYLine + + Split + 0 + Test Step \ Temperature + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + + + Sample Number + Current + + + 10 + false + + Test Plan \ Name + Test Plan \ Station + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYLine + + Split + 0 + Test Step \ Temperature + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + Split + 0 + Test Step \ Temperature + + + None + 0 + + + + None + 0 + + + + None + 0 + + + + + + true + false + false + false + Discharge + 1000 + false + + + Discharge + + Sample Number + Voltage + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYLine + + Split + 0 + Test Step \ Temperature + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + + + + Sample Number + Voltage + + + 10 + false + + false + false + + XYScatter + XYLine + Histogram + DataTable + + XYLine + + Split + 0 + Test Step \ Temperature + + + + + None + 0 + + + + + + None + 0 + + + + + + None + 0 + + + + + Split + 0 + Test Step \ Temperature + + + None + 0 + + + + None + 0 + + + + None + 0 + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenTap.Plugins.Demo.Battery.UI/Resources/batterydemo.png b/OpenTap.Plugins.Demo.Battery.UI/Resources/batterydemo.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b23c07f0b7cd2459c36ce3bdc02584bb9680f7 GIT binary patch literal 21432 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 ASO5S3 literal 0 HcmV?d00001 diff --git a/ResultsAndTiming/DemoBaseStep.cs b/ResultsAndTiming/DemoBaseStep.cs index 6d1c89a..c46c6da 100644 --- a/ResultsAndTiming/DemoBaseStep.cs +++ b/ResultsAndTiming/DemoBaseStep.cs @@ -3,7 +3,6 @@ // the sample application files (and/or any modified version) in any way // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. -using OpenTap; namespace OpenTap.Plugins.Demo.ResultsAndTiming { diff --git a/ResultsAndTiming/LimitCheckAndNoiseBaseStep.cs b/ResultsAndTiming/LimitCheckAndNoiseBaseStep.cs index 7fb2c7d..b1f3ab9 100644 --- a/ResultsAndTiming/LimitCheckAndNoiseBaseStep.cs +++ b/ResultsAndTiming/LimitCheckAndNoiseBaseStep.cs @@ -3,7 +3,6 @@ // the sample application files (and/or any modified version) in any way // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. -using OpenTap; namespace OpenTap.Plugins.Demo.ResultsAndTiming { diff --git a/ResultsAndTiming/OpenTap.Plugins.Demo.ResultsAndTiming.csproj b/ResultsAndTiming/OpenTap.Plugins.Demo.ResultsAndTiming.csproj index 7e40591..3d967ba 100644 --- a/ResultsAndTiming/OpenTap.Plugins.Demo.ResultsAndTiming.csproj +++ b/ResultsAndTiming/OpenTap.Plugins.Demo.ResultsAndTiming.csproj @@ -16,7 +16,7 @@ - true + false diff --git a/ResultsAndTiming/Properties/AssemblyInfo.cs b/ResultsAndTiming/Properties/AssemblyInfo.cs index a630e37..1b50976 100644 --- a/ResultsAndTiming/Properties/AssemblyInfo.cs +++ b/ResultsAndTiming/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/ResultsAndTiming/RampResultsStep.cs b/ResultsAndTiming/RampResultsStep.cs index 5ffb8a1..9b504cb 100644 --- a/ResultsAndTiming/RampResultsStep.cs +++ b/ResultsAndTiming/RampResultsStep.cs @@ -4,7 +4,6 @@ // you find useful, provided that you agree that Keysight Technologies has no // warranty, obligations or liability for any sample application files. using System.Collections.Generic; -using OpenTap; namespace OpenTap.Plugins.Demo.ResultsAndTiming { diff --git a/ResultsAndTiming/SineResultsStep.cs b/ResultsAndTiming/SineResultsStep.cs index 6ef133b..31140ca 100644 --- a/ResultsAndTiming/SineResultsStep.cs +++ b/ResultsAndTiming/SineResultsStep.cs @@ -5,7 +5,6 @@ // warranty, obligations or liability for any sample application files. using System; using System.Collections.Generic; -using OpenTap; namespace OpenTap.Plugins.Demo.ResultsAndTiming { diff --git a/ResultsAndTiming/Tests/DemonstrationAllSteps.TapPlan b/ResultsAndTiming/Tests/DemonstrationAllSteps.TapPlan index 9587c5a..c8ddf3e 100644 --- a/ResultsAndTiming/Tests/DemonstrationAllSteps.TapPlan +++ b/ResultsAndTiming/Tests/DemonstrationAllSteps.TapPlan @@ -3,23 +3,17 @@ - 10 True 0.2 Charge PSU - 0.1 - 4.2 - 5 True 0.2 Discharge PSU - 0.8 - 2.2 diff --git a/ResultsAndTiming/Tests/Test Bench Profile/DUTs.xml b/ResultsAndTiming/Tests/Test Bench Profile/DUTs.xml index 15f742d..c184460 100644 --- a/ResultsAndTiming/Tests/Test Bench Profile/DUTs.xml +++ b/ResultsAndTiming/Tests/Test Bench Profile/DUTs.xml @@ -8,6 +8,15 @@ TimeDut 0.1 + + 0.3 + 3 + 4.2 + 0.01 + + + Bat + diff --git a/ResultsAndTiming/TimeActivityStep.cs b/ResultsAndTiming/TimeActivityStep.cs index e144d45..947b24e 100644 --- a/ResultsAndTiming/TimeActivityStep.cs +++ b/ResultsAndTiming/TimeActivityStep.cs @@ -5,7 +5,6 @@ // warranty, obligations or liability for any sample application files. using System.Collections.Generic; using System.Threading; -using OpenTap; namespace OpenTap.Plugins.Demo.ResultsAndTiming { diff --git a/ResultsAndTiming/TimeDut.cs b/ResultsAndTiming/TimeDut.cs index 6b23fe0..1365274 100644 --- a/ResultsAndTiming/TimeDut.cs +++ b/ResultsAndTiming/TimeDut.cs @@ -5,7 +5,6 @@ // warranty, obligations or liability for any sample application files. using System.Diagnostics; using System.Threading; -using OpenTap; namespace OpenTap.Plugins.Demo.ResultsAndTiming { diff --git a/ResultsAndTiming/TimeInst.cs b/ResultsAndTiming/TimeInst.cs index 600f409..ec399d0 100644 --- a/ResultsAndTiming/TimeInst.cs +++ b/ResultsAndTiming/TimeInst.cs @@ -5,7 +5,6 @@ // warranty, obligations or liability for any sample application files. using System.Diagnostics; using System.Threading; -using OpenTap; namespace OpenTap.Plugins.Demo.ResultsAndTiming { diff --git a/ResultsAndTiming/TimeResourceActivityStep.cs b/ResultsAndTiming/TimeResourceActivityStep.cs index 859e79a..8f66e78 100644 --- a/ResultsAndTiming/TimeResourceActivityStep.cs +++ b/ResultsAndTiming/TimeResourceActivityStep.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Threading; -using OpenTap; using OpenTap.Plugins.Demo.ResultsAndTiming; diff --git a/ResultsAndTiming/package.xml b/package.xml similarity index 95% rename from ResultsAndTiming/package.xml rename to package.xml index aa3f9eb..9922290 100644 --- a/ResultsAndTiming/package.xml +++ b/package.xml @@ -7,9 +7,6 @@ Emulated PSU - - - Keysight Technologies, Inc. https://github.com/opentap/Demonstration @@ -21,6 +18,9 @@ + + +