Software pentru analiza regulatoarelor PID

Limbaj programare: C#

Sumar

Regulatorul PID este un algoritm de control utilizat in contolul proceslor industriale. Implementarea acestui algoritm in diverse aplicatii implica o analiza a procesului cat si o implementare software eficienta. Necesitatea implementarii acestui algoritm a aparut in urma analizei sistemului pentru deshidratarea fructelor. Astfel pentru controlul riguros al temperaturii si umiditatii aerului utilizat pentru procesul de deshidratare s-a dorit implementarea unui algoritm flexibil si eficient. Solutia software prezentata a fost dezvoltata cu scopul de a analiza comportamentul unui regulator PID in functie de modificarea valorii programate cat si a coeficientilor Kp, Ki si Kd.

Utilitate

Programul se utilizeaza pentru analiza proceslor si pentru stabilirea parametrilor regulatoarelor PID utilizate in industrie. Software-ul fi utilizat pentru stabilirea parametrilor Kp, Ki, K samd. pentru procese de: incalzire, racire, umidificare, dezumidificare, ventilare, miscare etc.

Mod de livrare

Produsul software se poate livra in mai multe formate: program executabil (*.exe), librarie (*.dll), clasa pentru C++, C#, functii pentru C.

 

Interfata grafica si modul de utilizare

Pentru usurarea vizualizarii parametrilor, acestia sunt afisati atat grafic cat si text. Procesul poate fi oprit de asemenea pentru analiza in detaliu a elementelor. Pe ecran sunt afisate valorile pentru eroare, valoarea proportionala, valoarea derivativa si valoarea de iesire. Procesul este definit de o functie de transfer definita in program care ia in considerare valoarea de iesire cat si valoarea actuala. Pentru modificarea rapida a valorii programate, s-au introdus butoanele pentru Ramp UP, Ramp Down si Toggle, cu valorile aferente afisate deasupra acestora. Intervalul la care se face apelarea regulatorului PID, intervaul de calcul a valorii de proces si raportul intre valoarea de proces si timpul scurs intre calcule pot fi configurate de catre utilizator.

Implementarea software

Pentru mentinerea independentei regulatorului PID fata de procesul in care acesta este utilizat, am creat clasa cPID care contine o structura care defineste regulatorul si functionarea acestuia.

/* define the PID regulator variables */
public struct xPID_Regulator
{
    public double dSetPoint; /* the target value */
    public double dProcessValue; /* the actual process value */
    public double dDt; /* the regulator call interval */
    public double dOutput; /* the output value */
    public double dPrevError; /* the error from the previous call */

    public double dKp; /* proportional coefficient */
    public double dKi; /* integral coefficient */
    public double dKd; /* derivative coefficient */

    public double dError; /* SP - PV is calculated internaly = proprtional component */
    public double dIntegral; /* the integral component is calculated internaly */
    public double dDerivative; /* the derivative component is calculated internaly */

    public bool bIsStaturated;
    public int iSaturationLockSign; /* when saturated, the regulator will unlock if the error sign will change */
    public double dSaturatedMax; /* the max value of the output, over this the regulator is saturated and no calculations are made */
    public double dSaturatedMin; /* the min value of the output, under this the regulator is saturated and no calculations are made */

    public bool bIsNegative; /* for example, for flaps, if we need larger humidity then we close the flaps, so the action is negative */
}

La initializare, fiecare regulator PID primeste propria structura. De exemplu daca vom avea doua regulatoare, unul pentru reglarea temperaturii si unul pentru reglarea umiditatii, vom declara doua regulatoare PID:

private static cPID.xPID_Regulator pidTemperature;
private static cPID.xPID_Regulator pidHumidity;

 

Functia care stabileste valoarea dOutput de iesirie a regulatorului PID trebuie apelata la intervale dDt egale prin intermediul unui timer. Functia calculeaza valorile dError, dIntegral, dDerivative si valoarea necesara iesirii pentru a duce valoarea de proces dProcessValue catre valoarea programata dSetPoint. Functia blocheaza calculul parametrilor daca regulatorul este saturat, adica daca valoarea de iesire dOutput depaseste limitele setate prin dSaturatedMax si dSaturatedMin. Calculul parametrilor este blocat pentru a evita acumularea de valori prea mari in componenta integrala dIntegral, care ar duce la intarizierea raspunsului regulatorului cand valoarea de proces revine la valori apropiate de valoarea programata.

        public static void vPID_Process(ref xPID_Regulator Regulator)
        {
            /* calculate the difference between the desired value and the actual value */
            Regulator.dError = Regulator.dSetPoint - Regulator.dProcessValue;
            int iSign = Math.Sign(Regulator.dError);

            /* if the regulator is saturated, we unlock if the error sign changes */
            if (iSign != Regulator.iSaturationLockSign)
            {
                Regulator.bIsStaturated = false;
            }

            /* calculate the difference between the desired value and the actual value */
            /* do not delete - part of the algorithm - Regulator.dError = Regulator.dSetPoint - Regulator.dProcessValue; */

            /* test if the regulator is not in satruation */
            if (Regulator.bIsStaturated == false)
            {
                /* track error over time, scaled to the timer interval */
                Regulator.dIntegral = Regulator.dIntegral + (Regulator.dError * Regulator.dDt);
            }

            /* determin the amount of change from the last time checked */
            Regulator.dDerivative = (Regulator.dError - Regulator.dPrevError) / Regulator.dDt;

            /* calculate how much drive the output in order to get to the desired setpoint. */
            Regulator.dOutput = (Regulator.dKp * Regulator.dError) + (Regulator.dKi * Regulator.dIntegral) + (Regulator.dKd * Regulator.dDerivative);

            /* get the last sign of the error to unlock from saturation */
            Regulator.iSaturationLockSign = 0;
            if (Regulator.dError != 0)
            {
                Regulator.iSaturationLockSign = Math.Sign(Regulator.dError);
            }

            /* if the output value goes the other way then we negate the output */
            if (Regulator.bIsNegative == true)
            {
                Regulator.dOutput *= (-1);
            }

            Regulator.bIsStaturated = false;
            /* check max and min values */
            if (Regulator.dOutput > Regulator.dSaturatedMax)
            {
                Regulator.dOutput = Regulator.dSaturatedMax;
                Regulator.bIsStaturated = true;
            }

            if (Regulator.dOutput < Regulator.dSaturatedMin)
            {
                Regulator.dOutput = Regulator.dSaturatedMin;
                Regulator.bIsStaturated = true;
            }

            /* remember the error for the next time around. */
            Regulator.dPrevError = Regulator.dError;
        }