3 votos

¿Comprender el flujo de un controlador PI?

Yo soy teóricamente Conozco el funcionamiento de un controlador PID, pero nunca he implementado uno. Estoy implementando un método de control para conducir una válvula sobre PWM.

Detalles del caso de uso: Los sistemas tienen dos canales ADC, uno de entrada y otro de retroalimentación. La lectura de los canales ADC es de ejecución libre, con la toma de muestras suficientes.

La aplicación existente: Hay un bucle infinito, que hace dos trabajos solamente: Leer los valores del ADC y generar el PWM. Hay una interrupción del temporizador configurada para invocar a los 20 mseg. Así que "¿Ha transcurrido el tiempo?" en el diagrama de flujo de abajo será evaluado "Sí" después de cada 20 mseg. Abajo está el diagrama de flujo de lo que estoy haciendo ahora.

enter image description here

El siguiente es el programa que estoy investigando:

/*
    Some information on variables that are being used:

    CURR_OUT_CH is Feedback channel
    CMD_INP_CH is the channel where external input is applied.
    So, ADC_Val.fADC_Final_mAVal[CURR_OUT_CH] is where I am receiving the value of feedback
    And, ADC_Val.fADC_Final_mAVal[CMD_INP_CH ] is where I am receiving the value of external input that I am trying to achieve
    MAX_ALLOWABLE_DUTY_CYCLE  is a macro set to ((uint16_t)480) which Maps to 60% - This is a requirement.

        (Op-Amp output is in mV, I convert it into mA based on resistor values)

    (Config[chUser_Config_Mode].uiMaxCMD_I) is 350. (max current allowed through, in mA)
*/

#define RESTRICT(x, low, high)   (x = (x)<(low)?(low):((x)>(high)?(x=high):(x)))

typedef struct {

    float fFeedback;
    float fOutput;
    float Kp;
    float Ki;
    float fIntegralError;
    float fSetpoint;

} PIControl_t;

PIControl_t PI;
uint16_t Load_Dutycount;

void PICompute(PIControl_t *pPI) 
{
    // I know that if PI is already a global, then taking the pointer doesn't make sense here,
    // but, I may have to add another PI for a different sensor here, that is why I have used 
    // it this way!

    // Instantaneous error is always local
    float fError = 0.0;

    // The classic PID error term
    fError = pPI->fSetpoint - pPI->fFeedback;

    // Compute the integral term
    pPI->fIntegralError += (pPI->Ki * fError);

    // Run all the terms together to get the overall output
    pPI->fOutput = (pPI->Kp * fError) + (pPI->fIntegralError);
}

void Update_PWM_Module(void)
{
    // Might want to get rid of this fCount, lets see.
    float fCount = 0.0;

    // Timer hasn't generated an interrupt yet (Integration time hasn't elapsed)
    // ISR sets the bCompute variable - Flags are Not the best way, but does what it should.
    // And, Timer doesn't start counting if bCompute is set
    if(!bCompute)
    {
        // No control action needed, return!
        return;
    }

    // Assign the feedback value read for PI output computation
    PI.fFeedback = ADC_Val.fADC_Final_mAVal[CURR_OUT_CH];

    // Compute the PI Controller output
    PICompute(&PI);

    // Formulate the value to be used to generate PWM
    ADC_Val.fADC_Final_mAVal[CURR_OUT_CH] = ADC_Val.fADC_Final_mAVal[CURR_OUT_CH] + PI.fOutput;

    // Map Output to no. of counts
    fCount = (float) ((ADC_Val.fADC_Final_mAVal[CURR_OUT_CH] * MAX_ALLOWABLE_DUTY_CYCLE) / (float)(Config[chUser_Config_Mode].uiMaxCMD_I));

    // Convert into compatible Duty Count type - uint16_t
    Load_Dutycount = (uint16_t) fCount;

    // Bound the output count between worst case lower and higher points
    RESTRICT(Load_Dutycount, MIN_DUTY_CYCLE_COUNT, MAX_ALLOWABLE_DUTY_CYCLE);

    // Generate PWM
    Generate_PWM(Load_Dutycount);

    // Assign the latest external input value read from ADC as the Setpoint for PI computation
    PI.fSetpoint = ADC_Val.fADC_Final_mAVal[CMD_INP_CH] ;

    // Not sure about this --- Because I think with a new Setpoint, the integrated error (which was developed based on previous Setpoints) will have no significance.
    PI.fIntegralError = 0.0;

    // Start integration all over again (Timer doesn't start counting if bCompute is set)
    bCompute = false;
}    

int main(void)
{
    // Some code for Power-ON initialization like,
    //    ADC
    //    Timer
    //    PWM
    //    PI variables
    //    Everything else which needs one-time initialization before going into the infinite loop

    while(1)
    {
        Read_ADC();
        Update_PWM_Module();
    }
}

Una vez generado el PWM, su funcionamiento es libre. El ciclo de trabajo se mantendrá constante a menos que lo cambie, por lo que sólo se cambia periódicamente basado en el cálculo PI.

Para que quede claro, cuando digo "anular el valor del error integrado", me refería a pPI->integralError = 0.0; en el programa C.

Planteamiento del problema: El tiempo total de ejecución del bucle cuando el temporizador no ha transcurrido es de aproximadamente 2 mseg. El tiempo de ejecución aumenta, por supuesto, cuando se realiza el cálculo de PI y se invoca la función de generación de PWM.

Estoy sondeando las dos señales:
- Salida de la retroalimentación a la salida del amplificador operacional que se utiliza.
- Entrada al sistema.

Mi pregunta es si el flujo operativo es correcto. ¿Estoy en lo cierto en cuanto a generar el PWM sólo después de que se haya realizado el cálculo PI, y en cuanto a restablecer el valor del error integrado a 0,0 cada vez que se asigna un nuevo Setpoint? Al probar con una entrada escalonada de 0-4V, 0,5 Hz, en el osciloscopio veo que el sistema tarda unos 120 mseg en elevar su salida a la entrada. Puedo correlacionar que los valores P e I tendrán que ser sintonizados para mejorar el tiempo. Este post no trata mucho de afinar los valores de los factores P e I.

Lectura relacionada: Las preguntas en electronics.stackexchange las he leído y están muy relacionadas:

6voto

transistor Puntos 2074

Yo: Pero no has explicado por qué restableces / anulas el término integral.

Weda: Porque pensé que con un nuevo punto de ajuste, el error integrado (que se desarrolló en base a los puntos de ajuste anteriores) no tendría importancia. Creo que aquí es donde tengo una confusión fundamental / falta de comprensión.

Te daré mi ejemplo de "PI para principiantes" que parece ayudar a algunos en el trabajo:

  • Utilizaremos un controlador PI en el control de crucero de un coche.
  • El punto de ajuste es de 80 km/h.
  • La banda proporcional es de 10 km/h. Esto significa un 100% de aceleración hasta los 70 km/h y una reducción del 10% del acelerador por cada 1 km/h por encima de los 70 km/h, llegando al 0% de aceleración a los 80 km/h.

Control sólo proporcional

enter image description here

Figura 1. Respuesta del control de crucero sólo P. Obsérvese que nunca se alcanza la velocidad de consigna de 80 km/h.

Conectamos el control de crucero. Se acelera hasta los 70 km/h con el acelerador al 100%. Ya debería estar claro que nunca alcanzaremos los 80 km/h porque con la resistencia al rodamiento y al viento no podemos mantener los 80 km/h con cero potencia. Digamos que se establece en 77 kph con un 30% de potencia. Eso es lo máximo que podemos conseguir con el control sólo P.

Control proporcional-integral

enter image description here

Figura 2. La respuesta con la adición del control integral.

Cuando se añade la acción integral, el término integral sigue aumentando a una velocidad proporcional al error. Esto se puede ver en la curva integral de la Figura 2 como una tasa de subida inicial alta debido al gran error inicial que cae hasta la subida cero (línea de nivel) cuando el error se elimina finalmente.

enter image description here

_Figura 3. La función clásica de control PID. Fuente: Wikipedia - Controlador PID ._

Una cosa que se me ocurrió bastante tarde fue que cuando la acción integral corrige la salida, el error cae a cero, por lo que la contribución del control proporcional también cae a cero. La salida cuando el error es cero se mantiene puramente por la acción integral.


Tenga en cuenta que si el punto de ajuste cambia o la carga cambia (el coche se encuentra con una colina o un viento en contra) que el error cambiará a un valor distinto de cero, el control P aumentará inmediatamente de cero y la acción integral continuará desde su valor actual - no desde cero.


Hay un simple Excel Simulador PI en Ingenieros Excel y esto puede ser de utilidad. No sé si es el mejor.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X