예제 #1
0
 public int CompareTo(object obj)
 {
     try {
         PIDSet p = ( PIDSet )obj;
         return(Temp.CompareTo(p.Temp));
     }
     catch {
         return(-1);
     }
 }
예제 #2
0
 public bool EqualTo(PIDSet p)
 {
     if (p != null)
     {
         return((this.P == p.P) && (this.I == p.I) && (this.D == p.D));
     }
     else
     {
         return(false);
     }
 }
예제 #3
0
        public virtual PIDSet getPidParams( )
        {
            PIDSet pid = new PIDSet( );

            gpib_.Write(":SOUR:TEMP:LCON:GAIN?");
            pid.P = readFloat( );
            gpib_.Write(":SOUR:TEMP:LCON:INT?");
            pid.I = readFloat( );
            gpib_.Write(":SOUR:TEMP:LCON:DER?");
            pid.D = readFloat( );

            return(pid);
        }
예제 #4
0
 public void setCurrSourcePidParams(PIDSet pid)
 {
     gpib_.Write(SET_SOURCE_CURRENT);
     setCurrentSourcePidParams(pid.P, pid.I, pid.D);
     gpib_.Write(SET_SOURCE_TEMPERATURE); // be pragmatic and set back to temperature ctrl
 }
예제 #5
0
 public virtual void setTempSourcePidParams(PIDSet pid)
 {
     setTemperatureSourcePidParams(pid.P, pid.I, pid.D);
 }
예제 #6
0
 public virtual void setPidParams(PIDSet pid)
 {
     setTempSourcePidParams(pid);
 }
예제 #7
0
        public double StabilizeTemperatureSelfTuningFalse( ) // was StabilizeTemperature
        {
            if (doOverrideSettings)
            {
                settings_ = overridingSettings_;
            }

            gpib_.Write(SET_SOURCE_TEMPERATURE);
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
            var target = this.getTargetTemperature( );

            LogMessage("Starting to stabilize");
            bool     hitTimeout = false;
            TimeSpan timeout    = new TimeSpan(0, 0, 0, 0, ( int )(settings_.StabilizationTimeout * 1000));
            DateTime start      = DateTime.UtcNow;

            Queue <double> tempQ  = new Queue <double>( );
            double         avg    = 0;
            double         stddev = 1000; // a large number
            double         temp;
            double         dif;
            TimeSpan       delay = new TimeSpan(0, 0, 0, 0, ( int )(settings_.StabilizationDelay * 1000));

            ;

            Stopwatch t = new Stopwatch( );

            t.Start( );
            PIDSet PID = new PIDSet( ), stablePIDset_;

            double sum           = 0;
            double sum2          = 0;
            bool   exitForbidden = true;
            int    iteration     = 0;

            do
            {
                try {
                    iteration++;
                    hitTimeout = (DateTime.UtcNow - start) > timeout;
                    Thread.Sleep(( int )delay.TotalMilliseconds);
                    stablePIDset_ = calcStablePidSet(target);

                    temp = measureTemperature( );
                    tempQ.Enqueue(temp);
                    sum  += temp;
                    sum2 += Math.Pow(temp, 2);
                    if (tempQ.Count > settings_.StabilizationSamples)
                    {
                        double tdequed = tempQ.Dequeue( );
                        sum          -= tdequed;
                        sum2         -= Math.Pow(tdequed, 2);
                        exitForbidden = false;
                    }

                    avg = sum / tempQ.Count;

                    stddev = Math.Sqrt(sum2 / ( double )tempQ.Count - Math.Pow(avg, 2));

                    bool stdDevOK = (stddev < settings_.MaxTStdDev);
                    bool offsetOK = (Math.Abs(avg - target) < settings_.MaxTError);

                    if (debugMode_)
                    {
                        LogMessage(("Iteration = " + iteration + " Samples used in calculation = " + settings_.StabilizationSamples));
                        LogMessage(("T = " + temp));
                        LogMessage(("stddev = " + stddev + " Limit = " + settings_.MaxTStdDev + " OK =" + stdDevOK.ToString( )));
                        LogMessage(("Mean offset = " + (avg - target) + " Limit = " + settings_.MaxTError + " OK =" + offsetOK.ToString( )));
                        LogMessage("----");
                    }

                    isStable_ = stdDevOK && offsetOK;

                    if (isStable_)
                    {
                        if (!PID.EqualTo(stablePIDset_))
                        {
                            LogMessage("Switching to stable PID parameters"); // ...if necessary
                            setTempSourcePidParams(stablePIDset_);
                            PID       = stablePIDset_;
                            isStable_ = false; // isStable must be recalculated at least once if PID's were changed..
                        }
                    }
                    else if (!PID.EqualTo(settings_.Fast))
                    {
                        LogMessage("Switching to fast PID parameters");
                        setTempSourcePidParams(settings_.Fast);
                        PID = settings_.Fast;
                    }

                    dif = temp - target;
                    if (writeLogMessages_)
                    {
                        if (t.ElapsedMilliseconds > 10000)
                        {
                            LogMessage("Currently at: " + measureTemperature( ) + ". Dif is: " + dif);
                            t.Reset( );
                            t.Start( );
                        }
                    }
                }
                catch (Exception ex) {
                    LogMessage("Got an exception in stabilization loop: " + ex.Message + "(this has no effect on temperature)");
                    continue;
                }
            } while((!hitTimeout && !isStable_) || exitForbidden || stabilizeForever_);

            DateTime stop = DateTime.UtcNow;

            if (hitTimeout)
            {
                LogMessage("Hit timelimit while stabilizing temperature");
                throw new Exception("Hit timelimit while stabilizing temperature");
            }
            else
            {
                LogMessage("Done stabilizing after " + (stop - start).TotalSeconds.ToString("####.0") + " Seconds.");
                return((stop - start).TotalMinutes);
            }
        }
예제 #8
0
        public double StabilizeTemperatureSelfTuningTrue( ) // Experimental self-tuning of the PID controller.
        {
            gpib_.Write(SET_SOURCE_TEMPERATURE);
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");

            // Get values from settings_
            // Note that StabilizationSamples and StabilizationDelay combines to give a lower bound on time,
            // e.g., StabilizationSamples = 10 and StabilizationDelay = 0.1 yields 1.0 seconds.

            PIDSet PID = settings_.StabilizationPID;

            LogMessage(string.Format("StabilizationPID = {0}, {1}, {2} before stabilization.", PID.P, PID.I, PID.D));

            int samples = settings_.StabilizationSamples;

            LogMessage(string.Format("StabilizationSamples = {0} samples.", samples));

            TimeSpan delay = new TimeSpan(0, 0, 0, 0, ( int )(settings_.StabilizationDelay * 1000));

            LogMessage(string.Format("StabilizationDelay = {0} seconds.", delay.TotalSeconds));

            TimeSpan timeout = new TimeSpan(0, 0, 0, 0, ( int )(settings_.StabilizationTimeout * 1000));

            LogMessage(string.Format("StabilizationTimeout = {0} seconds.", timeout.TotalSeconds));

            double stdDev = settings_.StabilizationStdDev;

            LogMessage(string.Format("StabilizationStdDev = {0} degree Celcius.", stdDev));

            // Chi-square value for samples degrees of freedom, was "double chi2 = settings_.StabilizationChi2;"
            double alpha = settings_.StabilizationAlpha;
            double chi2  = Syntune.UberMath.FSharp.Statistics.Newton.inverseChi2(0.01, samples, 1.0 - alpha);
            // string.Format( "StabilizationChi2 = {0}.", chi2 ).LogInfo( );

            double gamma = settings_.StabilizationGamma; // Hand-tuned constant for PID tuning
            // string.Format( "StabilizationGamma = {0}.", gamma ).LogInfo( );

            // Upper bound for convergence: sumOfSquares / acceptableVariance < chi2
            // The Chi-squared value is choosen based on sample size and the confidence desired.
            // Please consult a textbook in statistics (or Beta) for a table over the Chi-squared distribution.
            // This criteria only an approximate solution but it seems to work well in practice.
            double upperBound = chi2 * Math.Pow(stdDev, 2);

            // Measuremet variables

            var            targetTemperature = this.getTargetTemperature( );
            double         difference        = 0;
            double         square            = 0;
            double         sumOfSquares      = 0;
            Queue <double> squares           = new Queue <double>( );

            // Auxilliary variables for PID tuning
            // The tuning algorithm is based on "Self-Tuning of PID Controllers by Adaptive Interaction"
            // by Feng Lin et al.
            double auxP = 0, auxI = 0, auxD = 0, weight;

            // The number of iterations done; just interesting to know
            int numberOfIterations = 0;

            LogMessage("Stabilizing ...");

            var start = DateTime.UtcNow;

            // Continue to measure until timeout or a sufficient numer of samples and convergence

            do
            {
                Thread.Sleep(( int )delay.TotalMilliseconds);
                numberOfIterations++;

                difference    = targetTemperature - measureTemperature( );
                square        = Math.Pow(difference, 2);
                sumOfSquares += square;
                squares.Enqueue(square);

                // string.Format( "{0}", difference ).LogInfo( ); // Just verifying convergence

                auxD   = (difference - auxD) / delay.TotalSeconds;
                auxI   = difference * delay.TotalSeconds + auxI;
                auxP   = difference;
                weight = gamma * difference * delay.TotalSeconds;

                // The constant D have been hardwired to 0, which seems to work well in practise.
                // Dynamic D behave unpredictable for many values of gamma.
                PID = new PIDSet {
                    P = PID.P - weight * auxP,
                    I = PID.I - weight * auxI,
                    D = 0 // PID.D - weight * auxD
                };

                setTempSourcePidParams(PID);

                if (squares.Count > samples)
                {
                    sumOfSquares -= squares.Dequeue( );
                }
            } while((DateTime.UtcNow - start) < timeout &&
                    (squares.Count < samples || upperBound < sumOfSquares));

            var stop = DateTime.UtcNow;

            settings_.StabilizationPID = PID;
            LogMessage(string.Format("StabilizationPID = {0}, {1}, {2} after {3} iterations.", PID.P, PID.I, PID.D, numberOfIterations));

            if ((stop - start) < timeout)
            {
                LogMessage("The temperature stabilized after " + (stop - start).TotalSeconds.ToString("####.0") + " seconds.");
                return((stop - start).TotalSeconds);
            }
            else
            {
                LogMessage("Hit timelimit while stabilizing temperature");
                throw new Exception("Hit timelimit while stabilizing temperature");
            }
        }
예제 #9
0
        public PIDSet calcStablePidSet(double temp)
        {
            PIDSet low = new PIDSet( ), high = new PIDSet( ), p = new PIDSet( );

            settings_.StablePids.Sort( );

            low = settings_.StablePids[0];
            for (int i = 0; i < settings_.StablePids.Count; i++)
            {
                if (temp == settings_.StablePids[i].Temp)
                {
                    return(settings_.StablePids[i]);
                }

                if (temp > settings_.StablePids[i].Temp)
                {
                    low = settings_.StablePids[i];
                }
                else
                {
                    break;
                }
            }

            high = settings_.StablePids[settings_.StablePids.Count - 1];
            for (int i = settings_.StablePids.Count - 1; i > -1; i--)
            {
                if (temp == settings_.StablePids[i].Temp)
                {
                    return(settings_.StablePids[i]);
                }

                if (temp < settings_.StablePids[i].Temp)
                {
                    high = settings_.StablePids[i];
                }
                else
                {
                    break;
                }
            }

            if (low == settings_.StablePids[settings_.StablePids.Count - 1])
            {
                return(settings_.StablePids[settings_.StablePids.Count - 1]);
            }

            if (high == settings_.StablePids[0])
            {
                return(settings_.StablePids[0]);
            }


            p.Temp   = temp;
            p.P      = low.P + (temp - low.Temp) * ((high.P - low.P) / (high.Temp - low.Temp));
            p.I      = low.I + (temp - low.Temp) * ((high.I - low.I) / (high.Temp - low.Temp));
            p.D      = low.D + (temp - low.Temp) * ((high.D - low.D) / (high.Temp - low.Temp));
            p.ILimit = low.ILimit + (temp - low.Temp) * ((high.ILimit - low.ILimit) / (high.Temp - low.Temp));

            return(p);
        }