bclose

Controlando el Rover con un mando PS2

Usando un mando inalámbrico práctico

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.

Version R3Arduino MEGA o equivalente.
Adafruit V1 Un Motor Shield V1
  Chasis tractorUn chasis robot con 4 motores.
Porta bateriasUn porta pilas
Mando inalambrico Un mando inalámbrico tipo PS2
 

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
Receptor123456789
Mega222426283032343638
PindatacommandvibrationGND5VAttentionClockacknoledge

 

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
BotonUPDOWNRGHTLEFT
FLAGPSB_PAD_UPPSB_PAD_DOWNPSB_PAD_RIGHTPSB_PAD_LEFT

 

Botones de la derecha
BotonCircle RedCross BlueSquare PinkGreen Triangle
FLAG    PSB_REDPSB_BLUEPSB_PINKPSB_GREEN

 

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

Botones Traseros
BotonL1L2R1R2
FLAG    PSB_L1PSB_L2PSB_R1PSB_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 IzquierdoJoystick Derecho
EjeXYXY
FlagPSS_LXPSS_LYPSS_RXPSS_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.