Ejemplo n.º 1
0
        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!"));
        }