controla-arduino-con-el-mando-inalambrico-de-la-ps2

Controla Arduino con el mando inalámbrico de la PS2

Una de las mejoras formas de que disponemos para controlar un robot a distancia es emplear el mando de una Playstation 2. En Internet podéis encontrar multitud de ejemplos que optan por este controlador por sus excepcionales características técnicas, incluso en proyectos profesionales. Además es realmente barato, algo especialmente importante en nuestros proyectos caseros.

Entre sus características como controlador el mando de la PS2 es inalámbrico y dispone de un alcance bastante aceptable. Por otro lado dispone de una gran variedad de entradas que incluyen 4 botones de dirección sensibles a la presión, 4 botones de acción sensibles también a la presión, 2 palancas analógicas y 4 botones digitales ubicados en la parte frontal.

En cuanto al precio un clónico de este mando se puede conseguir en Ebay por de 9,90€. Un precio increíble que, junto con sus características técnicas, lo convierten en una de las mejoras opciones para controlar un robot a un coste mínimo.

En este tutorial vamos a aprender a conectar el mando de una PS2 a Arduino para poder usarlo en nuestros proyectos y poder controlar robots y automatismos de forma inalámbrica.

Material necesario

Además de nuestro Arduino (mini, Uno, Mega, o el que vosotros prefiráis) lo primero que necesitamos es, lógicamente, un mando de PS2 inalámbrico. Una simple búsqueda en Ebay nos mostrará una gran cantidad de clónicos. Buscamos uno en el rango de 9 a 10€, barato pero que tenga un mínimo de calidad.

arduino-mando-ps2

Por otro lado, en la mayoría de los casos necesitaremos un conversor lógico de nivel de 3,3V a 5V. El motivo es que, por lo general, nuestro Arduino opera a 5V, mientras que la electrónica del mando de la PS2 funciona a 3,3V. Podríamos hacer nuestro propio circuito de adaptación, pero no tienen ningún sentido dado que se venden por 1,10€, gastos de envío incluidos.

arduino-mando-ps2-level-converter

Para encontrar el conversor simplemente buscar “level converter” en Ebay. Estamos buscando un artículo similar al siguiente “JY MCY I2C LEVEL CONVERTER”, un dispositivo que permite adaptar 4 señales de forma bidireccional. Fijaros que el modelo que queremos tiene 6 pines (no compréis uno de 4 pines, que solo pueden adaptar 2 señales).

Conexión y montaje

Todo el montaje se realiza exclusivamente en el receptor, por lo que podemos dejar “tranquilo” al mando propiamente dicho. En primer lugar retiramos los tornillos del receptor para acceder a los terminales. Desoldamos los pines de conexión sustituyéndolos por nuestros propios cables, que soldaremos a la placa del receptor. Cerramos el receptor, dejando saliendo los cables por donde antes estaba la conexión con la vídeo consola.

Ahora empleamos un polímetro para identificar la función de cada uno de los cables que hemos soldado. No os fiéis de los esquemas de Internet, que identifican cada terminal por el color del cable que tuvieran soldado, porque el color de los cables y su conexión varían de un fabricante a otro. Verificarlo manualmente con un polímetro y la ayuda del siguiente esquema.

arduino-ps2-conexion

A continuación usamos una protoboard para realizar las conexiones con nuestro conversor digital (o lo soldamos directamente). En el lado de baja tensión se conectan las cuatro señales del mando, ground, y alimentación, que será proporcionada por Arduino. En el lado de alta tensión conectamos cuatro pines, ground, y +5V que será convertido por el conversor a +3,3V para alimentar el receptor.

El esquema definitivo es el siguiente.

arduino-ps2-esquema

Aquí podéis ver un ejemplo del montaje final, conectado a un Arduino Uno.

arduino-mando-ps2-montaje

Y aquí un montaje similar conectado a un Arduino Mini.

arduino-mini-mando-ps2

Con esta combinación queda un montaje bastante compacto que cabe fácilmente en cualquier robot, y con los pines libres de ambas protoboard tenemos suficientes conexiones para el resto de elementos que la requieran.

Librería y código

Vamos a por el código. Afortunadamente para nosotros la parte difícil está resuelta en una magnífica librería disponible en https://github.com/madsci1016/Arduino-PS2X. Simplemente descargamos e importamos la librería, y cargamos el Sketch de ejemplo.

El código del ejemplo es demasiado extenso y tiene líneas en exceso (cómo es lógico ya que el objetivo es mostrar todas las posibilidades). No es en absoluto difícil analizar y adaptarlo a nuestras necesidades. Sin embargo, os dejo un código reducido para que podáis emplear fácilmente como punto de partida para vuestros proyectos.

#include <PS2X_lib.h>

PS2X ps2x;

int error = 0; 
byte type = 0;
byte vibrate = 0;

void setup(){
  Serial.begin(57600);

  error = ps2x.config_gamepad(13,11,10,12, true, true);   //setup pins and settings:  GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error

  if(error == 0){
    Serial.println("Found Controller, configured successful");
    Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
    Serial.println("holding L1 or R1 will print out the analog stick values.");
    Serial.println("Go to www.billporter.info for updates and to report bugs.");
  }

  else if(error == 1)
  Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");

  else if(error == 2)
  Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");

  else if(error == 3)
  Serial.println("Controller refusing to enter Pressures mode, may not support it. ");

  type = ps2x.readType();   
}

void loop(){ 

  if(type == 1){ 
    ps2x.read_gamepad(false, vibrate);  //Lectura del estado

    //Lectura de los botones de dirección  
    if(ps2x.Button(PSB_PAD_UP)) {
      Serial.print("Up held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);
    }
    if(ps2x.Button(PSB_PAD_RIGHT)){
      Serial.print("Right held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);
    }
    if(ps2x.Button(PSB_PAD_LEFT)){
      Serial.print("LEFT held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);
    }
    if(ps2x.Button(PSB_PAD_DOWN)){
      Serial.print("DOWN held this hard: ");
      Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);
    }   

    //Lectura del estado de botones
    if (ps2x.NewButtonState())
    {
      if(ps2x.Button(PSB_RED))
      Serial.println("Circle pressed");
      if(ps2x.Button(PSB_GREEN))
      Serial.println("Triangle pressed");
      if(ps2x.Button(PSB_PINK))
      Serial.println("Square pressed");
      if(ps2x.Button(PSB_BLUE))
      Serial.println("X pressed");
      
      if(ps2x.Button(PSB_START))
      Serial.println("Start is being held");
      if(ps2x.Button(PSB_SELECT))
      Serial.println("Select is being held");
      
      if(ps2x.Button(PSB_L3))
      Serial.println("L3 pressed");
      if(ps2x.Button(PSB_R3))
      Serial.println("R3 pressed");
      if(ps2x.Button(PSB_L2))
      Serial.println("L2 pressed");
      if(ps2x.Button(PSB_R2))
      Serial.println("R2 pressed");
    }      

    //Lectura de las palancas analógicas
    Serial.print("StickValues:");
    Serial.print(ps2x.Analog(PSS_LY), DEC); //Mando izquierdo
    Serial.print(",");
    Serial.print(ps2x.Analog(PSS_LX), DEC); 
    Serial.print(",");
    Serial.print(ps2x.Analog(PSS_RY), DEC); //Mando derecho
    Serial.print(",");
    Serial.println(ps2x.Analog(PSS_RX), DEC); 
  }
  else
  {
    return;
  }

  delay(500);  
}

Por último decir que, en general, la librería en sí es bastante pesada y consume una buena parte de la memoria de nuestro pequeño Arduino. No obstante es posible optimizarla y reducirla eliminando partes de código dedicadas a otros controladores (guitar hero, por ejemplo). Además es un buen ejercicio de aprendizaje, por lo que os invito a que la leáis e intentéis optimizarla.

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full