Objetivos

 

  • Seguimos jugando con los motores de corriente continua y la controladora Motor Shield V1 de Adafruit.
  • Buscamos que el Rover pueda buscar su ruta de forma autónoma evitando obstáculos.
  • Veremos las nociones básicas del movimiento autónomo.
  •  

    Material requerido

     

    Imagen montado

    Robot Rover 4×4

     

    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).

  • Un algoritmo, por si aún no habíamos hablado antes de ello, es un procedimiento estandarizado  para resolver un problema concreto.
  • En nuestro caso el algoritmo será sencillamente girar a la izquierda cuando detecte un obstáculo a menos de una distancia estipulada, lo que no es un algoritmo muy sofisticado que digamos, pero por algún sitio hay que empezar.
  •  

    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).

  • En principio, seguramente podríamos usar un UNO para todo esto, pero un MEGA es mas cómodo, porque el Motor Shield no nos tapa todos los pines y además vamos a cargar varias librerías, que aunque no son grandes, no estoy seguro como andaríamos de memoria con el UNO. 
  •  

    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.

  • Este es un truco muy interesante cuando lo que vais a conectar no consume mas de los 20mA que un Arduino de 5V es capaz de suministrar o recibir, y en ocasiones nos evita andar haciendo cosas raras para buscar los 5V. Pero aseguraros de que no sobrepasareis este límite. 
  • 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

     

    Esquema de protoboard

  • No os fieis del dibujo y fijaros en los nombres de los pines y la tabla de conexión. No es fácil que lo queméis, pero los cementerios están llenos de optimistas.
  • 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.

    Detalle de montaje

    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.

  • Aunque tendríamos que pensar en alguna manera de evitar que gire una vez a cada lado y siempre se dé de frente contra el obstáculo al final. 
  • 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

     

  • Seguimos usando la controladora de Adafruit MotorShield.
  • Vimos un algoritmo muy básico para mover el robot de modo autónomo
  • Planteamos algunos métodos de sofisticar el movimiento.
  •  

    Deja una respuesta