Un Controlador PID para Robots Lego Mindstorms
Un Controlador PID para Robots Lego Mindstorms
Un Controlador PID para Robots Lego Mindstorms
Un controlador PID es una técnica común utilizada para controlar una amplia variedad de maquinaria,
incluidos vehículos, robots e incluso cohetes. La descripción matemática completa de un controlador PID
es bastante compleja, pero una comprensión mucho más simple es realmente todo lo que se necesita
para usar un PID de manera efectiva.
Este documento es una descripción de cómo crear un controlador PID para su uso con lego mindstorms
robots utilizando el lenguaje de programación NXT-G.
Será más fácil si tenemos una tarea real en mente, así que describiré cómo crear un PID para hacer el
seguimiento de líneas. Una vez creado, se puede usar el mismo PID, con solo modificaciones menores,
con cualquier otra aplicación de Mindstorms, como obtener un robot que pueda conducir lo más recto
posible, o incluso para un robot que pueda equilibrarse con nada más que 2 ruedas tocando el suelo como
un Segway.
Un PID es realmente bastante sencillo y la descripción típica de un PID es fácilmente entendida por
cualquier persona que haya tenido Cálculo. Este documento está dirigido a niños de First Lego League
de tercero a octavo grado. Como no hay muchos niños que hayan tenido Cálculo, trataré de construir todo
el concepto desde un punto de partida muy simple sin usar ningún Cálculo.
Así que comencemos con el diseño básico de un robot que sería adecuado para el seguimiento de líneas.
A la derecha hay un dibujo simplificado de una vista superior del robot con todos los detalles que
necesitamos. El robot es un robot de dirección diferencial con dos motores, cada uno conectado a una de
las ruedas A y C. El robot tiene un sensor de luz montado en la parte delantera que apunta hacia abajo
para que no vea nada más que la alfombra (piso, suelo, mesa, lo que sea que esté encendido el robot).
El círculo rojo representa el punto bastante pequeño en la alfombra que el sensor de luz realmente puede
"ver". El resto del robot es el rectángulo grande con una flecha, la flecha muestra la dirección normal de
viaje.
Nuestro objetivo es conseguir que el robot siga la línea negra
gorda. El seguimiento de líneas es un comportamiento robótico básico y a menudo es una de las primeras
cosas que las personas aprenden. Un dispositivo móvil que puede seguir una línea muestra todas las
características de un verdadero robot. Utiliza un sensor para recopilar información sobre el mundo que lo
rodea y cambia su comportamiento dependiendo de esa información.
Los seguidores de línea se pueden construir con un sensor de luz, o dos, o una docena o la cantidad que
tenga. En general, cuantos más sensores de luz tenga, mejor podrá seguir una línea. Aquí nos limitaremos
a un solo sensor de luz Mindstorms. Incluso con un solo sensor, deberíamos poder construir un robot que
pueda rastrear la línea con mucha precisión, incluso si la línea tiene curvas. Lo que generalmente pierdes
con un solo sensor es la capacidad de seguir la línea mientras te mueves rápido. A menudo, cuantos más
sensores tenga, más rápido podrá moverse el robot mientras sigue la línea.
El primer truco que usaremos, que no está relacionado con un PID, es que no intentaremos seguir la línea.
En su lugar, intentaremos seguir el borde de la línea. ¿Por qué? Porque si seguimos la línea en sí (el
negro), cuando el robot se sale de la línea y el sensor "ve blanco", no sabemos de qué lado de la línea
estamos. ¿Estamos a la izquierda o a la derecha de la línea? Si seguimos el borde de la línea, entonces
podemos decir en qué dirección estamos fuera del borde a medida que el robot se aleja de la línea. Si el
sensor de luz "ve blanco", entonces sabemos que está a la izquierda del borde de la línea (y de la línea).
Si "ve negro", entonces sabemos que está a la derecha del borde de la línea (y en la línea). Esto se llama
un "seguidor de la línea dela mano izquierda " ya que está siguiendo el borde izquierdo de la línea.
Necesitamos saber qué valores devuelve el sensor de luz cuando "ve blanco" y cuándo "ve negro". Un
sensor típico no calibrado podría dar una lectura "blanca" de 50 y una lectura "negra" de 40 (sin calibrar,
en una escala de 0 a 100). Es conveniente dibujar los valores en una simple recta numérica para ayudar
a visualizar cómo convertimos los valores del sensor de luz en cambios en el movimiento del robot. A
continuación se muestran nuestros valores de luz inventados para blanco y negro.
Simplemente dividiremos el rango en dos piezas iguales y diremos que si el nivel de luz es inferior a 45
queremos que el robot gire a la izquierda. Si es mayor de 45 queremos girar a la derecha. No entraré en
cómo se deben hacer exactamente los giros. Solo diré que los giros suaves funcionan bien para una línea
bastante recta. Una línea con muchas curvas generalmente necesita hacer giros más bruscos. Para giros
suaves, puede usar niveles de potencia del 50% en la rueda rápida y del 20% en la rueda lenta. Para
giros más bruscos en una línea curva, es posible que deba usar un 30% de potencia para la rueda rápida
y la costa o frenar la rueda lenta. Independientemente de los niveles de potencia que use, los números
serán los mismos para las dos vueltas, simplemente cambie qué motor obtiene el número grande y cuál
obtiene el número más pequeño (o un comando stop).
Este tipo de seguidor de línea seguirá una línea, pero no es muy bonita. Se ve bien en línea recta con los
motores programados para giros suaves. Pero si la línea tiene curvas, entonces debe decirle al robot que
use giros más agudos para seguir la línea. Eso hace que el robot se balancee hacia adelante y hacia atrás
a través de la línea. El robot solo "sabe" cómo hacer dos cosas; girar a la izquierda y girar a la derecha.
Este enfoque se puede hacer que funcione, pero no es muy rápido o preciso y se ve terrible.
En el enfoque anterior, el robot nunca conduce recto,incluso si está perfectamente alineado con el borde
de la línea y la línea es recta. Eso no parece muy eficiente, ¿verdad?
Intentemos arreglar eso. En lugar de dividir nuestra línea numérica de valor de luz en dos regiones,
divídala en tres.
Así que ahora si el nivel de luz es inferior a 43 queremos que el robot gire a la izquierda. Si el valor de luz
está entre 44 y 47 queremos que vaya recto (zoom zoom). Si el nivel de luz es superior a 47 queremos
girar a la derecha. Esto se puede implementar fácilmente en Mindstorms NXT-G con un interruptor (sí /
no) dentro de un interruptor. En realidad, solo tienes que hacer dos pruebas, no tres.
Este enfoque funciona mejor que el primero. Al menos ahora el robot a veces se mueve hacia adelante.
Al igual que con el primer enfoque todavía tienes que decidir qué tipo de giros necesitas y eso
generalmente depende de las características de la línea que estás siguiendo. El robot probablemente
seguirá cazando una buena cantidad.
El lector astuto probablemente habrá pensado "bueno, si tres rangos de luz son mejores que dos, ¿qué
hay de agregar aún más?" Ese es el comienzo de un PID.
Para ayudar a entender "más tipos de giros" reharemos o numeraremos la línea un poco y la
convertiremos en un gráfico. Nuestro eje X (horizontal) serán nuestros valores de luz al igual que en las
líneas numéricas. El eje Y (vertical) bien es nuestro eje de "giro".
A la izquierda está nuestra configuración original de dos niveles expresada en un gráfico. El robot solo
puede hacer dos cosas (mostradas por las líneas azules), girar a la derecha o a la izquierda y los giros
son siempre los mismos excepto por su dirección. En el centro está el seguidor de tres niveles. El rango
central agregado es donde el robot conduce directamente (Turn=0). Los giros son los mismos que antes.
A la derecha hay un seguidor de línea proporcional. En un seguidor de línea proporcional el giro varía
suavemente entre dos límites. Si la lectura del sensor de luz dice que estamos cerca de la línea, entonces
hacemos un pequeño giro. Si estamos lejos de la línea, entonces hacemos un gran giro. Proporcional es
un concepto importante. Proporcional significa que hay una relación lineal entre dos variables. Para
decirlo aún más simple, proporcional significa que un gráfico de las variables entre sí produce una línea
recta (como en el gráfico de la derecha anterior).
y = mx + b
Donde y es la distancia hacia arriba (o hacia abajo) el eje Y, x la distancia en el eje X, m es la pendiente
de la línea y b es la intersección Y, el punto donde la línea cruza el eje Y cuando x es cero. La pendiente
de la línea se define como el cambio en el valor y dividido por el cambio en el valor x utilizando cualquier
par de puntos en la línea.
Si no sabes mucho sobre líneas (o has olvidado lo que alguna vez te fue nuevo) ampliaré un poco y haré
algunas simplificaciones a nuestro gráfico y ecuación. Primero, cambiaremos el centro de nuestra línea
numérica de luz (el eje X) a cero. Eso es fácil de hacer. Para nuestro rango de valores de luz 40 y 50, solo
restamos 45 (ese es el promedio de 40 y 50, (40 + 50) / 2 ) de todas nuestras lecturas de luz. Llamaremos
a ese resultado el error. Entonces, si el valor de luz es 47 restamos 45 y obtenemos un error=2.
El error nos dice qué tan lejos del borde de la línea estamos. Si el sensor de luz está exactamente en el
borde de la línea, nuestro error es cero, ya que el valor de la luz es 45 y restamos 45 de todas nuestras
lecturas. Si el sensor está todo el camino hacia el blanco, nuestro error es +5. Todo el camino hacia el
negro el error es -5.
y = mx
La pendiente es una constante de proporcionalidad y es el factor por el que hay que multiplicar
el error (valor x) para convertirlo en un Turn (valor y). Eso es algo importante para recordar.
La "pendiente" tiene un par de nombres que significan lo mismo, al menos en este contexto. En la literatura
PID las pendientes (constantes de proporcionalidad, m en la ecuación de una recta) se llaman "K" (por
error ortográfico de la palabra "constant"?). Varias Kaparecen en toda la literatura de PID y son muy
importantes. Se puede pensar en una K (o m o pendiente o constante de proporcionalidad) como un factor
de conversión. Usas K para convertir un número que significa una cosa (valores de luz o error en nuestro
caso) en otra cosa como un giro. Eso es todo lo que hace una K. Muy simple y muy potente.
Así que usando estos nuevos nombres para nuestras variables la ecuación de la recta es;
Turn = K*(error)
En palabras, eso es "tomar el error y multiplicarlo por la constante de proporcionalidad K para obtener el
giro necesario. El valor Turn es la salida de nuestro controlador P y se llama el "término P" ya que este
es sólo un controlador proporcional.
Es posible que haya notado que en el último gráfico la línea no se extiende fuera del rango de error de -
5 a +5. Fuera del rango de -5 a +5 no podemos decir qué tan lejos está el sensor de la línea. Todo el
"blanco" se ve igual una vez que el sensor no puede ver ningún negro en absoluto. Recuerde que este
rango es arbitrario, su rango estará determinado por la configuración del sensor de luz, los colores de la
alfombrilla, etc. Una vez que el sensor de luz se aleja demasiado del borde de la línea, comienza a dar
una lectura constante, lo que significa que la lectura del sensor de luz ya no es proporcional al error. Solo
podemos juzgar qué tan lejos está el sensor del borde de la línea cuando el sensor está realmente
bastante cerca de él. En ese estrecho rango, la lectura del sensor de luz es proporcional a la distancia.
Por lo tanto, nuestra configuración del sensor tiene un rango limitado sobre el cual proporciona información
proporcional. Fuera de ese rango nos dice la dirección correcta pero la magnitud (tamaño) es incorrecta.
La lectura del sensor de luz, o el error,es más pequeño de lo que debería ser y no da una idea tan buena
de cuál debería ser el giro para corregir el error.
En la literatura PID, el rango sobre el cual el sensor da una respuesta proporcional se llama "rango
proporcional" (ir figura :D ). El rango proporcional es otro concepto muy importante en los CI. En nuestro
seguidor de línea el rango proporcional para el sensor de luz es de 40 a 50, para el error es de -5 a +5.
Nuestros motores también tienen un rango proporcional, desde -100 (potencia completa hacia atrás) hasta
+100 (potencia completa hacia adelante). Solo diré un par de cosas al respecto sobre la importancia del
rango proporcional:
(1) Desea que el rango proporcional sea lo más amplio posible. El rango proporcional de nuestro sensor
de luz es bastante pequeño, es decir, el sensor tiene que estar bastante cerca del borde de la línea para
obtener información proporcional. Exactamente qué tan amplio es el rango depende principalmente de
qué tan alto están los sensores por encima de la alfombrilla. Si el sensor está muy cerca de la alfombrilla,
digamos 1/16 de pulgada, entonces el sensor está viendo un círculo muy pequeño en la alfombrilla. Un
pequeño movimiento de lado a lado del sensor de luz hará oscilar el error de -5 a +5, eso es todo el
camino a través de nuestro rango proporcional. Se podría decir que el sensor tiene "visión de túnel", ya
que solo puede ver una parte muy pequeña de la alfombra. El sensor tiene que estar muy cerca del borde
de la línea para obtener una lectura que no sea "blanca" o "negra". Si el sensor se mueve más alto de la
alfombra, entonces ve un círculo más grande en la alfombra. A una altura de aproximadamente 1/2
pulgada, el sensor de luz parece estar mirando un círculo en la alfombrilla que tiene aproximadamente
1/2 pulgada de ancho. Con el sensor tan alto, el rango proporcional es mucho más amplio, ya que el
sensor de luz solo necesita permanecer dentro de +/- 1/2 pulgada del borde de la línea para mantener
una salida proporcional. Desafortunadamente, hay dos inconvenientes en un sensor de luz alta. Primero,
un sensor de luz alta "ve" y responde a las luces de la habitación mucho más que un sensor bajo. Un
sensor alto también tiene menos diferencia entre blanco y negro que un sensor bajo. A una distancia
suficientemente grande, el blanco y el negro darán la misma lectura.
(2) Fuera del rango proporcional, el controlador moverá las cosas en la dirección correcta, pero tenderá a
corregirse. La respuesta proporcional del controlador está limitada por el rango proporcional.
¿Cómo podemos implementar los giros? ¿Cuáles deberían ser los niveles reales de potencia del motor?
Una forma de hacer los giros es definir un "nivel Target power ", que llamaré "Tp". Tp es el nivel de
potencia de ambos motores cuando se supone que el robot debe ir en línea recta, lo que hace cuando
el error= 0. Cuando el error no es cero usamos la ecuación Turn = K*(error)para calcular cómo cambiar
los niveles de potencia para los dos motores. Un motor obtendrá un nivel de potencia de Tp+Turn,el otro
motor obtendrá un nivel de potencia de Tp-Turn. Tenga en cuenta que dado que nuestro error es de -5
a +5, eso significa que Turn puede ser positivo o negativo, lo que corresponde a giros en direcciones
opuestas. Resulta que eso es exactamente lo que queremos, ya que automáticamente establecerá el
motor correcto como el motor rápido y el otro como el motor lento. Un motor (asumiremos que es el motor
a la izquierda del robot conectado al puerto A) siempre obtendrá el valor Tp+Turn como su nivel de
potencia. El otro motor (lado derecho del robot, puerto C) siempre obtendrá Tp-Turn como su nivel de
potencia. Si el error es positivo, entonces Turn es positivo y Tp+Turn es mayor que Tp y el motor
izquierdo acelera mientras que el motor derecho se ralentiza. Si el error cambia de signo y se vuelve
negativo (lo que significa que hemos cruzado el borde de la línea y estamos "viendo negro")
entonces Tp+Turn es ahora menor que Tp y el motor izquierdo se ralentiza y el motor derecho acelera
ya que Tp-Turn es mayor que Tp. (Recuerda que lo negativo de un negativo es un positivo). Simple ¿eh?
Esperemos que sea un poco más claro a medida que avanzamos.
Primero necesitamos medir los valores que devuelve el sensor de luz para blanco y negro. A partir de
esos dos números podemos calcular el offset,es decir, cuánto restar de una lectura de luz bruta para
convertirla en un valor de error. El desplazamiento es solo el promedio de las lecturas en blanco y negro.
Para simplificar, asumiré que el desplazamiento ya se ha medido y almacenado en una variable
llamada offset. (Una buena actualización sería hacer que el robot mida los niveles de blanco y negro y
calcule el desplazamiento).
Kp = (0 - 50)/(-5 - 0) = 10.
Usaremos el valor Kp=10 para convertir un valor de error en un valor de giro. En palabras, nuestra
conversión es "por cada cambio de 1 unidad en el error aumentaremos la potencia de un motor en 10".
La potencia del otro motor disminuye en 10.
Entonces, en pseudo código ("pseudo código" significa que esto no es NXT-G real, o cualquier otro tipo
de código de programa, sino que es solo una lista detallada de lo que queremos que haga el programa):
Eso es todo, bueno, casi. Hay un problema sutil que debe ser corregido. Pero pruébalo de todos modos.
Si su robot parece evitar el borde de la línea, en lugar de tratar de encontrarlo, la causa más probable es
que haya cambiado las direcciones de giro. Cambie Kp a -10 y vea qué sucede. Si eso corrige las
direcciones de giro, cambie Kp de nuevo a +10 y cambie las señales en las dos líneas eléctricas a;
powerA = Tp - Turn
powerC = Tp + Turn
Hay dos "parámetros sintonizables" y una constante en este controlador P. La constante es el valor de
desplazamiento (el promedio de las lecturas del sensor de luz blanca y negra). Tendrás que escribir un
breve programa para medir los niveles de luz en tu colchoneta con tu robot. Necesitas un valor "negro" y
un valor "blanco". Calcule el promedio y colókerlo en el programa controlador P en la variable offset. Casi
todos los seguidores de línea requieren que usted (o el código escrito por usted y ejecutado por el robot)
haga este paso.
El valor Kp y la potencia objetivo Tp son los parámetros sintonizables. Un parámetro sintonizable tiene
que ser determinado por ensayo y error. Kp controla qué tan rápido el controlador intentará volver al borde
de la línea cuando se haya alejado de él. Tp controla qué tan rápido se mueve el robot a lo largo de la
línea.
Si la línea es bastante recta, puede usar un Tp grande para que el robot funcione a alta velocidad y
un Kp pequeño para que los giros (correcciones) sean suaves.
Si la línea tiene curvas, especialmente las agudas, habrá un valor máximo de Tp que funcionará. Si Tp es
más grande que ese máximo, no importará qué kp sea, el robot perderá la línea cuando se encuentre con
una curva porque se está moviendo demasiado rápido. Si Tp es realmente pequeño, entonces casi
cualquier valor de Kp funcionará, ya que el robot se moverá muy lentamente. El objetivo es hacer que el
robot se mueva lo más rápido posible sin dejar de ser capaz de seguir la línea de interés.
Habíamos adivinado un valor inicial para Kp de 10. Para Tp, puede comenzar incluso más bajo de lo
sugerido anteriormente, tal vez 15 (el robot se moverá bastante lento). Pruébelo y vea cómo funciona. Si
pierde la línea porque el robot parece girar lentamente, aumente Kp en un par e inténtelo de nuevo. Si
pierde la línea porque el robot parece hiperactivo en la caza de ida y vuelta para la línea, disminuya Kp.
Si el robot parece seguir la línea bastante bien, aumente el Tp y vea si puede seguir la línea a la velocidad
más rápida. Para cada nuevo Tp tendrás que determinar un nuevo Kp,aunque kp por lo general no
cambiará demasiado.
Seguir una línea recta suele ser bastante fácil. Seguir una línea con curvas suaves es un poco más difícil.
Seguir una línea con curvas pronunciadas es lo más difícil. Si el robot se mueve lo suficientemente lento,
entonces se puede seguir casi cualquier línea, incluso con un controlador muy básico. Queremos obtener
un buen seguimiento de líneas, buena velocidad y la capacidad de manejar curvas suaves. (Las líneas
con esquinas afiladas generalmente toman seguidores de línea más especializados o velocidades de
robot muy bajas).
Es probable que el mejor controlador P sea diferente para cada tipo de línea (ancho de línea, nitidez de
curvas, etc.) y para diferentes robots. En otras palabras, un controlador P (o un controlador PID para el
caso) está sintonizado para un tipo particular de línea y robot y no necesariamente funcionará bien para
otras líneas o robots. El código funcionará para muchos robots (y muchas tareas) pero los
parámetros, Kp, Tp y offset,tienen que ser ajustados para cada robot y cada aplicación.
NOTA: Este trabajo se realizó utilizando NXT-G versión 1.1 que solo admite enteros. NXT-G versión 2
admite números de coma flotante, por lo que es posible que no sea necesario lo siguiente si tiene la
versión 2 o posterior.
En el proceso de ajuste del controlador P, ajustará el valor kp hacia arriba y hacia abajo. El rango
esperado de valores que podría ser Kp depende exactamente de lo que esté haciendo el controlador P.
¿Qué tan grande es el rango de entrada y qué tan grande es el rango de salida? Para nuestro controlador
P seguidor de línea, el rango de entrada es de aproximadamente 5 unidades de luz, y el rango de salida
es de 100 unidades de potencia, por lo que parece probable que Kp esté cerca de 100/5 = 20. En algunos
casos, el Kp esperado no será tan grande. ¿Qué pasa si el Kp esperado es uno? Dado que las variables
en NXT-G están limitadas a enteros, cuando intenta ajustar el valor Kp todo lo que puede intentar es ...-
2, -1, 0, 1, 2, 3, ... . No puede introducir 1.3, por lo que no puede probar Kp= 1.3. ¡No puedes usar ningún
número con un punto decimal! Pero probablemente habrá una gran diferencia en el comportamiento del
robot cuando cambie el Kp por el menor cambio posible de 1 a 2. Con Kp=2 el robot intenta el doble de
corregir el error en comparación con Kp=1. El nivel de potencia del motor cambia el doble para el mismo
cambio en los niveles de luz. Realmente nos gustaría tener un control más fino de Kp.
Es bastante fácil solucionar este problema. Todo lo que haremos es multiplicar el Kp por una potencia de
diez para aumentar el rango utilizable dentro de la restricción de enteros. Si se espera que Kp pueda
estar cerca de 1, entonces un valor de 100 como multiplicador sería una buena apuesta. De hecho,
probablemente sea mejor seguir adelante y usar siempre 100 *Kp como el número que realmente ingresa
en el programa. Una vez multiplicado Kp por 100 ahora podemos introducir lo que habría sido 1,3 como
130. 130 no tiene punto decimal, por lo que NXT-G está contento con el número.
Pero, ¿no tira eso a la basura el cálculo? Sí, pero es fácil de arreglar. Una vez hayamos calculado el
término P dividiremos por 100 para quitar nuestro multiplicador. Recuerde nuestra ecuación que define el
controlador P de antes;
Turn = Kp*(error)
Multiplicaremos Kp por 100, lo que significa que nuestro Turn calculado es 100 veces más grande de lo
que debería ser. Antes de usar Turn debemos dividirlo por 100 para arreglar eso.
Por lo tanto, nuestro nuevo y mejorado pseudo código para una línea que sigue al controlador P es:
En este caso, un problema es que cuando calculamos el nivel de potencia del motor (por ejemplo, powerC
= Tp-Turn) es posible obtener un número negativo para la potencia. Queremos que un número negativo
signifique que el motor debe invertir la dirección. Pero el puerto de datos en un bloque NXT-G MOTOR
no entiende eso. El nivel de potencia es siempre un número entre 0 y +100. La dirección del motor está
controlada por un puerto de entrada diferente. Para que el motor reaccione correctamente cuando la
potencia es negativa, deberá manejarlo en el programa. Aquí hay una manera de hacerlo;
El bloque MOTOR recibe la potencia (potencia A para el motor A) a través de un cable de datos. La
dirección se establece con las casillas de verificación en la ventana de parámetros del motor.
Necesitará un fragmento de código similar para el motor C. Ahora, cuando la potencia calculada sea
negativa, los motores se controlarán adecuadamente. Una cosa que esto hace es permitir que el
controlador P vaya hasta un "giro de radio de giro cero" y el robot pueda girar en su lugar si es necesario.
Por supuesto, eso puede no ayudar.
Hay un par de otras cosas que podrían ser problemas sutiles. ¿Qué sucede cuando se envía un nivel de
potencia superior a 100 al motor? Resulta que el motor solo trata el número como 100. Eso es bueno para
el programa, pero no es lo mejor que puede suceder en un controlador P (o PID). Realmente preferiría
que el controlador nunca intente pedirle a los motores que hagan algo que no pueden. Si la potencia
solicitada no está muy por encima de 100 (o por debajo de -100), entonces probablemente esté bien. Si
la potencia solicitada es mucho mayor que 100 (o mucho menor que -100), a menudo significa que el
controlador se está saliendo de control. Por lo tanto, ¡asegúrese de tener un extintor de incendios a mano!
Esperemos que hayas recogido lo suficiente como para entender un controlador P (proporcional). Es
bastante simple. Use un sensor para medir algo que está tratando de controlar. Convierta esa medición
en un error. Para el seguidor de línea lo hicimos restando el promedio de los valores de luz en blanco y
negro. Multiplica el error por un factor de escala llamado Kp. El resultado es una corrección para el
sistema. En nuestro ejemplo de seguidor de línea, la corrección se aplica como un aumento / disminución
en el nivel de potencia de los motores. El factor de escala Kp se determina utilizando un poco de conjetura
educada y luego se ajusta por ensayo y error.
Los controladores P pueden manejar una sorprendente amplia gama de problemas de control, no solo
siguiendo una línea con un robot Lego. En general, los controladores P funcionan muy bien cuando se
cumplen algunas condiciones.
1. El sensor debe tener un amplio rango dinámico (lo que desafortunadamente no es cierto para
nuestro robot de seguimiento de línea).
2. Lo que se está controlendo (motores en nuestro caso) también debe tener un amplio rango
dinámico, es decir, deben tener una amplia gama de niveles de "potencia" con niveles
individuales de "potencia" que estén muy juntos (los motores NXT son bastante buenos en
este sentido).
3. Tanto el sensor como la cosa que se está controlendo deben responder rápidamente.
"Rápido" en este caso es "mucho más rápido que cualquier otra cosa que esté sucediendo
en el sistema". A menudo, cuando se controlan los motores, no es posible obtener una
respuesta "rápida", ya que los motores tardan en reaccionar a un cambio en la potencia. Los
motores Lego pueden tardar unas décimas de segundo en reaccionar a un cambio en los
niveles de potencia. Eso significa que las acciones del robot se están quedando atrás de los
comandos del controlador P. Eso dificulta el control preciso con un controlador P.
Para mejorar la respuesta de nuestro controlador P añadiremos un nuevo término a la ecuación. Este
término se llama la integral,la "I" en PID. Las integrales son una parte muy importante de las matemáticas
avanzadas, afortunadamente la parte que necesitamos es bastante sencilla.
Sí, es así de simple. Hay algunos problemas sutiles que omitiremos por el momento.
Cada vez que leamos el sensor de luz y calculemos un error añadiremos ese error a una variable que
llamaremos integral (inteligente ¿eh?).
Esa ecuación puede parecer un poco extraña, y lo es. No está escrito como una declaración matemática,
está escrito en una forma común utilizada en la programación para sumar una serie de valores.
Matemáticamente no tiene ningún sentido. En la programación de computadoras, el signo igual tiene un
significado algo diferente al de las matemáticas. (Usaré la misma fuente de máquina de escribir que usé
para los ejemplos de pseudocódigo para resaltar que es una forma de programación y no una forma
matemática adecuada). El "=" significa hacer los cálculos a la derecha y guardar el resultado en la variable
nombrada a la izquierda. Queremos que la computadora obtenga el valor antiguo de integral,agregue
el error y luego guarde el resultado nuevamente en integral.
Lo anterior es la ecuación básica para un controlador PI. El giro es nuestra corrección para los motores.
El término proporcional es Kp*(error) y el término integral es Ki*(integral).
¿Qué hace exactamente el término integral por nosotros? Si el error mantiene el mismo signo durante
varios bucles, la integral se hace cada vez más grande. Por ejemplo, si comprobamos el sensor de luz y
calculamos que el error es 1, poco tiempo después volvemos a comprobar el sensor y el error es 2, luego
la próxima vez que el error sea 2 de nuevo, entonces la integral será 1 + 2 + 2 = 5. La integral es 5, pero
el error en este paso en particular es solo 2. La integral puede ser un factor importante en la corrección,
pero generalmente toma un tiempo para que la integral se acumule hasta el punto en que comienza a
contribuir.
Otra cosa que hace la integral es ayudar a eliminar pequeños errores. Si en nuestro seguidor de línea el
sensor de luz está bastante cerca del borde de la línea, pero no exactamente en él, entonces el error será
pequeño y solo se necesitará una pequeña corrección para solucionarlo. Es posible que pueda corregir
ese pequeño error cambiando Kp en el término proporcional, pero eso a menudo conducirá a un robot
que oscila (se tambalea hacia adelante y hacia atrás). El término integral es perfecto para corregir
pequeños errores. Dado que la integral suma el error s, varios errorespequeños consecutivos
eventualmente hacen que la integral sea lo suficientemente grande como para marcar la diferencia.
Una forma de pensar en el término integral es que es la "memoria" del controlador. La integral es el
historial acumulativo del error y le da al controlador un método para corregir errores que persisten durante
mucho tiempo.
Pasé por alto un tema menor (OK, realmente no es menor, pero vamos a hacerlo así), el momento. La
integral es realmente la suma del error*(delta time). El tiempo Delta(dT)es el tiempo entre la última vez
que revisamos el sensor y el tiempo de la verificación más reciente del sensor;
Así que cada vez que añadimos a la integral lo que debemos añadir son los tiempos de error del dT. Es
bastante fácil hacer que el robot mida el dT. Simplemente leíamos un temporizador cada vez que leíamos
el sensor de luz. Si restamos la última vez de la hora actual obtenemos el tiempo desde la última
lectura dT. (Hay mejores maneras de hacer esto, pero me saltaré el trabajo ya que no son necesarias).
Pero, ¿no sería bueno si no tuviera que medir el dT y hacer la multiplicación? Bueno, ¿y si el dT es
siempre el mismo? Cada vez que añadimos a la integral tenemos ese mismo término dT. Así que
podemos tomar ese factor de dT de error*(dT) y simplemente hacer la suma de la manera en que lo
hacíamos antes;
Sólo cuando queremos hacer otro cálculo con integral necesitamos realmente multiplicar por dT. Pero
espera que hay más...
Podemos hacer aún más para ocultar el plazo. El término integral en la ecuación del controlador PI
es Ki*(integral)*dT. Pero Ki es un parámetro que tenemos que afinar (al igual que Kp) así que ¿por qué
no simplemente reemplazar la parte Ki * dT con un nuevo Ki? El nuevo Ki es diferente del original, pero
como no conocemos ninguno de los dos, realmente no importa cuál usemos o cómo lo llamemos. No
importa cómo lo llamemos o lo que represente, todavía tenemos que encontrar el valor correcto en gran
medida por ensayo y error.
Así que hemos eliminado completamente el elemento tiempo para el término integral con la restricción de
que todos los pasos de tiempo, dTs, son iguales (o aproximadamente iguales).
Cabe mencionar un último detalle sobre la integral. Normalmente la integral solo se puede mover hacia
cero, donde no aporta nada al controlador, al tener valores de error añadidos que son el signo opuesto a
la mayoría de los que ya hemos recogido en integral. Por ejemplo, si durante varios ciclos a través del
bucle el errors es 1,2,2,3,2,1 que suma una integral de 11. Pero el error en el último punto de datos es
solo 1, que es mucho más pequeño que la integral en ese punto. La única forma de que la integral se
mueva hacia cero es obtener una cadena de errornegativo s para contrarrestar la cadena anterior
de errorpositivo s para "reducir" la integral. Por ejemplo, si los siguientes errores son -2,-2,-3 entonces
la integral caerá de 11 a 4 y aún necesitaríamos más errores negativos para bajar la integral a cero.
Además, la integral quiere que el error total se distribuya uniformemente entre errores positivos y
negativos.
Si sucede algo que empuja a nuestro robot de seguimiento de línea a la izquierda del borde de la línea,
el término integral no solo quiere volver al borde de la línea, también quiere sobrepasar el borde a la
derecha tanto como la perturbación original era la izquierda. Así que la integral tiende a "terminar" si hay
grandes errores que persisten por un tiempo. Esto puede causar problemas con los controladores que
incluyen un término integral. A veces, esta tendencia del término integral a querer sobrepasarse cuando
intenta corregir el error es un problema lo suficientemente grande como para que el programador deba
hacer algo con el término integral para que no cause problemas. Si la integral de cuerda es un problema
dos soluciones comunes son (1) cero la integral, es decir, se establece la variable integral igual a cero,
cada vez que el error es cero o el error cambia de signo. (2) "Amortiguar" la integral multiplicando
la integral acumulada por un factor menor que uno cuando se calcula una nueva integral. Por ejemplo;
Esto reduce el valor integral anterior en 1/3 cada vez a través del bucle. Si piensas en el término integral
como la "memoria" de los controladores, entonces esta amortiguación lo está obligando a olvidarse de las
cosas que sucedieron hace "mucho" tiempo.
Para agregar el término integral al controlador necesitamos agregar una nueva variable para Ki y otra
para la integral en sí. Y no olvides que estamos multiplicando nuestros K por 100 para ayudar con las
restricciones matemáticas enteras.
Nuestro controlador ahora contiene un término proporcional (P) que intenta corregir el error actual y un
término integral (I) que intenta corregir errores pasados s, ¿hay alguna manera de que el controlador
mire hacia adelante en el tiempo y tal vez intente corregir el error que ni siquiera ha ocurrido todavía?
Sí, y la solución es otro concepto de las matemáticas avanzadas llamado derivada. Ahhh, está la "D" en
PID. Al igual que la integral,la derivada puede representar algunas matemáticas bastante serias.
Afortunadamente para nosotros, lo que necesitamos para el PID es bastante simple.
Podemos mirar hacia el futuro asumiendo que el siguiente cambio en el error es el mismo que el
último cambio en el error.
Eso significa que se espera que el siguiente error sea el error actual más el cambio en el error entre las
dos muestras de sensores anteriores. El cambio en el error entre dos puntos consecutivos se
denomina derivada. La derivada es la misma que la pendiente de una línea.
Eso puede sonar un poco complejo de calcular, pero realmente no es tan malo. Un conjunto de datos de
muestra ayudará a ilustrar cómo funciona. Supongamos que el error actual es 2 y el error anterior era 5.
¿Cuál predeciríamos que sería el próximo error? Bueno, el cambio en el error es la derivada que es;
que para nuestros números es 2 - 5 = -3. Por lo tanto, la derivada actual es -3. Para usar la derivada para
predecir el siguiente error usaríamos
que para nuestros números es 2 + (-3) = -1. Así que predecimos que el siguiente error será -1. En la
práctica, en realidad no vamos hasta el final y predecimos el siguiente error. En su lugar, solo usamos
la derivada directamente en la ecuación del controlador.
El término D, al igual que el término I, en realidad debería incluir un elemento de tiempo, y el término D
"oficial" es;
Kd ( derivada ) / ( dT )
Al igual que con los términos proporcionales e integrales tenemos que multiplicar por una constante.
Dado que esta es la constante que va con la derivada se llama Kd. Nótese también que para el término
derivado dividimos por dT mientras que en el término integral habíamos multiplicado por dT. No se
preocupe demasiado por qué es así, ya que vamos a hacer el mismo tipo de trucos para deshacerse
del dT del término derivado como lo hicimos para el término integral. La fracción Kd/dT es una
constante si dT es la misma para cada bucle. Así que podemos reemplazar Kd/dT por otro Kd. Dado que
este K, al igual que el Ks anterior, es desconocido y tiene que ser determinado por ensayo y error, no
importa si es Kd / dT o simplemente un nuevo valor para Kd.
Es bastante obvio que "predecir el futuro" sería algo útil para poder hacer, pero ¿cómo ayuda exactamente?
¿Y qué tan precisa es la predicción?
Si el error actual es peor que el error anterior, entonces el término D intenta corregir el error. Si
el error actual es mejor que el error anterior, entonces el término D intenta evitar que el controlador
corrija el error. Es el segundo caso el que resulta especialmente útil. Si el error se acerca a cero,
entonces nos estamos acercando al punto en el que queremos dejar de corregir. Dado que el sistema
probablemente tarda un tiempo en responder a los cambios en la potencia de los motores, queremos
comenzar a reducir la potencia del motor antes de que el error haya llegado a cero, de lo contrario nos
excederemos. Cuando se pone de esa manera, podría parecer que la ecuación para el término D tendría
que ser más compleja de lo que es, pero no lo es. Lo único de lo que tienes que preocuparte es de hacer
la resta en el orden correcto. El orden correcto para este tipo de cosas es "actual" menos "anterior". Así
que para calcular la derivada tomamos el error actual y restamos el erroranterior.
Para añadir el término derivado al controlador necesitamos añadir una nueva variable para Kd y una
variable para recordar el último error. Y no olvides que estamos multiplicando nuestros K por 100 para
ayudar con las matemáticas enteras.
Personas muy inteligentes ya han descubierto cómo sintonizar un controlador PID. Como no soy tan
inteligente como ellos, usaré lo que aprendieron. Resulta que la medición de un par de parámetros para
el sistema le permite calcular valores "bastante buenos" para Kp, Ki y Kd. No importa mucho cuál es el
sistema exacto que se está controlendo, las ecuaciones de afinación casi siempre funcionan bastante
bien. Existen varias técnicas para calcular el Ks, una de ellas se llama el "Método Ziegler-Nichols", que
es la que utilizaremos. Una búsqueda en Google localizará muchas páginas web que describen esta
técnica con todos sus detalles sangrientos. La versión que usaré es casi directamente de la página Wiki
sobre controladores PID (el mismo tratamiento se encuentra en muchos otros lugares). Solo haré un
pequeño cambio al incluir el tiempo de bucle(dT)en los cálculos que se muestran en la tabla a continuación.
1. Establezca los valores Ki y Kd en cero, lo que desactiva esos términos y hace que el
controlador actúe como un simple controlador P.
2. Establezca el término Tp en uno pequeño. Para nuestros motores, 25 podría ser un buen
lugar para comenzar.
3. Establezca el término Kp en un valor "razonable". ¿Qué es "razonable"?
1. Simplemente tomo el valor máximo que queremos enviar al control de potencia
del motor (100) y lo divido por el valor de error máximo utilizable. Para nuestro
robot de seguimiento de línea, hemos asumido que el error máximo es 5, por
lo que nuestra suposición en Kp es 100/5 = 20. Cuando el error es +5, la
potencia del motor oscilará en 100 unidades. Cuando el error es cero, la
potencia del motor se ubicará en el nivel Tp.
2. O bien, simplemente establezca Kp en 1 (o 100) y vea qué sucede.
3. Si ha implementado que las K se ingresan como 100 veces su valor real, debe
tenerlo en cuenta aquí. 1 se ingresa como 100, 20 como 2000, 100 como
10000.
4. Ejecute el robot y observe lo que hace. Si no puede seguir la línea y se aleja, aumente Kp. Si
oscila salvajemente, entonces disminuya Kp. Siga cambiando el valor de Kp hasta que
encuentre uno que siga la línea y dé una oscilación notable, pero no realmente salvajes.
Llamaremos a este valor kp "Kc" ("ganancia crítica" en la literatura PID).
5. Usando el valor Kc como Kp,ejecute el robot a lo largo de la línea e intente determinar qué
tan rápido está oscilando. Esto puede ser complicado, pero afortunadamente la medición no
tiene que ser tan precisa. El período de oscilación(Pc)es el tiempo que tarda el robot en
balancearse de un lado de la línea al otro y luego volver al lado donde comenzó. Para los
robots Lego típicos, la PC probablemente estará en el rango de aproximadamente 0.5
segundos a un segundo o dos.
6. También necesita saber qué tan rápido el robot circula a través de su bucle de control.
Simplemente establecí el bucle en un número fijo de pasos (como 10,000) y el tiempo que
tarda el robot en terminar (o hacer que el robot haga el tiempo y muestre el resultado). El
tiempo por bucle (dT) es el tiempo medido dividido por el número de bucles. Para un
controlador PID completo, escrito en NXT-G, sin zumbidos o silbidos adicionales, el dT estará
en el rango de 0.015 a 0.020 segundos por bucle.
7. Utilice la tabla siguiente para calcular un conjunto de valores de Kp, Kiy Kc. Si solo desea un
controlador P, use la línea en la tabla marcada P para calcular el Kp "correcto"(Ki' y Kd' son
cero). Si desea un controlador PI, use la siguiente línea. El controlador PID completo es el
resultado final.
8. Si ha implementado que las K se ingresan todas como 100 veces su valor real, no tiene que
tener eso en cuenta en estos cálculos. Ese factor de 100 ya se tiene en cuenta en el
valor Kp = Kc que determinó.
9. Ejecute el robot y vea cómo se comporta.
10. Modifique los valores de Kp, Ki y Kd para obtener el mejor rendimiento posible. Puede
comenzar con ajustes bastante grandes, digamos el 30% y luego probar ajustes más
pequeños para obtener el rendimiento óptimo (o al menos aceptable).
11. Una vez que tenga un buen conjunto de K, intente aumentar el valor de Tp, que controla la
velocidad recta del robot.
12. Reajuste las K o tal vez incluso vuelva al paso 1 y repita todo el proceso para el nuevo valor
tp.
13. Sigue repitiendo hasta que el comportamiento del robot sea aceptable
Los primos (apóstrofos) en Ki' y Kd' son solo para recordarle que se calculan asumiendo que dT es
constante y dT se ha enrollado en los valores de K.
Estos son los valores que medí para mi robot de prueba (el que se muestra en el video vinculado más
adelante). Kc era 300 y cuando Kp= Kc el robot oscilaba a unos 0,8 segundos por oscilación por lo
que Pc es 0,8. Medí pc simplemente contando en voz alta cada vez que el robot giraba completamente
en una dirección en particular. Luego comparé mi percepción de lo rápido que estaba contando con "1-
papa - 2-papa - 3-papa ...". Eso no es "ingeniería de precisión", pero funciona lo suficientemente bien, por
lo que lo llamaremos "ingeniería práctica". El tiempo de bucle, dT,es de 0,014 segundos/bucle
determinado simplemente ejecutando el programa durante 10.000 bucles y haciendo que NXT muestre el
tiempo de ejecución. Usando la tabla anterior para un controlador PID obtenemos;
Kp = (0.60)(Kc) = (0.60)(300)
= 180 Ki = 2(Kp)(dT) / (Pc) = 2(180)(0.014) /
(0.8) = 6.3 (que se redondea a 6) Kd = (Kp)(Pc) / ((8)(dT)) = (180)(0.8) / ((8)(0.014)) = 1286
Después de un ajuste adicional de prueba y error, los valores finales fueron 220, 7 y 500
para Kp, Ki y Kd respectivamente. Recuerde que todos mis K se ingresan como 100x su valor real, por
lo que los valores reales son 2.2, 0.07 y 5.
La tabla y el método descritos anteriormente son un buen punto de partida para optimizar su PID. A veces
ayuda tener una mejor idea de cuál será el resultado de aumentar (o disminuir) una de las tres K. La
siguiente tabla está disponible en muchos sitios web. Esta versión en particular es de la Wiki en
controladores PID.
Los primos (apóstrofos) en Ki' y Kd' son solo para recordarle que se calculan asumiendo que dT es
constante y dT se ha enrollado en los valores de K.
Estos son los valores que medí para mi robot de prueba (el que se muestra en el video vinculado más
adelante). Kc era 300 y cuando Kp= Kc el robot oscilaba a unos 0,8 segundos por oscilación por lo
que Pc es 0,8. Medí pc simplemente contando en voz alta cada vez que el robot giraba completamente
en una dirección en particular. Luego comparé mi percepción de lo rápido que estaba contando con "1-
papa - 2-papa - 3-papa ...". Eso no es "ingeniería de precisión", pero funciona lo suficientemente bien, por
lo que lo llamaremos "ingeniería práctica". El tiempo de bucle, dT,es de 0,014 segundos/bucle
determinado simplemente ejecutando el programa durante 10.000 bucles y haciendo que NXT muestre el
tiempo de ejecución. Usando la tabla anterior para un controlador PID obtenemos;
Kp = (0.60)(Kc) = (0.60)(300)
= 180 Ki = 2(Kp)(dT) / (Pc) = 2(180)(0.014) /
(0.8) = 6.3 (que se redondea a 6) Kd = (Kp)(Pc) / ((8)(dT)) = (180)(0.8) / ((8)(0.014)) = 1286
Después de un ajuste adicional de prueba y error, los valores finales fueron 220, 7 y 500
para Kp, Ki y Kd respectivamente. Recuerde que todos mis K se ingresan como 100x su valor real, por
lo que los valores reales son 2.2, 0.07 y 5.
La tabla y el método descritos anteriormente son un buen punto de partida para optimizar su PID. A veces
ayuda tener una mejor idea de cuál será el resultado de aumentar (o disminuir) una de las tres K. La
siguiente tabla está disponible en muchos sitios web. Esta versión en particular es de la Wiki en
controladores PID.
MPEG4 - MP4 (644KB) QuickTime - MOV (972KB) MPG (3.6M) AVI (3.6M)
En general, el seguidor de línea parece funcionar bastante bien. Si miras el video de cerca, verás que el
robot "mueve la cola" un poco a medida que sale de las esquinas. Ese es el PID oscilando un poco.
Cuando el robot está corriendo hacia la cámara, puede ver la mancha roja en la alfombra desde el LED
del sensor de luz. Parece estar siguiendo el borde de la línea bastante bien.
El controlador PID básico debería funcionar para muchos problemas de control diferentes y, por supuesto,
se puede usar como un controlador P o PI en lugar de un PID. Tendría que llegar a una nueva definición
del error y el PID tendría que ajustarse para la tarea en particular.
Dado que este documento está dirigido a niños mayores de FLL, realmente no quiero dar el código.
Deberían ser capaces de escribir el suyo propio.
El pseudocódigo tiene casi todo lo que necesita para el PID en sí. Es posible que tenga que agregar algún
código de configuración y tal vez una forma adecuada de detener el bucle de seguimiento de línea.
Como un poco de ayuda, aquí hay un MyBlock que toma dos entradas, la potencia objetivo Tp y el
valor Turn, y controla los dos motores. Este MyBlock también trata adecuadamente los niveles de
potencia negativos. Incluso pita cuando un motor invierte direcciones, lo cual es útil para la puesta a punto.
Una línea correctamente ajustada después de la PID rara vez debería tener que invertir las direcciones
del motor.
PID_LF_MotorControl.rbt es el archivo RBT de NXT-G v1.1. Una captura de pantalla del programa está
en PID_LF_MotorControld.png
Para un excelente ejemplo de otro controlador PID en un robot Mindstorms, vea Philos equilibrando
segway como robot. El PID está escrito en NQC ("no del todo C"). El equilibrio es un problema de
control mucho más complicado que seguir una línea. (¡Lo sé porque lo he probado! )
Existen métodos avanzados para ajustar un controlador PID. Por lo general, requiere hardware y / o
software que un constructor de robots Lego no tiene.
Algunos controladores PID son mucho más fáciles de ajustar que otros. Por ejemplo, un controlador PID
se utiliza a menudo para controlar la temperatura en un horno. Este es un trabajo de ajuste bastante fácil
ya que el horno es bastante estable, aunque puede estar lejos de su temperatura objetivo, incluso cuando
el PID está mal ajustado. Los controladores PID también se utilizan para controlar los robots de equilibrio.
Eso es mucho más difícil de sintonizar ya que el PID tiene que ser sintonizado bastante bien, de lo
contrario, el robot simplemente se cae. Es difícil ajustar el PID si el robot se cae rápidamente cada vez
que se enciende.
Existen variantes del método de Ziegler-Nichols y otros métodos para ajustar un PID.
Los IDOS han existido durante mucho tiempo y precedieron al control por computadora. Un PID puede, y
a menudo lo ha hecho, ser implementado en sistemas puramente mecánicos. Es decir, ninguna
computadora o incluso ninguna parte eléctrica.
Sería interesante que el programa NXT-G escribiera datos en un archivo mientras se ejecuta el PID. A
continuación, transferiría los datos a la PC para su análisis. Esta sería una excelente manera de
determinar Pc. Creo que la versión 2.0 de NXT-G puede transferir datos a la PC en tiempo real para
graficar. Escribir en un archivo de datos (o enviar los datos a través de Bluetooth) tiene algunos problemas
cuando se usa con un PID. Escribir en un archivo es un proceso bastante lento, por lo que el tiempo de
bucle del PID aumentará, creo que transmitir cualquier cosa a través de Bluetooth también es bastante
lento. Eso significa que el PID tarda más en repetirse y está midiendo el error y actualizando los motores
con menos frecuencia. Otro problema con la escritura en un archivo es que periódicamente la rutina de
escritura de archivos toma una gran cantidad de tiempo (hasta 0.1 segundos) para hacer algo de
"limpieza". Esto se puede evitar "extendiendo previamente" el archivo al límite cuando se abre el archivo
por primera vez. Un archivo NXT-G puede ser tan grande como 32K si tienes tanto espacio libre en el
NXT-G. Si intentas extender previamente el archivo de datos y no tienes suficiente memoria, el NXT-G no
da ninguna indicación de que haya habido un problema. Si utiliza un método como este, entonces el
valor de PC que obtiene es relevante solo para el dT particular que tiene el programa "PID con registro".
Si desea medir la PC y luego eliminar el código de registro de datos del programa para que se repita más
rápido, la PC ya no es válida. Una solución parcial es forzar que todos los bucles del PID tomen la misma
cantidad de tiempo. Al principio del bucle, establezca un temporizador en cero. Al final del bucle, ESPERE
un período de tiempo más largo que el dTnormal del bucle. Puede utilizar esta técnica para mantener
constantes los tiempos de bucle incluso si agrega o elimina grandes trozos de código (como el registro de
datos). Por supuesto, eso significa que siempre tiene el bucle PID más lento de lo que podría ser, y está
perdiendo el tiempo en cada ciclo de bucle.
He jugueteado un poco con la escritura de datos en un archivo mientras el PID se está ejecutando. Es útil
iniciar el archivo de datos con una lista de los valores Tp, offset, Kp, Ki y Kd. Los buenos datos para
registrar cada vez que se ejecuta el bucle PID son el tiempo, el error,la salida PID y el ángulo de uno de
los ejes del motor. A partir de esos datos, puede reconstruir la integral y la derivada para que no necesiten
ser registradas.
No me queda claro qué tan rápido debe ciclar el PID, es decir, qué tan pequeño debe ser dT, para obtener
un buen controlador. Sospecho que el PID necesita ciclar más rápido que el tiempo de respuesta de los
motores. Quizás varias veces más rápido. Pedalear el PID mucho más rápido que eso probablemente no
ayude mucho, ya que las cosas no están cambiando tan rápido. El tiempo de respuesta de los motores
NXT, cuando en realidad están moviendo un robot, está en el rango de un par de décimas de segundo.
El PID probablemente debería circular en digamos 1/5 a 1/10 de ese tiempo, o alrededor de 0.010 a 0.030
segundos por bucle. El programa PID básico descrito anteriormente tiene un dT de aproximadamente
0.015 segundos, que debería ser lo suficientemente rápido. Si el programa también registra datos a
medida que se ejecuta, entonces el dT se eleva a aproximadamente 0.030 segundos por bucle.
El uso de valores de luz en bruto (escala de 0 a 1023), en lugar de valores de luz no calibrados, podría
aumentar el rango dinámico de los sensores de luz. Para nuestro ejemplo, los valores de luz negro serían
400 y blanco 500. El desplazamiento sería 450 con un rango de +/-50 en lugar de +/-5. Los valores de
luz en bruto están disponibles desde un puerto de datos en el bloque del sensor de luz. Si calibra su
sensor de luz bajo sus condiciones de iluminación y usa los valores calibrados, entonces el blanco será
aproximadamente 100 y el negro será aproximadamente 0. Esta es otra forma de aumentar el rango
proporcional del sensor de luz. Tanto en el modo crudo como en el calibrado, los valores de luz
probablemente no sean precisos en el último dígito, pero es de esperar que los valores sean algo más
precisos que usar un rango de valores de luz de solo 10 más o menos.
Al crear un controlador PID, a menudo hay un par de formas diferentes de definir el error. Para nuestro
seguidor de línea, el error es proporcional a qué tan lejos está el sensor del borde de la línea. La derivada
es la rapidez con la que el sensor se mueve hacia o lejos del borde de la línea. La integral es la suma de
las distancias desde el borde de la línea, que realmente no tiene mucha importancia física (aunque todavía
ayuda al controlador). Hay otras formas de hacer las cosas. Podríamos definir el error como la rapidez
con la que nos movemos hacia o lejos del borde de las líneas. En otras palabras, el error es ahora lo que
era la derivada en nuestro seguidor de línea. Para esta nueva definición de error, la derivada se convierte
en la rapidez con la que estamos acelerando hacia o lejos del borde de la línea. La integral se convierte
en lo lejos que estamos del borde de la línea, lo que tiene sentido físico. Qué método funciona mejor a
menudo depende de qué tan preciso pueda medir el error y cuánto ruido (fluctuación aleatoria) hay. Si
usamos la velocidad como error, tiene que calcularse a partir de la lectura de la luz y es la derivada de la
lectura de la luz. Para obtener la derivada para el PID tenemos que tomar la derivada de una derivada.
La derivada de una derivada probablemente no funcionará muy bien con nuestro limitado rango
proporcional de valores de luz.
Para el "seguidor de línea de tres niveles", los tres rangos no necesitan ser del mismo tamaño. Si este
tipo de seguidor es lo suficientemente bueno, a menudo es mejor hacer que el rango central sea más
grande que los dos rangos externos. Algo así como 42 a 47 quizás para nuestros valores de ejemplo. Lo
único de lo que tienes que preocuparte es que esto se vuelve bastante sensible a pequeños cambios en
la iluminación de la habitación. Los tres rangos uniformes (y el enfoque original de dos rangos) son
bastante insensibles a los cambios en la iluminación de la habitación. Si hace que el rango central sea
demasiado grande, corre el riesgo de que un pequeño cambio en la iluminación de la habitación mueva
su rango de luz fuera de lo que esperaba. Es posible que el sensor de luz nunca devuelva números en el
rango más bajo o más alto y que el robot nunca gire en una de las dos direcciones.