DESARROLLANDO ALGORITMOS DE CONTROL PID (PARTE 3)

Standard

Que tal, amigos lectores, me es muy grato estar con ustedes de nuevo. Lamento haber tardado un poco con esta entrega, la cual es el capítulo final de esta mini serie. Pero como se darán cuenta, traté de explicar claramente los detalles que ella se exponen, así que valió la pena esperar. Go ahead!.

Para dar seguimiento de forma clara, traigo ante ustedes de nueva cuenta el diagrama de bloques de un sistema de control digital en lazo cerrado.

1

En el blog anterior les expliqué la forma de programar la frecuencia de muestreo en la plataforma arduino, la cual visualizando los bloques nos encargamos de elaborar la cajita que se muestra con el nombre de reloj y la parte del primer bloque que corresponde al muestreo y retención (sample and hold, S/H).

Aprovecho este momento para aclarar que la parte de muestreo y retención corresponde a la lectura de datos arrojada por el transductor o sensor que se esté implementando en el sistema. En el blog anterior me limité a indicarlo sólo como un comentario, ya que,  el desarrollo de software que involucra esta parte varía conforme al tipo de sensor o transductor que se decida implementar. El propósito de esta mini serie es explicar los conceptos de forma teórico-general.
Una vez concluida la etapa anterior, tenemos que continuar con la parte A/D (Analog-digital converter) del primer bloque. La verdad esto es algo muy sencillo de realizar en las diversas plataformas que ofrece arduino. Solo basta con escribir la función analogRead() durante el desarrollo de nuestro software para crear esta etapa. La mayoría de las distribuciones de arduino, si no es que todas, manejan convertidores analógico-digitales en la arquitectura de sus microcontroladores. En el caso de arduino UNO y arduino MEGA 2560, ambos cuentan con un ADC de 10 bits. Lo cual significa que nos brindará un rango de información de 0 a 1023. Con todo lo anterior ya establecido nos garantizamos que la CPU de nuestra plataforma reciba información procesable para ella. Por lo que continuamos con el siguiente bloque de nuestro sistema.

A continuación, viene algo gracioso, si seguimos tal cual la estructura del diagrama de bloques mostrado anteriormente, nos damos cuenta que sigue establecer la computadora digital de nuestro sistema. Y lo gracioso es que en realidad no tenemos que hacer algo al respecto, ya que se puede decir que todo microcontrolador posee una CPU, al igual que una computadora. Para el caso específico de un Arduino UNO, se cuenta con un microcontrolador ATmega328P, de la compañía Atmel posee una CPU llamada AVR Core. En las siguientes imágenes muestro a la izquierda la arquitectura general del microcontrolador y a la derecha la arquitectura de la CPU AVR Core del microcontrolador.

AVR

Para concluir esta parte del diagrama de control digital, agrego como recordatorio que la función principal del núcleo de la CPU es asegurar la ejecución correcta del programa, por lo tanto, la CPU debe ser capaz de acceder a memorias, realizar cálculos, controlar periféricos y manejar interrupciones. En resumen, La CPU se encarga de procesar toda la información durante el tiempo de ejecución de nuestro sistema.

Pasando a la siguiente etapa nos encontramos con el bloque D/A, el cual es el convertidor digital-analógico y el bloque del circuito de retención. Quiero hacer énfasis que la mayoría de las distribuciones de arduino no poseen salidas analógicas. Distribuciones como Arduino Due si poseen esta característica, las más populares como Arduino UNO y MEGA 2560 no poseen salidas analógicas. Hay quienes afirman que poseen salidas analógicas, pero no es así. Las salidas que poseen y que emulan el funcionamiento de una señal analógica son las salidas PWM. En la mayoría de los casos es posible hacer funcionar un actuador con las señales PWM, aunque requiera naturalmente una señal analógica. Lo explicado anteriormente nos brinda grandes ventajas a la hora de estar manipulando un proceso.

Regresando nuevamente al convertidor digital-analógico. En esta parte de nuestro sistema lo que se hace, en resumen, es convertir la información binaria a pulsos eléctricos proporcionales a la magnitud de la información, mientras que el circuito de retención lo que hace es hacer que esos pulsos se conecten entre ellos y formen una señal de salida. La siguiente imagen muestra lo anteriormente explicado aplicado a una señal triangular.

Señales

Los pulsos ilustrados en azul corresponden al trabajo realizado por el D/A, mientras que la señal en verde corresponde al trabajo realizado por el circuito de retención. En este caso y que también aplica para arduino, estamos apreciando un retenedor de orden 0. Como pueden apreciar la señal resultante color verde se asemeja a la señal original de color rojo, que, aunque no es igual, con esa forma resultante nos sirve para cumplir nuestro objetivo, ya que, en la mayoría de los casos, los actuadores la reconocen como si se tratara de la señal original.
Ahora demostrando lo anteriormente explicado, completamente acorde a las salidas PWM de arduino tenemos la siguiente imagen que ilustra lo que les mencioné anteriormente.

PWM

Los pulsos color negro que se muestran corresponden a la señal PWM, mientras que la señal de color lila sería la señal analógica equivalente. Conforme varíe en ancho de pulso, aunque todos sus picos sean de un voltaje determinado (5V para las distribuciones populares de arduino) su ciclo de trabajo será mayor o menor. ¿Qué significa el ciclo de trabajo?, en pocas palabras que el voltaje equivalente tendrá un valor determinado por el ancho de pulso. En la imagen se muestra lo que acabo de mencionar. Ahora ¿Cómo establecemos el funcionamiento de estos 2 bloques en Arduino?, simplemente escribiendo en nuestro código la función analogWrite().

Como pueden apreciar, todo lo anterior en la plataforma arduino se logra con relativa facilidad. A partir de aquí comienza la parte medular de esta serie. El desarrollo de un controlador PID para un determinado sistema. En la primer entrega de esta serie mostré la siguiente imagen:

PID

La cual muestra la arquitectura de un sistema de control clásico, el cual como pueden apreciar, es distinto a la arquitectura de un sistema de control digital. Lo muestro porque aquí se aprecia visualmente el bloque que contiene todo el desarrollo del controlador. Seguramente se preguntaran, ¿Dónde se encuentra ese bloque en el diagrama de control digital?.

Antes de responder esa pregunta quiero aclarar que en los sistemas de control clásico no se dispone de una CPU que se encargue de procesar la información y es un sistema continuo en el tiempo, es decir no muestrea información a determinada frecuencia. Caso contrario de un sistema de control digital, donde si disponemos de una CPU y la información si es muestreada. Entonces como la CPU es quien procesa toda la información y en resumen un controlador PID es un cálculo matemático para corregir errores en nuestro sistema, el bloque que corresponde al controlador, se encuentra embebido en el bloque que corresponde a nuestra computadora digital, y esto se logra desarrollando el controlador PID en nuestro software.
El controlador PID tiene los atributos de las 3 acciones de control (Proporcional, Integral, Derivativo). El bloque proporcional provee una respuesta rápida a disturbios del sistema. La parte derivativa asegura una respuesta agresiva para disturbios súbitos y de esta manera corregir el error, la parte integral corrige el error en estado estacionario.

La ecuación que describe al controlador PID es la siguiente:

PID-EC

Donde:
e(t) = Error del sistema
∫e(τ)dτ = Integral definida del error durante el tiempo de ejecución
de/dt= Variación del error respecto al tiempo de ejecución.
Kp = ganancia proporcional
Ki = ganancia integral
Kd = ganancia derivativa

La razón por la que a muchos se les dificulta desarrollar estos algoritmos mediante software, es porque no saben cómo codificar una integral y una derivada. Con la parte proporcional no suceden complicaciones porque se trata simplemente de una multiplicación. A continuación, les explico cómo desarrollar el controlador PID en nuestro código arduino.

Lo primero que hay que hacer es definir todos los errores en nuestro código. Partiendo que e(t)=Error del sistema, pues simplemente necesitamos comparar el valor deseado de la variable a controlar con el valor real medido por el sensor. Es decir:

e(t)=valorDeseado-valorReal

El error anterior multiplicado por la ganancia proporcional nos da como resultado el controlador proporcional. La parte más sencilla del controlador PID. Es decir:
ControladorProporcional= Kp*e(t)

Ahora continuamos definiendo el controlador integral. Aquí tenemos que caer en cuenta que el trasfondo de un integral en el cálculo es realizar una suma muchas veces. Aunque no lo crean la integral en realidad es una suma disfrazada de algo muy maquiavélico. En otras palabras, es una sumatoria. Si no me creen, los invito a leer un poco cualquier libro de cálculo integral. Entonces tomando en cuenta lo anterior y recordando que en arduino nuestro código itera de forma infinita dentro de la función void loop(), es posible lograr el cálculo de una integral, aunque en nuestro código no escribamos literalmente una integral. Esto se logra de la siguiente manera.
Partiendo de la definición previa de e(t) y tomando en cuenta que la integral del error respecto al tiempo es la sumatoria de todos los valores que pueda adquirir el error durante el tiempo de ejecución. El controlador integral se define de la siguiente manera:

e(t)=valorDeseado-valorReal;
integral=integral+e(t);
Controlador integral=ki*integral;
Return Controlador integral;

Si aprecian el texto anterior es un pseudocódigo. Lo ejemplifiqué de esta manera para que sea más clara la explicación. Con esto logramos desarrollar la parte integral de nuestro controlador PID. ¡Cómo pueden ver se trata de una SUMA! Una simple suma dentro de un bucle infinito.

Por último, les muestro como desarrollar un controlador derivativo, conociendo la definición de e(t) y el concepto de la derivada, una definición válida para este controlador es “variación del error respecto al tiempo”. Es decir, si al tiempo “t1” el error adquiere un valor de 20 en ese instante, y al tiempo “t2” el error adquiere un valor de 30. ¿Cuánto varió? La respuesta es 10 como seguramente lo pensaron, es decir “t2-t1” = 10. El pseudocódigo queda de la siguiente manera:

e(t) = valorDeseado-valorReal;
derivada = e(t) – ErrorPasado;
Controlador derivativo = kd * derivada;
ErrorPasado = e(t);
Return Controlador derivativo;

En conclusión, el controlador derivativo es una RESTA! Una simple resta dentro de un bucle infinito.
¿Ahora todo parece muy sencillo no?, créanme que para mí comprender esto fue realmente pasar muchas noches de estudio, al final si tienes lo suficientemente fuertes tus conocimientos matemáticos, son conceptos que al final se comprenden rápidamente, sinceramente aunque me considero buen estudiante y me encantan las matemáticas, me di cuenta durante el transcurso de mi carrera profesional que sabía resolver problemas matemáticos, pero no conocía claramente los conceptos de la lógica matemática. Muchas veces en estas materias evadimos la teoría, y por experiencia les comparto que es algo que no deben hacer, porque muy probablemente se topen con la misma barrera que yo tuve que enfrentar. Y como mencioné en la primera parte de esta mini serie, realmente cuando no entendemos el concepto se nos complica en demasía. En cambio, cuando se conoce el trasfondo, nos damos cuenta que es algo verdaderamente sencillo tal y como aquí se los demostré.
A continuación, les muestro una imagen del desarrollo de un controlador PID mediante el uso de funciones en Arduino.

PIDCorrecto

Por último, viene la pregunta que seguramente aquellas personas con bases de control tengan en sus mentes en este momento. ¿Cómo sintonizar las ganancias del controlador? Pues como ya saben, en la escuela nos enseñan algunos métodos que siguen requiriendo un buen nivel matemático por parte del desarrollador. Pero en base a mi experiencia desarrollando controladores para distintos proyectos, no me da vergüenza compartirles que yo los sintonizo, experimentando, es decir a tanteo. A fin de cuentas, lo estoy utilizando en un sistema físico, en mi experiencia me es mucho más fácil y rápido sintonizar repito a tanteo. Al principio estaba un poco cerrado en este aspecto ya que yo quería aplicar los clásicos métodos de Ziegler-Nichols, sin embargo, durante la práctica me fue mucho más rápido sintonizar a tanteo y créanme que he tenido excelentes resultados.
Aclaro que esta función será llamada dentro de nuestra función void loop() cuantas veces itere nuestro algoritmo. Para finalizar los invito a que analicen en la imagen anterior la parte remarcada en amarillo y compárenla con la ecuación del controlador PID que en este mismo documento ilustré atrás, terminarán concluyendo que son exactamente iguales, por lo tanto ¡habemus PID!

Amables lectores, al igual que mis presentaciones pasadas les agradezco que se hayan tomado algo de su tiempo para leer mi post, espero que les sea de utilidad y me retiro por el momento no sin antes mandarles un fuerte abrazo y mis mejores deseos, hasta Pronto.

                             filipini

 Earvin Ricardo Casillas Filippini

 Desarrollador Mecatrónico

One thought on “DESARROLLANDO ALGORITMOS DE CONTROL PID (PARTE 3)

  1. David Acosta

    buenas noches
    Ing. Earvin Ricardo Casillas Filippini
    Mi nombre es David Acosta, soy de Bogotá y estoy cursando Ing. Electrónica en la Universidad los libertadores, me pareció muy interesante este blog además de ser muy bueno.
    tengo el siguiente trabajo: ingresar una señal analógica por una de los pines analógicos del arduino, la cual debe salir por otro pin analógico con 10 muestras. Es para la materia de control digital.
    Agradezco su amable atención y quedo muy atento a su valiosa respuesta.

Leave a Reply

Your email address will not be published. Required fields are marked *