programar bucles PID en C

11

Soy un ingeniero eléctrico que se introdujo en el mundo digital y aprendí sobre la marcha. Estoy programando un procesador TI para hacer un bucle PID (proporcional-integral-derivado) , ilustrado en este diagrama:

Imagen de bucle PID de Wikipedia

También lo describiré:

Op-amp de retroalimentación negativa, con terminal no inversor conectado a tierra. Entrada a través del terminal negativo. El circuito de retroalimentación es un circuito de la serie RE en paralelo con una resistencia y todo eso en paralelo con una tapa.

¿Alguien tiene alguna idea de cómo convertir este circuito a código C? Estoy un poco fuera de mi elemento en esto y podría usar la ayuda.

Ingeniero Jedi
fuente
Puede vincular a una imagen y alguien ayudará a convertir ese enlace en una imagen real para usted.
Joachim Sauer
2
El enlace que usted mismo publicó proporciona un pseudocódigo básico para hacerlo. Si no le importa C #, aquí hay un ejemplo de un ciclo pid en C # .
Neil
1
Neil tiene razón. He implementado casi exactamente ese ciclo en C en TI. Una pista: use un bucle de tiempo constante y factorice el fijo dten las constantes, en lugar de hacer divisiones y multiplicaciones adicionales en el bucle.
AShelly
1
@Neil que fue un enlace que agregué en la revisión 2 porque no sabía qué era un bucle PID y sospechaba que muchos otros tampoco.
@MichaelT, ah mis disculpas entonces.
Neil

Respuestas:

18

El circuito

Ok, acabo de crear una cuenta aquí cuando vi esta pregunta. No puedo editar tu pregunta para poder corregir el error tipográfico que hiciste. Creo que te referías al circuito de la serie RC en paralelo en lugar de RE (si es así, no tengo una sola pista de lo que significa)

Parece que el circuito analógico que desea simular usando C se parece a esto

                         Ci
                  |------| |--------------|
                  |           Rp          |
                  |----/\/\/\/\-----------|
                  |          Rd    Cd     |
           Rf     |----/\/\/\---| |-------|
Vin o----/\/\/\---|                       |
                  |    |\                 |
                  |    | \                |
                  |----|- \               | 
                       |   \              |
                       |    \-------------|---------o  Vout
                       |    /
                       |   /
                       |+ /
                   ----| /
                  |    |/
                  |
                  |
               ___|___ GND
                _____
                 ___
                  _

LEGEND:
  Vin is the input signal.
  Vout is the Output.
  Rp controls the propotional term ( P in PID) 
  Ci controls the Integral term ( I id PID)
  Rd and Cd controls the differential term ( D in PID)
  Rf is the gain control, which is common to all of the above controllers.

(No pude resistir mi impulso de dibujar esto, ya que quería contarte cómo los ingenieros eléctricos / electrónicos solían comunicarse en foros y correos electrónicos sin imágenes ... y por qué nos encanta la mensajería, la fuente de ancho fijo)

Debo confesar que el circuito que está utilizando es simple de configurar pero matemáticamente muy complejo, cuando se trata de sintonizar las constantes Propotional, Integral y Derivada del sistema a un valor deseado individualmente, no es posible.

Le sugiero que use el circuito de esta fuente para estudiar.

Aunque es un poco tedioso de configurar, matemáticamente es mucho más simple de analizar, ya que puede relacionarlo directamente con la forma matemática estándar en lugar de la ideal.

Por último, el Vout va a controlar un motor o lo que sea necesario controlar. Y Vin es el proceso de voltaje variable.

Antes de mojarse los pies en C (¿mar?)

Supongo que está leyendo las señales de algún tipo de convertidor analógico a digital. Si no, entonces tendría que simular la señal como entrada.

Si utiliza el formulario estándar que tenemos,

Suponiendo que el tiempo de ejecución del bucle es lo suficientemente pequeño (un proceso lento), podemos usar la siguiente función para calcular la salida,

output = Kp * err + (Ki * int * dt) + (Kd * der /dt);

dónde

Kp = Proptional Constant.
Ki = Integral Constant.
Kd = Derivative Constant.
err = Expected Output - Actual Output ie. error;
int  = int from previous loop + err; ( i.e. integral error )
der  = err - err from previous loop; ( i.e. differential error)
dt = execution time of loop.

donde inicialmente 'der' e 'int' serían cero. Si usa una función de retardo en el código para sintonizar la frecuencia del bucle para decir 1 KHz, entonces su dt sería 0.001 segundos.

Dibujando en C

Encontré este excelente código para PID en C, aunque no cubre todos los aspectos, no obstante es bueno.

//get value of setpoint from user
while(1){
  // reset Timer
  // write code to escape loop on receiving a keyboard interrupt.
  // read the value of Vin from ADC ( Analogue to digital converter).
  // Calculate the output using the formula discussed previously.
  // Apply the calculated outpout to DAC ( digital to analogue converter).
  // wait till the Timer reach 'dt' seconds.
}

Si tomamos un proceso lento, entonces podemos usar una frecuencia más baja tal que dt >>> tiempo de ejecución del código para un solo ciclo (mucho mayor que). En tales casos, podemos eliminar el temporizador y utilizar una función de retraso en su lugar.

D34dman
fuente
66
El diagrama de Ascii me dejó alucinado. +1
l46kok
1
el enlace "esta fuente" no funciona
Ccr
Oh, lamento escuchar eso, se perdió un buen recurso :(. Bueno, el concepto se ha explicado en el código de ejemplo del bucle while que había compartido. No tengo experiencia en cómo manejar esta situación, tal vez algunos editores puedan solucionarlo con mensaje apropiado. (el enlace muerto)
D34dman
2
La "fuente" que falta puede estar disponible aquí: educypedia.karadimov.info/library/piddocs.pdf
David Suarez