Circuitos de control PID con anomalías grandes e impredecibles

10

Pregunta corta
¿Hay una forma común de manejar anomalías muy grandes (orden de magnitud) dentro de una región de control uniforme?

Antecedentes
Estoy trabajando en un algoritmo de control que impulsa un motor a través de una región de control generalmente uniforme. Sin carga / carga mínima, el control PID funciona muy bien (respuesta rápida, poco o ningún exceso). El problema con el que me encuentro es que generalmente habrá al menos una ubicación de alta carga. El usuario determina la posición durante la instalación, por lo que no hay una forma razonable de saber cuándo / dónde esperarla.

Cuando sintonizo el PID para manejar la ubicación de alta carga, causa grandes brotes excesivos en las áreas no cargadas (lo que esperaba completamente). Si bien está bien sobrepasar el recorrido medio, no hay paradas mecánicas en el gabinete. La falta de paradas duras significa que cualquier sobreimpulso significativo puede / hace que el brazo de control se desconecte del motor (produciendo una unidad muerta).

Cosas que estoy creando prototipos

  • PID anidados (muy agresivo cuando está lejos del objetivo, conservador cuando está cerca)
  • Ganancia fija cuando está lejos, PID cuando está cerca
  • PID conservador (funciona sin carga) + un control externo que busca que el PID se detenga y aplique energía adicional hasta que: se alcance el objetivo o se detecte una velocidad de cambio rápida (es decir, abandone el área de alta carga)

Limitaciones

  • Viaje completo definido
  • No se pueden agregar paradas duras (en este momento)
  • El error probablemente nunca se pondrá a cero
  • La carga alta podría haberse obtenido a partir de un recorrido inferior al 10% (lo que significa que no hay "inicio de funcionamiento")
Adam Lewis
fuente

Respuestas:

2

Su cálculo de error no parece acumular error al trabajar con el término derivado, y es posible que desee modificarlo, ya que solo el término derivado puede reaccionar a cambios rápidos en el proceso.

Si entendí bien tu código

// Determine the error delta
dE = abs(last_error - new_error);
last_error = new_error;

siempre calculará el término de control en función del error actual, que es la forma tradicional en que se implementó el PID. Está bien ya que se supone que el término I se ocupa del error acumulado de todos modos.

Sin embargo, tuve un cliente al que se le ocurrió la siguiente idea que quizás quieras probar. Como tiene una parte de la curva del proceso donde se necesitan cambios más agresivos, puede dejar que se acumule incluso el error de la parte D:

if(TD)                                                 // Calculate D term
{  
   Last_C += (Error - Last_C) / TD;                    // D term simulates
   Dterm = (Error - Last_C) * KD;                      // capacitor discharging
}
else    
   Dterm = 0;                                          // D term is OFF (TD is 0)

Hay dos cosas interesantes a tener en cuenta aquí:

  • El valor TD no es la ganancia derivada (que es KD) sino el tiempo derivado, una constante del usuario que controla el tiempo de acumulación de errores. Si se estableció en cero, la parte D del PID se desactiva sin tener en cuenta el valor de ganancia KD establecido.

  • Observe cómo se usó el error actual para 'cargar' el valor Last_C antes de llevarlo al cálculo de la parte D. La variable Last_C está actuando como un condensador, se acumularía mientras el error fuera grande, de modo que su parte derivada actuaría también en base a un 'historial' reciente del error, y después de eso (cuando el error era menor) este 'historial 'se descargará como un condensador.

Por supuesto, debe limitar la salida total de la forma en que probablemente ya lo haga (reinicio anti enrollamiento, transferencia automática a manual sin interrupciones y otras cosas habituales).

Puedo publicar más detalles sobre otros términos de mi algoritmo PID si lo encuentra útil, pero es posible que desee probar esto y ver qué sucede. Sirvió bien a mi cliente durante años.

Drazen Cika
fuente
Gracias por el aporte. Voy a tener que probar esto. A simple vista parece tener sentido.
Adam Lewis
Ya veo, por lo que tiene una contribución de término D dentro de su PID 'principal' más lo que la detección de pérdida aporta al cálculo.
Drazen Cika
1
Eso es correcto. El Dterm del PID se usa, aunque no muy agresivo, durante la sintonización. Lo que hace que este problema sea aún más difícil es que la carga puede liberarse en un lapso de tiempo muy corto. Es decir, un enlace que se está desacoplando. Esta eliminación abrupta de la fuerza provoca grandes sobreimpulsos cuando hay alguna función de suavizado (sumatoria) aplicada a las fuerzas de bloqueo.
Adam Lewis
Problema perverso, sería interesante saber qué tan bien algún algoritmo de lógica difusa manejaría esto. Al menos, podría incorporar más de su experiencia relacionada con problemas al algoritmo, en lugar de permanecer confinado dentro de las soluciones estándar. De todos modos, buena suerte con esto :-)
Drazen Cika
1

Solución inicial

stalled_pwm_output = PWM / | ΔE |

PWM = Valor máximo de PWM
ΔE = last_error - new_error

La relación inicial aumenta con éxito la salida PWM en función de la falta de cambio en el motor. Consulte el gráfico a continuación para ver la salida de muestra.

Este enfoque hace que la situación en la que el PID no agresivo se estancó. Sin embargo, tiene el desafortunado (y obvio) problema de que cuando el PID no agresivo es capaz de alcanzar el punto de ajuste e intenta disminuir, el stalled_pwm_output aumenta. Este aumento provoca un gran sobreimpulso cuando se viaja a una posición sin carga.

1 / ΔE vs ΔE

Solución actual

Teoría

stalled_pwm_output = (kE * PID_PWM) / | ΔE |

kE = Constante de escala
PID_PWM = Solicitud PWM actual del PID no agresivo
ΔE = last_error - new_error

Mi relación actual todavía usa el concepto 1 / ΔE, pero usa la salida PID PWM no agresiva para determinar la salida_de_pwm. Esto permite que el PID acelere el stall_pwm_output cuando comienza a acercarse al punto de ajuste objetivo, pero permite una salida de PWM del 100% cuando está parado. La constante de escala kE es necesaria para garantizar que el PWM llegue al punto de saturación (más de 10,000 en los gráficos a continuación).

Pseudocódigo

Tenga en cuenta que el resultado de cal_stall_pwm se agrega a la salida PID PWM en mi lógica de control actual.

int calc_stall_pwm(int pid_pwm, int new_error)
{
    int ret = 0;
    int dE = 0;
    static int last_error = 0;
    const int kE = 1;

    // Allow the stall_control until the setpoint is achived
    if( FALSE == motor_has_reached_target())
    {
        // Determine the error delta
        dE = abs(last_error - new_error);
        last_error = new_error;

        // Protect from divide by zeros
        dE = (dE == 0) ? 1 : dE;

        // Determine the stall_pwm_output
        ret = (kE * pid_pwm) / dE;
    }

    return ret;
}

Datos resultantes

Salida PWM estancada Salida PWM estancada

Tenga en cuenta que en el gráfico de salida de PWM estancado, la caída repentina de PWM a ~ 3400 es una característica de seguridad incorporada activada porque el motor no pudo alcanzar la posición en un tiempo determinado.

Salida PWM sin carga Salida PWM sin carga

Adam Lewis
fuente
1

No dices qué estás controlando ... ¿la velocidad del motor? ¿posición? Bueno, sea lo que sea, el primer paso sería definir cuál sería un error aceptable. Por ejemplo, si el control es para velocidad, se puede establecer un error máximo de 1% del objetivo. Sin definir el error aceptable, no puede determinar cuánta resolución necesita para el conteo de ADC o PWM. Sin eso, la compensación PID podría ser perfecta, pero aún tendría oscilaciones de ciclo límite.

Entonces necesita conocer la dinámica del sistema de bucle abierto. Sin eso, no puede saber qué ganancias se necesitan para las partes proporcionales (P), integrales (I) y derivadas (D) del bucle. Puede medir la dinámica con el paso de entrada (cambio de paso en el nivel de unidad o PWM), o cambios de paso en la carga (parece que esto sería relevante para usted).

El uso del cambio de error de ciclo a ciclo, en el denominador de su algoritmo de control, para modificar el valor PWM asegura que el ciclo nunca se resolverá. Esto asegura una oscilación del ciclo límite en el control. La mayoría de los clientes no tolerarían eso.

La parte P del bucle se encarga del error inmediato (responde a un error rápidamente). Pero tendrá una ganancia finita, por lo que quedará algún error. La parte I del bucle reacciona lentamente con el tiempo para aplicar ganancia infinita (tiempo infinito para ganancia infinita) para corregir ese error que quedó en la parte P.

Como la parte I es lenta, puede desfasarse con la corrección necesaria para la minimización de errores, incluso si tiene la ganancia correcta establecida. Entonces, se enrolla, tardando mucho en recuperarse. O, se deja en oposición a la parte P.

La mejor manera de manejar la liquidación es limitar el valor máximo almacenado en el integrador a solo un poco más de lo necesario para corregir el error proporcional en el peor de los casos. Si el integrador se desfasa y se opone al P, lo mejor que puede hacer es establecer el valor del integrador en cero. El algo puede diseñarse para detectar esto y restablecer el integrador cuando sea necesario.

gsills
fuente