Objetivos

 

  • Seguimos jugando con los motores de corriente continua y la controladora Motor Shield V1 de Adafruit.
  • Vamos a usar un controlador inalámbrico tipo PlayStation 2 para gobernar manualmente el Rover 4×4.
  • Veremos cómo usar las librerías de control: PSX.
  • Mostraremos cómo detectar las pulsaciones básicas de los botones del mando.
  •  

    Material requerido.

     

    Imagen montado

    Robot Rover 4×4

     

    Un control como Dios manda

     

    El control mediante Bluetooth es práctico porque siempre tenemos a mano un móvil con él, pero un poco errático y al final siempre nos deja la sensación de ser un tanto incomodo o de fundir las baterías del móvil demasiado deprisa y en el mejor de los casos, incómodo para estar un rato con él.

    Por eso, y como siempre solemos comentaros, al final, alguien tenía que venir con una solución “como Dios manda” y por eso el mercado nos proporciona una impecable para controlar nuestros robots, motores o proyectos varios con un mando único, que a muchos nos resultará familiar: Un mando como el de la PlayStation 2 inalámbrico.

    Estos mandos se pueden conseguir por poco dinero en estos momentos (Gran cosa las bajadas de precios de todos los componentes electrónicos) y tiene la enorme virtud de ser ergonómicos y muy cómodos de manejar, además de estar dotados de dos joysticks analógicos y como 14 botones incluidos.

    Estos mandos vienen con un receptor inalámbrico, que podemos conectar a nuestros Arduinos y usarlos para recibir las señales de control, sin complicarnos mucho la vida, y un mando inalámbrico aparte muy similar al que habréis usado más de uno para jugar con la PS2 de Sony.

    Compatible PS2

    Compatible PS2

    En esta sesión vamos a ver como conectar este tipo de mando inalámbrico a nuestros Arduinos y veréis que gracias a las librerías que nuevamente se ha trabajado Mr. Bill Porter, son pero que muy fáciles de implementar y usar.

     

    Conectando el receptor remoto

     

    Como estamos montando un Rover 4×4 vamos a utilizar un Arduino Mega como el que venimos usando en las sesiones anteriores, para que el que quiera pueda tener un robot funcional.

    Cuando empecé a mirar en Internet la información de este tipo de mandos me pareció bastante confusa y lo que es peor me pasé un buen número de horas tratando de hacerlo funcionar sin éxito

    El problema que puede ocurrir al conectar el receptor inalámbrico a tu Duino es que lo enchufes al revés (Yo desde luego lo hice y me dio una tarea que no veas hasta que me di cuenta) porque la información que hay en Internet es un poco oscura y hay que leer entre líneas  para comprender de que va el tema. En cuanto lo conectas bien no hay pérdida posible.

  • Si buscáis información en Internet, os encontrareis con que suelen describirte que es cada pin en función de un código de colores, que quizás sea estándar con los mandos de Sony, pero que con los compatibles solo va a servir para confundiros, así que olvidaros de los colores.
  •  

    En su lugar usad este diagrama, mirando desde le frontal del receptor (Desde donde no salen cables)Compatible con Sony PS2

    Tampoco es necesario que os compliquéis la vida entendiendo la utilidad de cada cable, ya que la librería que vamos a usar, se va a encargar de la gestión a condición de que definamos correctamente los pines.

    Lo más cómodo es que conectéis los pines a vuestro Arduino en secuencia. En mi caso que uso un MEGA y la tabla de conexión seria así:

    Conexión receptor PS2 a Arduino MEGA
    Receptor 1 2 3 4 5 6 7 8 9
    Mega 22 24 26 28 30 32 34 36 38
    Pin data command vibration GND 5V Attention Clock acknoledge

     

    Si disponéis de un pin header plano o a 90º es ideal para esto, porque dispondréis de un peine de pines que se conecta directamente a los conectores de la Mega y el enganche es más fiable,  porque están agrupados.

    Pines acodados

    De nuevo, tenemos un par de pines que son GND y 5V, pero como el consumo es despreciable podemos poner en HIGH el pin 30 y en LOW el pin 28.

  • Aunque en la documentación dice que el pin 30 debe ser alimentado a 3.3V yo he probado con 5V sin ningún problema y eso que lo he tendido encendido largo y tendido. 
  •  

    El programa de control

     

    Lo primero es descargar la librería PS2X_lib y que la instaléis siguiendo el procedimiento habitual.

    Como ya es costumbre de la casa, vamos a empezar con un programa mínimo para comprobar unos pocos botones y después iremos viendo el resto de los mandos disponibles.

    Vamos a empezar incluyendo la librería y creando un controlador tipo para el manejo del mando.

    Prog_96_1

    #include <PS2X_lib.h>  //for v1.6
    PS2X ps2x; // Creamos la clase del mando PS2

    Después vamos a definir el setup para que nos alimente el receptor con GND y 5V.

    Serial.begin(57600);
    pinMode(28, OUTPUT) ; pinMode(30, OUTPUT);
    digitalWrite(28, LOW);      //Set Ground for remote
    digitalWrite(30, HIGH);     // Set 5V for remote
    delay(500);

    Ya habíamos usado antes este truco de alimentar algo con un pin del Arduino, pero recordar que este no debe superar los 40 mA Vamos a hora a definir los pines que vamos a usar en la librería con la línea:

    error = ps2x.config_gamepad(34,24,32,22, true, true)
    //(clock, command, attention, data, Pressures?, Rumble?)

    Fijaros que es aquí donde especificamos que pines vamos a usar y a que funciones del mando a distancia corresponden, por eso elegí que fueran consecutivos (Recordad que la vagancia es muy valiosa si te ahorra trabajo inútil), pero podéis definir los que queráis en función del modelo de Arduino que estéis usando.

    Y por último, en el setup, vamos a asegurarnos de que hay un mando disponible e imprimimos el tipo en caso afirmativo:

    error = ps2x.config_gamepad(34,24,32,22, true, true);
    if(error == 0)
    Serial.println("Controlador encontrado y configurado");
    type = ps2x.readType();
    if ( type == 1)
         Serial.println("Hallado controlador DualShock.");

    Después de esto, si hemos detectado correctamente el mando ya podemos pasar a controlar los botones que se pulsan, Pero antes tenemos que salir si no hemos detectado el mando:

    String S, Sentido = "" ;
    if(error == 1) return;     //Salir si no encontramos mando

    Vamos a hacer un pequeño programa que detecte los botones de la mano izquierda: UP, DOWN, LEFT, RIGTH.

    Detalle botones analogicos

    while(true)
      {   ps2x.read_gamepad();          //Leemos el mando  
         
          if(ps2x.Button(PSB_PAD_UP))          //Es TRUE mientras se pulsa el boton
              Serial.println("UP");
          else if(ps2x.Button(PSB_PAD_DOWN))
              Serial.println("DOWN");
          else if(ps2x.Button(PSB_PAD_RIGHT))
              Serial.println("RIGHT");
          else if(ps2x.Button(PSB_PAD_LEFT))
              Serial.println("LEFT");
          else
              Serial.println("STOP");
      }

    Si volcáis este programa Prog_96_1 a vuestro Arduino, veréis que detecta con un mensaje en la consola el botón que pulsáis. Naturalmente la librería provee variables para todos los botones disponibles en el mando mediante la función ps2x.Button().

    Botones de la izquierda
    Boton UP DOWN RGHT LEFT
    FLAG PSB_PAD_UP PSB_PAD_DOWN PSB_PAD_RIGHT PSB_PAD_LEFT

     

    Botones de la derecha
    Boton Circle Red Cross Blue Square Pink Green Triangle
    FLAG     PSB_RED PSB_BLUE PSB_PINK PSB_GREEN

     

    Más los botones centrales, de SELCT ( PSB_SELECT) y Start (PSB_START) . Para los botones traseros tenemos:

    Botones Traseros
    Boton L1 L2 R1 R2
    FLAG     PSB_L1 PSB_L2 PSB_R1 PSB_R2

     

    Los botones de la izquierda, tienen además, la curiosidad de que detectan de modo analógico la presión que ejerces en ellos con valores entre 0 y 255, mediante el comando

    ps2x.Analog( Flag )

    Donde Flag representa cualquiera de los valores indicados en la primera table. Por ejemplo para imprimir la intensidad con que s epulsa el botón UP, bastaría con hacer:

    Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);

     

    Leyendo los joysticks del mando

     

    Por ultimo para detectar el movimiento de los dos joysticks incluidos en el mando, tenemos que entender que al ser analógicos tenemos que leer de cada uno, dos valores, X e Y, tal y como hacíamos en una sesión previa Joystick y Servo.

    Como el mando nos devuelve un valor entre 0 y 255, cuando el joystick esta en reposo en la posición central, la lectura que nos da es de 127 tanto en X como en Y. Espero que el siguiente gráfico os resulte sencillo:

    imagen de posicion

    Para leer los joysticks tenemos que leer independientemente la posición en X e Y de cada uno de ellos

    Joystick Izquierdo Joystick Derecho
    Eje X Y X Y
    Flag PSS_LX PSS_LY PSS_RX PSS_RY

    Para leer los valores de los joysticks podemos usar el siguiente trozo de código:

    Serial.print("Stick Values:");
    Serial.print(ps2x.Analog(PSS_LY), DEC);
    Serial.print(",");
    Serial.print(ps2x.Analog(PSS_LX), DEC);
    Serial.print(",");
    Serial.print(ps2x.Analog(PSS_RY), DEC);
    Serial.print(",");
    Serial.println(ps2x.Analog(PSS_RX), DEC);

    Ahora te puede parecer muy complicado pero es una tontería (En serio), simplemente el mando tiene tantos botones que hay que usar un montón de flags para definir cada uno, pero siempre es lo mismo.

    La librería viene con un ejemplo magnifico de uso, pero tiene el inconveniente de que muestra todas las posibilidades a la vez y puede ser un poco avasallador, pero si vais a usar este mando desde luego os recomiendo que la echéis una ojeada.

  • El ejemplo es muy claro y auto expiclativa pero usa poco menos que todos los botones y comprueba ademas si tu mando es un DUal SHock controller tipico o si por el contrarion esla guitarra del Guitar Hero, lo que abre un monton de posibilidades con una guitarra de esas y aplicaciones musicales en Arduino.
  •  

    Para aquellos que hayáis hecho el montaje como el de este ejemplo, os pongo el ejemplo corregido para que os funcione a la primera, en la que simplemente he adaptado el ejemplo incluido a nuestros pines. Prog_96_2.

     

    Moviendo nuestro robot con el mando de la PS2

     

    Solo nos queda ya montar un programa completo que incorpore el control de los motores y la dirección del movimiento respondiendo a las pulsaciones del mando a distancia.

    Vamos a empezar  usando los 4 botones de la izquierda como controles simples de dirección. Para ello tenemos que incluir un par de librerías. Una para el control de la controladora de motores  y otra para el manejo del mando de la PS2:

    Prog_96_3

    #include <AFMotor.h>
    #include <PS2X_lib.h>  //for v1.6
    PS2X ps2x; // Creamos la clase del mando PS2
    
    AF_DCMotor Motor1(1);                 // Instanciamos los motores
    AF_DCMotor Motor2(2);
    AF_DCMotor Motor3(3);
    AF_DCMotor Motor4(4);

    Y definimos algunas variables que usaremos luego

    int  error = 0;       // Para reconocer el mando
    byte type = 0;     // Tipo del mando. Volveremos sobre ello
    int Vel = 180 ;    // Define la velocidad base del Rover

    En el setup, definimos los pines que alimenten el mando de la PS2

    void setup()
       {  Serial.begin(57600);
          pinMode(28, OUTPUT) ; pinMode(30, OUTPUT);
          digitalWrite(28, LOW);      // Ground para el receptor
          digitalWrite(30, HIGH);     // 5V para el receptor
          delay(500);
    
         // GamePad(clock, command, attention, data, Pressures?, Rumble?)
         error = ps2x.config_gamepad(34,24,32,22, true, true);
         if(error == 0)
              Serial.println("Controlador encontrado y configurado");  
         type = ps2x.readType();
         if ( type == 1)
              Serial.println("Hallado controlador DualShock.");
       }

    Fijaros en la línea

    error = ps2x.config_gamepad(34,24,32,22, true, true);

    Aquí es donde inicializamos el controlador de la PS2 con los pines que usamos y nos aseguramos de que no haya error,  para indicar que ha encontrado un mando compatible. Y por último leemos el tipo de mando que ha encontrado, que puede ser de varios tipos, Tipo DualShock = 1 o tipo Guitar Hero = 2.

    Por último el loop es una variante del programa Prog_76_1, al que añadimos el control de los movimientos del robot que ya vimos en las sesiones previas.

    void loop()
       {   
          if(error == 1) return; //Salir si no encontramos mando
          While(true)
             {   ps2x.read_gamepad();          //Leemos el mando
                 if(ps2x.Button(PSB_PAD_UP))   //Es TRUE mientras se pulsa el boton
                     { Serial.println("UP");  Avance(); }
                 else if(ps2x.Button(PSB_PAD_DOWN))
                     { Serial.println("DOWN"); Retroceso(); }
                 else if(ps2x.Button(PSB_PAD_RIGHT))
                     { Serial.println("RIGHT"); giroDerecha();}
                 else if(ps2x.Button(PSB_PAD_LEFT))
                     { Serial.println("LEFT"); giroIzquierda() ; }
                 else
                     { Serial.println("STOP"); Paro() ; } 
                 delay(500);  // Para que no saque mensajes continuamente
             }
       }

    Aquí os dejo el programa completo Prog_96_3.

    Y un video con el resultado del robot montado y completo

     

     

    Resumen de la sesión

    <  

  • Presentamos un mando tipo PS2 para gobernar remotamente nuestros proyectos
  • Os presentamos las librerías PSX para el control de los mandos de Sony DualShock y Guitar Hero.
  • Vimos el modo de vincular estos mandos a nuestros proyectos y la forma de reconocer por programa las pulsaciones realizadas.
  •  

    Deja una respuesta