public override void ToDo(object Arg) { var settings = (IVDefRSettingsControlModel)Arg; var setVolt = settings.ScanningVoltage; var setCond = settings.SetConductance; var condDev = settings.Deviation; var stabilizationTime = settings.StabilizationTime; var minSpeed = settings.MinSpeed; var maxSpeed = settings.MaxSpeed; var minValue = settings.IVMinValue; var maxValue = settings.IVMaxValue; var epsilon = settings.Epsilon; var nPoints = settings.NPoints; var nCycles = settings.NCycles; var sourceMode = settings.SourceMode; var compliance = settings.Compliance; var minPos = settings.MotorMinPos; var maxPos = settings.MotorMaxPos; var fileName = string.Join("\\", settings.FilePath, settings.SaveFileName); var inRangeCounter = 0; var outsiderCounter = 0; onStatusChanged(new StatusEventArgs("Starting the measurement.")); onProgressChanged(new ProgressEventArgs(0.0)); motor.Enabled = true; motor.Velosity = maxSpeed; smu.SourceMode = sourceMode; smu.Compliance = compliance; smu.Voltage = setVolt; smu.SwitchON(); onStatusChanged(new StatusEventArgs("Reaching the specified resistance / conductance value.")); // Was changed here var interval = setCond * (1.0 - 1.0 / Math.Sqrt(2.0)); while (true) { if (!IsRunning) { break; } var measuredResistance = smu.MeasureResistance(); var scaledConductance = (1.0 / measuredResistance) / ConductanceQuantum; var statusStr = string.Format( "Motor position is: {0}; the derired resistence is {1}; the current resistance is {2}", motor.Position.ToString("G4", NumberFormatInfo.InvariantInfo), settings.SetResistance.ToString("G4", NumberFormatInfo.InvariantInfo), measuredResistance.ToString("G4", NumberFormatInfo.InvariantInfo) ); onStatusChanged(new StatusEventArgs(statusStr)); var speed = minSpeed; try { //var k = (scaledConductance >= 1.0) ? Math.Log10(scaledConductance) : scaledConductance; //var x = Math.Abs(scaledConductance - setCond); //var factor = (1.0 - Math.Tanh((-1.0 * x + Math.PI / k) * k)) / 2.0; var factor = (1.0 - Math.Tanh(-1.0 * Math.Abs(scaledConductance - setCond) / interval * Math.PI + Math.PI)) / 2.0; speed = minSpeed + (maxSpeed - minSpeed) * factor; } catch { speed = minSpeed; } motor.Velosity = speed; if ((scaledConductance >= setCond - (setCond * condDev / 100.0)) && (scaledConductance <= setCond + (setCond * condDev / 100.0))) { if (motor.IsEnabled == true) { motor.Enabled = false; } if (!stabilityStopwatch.IsRunning) { inRangeCounter = 0; outsiderCounter = 0; stabilityStopwatch.Start(); onStatusChanged(new StatusEventArgs("Stabilizing the specified resistance / conductance value.")); } ++inRangeCounter; } else { if (motor.IsEnabled == false) { motor.Enabled = true; } if (scaledConductance > setCond) { motor.PositionAsync = maxPos; } else { motor.PositionAsync = minPos; } if (stabilityStopwatch.IsRunning == true) { ++outsiderCounter; } } if (stabilityStopwatch.IsRunning) { if (stabilityStopwatch.ElapsedMilliseconds > 0) { onProgressChanged(new ProgressEventArgs((double)stabilityStopwatch.ElapsedMilliseconds / 1000.0 / stabilizationTime * 100)); } if ((double)stabilityStopwatch.ElapsedMilliseconds / 1000.0 >= stabilizationTime) { var divider = outsiderCounter > 0 ? (double)outsiderCounter : 1.0; if (Math.Log10((double)inRangeCounter / divider) >= 1.0) { stabilityStopwatch.Stop(); break; } else { inRangeCounter = 0; outsiderCounter = 0; stabilityStopwatch.Restart(); } } } } onStatusChanged(new StatusEventArgs("Measuring I-V curve(s) in a defined range.")); var currCycle = 1; while (currCycle <= nCycles) { switch (sourceMode) { case SMUSourceMode.Voltage: { var ivDataFirstBranch = smu.LinearVoltageSweep(-1.0 * epsilon, maxValue, nPoints); var ivDataSecondBranch = smu.LinearVoltageSweep(epsilon, minValue, nPoints); IV_Data[] res; selectIV_Data(ref ivDataFirstBranch, ref ivDataSecondBranch, out res); IVData.AddLast(res); onDataArrived(new ExpDataArrivedEventArgs(getIVString(ref res))); } break; case SMUSourceMode.Current: { var ivDataFirstBranch = smu.LinearCurrentSweep(-1.0 * epsilon, maxValue, nPoints); var ivDataSecondBranch = smu.LinearCurrentSweep(epsilon, minValue, nPoints); IV_Data[] res; selectIV_Data(ref ivDataFirstBranch, ref ivDataSecondBranch, out res); IVData.AddLast(res); onDataArrived(new ExpDataArrivedEventArgs(getIVString(ref res))); } break; case SMUSourceMode.ModeNotSet: throw new ArgumentException(); } ++currCycle; } smu.SwitchOFF(); onStatusChanged(new StatusEventArgs("Saving data to file.")); SaveToFile(fileName); onStatusChanged(new StatusEventArgs("Measurement is done!")); if (motor != null) { motor.Dispose(); } if (smu != null) { smu.Dispose(); } this.Stop(); }
public override void ToDo(object Arg) { onExpStarted(new StartedEventArgs()); onStatusChanged(new StatusEventArgs("Experiment started.")); onProgressChanged(new ProgressEventArgs(0.0)); iv_FET_CurveDataSet = new LinkedList <IV_FET_DataContainer>(); var settings = (FET_IVModel)Arg; #region Gate SMU settings smuVg.SourceMode = SMUSourceMode.Voltage; smuVg.Compliance = settings.Gate_Complaince.RealValue; smuVg.Averaging = settings.Ke_IV_FET_Averaging; smuVg.NPLC = settings.Ke_IV_FET_NPLC; smuVg.Voltage = settings.VgStart.RealValue; smuVg.SwitchON(); #endregion #region Drain-Source SMU settings smuVds.SourceMode = settings.SMU_SourceMode; smuVds.Compliance = settings.DS_Complaince.RealValue; smuVds.Averaging = settings.Ke_IV_FET_Averaging; smuVds.NPLC = settings.Ke_IV_FET_NPLC; switch (settings.SMU_SourceMode) { case SMUSourceMode.Voltage: smuVds.Voltage = settings.VdsStart.RealValue; break; case SMUSourceMode.Current: smuVds.Current = settings.VdsStart.RealValue; break; case SMUSourceMode.ModeNotSet: break; default: break; } smuVds.SwitchON(); #endregion #region General settings var currentVg = settings.VgStart.RealValue; var current_DS_value = settings.VdsStart.RealValue; var dVg = (settings.VgStop.RealValue - settings.VgStart.RealValue) / (settings.N_VgStep - 1); var d_DS_value = (settings.VdsStop.RealValue - settings.VdsStart.RealValue) / (settings.N_VdsSweep - 1); #endregion if (settings.MeasureLeakage == true) { for (int i = 0; i < settings.N_VgStep; i++) { onDataArrived(new ExpDataArrivedEventArgs(string.Format("Vg = {0}", currentVg.ToString(NumberFormatInfo.InvariantInfo)))); singleIV_FET_CurveData = new LinkedList <IV_FET_Data>(); if (!IsRunning) { break; } for (int j = 0; j <= settings.N_VdsSweep; j++) { if (!IsRunning) { break; } switch (settings.SMU_SourceMode) { case SMUSourceMode.Voltage: { smuVds.Voltage = current_DS_value; var drainVoltage = current_DS_value; var drainCurrent = smuVds.Current; var leakageCurrent = smuVg.Current; onDataArrived(new ExpDataArrivedEventArgs(string.Format( "{0}\t{1}\t{2}\r\n", drainVoltage.ToString(NumberFormatInfo.InvariantInfo), drainCurrent.ToString(NumberFormatInfo.InvariantInfo), leakageCurrent.ToString(NumberFormatInfo.InvariantInfo)))); singleIV_FET_CurveData.AddLast(new IV_FET_Data(drainVoltage, drainCurrent, leakageCurrent)); onStatusChanged(new StatusEventArgs(string.Format("Measuring I-V Curve # {0} out of {1}. Leakage current I = {2}", (i + 1).ToString(NumberFormatInfo.InvariantInfo), settings.N_VgStep, leakageCurrent.ToString("G4", NumberFormatInfo.InvariantInfo)))); } break; case SMUSourceMode.Current: { smuVds.Current = current_DS_value; var drainVoltage = smuVds.Voltage; var drainCurrent = current_DS_value; var leakageCurrent = smuVg.Current; onDataArrived(new ExpDataArrivedEventArgs(string.Format( "{0}\t{1}\t{2}\r\n", drainVoltage.ToString(NumberFormatInfo.InvariantInfo), drainCurrent.ToString(NumberFormatInfo.InvariantInfo), leakageCurrent.ToString(NumberFormatInfo.InvariantInfo)))); singleIV_FET_CurveData.AddLast(new IV_FET_Data(drainVoltage, drainCurrent, leakageCurrent)); onStatusChanged(new StatusEventArgs(string.Format("Measuring I-V Curve # {0} out of {1}. Leakage current I = {2}", (i + 1).ToString(NumberFormatInfo.InvariantInfo), settings.N_VgStep, leakageCurrent.ToString("E4", NumberFormatInfo.InvariantInfo)))); } break; case SMUSourceMode.ModeNotSet: throw new ArgumentException(); default: throw new ArgumentException(); } var gateProgress = 1.0 - (settings.N_VgStep - (double)i) / settings.N_VgStep; var dsProgress = (1.0 - (settings.N_VdsSweep - (double)j) / settings.N_VdsSweep) / settings.N_VgStep; var totalProgress = (gateProgress + dsProgress) * 100.0; onProgressChanged(new ProgressEventArgs(totalProgress)); current_DS_value += d_DS_value; } var ivData = new IV_FET_DataContainer(currentVg, singleIV_FET_CurveData); iv_FET_CurveDataSet.AddLast(ivData); current_DS_value = settings.VdsStart.RealValue; switch (settings.SMU_SourceMode) { case SMUSourceMode.Voltage: smuVds.Voltage = current_DS_value; break; case SMUSourceMode.Current: smuVds.Current = current_DS_value; break; case SMUSourceMode.ModeNotSet: throw new ArgumentException(); default: throw new ArgumentException(); } if (i != settings.N_VgStep - 1) { currentVg += dVg; smuVg.Voltage = currentVg; } Thread.Sleep((int)(settings.IV_FET_GateDelay.RealValue * 1000)); } } else { for (int i = 0; i < settings.N_VgStep; i++) { onStatusChanged(new StatusEventArgs(string.Format("Measuring I-V curve # {0} out of {1}", (i + 1).ToString(NumberFormatInfo.InvariantInfo), settings.N_VgStep))); onDataArrived(new ExpDataArrivedEventArgs(string.Format("Vg = {0}", currentVg.ToString(NumberFormatInfo.InvariantInfo)))); singleIV_FET_CurveData = new LinkedList <IV_FET_Data>(); if (!IsRunning) { break; } switch (settings.SMU_SourceMode) { case SMUSourceMode.Voltage: { var ivData = smuVds.LinearVoltageSweep(settings.VdsStart.RealValue, settings.VdsStop.RealValue, settings.N_VdsSweep); onDataArrived(new ExpDataArrivedEventArgs(ivData.ToStringExtension())); var query = from ivDataPoint in ivData select new IV_FET_Data(ivDataPoint.Voltage, ivDataPoint.Current, double.NaN); foreach (var item in query) { singleIV_FET_CurveData.AddLast(item); } } break; case SMUSourceMode.Current: { var ivData = smuVds.LinearCurrentSweep(settings.VdsStart.RealValue, settings.VdsStop.RealValue, settings.N_VdsSweep); onDataArrived(new ExpDataArrivedEventArgs(ivData.ToStringExtension())); var query = from ivDataPoint in ivData select new IV_FET_Data(ivDataPoint.Voltage, ivDataPoint.Current, double.NaN); foreach (var item in query) { singleIV_FET_CurveData.AddLast(item); } } break; case SMUSourceMode.ModeNotSet: throw new ArgumentException(); default: throw new ArgumentException(); } var ivSingleCurveWithDescription = new IV_FET_DataContainer(currentVg, singleIV_FET_CurveData); iv_FET_CurveDataSet.AddLast(ivSingleCurveWithDescription); current_DS_value = settings.VdsStart.RealValue; if (i != settings.N_VgStep - 1) { currentVg += dVg; smuVg.Voltage = currentVg; } Thread.Sleep((int)(settings.IV_FET_GateDelay.RealValue * 1000)); var gateProgress = 1.0 - (settings.N_VgStep - (double)(i + 1)) / settings.N_VgStep; onProgressChanged(new ProgressEventArgs(gateProgress * 100)); } } smuVg.SwitchOFF(); smuVds.SwitchOFF(); smuVg.Voltage = 0.0; switch (settings.SMU_SourceMode) { case SMUSourceMode.Voltage: smuVds.Voltage = 0.0; break; case SMUSourceMode.Current: smuVds.Current = 0.0; break; case SMUSourceMode.ModeNotSet: throw new ArgumentException(); default: throw new ArgumentException(); } SaveToFile(string.Format("{0}\\{1}", settings.IV_FET_DataFilePath, settings.IV_FileName)); onExpFinished(new FinishedEventArgs(0)); onStatusChanged(new StatusEventArgs("Measurement completed!")); }