Objetivos
Material requerido
Algunos comentarios previos
En principio, esta sesión estaba pensada para montar un sistema de control a distancia de nuestro Robot, pero dado que en esta humilde página aspiramos a poner los medios, para que quien lo desee pueda aprender a programar y dado que nuestro flamante robot con tracción total está en marcha, no he podido resistirme a intentar una prueba con un sistema autónomo de control.
Me refiero naturalmente a dotar a nuestro Rover con algún sensor de obstáculos y una pequeña toma de decisiones en función de ello para ver qué pasa. Y qué mejor que uno sensor que ya conocemos por sesiones previas: El sensor ultrasónico de distancia.
En un tutorial anterior vimos cómo manejarlo y sería bastante fácil de incorporar a nuestro pequeño robot 4×4 en el frontal. Naturalmente la cosa puede hacerse tan complicado como queramos con múltiples sensores de distancia y sensores de luz, o de sonido.
Pero para este primer prototipo, aplicaremos una regla básica de la ingeniería: KISS, por sus iniciales en inglés (Keep It Simple Stupid, que no creo que necesite traducción) y ya tendremos tiempo de complicarnos la vida (Que en el fondo es lo que nos pone).
Conectando el sensor
Ya vimos en una sesión previa como conectar el sensor de distancia por ultrasonidos a un Arduino UNO. En esta ocasión voy a usar un Arduino MEGA, porque necesitamos disponer de pines libres para conectar el Sensor de distancia (2) y dejar sitio para el mando a distancia (como 6).
Solo hay que tener en cuenta que como no tenía a mano el pin de 5V, porque quedaba oculto por el Motor Shield, he usado el pin 52 como alimentación, (Porque el sensor ultrasónico no consume casi nada y un pin del MEGA tiene capacidad para alimentarlo), y tenemos el GND al lado.
He elegido estos pines por pura vagancia, para que sea fácil pasar los cables, pero vosotros podéis elegir los que queráis, claro está.
Vamos a incluir aquí un esquema de los pines en los que lo he conectado yo para que podáis usar los mismos y no necesitéis modificar los programas.
Solo hay que tener en cuenta que como no tenía a mano el pin de 5V, porque quedaba oculto por el Motor Shield, he usado el pin 52 como alimentación, (Porque el sensor ultrasónico no consume casi nada y un pin del MEGA tiene capacidad para alimentarlo), y tenemos el GND al lado.
He elegido estos pines por pura vagancia, para que sea fácil pasar los cables, pero vosotros podéis elegir los que queráis, claro.
Sensor | GND | Vcc | Echo | Trigger |
MEGA | GND | 52 | 48 | 50 |
Color cable | Negro | Rojo | Azul | Morado |
En mi caso he sujetado el sensor de ultrasonidos, mediante una pieza de plástico que me hice con la impresora 3D, y celo al frontal del robot.
Vamos con el programa de control.
Un programa autónomo para el Rover 4×4
Como solo hemos montado un sencillo sensor de distancia, esta es toda la información que podemos usar y por eso la idea de movimiento autónomo se tiene que basar en la distancia al obstáculo más cercano.
No es la situación ideal pero nos servirá como primera aproximación. Por eso la idea que podemos aplicar, es algo así como lo siguiente.
Mientras no haya un obstáculo a menos de digamos 30 centímetros, avanzamos. Si por lo que sea la nos hemos metido en un problemas sin saber cómo y la distancia de un obstáculo es menor de digamos 15 cm, retrocedemos. Y si el obstáculo esta entre 15 y 30 cm, lo que hacemos es girar a la izquierda.
En todos los movimientos aplicamos un delay para asegurarnos de que el Rover se va moviendo poco a poco.
Vamos a partir del programa de la sesión anterior en la que teníamos los movimientos trabajados y simplemente cambiamos el setup de acuerdo con el principio descrito arriba.
Tenemos que instalar la Libreria new_ping en caso de que no la tengáis instalada, y si no sabeís como hacerlo, aquí teneís el procedimiento habitual.
Veamos un poco el programa:
Empezamos con las librerías y algunas definiciones como es habitual:
#include <NewPing.h> #include <AFMotor.h> #define TRIGGER_PIN 50 // Pin conectado al trigger. #define ECHO_PIN 48 // Pin conectado al echo del sensor. #define MAX_DISTANCE 200
Los defines, corresponden a los pines que hemos elegido en el MEGA y el max_distance especifica la máxima medida que me devuelve la librería del sonar, no tiene mucha importancia aquí. Tenemos ahora, que crear una instancia del sonar para uso del programa
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
Y en cuanto al setup, es de lo más simple. Definimos el pin 52 como de salida y lo ponemos en HIGH para que alimente el sonar, y ponemos un pequeño delay para asegúranos de que la alimentación es estable
void setup() { pinMode(52, OUTPUT) ; // Usaremos el pin 52 como VCC de 5V digitalWrite(52, HIGH) ; delay(50); // Por si acaso }
En cuanto al loop, tenemos que empezar enviando un pulso para medir la distancia:
unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS) int dist = uS / US_ROUNDTRIP_CM ;
Y ahora ya podemos pasar a decidir el movimiento de acuerdo a las reglas que mencionábamos arriba:
if (dist > 30) Avance() ; else if ( dist < 15) { Retroceso() ; delay(500); giroIzquierda() ; delay(500); } else { giroIzquierda() ; delay (400); } delay(250);
El resultado es bastante errático y con un comportamiento bastante extraño, como robótico en el peor sentido, y además se atasca sin que este muy claro porque, pero como primera aproximación puede valer.
Aquí os pongo un mini video con el resultado
Mejorando la navegación autónoma
Para ser una primera prueba no está del todo mal. Seguro que podríamos imaginar algún algoritmo un poco más sofisticado que mejorase la navegación.
Por ejemplo podríamos imaginar que el tiempo en que el robot está girando, dependa de la distancia al obstáculo detectado: Cuanto más próximo, más tiempo gira, O que la dirección en la que gira sea aleatoria.
Otro modo de mejorar la toma de decisiones, seria incluir más sensores y basarnos en ellos para los giros. Podríamos usar un sensor de luz y movernos buscando siempre el punto más luminoso de la habitación.
Imaginaros que usáramos dos sensores de distancia ligeramente desviados de la dirección del movimiento. De este modo podríamos considerar que si uno detecta un obstáculo, digamos a la derecha y el otro sensor no, la conclusión seria girar a la izquierda y viceversa.
De este modo con dos sensores de ultrasonidos, podríamos hacer giros adaptativos en función de la posición relativa de los obstáculos.
Como no tengo otro sensor disponible, me voy a quedar aquí, pero si el tema os interesa sería muy fácil de pensar en cómo darle vida propia al movimiento autónomo. Os lo dejo como tareas pendientes y si alguno se os ocurre alguna solución ingeniosa, no dejéis de contármelo.
Resumen de la sesión