bclose

Controlling a Rover via a PS2 joystick.

Objectives

 

 

    • We keep on playing with DC motors and with the Adafruit Motor Shield V1.
    • We are going to use a Playstation 2 wireless joystick or compatible to control the 4×4 Rover.
    • We will see how to use the control libraries: PSX.
    • We will show how to detect the strokes of the joystick’s buttons.

 

 

Bill of materials

Arduino Mega 2560 Arduino MEGA or equivalent.
Motor shield  An Adafruit Motor Shield V1
  Rover chasis
A rover chassis with 4 motors.
Battery holder battery holder.
PS2 wireless joystick  A PS2 wireless joystick plus the receiver

 

 

A remote control as God commands

 

The control via Bluetooth is practical because we always have a smart phone at hand, but it is a little erratic and in the end always leaves us an uncomfortable feeling or perhaps it runs down the battery too quickly and at best, its use is uncomfortable for long periods of time.

Therefore, as we always say, finally someone found a solution, “as God commands”, and that is why the market provides us a flawless solution to control our robots, engines or projects of any kind via a single remote command, which will be familiar to many people: a PlayStation 2 wireless joystick or compatible.

These controls are very cheap nowadays (due to the fall in the prices of all the electronic devices) and have the great virtue of being ergonomic and very comfortable to handle, besides providing two analog joysticks and 14 digital buttons.

These joysticks come with a wireless receiver, which can be connected to our Arduinos and used to receive the control signals, without very much trouble.

 

PS2 joystick
PS2 joystick adapter

In this chapter we are going to see how to connect this type of wireless joystick to our Arduinos and you will see that, thanks to the libraries devceloped by Mr. Bill Porter, it is very, very easy to implement and use.

 

 

Connecting the remote receiver

 

As we are assembling a 4×4 Rover,  we will use an Arduino Mega, as in previous chapters, in order to build a functional robot.

When we started to look for information on this type of control on the Internet, we found it quite confusing and, what is worse, we spent a lot of of hours trying to make it work without success.

When connecting the wireless receiver to your Duino you could wrongly  plug it the other way round (We certainly did it and it gave us a lot of trouble before realizing) because the information on the Internet is a little dark And you have to read between the lines to understand what is all about. As soon as you connect it properly there will be no more trouble.

 
  • If you look for information on the Internet, you will find that they each pin is usually described according to a color code, which perhaps may be standard in the Sony controls but confusing if you use a compatible joystick, so forget about the colours.
 

You should use this diagram instead, looking from the front of the receiver (where there is no wires)
PS2 joystick adapter pinout

You don’t need to worry about  understanding the purpose of each wire, since the library that we are going to use, will be in charge of the management, provided that we define the pins correctly.

The easier thing is to connect the pins to your Arduino in sequence. In our case, we have used a MEGA so the connection table would look like this:

 

Connection PS2 receiver to Arduino MEGA
Receiver 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 acknowledge

 

If you have a flat or L-shaped pin header it should be ideal, because you have a group of pins connected directly to the Mega pins and the hook is more reliable, because they are joined.

 

Pin strip

Again, we have to use GND and 5V but, as the consumption is despicable, we can set to HIGH the pin 30 and to LOW the pin 28.

 
  • Although the documentation says that the pin 30 must be powered to 3.3V, we have powered it with 5V without any problem for a long time.
 
 

The control sketch

 

First you have to download the library PS2X_lib and install it following the standard procedure.

As usual, we will start with a minimal sketch to check a few buttons and later we will see the rest of the available controls.

Let’s start by including the library and creating a PS2X object to handle the joystick.

Prog_96_1

#include <PS2X_lib.h>        // for v1.6
PS2X ps2x;                   // Creates the object for the PS2 joystick

 

Then we define the pins inside the setup() function so that we can drive the receiver with GND and 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);

We had already used this trick to drive something via an Arduino pin, but remember that it should not exceed 40 mA.

Let’s now define the pins used by the library:

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

Note that here is where we specify which pins we are going to use and to which functions of the remote control correspond, so we chose them to be consecutive (remember that laziness is very valuable if it saves us useless work), but you can define whichever pins you want, according to the Arduino model you are using.

And finally, in the setup, we make sure that there is a joystick available and print the type if so:

error = ps2x.config_gamepad(34,24,32,22, true, true);
if(error == 0)
Serial.println("Joystick found and setup");
type = ps2x.readType();
if ( type == 1)
     Serial.println("DualShock joystick found.");

After this, provided that we have detected the joystick correctly, we can test which buttons are pressed, otherwise, if no controller is found, we have to exit:

String S, Sentido = "" ;
if(error == 1) return;     // Exit if no controller is found

Let’s make a small sketch to detect which buttons are pressed on the left side: UP, DOWN, LEFT, RIGHT.

PS2 joystick detail
while(true)
  {   
      ps2x.read_gamepad();                 // We read the joystick
     
      if(ps2x.Button(PSB_PAD_UP))          // It is true while the button is pressed 
          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");
  }

If you upload this sketch Sketch_96_1 to your Arduino board, you will see in the serial monitor a message showing which button has been pressed. Naturally, the library provides variables for all the available buttons of the joystick via the ps2x.Button() function.

 

Left Buttons
Button UP DOWN RGHT LEFT
FLAG PSB_PAD_UP PSB_PAD_DOWN PSB_PAD_RIGHT PSB_PAD_LEFT

 

Right Buttons
Button Red Circle  Blue Cross  Pink Square Green Triangle
FLAG     PSB_RED PSB_BLUE PSB_PINK PSB_GREEN

 

Plus the center buttons, SELECT (PSB SELECT) and Start (PSB START).

These are the flags for the front buttons:

Front Buttons
Button L1 L2 R1 R2
FLAG     PSB_L1 PSB_L2 PSB_R1 PSB_R2

 

The buttons on the left also can also detect in an analogical way the pressure exerted on them with values ranging between 0 and 255, using the command:

ps2x.Analog(Flag)

Where Flag represents any of the values indicated in the first table. For example, to print the intensity with which you press the UP button, it would suffice to do:

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

 

 

Reading the joysticks

 

Finally to detect the movement of the two joysticks included in the controller, you have to understand that, as they provide analog values, we have to read two values from each, X and Y, just like we did in a previous chapter: Prototype with Joystick and Servo.

As the joystick returns a value between 0 and 255, when the joystick is at rest in the center position, the given reading is 127 in both axes, X and Y. I hope you will find the following graphic  useful:

 

Axis of coordinates

 

To read the joysticks we have to read independently the position in the axis X and Y of each of them:

 

Left stick Right stick
Axis X Y X Y
Flag PSS_LX PSS_LY PSS_RX PSS_RY

To read the values of the joysticks we can use the following piece of code:

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

Now it may seem very complicated but it is a nonsense (seriously), the PS2 joystick has so many buttons that you have to use a lot of flags to define each one, but it is always the same.

 

The library comes with a great example of how to use it, but has the disadvantage that it shows all the possibilities at the same time and can be a bit overwhelming, although if you are going to use this kind of  joystick I certainly recommend you taking a look.

 
  • The example is very clear and self explanatory but uses almost all the buttons and also check if your controller is a typical Dual Shock or if, on the other hand, is a Guitar Hero controller, which opens a lot of possibilities to musical applications in Arduino with one of those guitars.
 

For those of you who have made the assembly like in this example, we have put the corrected sketch to work at first, in which we have simply adapted the included example to use our pins.

Prog_96_2.

 

 

Moving our rover via a PS2 joystick

 

We only have to write a full sketch to include the control of the motors and the direction of the movement according to the strokes of the remote control.

Let’s start by using the 4 buttons on the left as digital direction controls. So, we have to include a couple of libraries: one to control the motor shield and another to control the PS2 joystick:

 

Prog_96_3

#include <AFMotor.h>
#include <PS2X_lib.h>                                                        // for v1.6
PS2X ps2x;                                                                   // Creates PS2 joystick object

AF_DCMotor Motor1(1);                                                        // Creates the motor objects
AF_DCMotor Motor2(2);
AF_DCMotor Motor3(3);
AF_DCMotor Motor4(4);

Now we define some variables to use them later:

int  error = 0;                                                              // To recognize the joystick
byte type = 0;                                                               // Model of joystick. We will back on it later 
int  speed= 180 ;                                                            // Defines the base speed of the Rover

In the setup, we define the pins to drive the PS2 controller

void setup()
   {  Serial.begin(57600);
      pinMode(28, OUTPUT) ; 
      pinMode(30, OUTPUT);
      digitalWrite(28, LOW);                                                 // Ground for the receiver 
      digitalWrite(30, HIGH);                                                // 5V for the receiver
      delay(500);

     // GamePad(clock, command, attention, data, Pressure?, Rumble?)
     error = ps2x.config_gamepad(34,24,32,22, true, true);
     if(error == 0)
          Serial.println("Controller found and setup");  
     type = ps2x.readType();
     if ( type == 1)
          Serial.println("DualShock controller found.");
   }

Pay attention to the following line:

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

This is where we initialize the PS2 receiver with the pins that we are going to use. After that, we make sure that there is no error and if so, we show that a compatible joystick has been found. Finally we read the type of joystick found, that can be either a DualShock = 1 or Guitar Hero = 2 joystick.

The final loop is a variant of the first sketch of this chapter,  to which we have added the control of the movements of the rover that we saw in previous chapters.

void loop()
   {   
      if(error == 1) return;                                            // Exit if no joystick is found 
      While(true)
         {   ps2x.read_gamepad();                                       // Read the joystick 
             if(ps2x.Button(PSB_PAD_UP))                                // It is TRUE while we press the button 
                 { 
                   Serial.println("UP");  
                   Forward(); 
             }
             else if(ps2x.Button(PSB_PAD_DOWN))
                 { 
                   Serial.println("DOWN"); 
                   Reverse(); 
             }
             else if(ps2x.Button(PSB_PAD_RIGHT))
                 { 
                   Serial.println("RIGHT"); 
                   TurnLeft();
             }
             else if(ps2x.Button(PSB_PAD_LEFT))
                 { 
                   Serial.println("LEFT"); 
                   TurnLeft() ; 
             }
             else
                 { 
                   Serial.println("STOP"); 
                   Stop();
             } 
             delay(500);                                                // Not to send messages continuously
         }
   }

Here is the full sketch:

Prog_96_3.

 

Summary

 

 

    • We have used a PS2 joystick to control our projects.
    • We have introduced the PSX libraries that will enable us to use the Sony DualShock  and Guitar Hero joysticks.
    • We have seen how to embed these commands into our projects and recognize the keystrokes performed.