En este Instructable aprendemos dos cosas:
Para el sistema de control, utilizo una versión simplificada de control PID y se utiliza algo de impresión 3D, y programación de Arduinos. La explicación de sistemas de control aplica a muchas otros robots, no tiene que ser el que se construye acá.
El costo del robot es menor a los $35, así que es una buena opción para enseñanza de temas avanzados de robótica, y se podría utilizar como base para robots tipo "micromouse" que resuelven un laberinto.
Gracias al apoyo de CrCibernetica.com quien me facilitó los motores DC y algunos otros componentes.
Lo que se ocupa:
Son dos piezas las que hay que imprimir. Yo lo imprimí con resolución baja de 300 micras y plástico PLA. Tal vez tengan que ajustar algo las medidas, o limar un poco el plástico para que todo ajuste bien. Los archivos 3D los pueden descargar de acá junto con todo el código del robot.
El S4A EDU viene listo para conectar las baterías, y para conectar los motores. Note como los cables van conectados. el MR y ML van al revés (note el cable café y rojo en l a foto)
Tenemos un robot que queremos se mueva en un pasillo, potencialmente un laberinto. El robot debe ser capaz de moverse en el laberinto sin chocar con las paredes y poder circular libremente.
Esta es la parte interesante:
Ahora si estamos listos para hacer el algoritmo.
Cada sensor del robot lee la distancia a la pared. Cuando el robot está exactamente en el centro, la distancia a la pared derecha y a la pared izquierda debería ser la misma. Definamos e(t) como el error en el instante de tiempo t. Para ser exactos
e(t) = sensorR(t) - sensorL(t),
es decir resto la lectura del sensor derecho a la lectura del sensor izquierdo.
Como se muestra en la primera foto hay tres situaciones:
Esto es importante, pues el signo del error e(t) nos indica la dirección del error. Esto lo vamos a utilizar en nuestra fórmula.
Lo que tenemos que lograr cuando controlamos el robot es garantizar de que el error sea siempre 0. Entonces nuestra meta de control es e(t) = 0.
Nos interesa entonces que el movimiento de los motores sea proporcional a el error e(t). Si speedR(t) y speedL(t) es la velocidad del motor derecho e izquierdo respectivamente. entonces las velocidades en cada instante, debería estar definidas,
speedR(t) = speedR(t) + e(t)
speedL(t) = speedL(t) - e(t)
Entonces el error informa la velocidad del motor, y mientras que suma para el motor derecho, resta para el izquierdo.
Con estas fórmulas ya podemos hacer que el robot camine y cuando se acerque a las paredes, comienza a girar de manera proporcional a la distancia de la pared. Sin embargo, este mecanismo de control puede hacer que el robot comience a ir de pared a pared, nunca encontrando el centro (oscilando alrededor del centro). Para eso podemos mejorar la respuesta
En la segunda foto se muestra el movimiento del robot en dos situaciones,
Esta información también la podemos utilizar para de alguna manera reforzar el cambio proporcional en la velocidad de motores. Definiendo d(t) = sensorR(t) - sensorL(t), nuestra función de error ahora quedaría así:
e(t) = d(t)+ [d(t) - d(t-1)]
Noten como si d(t-1) > d(t) el signo es negativo, y entonces le resta a la respuesta de e(t). Es decir, dado que el robot ya va en la dirección adecuada, que el cambio proporcional no sea tan intenso.
Solamente nos falta una cosa. Queremos poder cambiar el "peso" que tiene cada término en la ecuación anterior, entonces simplemente agregamos dos constantes que vamos a llamar Kp y Kd. La ecuación queda:
e(t) = Kp* d(t)+ Kd* [d(t) - d(t-1)]
Esta es la función que vamos a utilizar para luego corregir la velocidad de los motores con estas dos:
speedR(t) = speedR(t) + e(t)
speedL(t) = speedL(t) - e(t)
Ahora lo que nos queda es escribir el código para el Arduino.
EXTRA: He creado una Google Sheets donde metí las fórmulas y donde pueden cambiar las constantes Kp y Kd para que vean el efecto en el control de movimiento
El código lo pueden descargar de este github. Acá también utilizo esta librería para controlar los motores con el S4A EDU.
De todas maneras acá les dejo el código. Las explicaciones están en los comentarios, y las fórmulas corresponden al paso anterior
// @author Tomas de Camino Beck // Dic 2017 #include <robotkit.h></robotkit.h> //define variables a utilizar int error=0; int dif,difAnt=0; const float Kp=1.1; const float Kd=1.3; void setup() { //prepara los motores setMotors(); //Prepara los pines para lectura pinMode(A0, INPUT);//sensor izquierdo pinMode(A1, INPUT);//sensor derecho pinMode(A2, INPUT);//sensor central } void loop() { //calcula la diferencia dif = analogRead(A0) - analogRead(A2); // calculo del error (se redondea) error = round(Kp*(dif)+Kd*(difAnt-dif)); // para mantener en memoria la dif anterior difAnt=dif; //recalcula las velocidades de motores int speedL = constrain(255 - error, 0, 255);//velocidad izquierda int speedR = constrain(255 + error, 0, 255);//velcidad derecha //revisa el sensor central para dar vuelta if (analogRead(A1) < 980){ stopMotors(); delay(200); backward(150, 100); pivotLeft(200, 450); } //avanza hacia adelante con las velocidades calculadas // el tercer argumento es el tiempo que aplica esas velocidades forward(speedL, speedR ,5);
}
En el video se ve el robot funcionando. Sin embargo hay que ajustar los valores de Kp y Kd. Hay varias formas de hacerlo, sin embargo, para este caso es mejor de forma manual. Simplemente ajuste primero Kp, y cuando funcione de manera aceptable, comience a aumentar Kp. En principio comenzará a observar que el robot llega más rápido al centro sin oscilaciones.
En el video simplemente lo pongo a moverse por un pasillo. les queda a ustedes armar un laberinto