Datos personales

Mi foto
Algun dia, las maquinas también tendrán sueños...

martes, 16 de febrero de 2016

Robot Balancin V: El controlador PID.

En esta ocasión veremos un poco de programación, probablemente el proceso más difícil de desarrollar para mi fue el Controlador PID (Proporcional, integral, Derivativo), pero por supuesto estoy dispuesto a compartir mi explicación  para ustedes de modo que les paresca lo mas sencillo posible, el controlador PID usa tres acciones distintas para mantener el error lo mínimo posible en un sistema inestable, nuestro sistema es el robot, el setpoint es el ángulo ideal, es decir el ángulo  en donde se encuentra en posición vertical, como ya saben el robot es incapaz de mantenerse en equilibrio sin mover sus llantas hacia un lado o hacia el otro, la señal PWM aumenta si la perturbación en el sistema es alta, y esta señal está determinada por el PID.


Fórmula del algoritmo PID.

Aunque la fórmula parezca intimidante escribirla en el programa solo requiere de unas cuantas líneas de código, veamos que representan las siglas del PID.


Proporcional: La acción proporcional representa la respuesta inmediata que debe tener el sistema sobre el error, esto significa que si el error es pequeño la acción proporcional será mínima, si el error es grande la respuesta también lo será, en mi programa esta escrito de la siguiente forma:

                                                           Error = SetpointA - AnguloA; 

Error representa la acción proporcional, SetpointA representa el ángulo ideal del robot, AnguloA representa el ángulo en el cual se encuentra el robot, de modo que si recibe una perturbación el error aumentará proporcionalmente. 


Integral: La acción Integral es la suma de los errores cuya función es reducir el error lo más rápido posible, supongamos que el robot se inclina X grados hacia una dirección, el error se irá acumulando en cada bucle del programa de modo que mientras más tiempo pase inclinado mayor será la acción integral, recordemos que el bucle del programa dura unos cuantos microsegundos así que el error podría hacerse muy grande en muy poco tiempo 


IntState = IntState + Error / FHz;    
ultimoError = Error;
IntState = constrain(IntState, -5.0f, 5.0f);

IntState es la acción Integral, gracias a la línea ultimoError = Error; el error se irá acumulando en cada bucle, imaginemos que tenemos un error de 5, al siguiente bucle ultimoError será 5 y se sumará el nuevo error, a continuación esa suma     se convertirá en  ultimoError y así seguirá aumentando hasta llegar al setpoint, por último para evitar que se genere un desbordamiento en la suma de errores utilizaremos la función constrain para limitar este valor IntState = constrain(IntState, -5.0f, 5.0f);

Derivativo: La acción Derivativa se encarga de reducir el error lo más rapido posible anticipando el siguiente error, de modo que funciona como un vistazo a futuro que permite disminuir la perturbación lo más rapido posible, en el programa usaremos el valor del acelerómetro para anticiparnos a la perturbación 

Kd_fb = -K_d * gyroRate;

gyroRate se calcula en el filtro de kalman.

De esta forma la suma de todas las acciones (Proporcional, Integral y Derivativa) queda de la siguiente manera:

 Kp_fb = K_p * Error;
    
    Ki_fb = K_i * IntState;
    
    Kd_fb = -K_d * gyroRate;

    TorqueCMD = Kp_fb + Ki_fb + Kd_fb;



Kp_fb, Kp_fb y Kp_fb son los valores finales de las tres acciones, K_p, K_i y K_d son los valores que habremos de afinar nosotros, cada valor será distinto y dependen del peso y forma de su robot, otro valor a ajustar es el delay del bucle, aunque este valor no pertenece necesariamente al control PID afecta considerablemente la estabilidad del mismo, al final del código está escrito 
delay(delaytime); la variable delaytime será la que tendremos que ajustar además, incluso aunque hicieran uno robot fisicamente identico al mio, estos valores podrían requerir un valor distinto, para ajustar dichos valores:




Comenzar con K_p, K_i, K_d igualando 0, delaytime en 4.00,  y trabajar con K_p primero. Prueba establecer K_p a un valor de 1 y observar el robot. El objetivo es conseguir que el robot se mantenga en vertical, incluso si es muy inestable. Si el robot llega más allá y cae, reducir el valor de K_p. Si la respuesta del robot parece lenta, aumente el valor Kp.

Una vez que el robot es capaz de mantenerse un tiempo aunque sea breve en vertical, asignar un valor de 0.01 a K_d . Intentar aumentar este valor hasta que vea menos oscilaciones.

Una vez que el robot sea más estable, asignar un valor de 10 a K_i. Si el valor de K_i es demasiado alta, el robot se sacudirá izquierda y derecha rápidamente. Si es demasiado baja, no se verá ninguna diferencia perceptible. El Integral es acumulativo por lo tanto  el valor K_i tiene un impacto significativo.
Una vez que el robot sea lo suficientemente estable, se puede aumentar o disminuir un poco el valor delaytime  y ver si todavía es suficiente o más estable. El valor delaytime afecta la estabilidad y es un factor importante a considerar.

El resultado final del algoritmo quedará en la variable TorqueCMD = Kp_fb + Ki_fb + Kd_fb;
para posteriormente transformarla en una señal PWM, la salida se debe limitar a 255 o menos  (en mi caso fue limitada a 200) ya que la salida máxima PWM es de 255.


///////////////////////////PID////////////////////////////////////////
    ultimoError = Error;
    Error = SetpointA - AnguloA;
    IntState = IntState + Error / FHz;
    IntState = constrain(IntState, -5.0f, 5.0f);

    Kp_fb = K_p * Error;
    
    Ki_fb = K_i * IntState;
    
    Kd_fb = -K_d * gyroRate;

    TorqueCMD = Kp_fb + Ki_fb + Kd_fb;
    TorqueCMD = constrain(TorqueCMD, -200, 200);









                                                     





30 comentarios:

  1. excelente publicación ..felicitaciones

    ResponderEliminar
  2. y el código?, lo tendrás ala mano

    ResponderEliminar
  3. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  4. hola disculpa donde puedo ver explicado el filtro kalman ya implementado en arduino?

    ResponderEliminar
    Respuestas
    1. Yo use la librería y lo único y mas completo que encontré sobre ese tema esta en este post, te advierto que esta en inglés y no es fácil http://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-implement-it/

      Eliminar
  5. Ok muchas gracias, lo q pasa q yo hice un balancin como le llamas pero no implemente un filtro kalman sino un filtro complementario, el problema esq mi "BALANCIN" vibra mucho y quiero pensar q es por el ruido q aun mete la imu con el filtro complementario

    ResponderEliminar
    Respuestas
    1. Si vibra mucho puede deberse a muchos factores, desde un problema físico con los motores o como bien dices un problema con el filtro o te falta ajustar bien el pid, si tienes muy arriba el valor P eso podría ocasionar el problema, yo también probe con un filtro complementario y el resultado habría sido prácticamente el mismo, yo creo que te falta ajuste a tu pid

      Eliminar
    2. Ahora q mencionaste el problema fisico, mi motor esta raro porq hacia un lado gira mejor que para el otro.
      Eso igual podria ser un factor.

      Eliminar
    3. Si vibra mucho puede deberse a muchos factores, desde un problema físico con los motores o como bien dices un problema con el filtro o te falta ajustar bien el pid, si tienes muy arriba el valor P eso podría ocasionar el problema, yo también probe con un filtro complementario y el resultado habría sido prácticamente el mismo, yo creo que te falta ajuste a tu pid

      Eliminar
    4. Ahora q mencionaste el problema fisico, mi motor esta raro porq hacia un lado gira mejor que para el otro.
      Eso igual podria ser un factor.

      Eliminar
  6. Mi robot gira las ruedas cuando esta en vertical, y cuando se cae se detiene. Por qué podrá ser?

    ResponderEliminar
    Respuestas
    1. Es normal, esta programado para que cuando supere cierto limite los motores dejen de girar, ya solo tendrías que ajustar el pid y verificar que los encoders estén bien conectados

      Eliminar
    2. Es normal, esta programado para que cuando supere cierto limite los motores dejen de girar, ya solo tendrías que ajustar el pid y verificar que los encoders estén bien conectados

      Eliminar
    3. Es normal, esta programado para que cuando supere cierto limite los motores dejen de girar, ya solo tendrías que ajustar el pid y verificar que los encoders estén bien conectados

      Eliminar
    4. El problema es que yo no uso encoders, no se que deberia hacer

      Eliminar
    5. Sin encoders tendrías que quitar todo el código que tenga que ver con los encoders, eso incluye las interrupciones entre otras cosas, si dejas el código así no estoy seguro si funcione correctamente, además sin encoder va a quedar mas inestable

      Eliminar
  7. Amigo, si yo no uso encoders el codigo es el mismo o tengo que modificar (y cual?) alguna parte?

    ResponderEliminar
    Respuestas
    1. Sin encoders tendrías que quitar todo el código que tenga que ver con los encoders, eso incluye las interrupciones entre otras cosas, si dejas el código así no estoy seguro si funcione correctamente, además sin encoder va a quedar mas inestable

      Eliminar
  8. hola nuevamente y Gracias por los Grandes aportes! mi robot ya consigue estar en pie x varios minutos pero vibra mucho xp se debe este problema, como tienes mas experiencia sbes?

    ResponderEliminar
  9. Si vibra supongo que esta mal ajustado los valores del pid, solo ajustalo un poco, probablemente solo tengas que bajar un poco el KP, KD y aumentar el KI

    ResponderEliminar
  10. hola Gracias x las indicaciones disculpa la ignorancia!!! en tu codigo cuando t refieres a 0.5f 210 conteo x vuelta giro a que te refieres??? muy agradecido x tus respueta !!! Gracias

    ResponderEliminar
  11. hola amigo disculpa quisiera saber en que cambia el uso de un arduino mega enves del arduino uno en el proyecto del robot balancin

    ResponderEliminar
  12. Buenas podrias explicarme la parte sobre la comunicacion bluetooth y la aplicacion ?

    ResponderEliminar
  13. Podrias poner su funcionamiento mediante Bluetooth y poner una imagen mas clara sobre la parte de los encoders, o un programa especifico para leer los encoders, se te agradeceria. Muy buen proyecto, saludos.

    ResponderEliminar
  14. Pregunta: En lugar de filtro kalman puedo usar reles de 5v y separar las alimentaciones tanto del mando del rele y de los motores, así los motores reciben la señal pura de los reles y el ruido de los carbones de los motores no llegaria al acelerometro, el problemas es que no podria usar encoder.

    ResponderEliminar
  15. ¡Excelente proyecto! me fue de gran ayuda tu explicación, muchas gracias.

    ResponderEliminar
  16. Excelente proyecto y expliaccion,felicitacones !!

    ResponderEliminar