You are on page 1of 16

Control PID de Barra y Bola con Arduino

18 agosto, 2015
72 Comments
Es fácil entender el Control PID estudiando un sistema Barra y Bola y utilizando como
Controlador un Arduino. El objetivo es situar la bola en el centro de la barra inclinándola de
forma conveniente mediante un lazo cerrado de control.
Vídeo Resumen de 5 minutos:

Índice
 Sistema Barra y Bola
o Sensado de la posición de la Bola
 Acondicionamiento de la señal del sensor
 Calibración del sensor
o Actuador
o Controlador
o Alimentación de 5V
o Esquema del sistema completo
 Control PID
o Período de medida y reacción
o Cálculo de la velocidad de la bola
o Primera aproximación: El término Proporcional
o Deteniendo la bola: El término Diferencial
o Incrementando la precisión: El término Integral

Sistema Barra y Bola


Es un sistema clásico en la Ingeniería de Control.

 Mediante un Sensor de distancia, medimos la posición de la bola.


 Con un Controlador, mediante control PID, calculamos el ángulo en el que
deberíamos inclinar la barra para colocar y estabilizar la bola en el centro de la barra.
 Un Actuador modifica la inclinación de la barra.
Sistema Barra y Bola

Sensado de la posición de la Bola


La realizamos mediante el sensor de distancia mediante luz infrarroja y detector PSD:
SHARP GP2Y0A21.

Sensor SHARP
Tiene un rango de medida de 6 a 80 cm. Funciona con 5V y su salida es una tensión
relacionada con la distancia medida mediante esta curva característica:

Curva Sensor SHARP

Si la Bola se acerca más de 6cm al sensor, la medida es errónea. Limitamos el movimiento


de la bola en esa distancia.

Freno

Acondicionamiento de la señal del sensor


Para filtrar (paso bajo) la señal del sensor y tener una señal más precisa y repetitiva,
conectaremos un condensador electrolítico de 10μF entre la salida del sensor y tierra.
Efecto del condensador de filtrado

Como la tensión máxima que vamos a medir es de 3,1V, configuraremos la referencia de


tensión del Arduino a 3,3V mediante la instrucción:

analogReference(EXTERNAL);

y conectaremos el pin AREF con la salida de 3,3V del Arduino:

Conexión de la Referencia Analógica a la salida de 3,3V

De esta forma, los 1024 puntos que nos proporciona el Conversor Analógico Digital de 10
bit del Arduino tendrán un fondo de escala de 3,3V en lugar de los 5V por defecto. Así,
incrementamos la resolución de 5mV/ADC a 3mV/ADC.
Calibración del sensor
Para relacionar la tensión proporcionada por el sensor con la distancia en centímetros,
desplazaremos la bola por la barra tomando nota de la lectura en ADC. En el Software
desarrollado para el Arduino, se incluye un modo de funcionamiento en el que transmite
continuamente las lecturas del sensor por el puerto serie:
if(0){// Para calibrar sensor de Distancia

Serial.print(dist);

Serial.print("mm ADC: ");

Serial.println(measure);

Con 9 puntos a lo largo de la barra es suficiente. Obtenemos la curva de calibración del


sensor.

Calibración del Sensor de distancia


que en el Software queda definida como:

int dcal [] = { // Calibracion de ADC a Distancia

-193, -160, -110, -60, 0, 40, 60, 90, 120};

int ADCcal [] = {

177, 189, 231, 273, 372, 483, 558, 742, 970};

y para transformar las lecturas ADC del sensor, almacenadas en la variable measure, en la
posición en mm de la variable dist, aplicamos el siguiente algoritmo:

for(int i =0; i<8; i++){ // Aplicamos curva de Calibracion de ADC a mm

if (measure >= ADCcal[i] && measure< ADCcal[i+1]){

dist = map(measure,ADCcal[i],ADCcal[i+1],dcal[i],dcal[i+1]);

La variable dist tiene valores negativos y positivos: -193mm en el extremo izquierdo de la


barra, 120mm en el derecho y 0 en el centro. Como nuestro objetivo es dejar la bola en el
punto central, esta variable dist equivale al error utilizado en la bibliografía de sistemas de
control PID.
Actuador
Inclinaremos la barra con un Servo HEXTRONIK HX5010 de 6,9 kg.cm de par motor y una
biela de fibra de vidrio anclada a un extremo de la barra.

Actuador Servo

Como dice la Wikipedia, controlamos el giro del servo con pulsos de duración variable:
Control de la posición del servo mediante pulsos

En este servo en concreto la posición 0º se obtiene con pulsos de 0,5ms y el giro de 180º
con 2,3ms.

La biblioteca estándar (incluida en el IDE de Arduino) servo, incluye la


instrucción write(angle), siendo angle un integer entre 0 y 180, que nos permite ajustar la
posición del servo. Ésta es la instrucción que se usa habitualmente, pero como nosotros
queremos la máxima precisión en el giro del servo, utilizaremos writeMicroseconds en su
lugar. Su sintaxis es: servo.writeMicroseconds(μS), siendo μS los microsegundos de
duración del pulso. Dispondremos de valores entre 500 (posición arriba) y 2300 (posición
abajo), teniendo 1800 puntos distintos en lugar de sólo 180 usando la instrucción más
básica: write(angle).
Durante la puesta en marcha y ajuste, calcularemos la posición de reposo (barra
horizontal) con la ayuda de un nivel de burbuja.

Nivel de burbuja
Controlador
Utilizaremos un clon de Arduino con microcontrolador ATMEL ATMEGA328-PU
equiparable al Arduino UNO o al antiguo Duemilanove original.

 Recibe la medida de la posición de la bola en su entrada analógica A0.


 Emite pulsos para controlar el servo en su salida digital 12.
 A través de su conexión USB envía distintos juegos de datos para debug o tramas de
la forma:

173,173,-5,-5$ //dist,dist,vel,vel$

que son recibidas por un PC ejecutando una aplicación desarrollada en Processing y que
nos permitirá disfrutar de gráficas de la posición y la velocidad de la bola en función del
tiempo como ésta:

Gráfica de Processing

 Como bonus, enciende un led conectado a la salida 13 cuando la bola está situada a
menos de 8mm del centro.
Alimentación de 5V
El Arduino recibe los 5V necesarios para su funcionamiento a través de su conexión USB.
La potencia de su pin de 5V es insufiente para alimentar el servo, por lo que lo
alimentaremos con una fuente de alimentación auxiliar. ¡No olvides conectar la tierra de la
fuente de alimentación auxiliar con la tierra GND del Arduino! De lo contrario, las señales
de control del servo no tendrán un referencia común y no funcionará.

Esquema del sistema completo


Esquema Control PID de Barra y Bola con Arduino

Conexiones
Conexiones Arduino – Breadboard

Control PID
Una vez que tenemos implementado el sistema físico, llega el momento de dar al
controlador la inteligencia necesaria para mover la barra de forma tal que consigamos
nuestro objetivo: Dejar la bola quieta en el centro de la barra.

Software para Arduino: _70_Barra_y_Bola_v5_MicroSegundos


Período de medida y reacción
Las secuencias de medida y reacción (los ciclos de programa) no se harán tan rápido
como pueda el microcontrolador, sino cada 50ms (valor almacenado en la variable period).
Lo hacemos así porque los sistemas de control PID funcionan mejor si los ciclos de
medida y reacción siempre tienen la misma duración.
El microcontrolador, con reloj de 16MHz, tiene velocidad suficiente para hacer el ciclo de
programa en menos de 10ms. Pero con ciclos tan rápidos, la medida de la velocidad de la
bola pierde precisión porque las diferencias en la posición de la bola entre ciclos son
ínfimas y nosotros calculamos la velocidad de la bola como la diferencia en su posición en
2 ciclos consecutivos de programa.
Si alargamos el periodo a 100ms, la medida de la velocidad es más precisa, pero el servo
funciona de una forma perceptiblemente intermitente.

Tras las pruebas realizadas, un período de 50ms aporta mediciones aceptables de la


velocidad de la bola y un funcionamiento del servo fluido.

Cálculo de la velocidad de la bola


En el Software que implementa el control PID en el Arduino calculamos la velocidad como
la diferencia entre la posición actual de la bola (variable dist) y la que tenía en el ciclo
anterior (variable lastDist). Vamos a mejorar la precisión de está medida mediante un filtro
digital de paso bajo (Promediador) que consiste en obtener la media de la últimas 5
velocidades medidas. Las almacenamos en la matriz v[], y las tratamos con el siguiente
algoritmo en cada ciclo de programa:

for (int i=0; i<nvel-1; i++){ // Movemos todas hacia la izq

v[i] =v[i+1];

v[nvel-1]= (dist - lastDist); // Ponemos un dato nuevo

vel=0;

for (int i=0; i<nvel; i++){ // Calculamos la media

vel = vel+ v[i];

vel = vel/nvel;
El valor de la velocidad lo utilizaremos para calcular la componente Derivativa del control
PID. Además lo enviamos a través del puerto serie / cable USB para que lo reciba
el software Processing y nos lo represente gráficamente.
Primera aproximación: El término Proporcional
Si de lo que se trata es de llevar la bola al centro de la barra, parece lógico que debemos
inclinar la barra más, cuanto más alejada esté la bola del centro. El giro del servo, que
determina la inclinación de la barra, lo determinamos con el valor de la variable pos que
adopta valores negativos (hacia arriba):

pos < 0 : Servo Arriba

y positivos (hacia abajo) a partir del valor 0 que deja la barra en horizontal:

pos > 0 : Servo Abajo

Como tenemos la posición de la bola en la variable dist, “Inclinar más la barra cuanto más
lejos esté la bola del centro” se escribe en el software como:

pos=Kp*dist

siendo Kp una constante.

Así ya tenemos implementado el Término Proporcional del control PID.

– ¡No me digas que no es sencillo!

– Sí, claro… y que valor asignamos a Kp.


Para asignar un valor a Kp (como para los posteriores Kdiferencial y Kintegral)
comenzaremos por asignarle un valor cualquiera: 1, 100, 235, 0.01 o el que te apetezca y
observaremos el comportamiento del sistema.

Estamos buscando el valor más pequeño que sea suficiente para inclinar la barra cuando
la bola está cerca del objetivo pero todavía no ha llegado. Valores grandes hacen que la
bola alcance demasiada velocidad y ¡luego hay que detenerla en el centro!

Para el sistema construido, un valor adecuado es 2. Sólo con el término proporcional, la


bola nunca se estabiliza.

En el siguiente vídeo se muestran los efectos de:

– Kp =1. Demasiado bajo. Con poco efecto en las proximidades del punto 0.
– Kp =100. Demasiado alto. Acelera demasiado la bola.
– Kp =2. Es adecuado para nuestro sistema.

Deteniendo la bola: El término Diferencial


El término Diferencial opera sobre la diferencia de posiciones entre el ciclo actual y el
anterior. Es decir, sobre la velocidad de la bola, ya que el tiempo transcurrido entre una
medida y la siguiente es siempre el mismo. Ese tiempo es el periodo de medida y reacción
y en nuestro sistema son 50ms.

El término diferencial se escribe en el software como:

pos=Kd*vel

En las 3 primeras líneas de programa definimos los valores de las 3 constantes del control
PID:

float Kp =0;

float Kd = 100;

float Ki =0;

Lo que estamos haciendo es inclinar la barra oponiéndonos a la velocidad de la bola.


Comenzamos dando un valor cualquiera a Kd.

– ¿puedo darle el valor 10, que es mi número favorito?

– Sí, claro. Adelante.

Hemos puesto Kp=0 para que el término proporcional no participe y Kd=10 como punto de
partida. Se observa que es un valor insuficiente porque no reacciona suficiente como para
detener la bola.
Subimos a Kd=100: Sobre-reacciona y el sistema es inestable.

El valor correcto está entre 10 y 100. Probamos con 50, 25… observando el
comportamiento del sistema bajo control Derivativo. Un valor aceptable es Kd=35.

¡Conseguimos detener la bola con bastante eficacia!

Nuestro objetivo es detener la bola en el punto medio. El control proporcional acerca la


bola al centro inclinando la barra más cuanto más lejos esté. El control derivativo inclina la
barra más cuanto más rápido se mueva la bola y consigue detenerla. Observemos ahora la
acción conjunta de los 2 términos, definiendo la posición del servo como:

pos=Kp*dist+Kd*vel;

¡Esto ya funciona!

La acción combinada de los término Proporcional y Derivativo es un control PD, suficiente


para muchas aplicaciones. Una de sus debilidades es que cuando la bola se ha detenido
cerca del punto central ya no reacciona. Como la velocidad es 0, el término diferencial no
actúa. Como está cerca del punto central, la inclinación de la barra por el término
proporcional es pequeño y puede no ser suficiente como para que la bola se mueva. Es lo
que ocurre en esta ocasión:

Esto nunca ocurrirá en posiciones alejadas del centro porque el término proporcional ya
tendría suficiente entidad como para que su inclinación haga que la bola se mueva.

– ¿Incrementamos el término Proporcional?

Valores altos de Kp conllevan inestabilidad en el sistema como vimos en el vídeo anterior


con Kp=100.

La solución es la letra que nos falta para tener un auténtico control PID: la I de Integral.

Incrementando la precisión: El término Integral


El término Integral considera la posición de la bola (como el término Proporcional) y cuánto
tiempo lleva allí. Dicho de una forma más rigurosa: De la misma manera que el término
Derivativo actúa sobre la velocidad, que es la derivada de la posición de la bola a lo largo
del tiempo, el término Integral actúa sobre el área que queda bajo la curva de la posición a
lo largo del tiempo.
Base de los términos

Ese área depende del intervalo de integración. Si integramos ininterrumpidamente el área


bajo la curva, el término integral sólo aporta inestabilidad en el sistema. Sólo vamos a
integrar la posición de la bola cuando ésta se encuentre a menos de 4 cm del centro de la
barra. Cuando esté a menos de 8 mm del centro, damos por cumplido el objetivo y
dejamos de integrar. Si se sale de un intervalo reiniciamos I (I=0). Lo escribimos en el
software como:
int Rint = 8;

int Rext = 40;

if(abs(dist)>Rint && abs(dist)<Rext){

I=I+dist*Ki;

else {

I=0;

pos=Kp*dist+Kd*vel+I;

Es decir, que mientras la bola esté a menos de 4 cm y más de 8mm del centro, vamos a
coger su distancia al centro, la vamos a multiplicar por Ki y el resultado lo vamos a ir
acumulando en I. Cuanto más tiempo pase ahí, más grande se va a hacer I.

Como conclusión, el término integral aporta más precisión pero hay que acotar
convenientemente su acción porque de lo contrario conlleva demasiada inestabilidad.

You might also like