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 0000000..e9b23c0 Binary files /dev/null and b/OpenTap.Plugins.Demo.Battery.UI/Resources/batterydemo.png differ 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 @@ + + +